Lädt...


🔧 Introduction to Dependency Inversion and Dependency Injection with NestJS


Nachrichtenbereich: 🔧 Programmierung
🔗 Quelle: dev.to

Hello everyone, السلام عليكم و رحمة الله و بركاته

Today, I will delve into the concepts of Dependency Inversion and Dependency Injection, using NestJS as the example framework. These principles are crucial for writing maintainable, testable, and scalable code in modern software development. Let's explore these concepts through an example implementation involving file storage strategies.

Dependency Inversion Principle (DIP)

The Dependency Inversion Principle (DIP) is one of the five SOLID principles of object-oriented design. It states that:

  1. High-level modules should not depend on low-level modules. Both should depend on abstractions (e.g., interfaces).
  2. Abstractions should not depend on details. Details should depend on abstractions.

This principle helps in decoupling the software modules, making the system more modular and easier to maintain.

Dependency Injection (DI)

Dependency Injection is a design pattern that implements DIP. It allows a class to receive its dependencies from an external source rather than creating them itself. This can be done via constructor injection, method injection, or property injection. NestJS supports DI out-of-the-box using decorators.

Implementing Dependency Injection in NestJS

To illustrate these concepts, let's create a file storage system where we can switch between different storage strategies (e.g., Dropbox, Amazon S3) without changing the business logic.

Step 1: Define an Interface for the Storage Strategy

First, we define an interface IStorageStrategy that outlines the methods any storage strategy should implement:

export interface IStorageStrategy {
  uploadFile(file: Express.Multer.File, req?: Request): Promise<any>;
  _setAccessToken(): Promise<void>;
  download(file: string): Promise<Readable>;
  deleteFile(path: string): Promise<boolean>;
  getPresignedUrl(filepath: string): Promise<string>;
}

Step 2: Implement the Storage Strategies

Next, we implement the interface for different storage providers. Let's start with Dropbox:

import { Injectable } from '@nestjs/common';

@Injectable()
export class DropboxStorageStrategy implements IStorageStrategy {
  async _setAccessToken(): Promise<void> {
    // Implement logic to set access token
  }

  async uploadFile(file: Express.Multer.File, req?: Request): Promise<any> {
    // Implement logic to upload file to Dropbox
  }

  async download(file: string): Promise<Readable> {
    // Implement logic to download file from Dropbox
  }

  async deleteFile(path: string): Promise<boolean> {
    // Implement logic to delete file from Dropbox
  }

  async getPresignedUrl(filepath: string): Promise<string> {
    // Implement logic to get presigned URL from Dropbox
  }
}

Similarly, you would implement S3StorageStrategy for Amazon S3:

import { Injectable } from '@nestjs/common';

@Injectable()
export class S3StorageStrategy implements IStorageStrategy {
  async _setAccessToken(): Promise<void> {
    // Implement logic to set access token
  }

  async uploadFile(file: Express.Multer.File, req?: Request): Promise<any> {
    // Implement logic to upload file to S3
  }

  async download(file: string): Promise<Readable> {
    // Implement logic to download file from S3
  }

  async deleteFile(path: string): Promise<boolean> {
    // Implement logic to delete file from S3
  }

  async getPresignedUrl(filepath: string): Promise<string> {
    // Implement logic to get presigned URL from S3
  }
}

Step 3: Create a Service that Uses the Storage Strategy

We create a service MulterConfigService that depends on IStorageStrategy. Using DI, we inject the appropriate strategy at runtime:

import { Injectable, Inject } from '@nestjs/common';
import { MulterModuleOptions } from '@nestjs/platform-express';
import { IStorageStrategy } from './interfaces/storage-strategy.interface';

@Injectable()
export class MulterConfigService {
  constructor(
    @Inject('STORAGE_STRATEGY') private readonly storageStrategy: IStorageStrategy
  ) {}

  createMulterOptions(): MulterModuleOptions {
    return {
      storage: this.storageStrategy, // Adjust this line based on actual implementation
    };
  }
}

Step 4: Define Providers

Next, we define the providers to inject the correct storage strategy. In this example, we'll use Dropbox by default:

export const StorageStrategyProvider = [
  {
    provide: 'STORAGE_STRATEGY',
    useClass: DropboxStorageStrategy, // or S3StorageStrategy
  },
];

Step 5: Configure the Module

Finally, we configure the AppModule to include our providers and service:

import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { MulterConfigService } from './multer-config.service';
import { StorageStrategyProvider } from './storage-strategy.provider';
import { DropboxStorageStrategy } from './strategies/dropbox-storage.strategy';
import { S3StorageStrategy } from './strategies/s3-storage.strategy';

@Module({
  imports: [],
  controllers: [AppController],
  providers: [
    ...StorageStrategyProvider,
    DropboxStorageStrategy,
    S3StorageStrategy,
    MulterConfigService,
  ],
})
export class AppModule {}

Conclusion

By adhering to the Dependency Inversion Principle and using Dependency Injection, we have created a flexible and maintainable system where the storage strategy can be easily swapped out without modifying the core business logic. This makes our application more modular and easier to extend in the future.

By following these principles and patterns, you can build robust applications in NestJS that are well-architected and maintainable.

...

🔧 Introduction to Dependency Inversion and Dependency Injection with NestJS


📈 76.82 Punkte
🔧 Programmierung

🔧 From Dependency Inversion to Dependency Injection in Python


📈 50.41 Punkte
🔧 Programmierung

🔧 Software Design Principle: Inversion of Control(IOC) and Dependency Injection


📈 39.65 Punkte
🔧 Programmierung

🔧 Inversion of Control vs Dependency injection - can they be used interchangeably?


📈 38.03 Punkte
🔧 Programmierung

🔧 Inversion of Control (Design Principle) & Dependency Injection (Design Pattern)


📈 38.03 Punkte
🔧 Programmierung

🔧 The joy of the Service pattern and Dependency inversion


📈 36.22 Punkte
🔧 Programmierung

🔧 Learn Dependency Inversion Principle in C# (+ Examples)


📈 34.6 Punkte
🔧 Programmierung

🔧 #5 Dependency Inversion Principle ['D' in SOLID]


📈 34.6 Punkte
🔧 Programmierung

🔧 Princípios SOLID em GoLang - Dependency Inversion Principle (DIP)


📈 34.6 Punkte
🔧 Programmierung

🔧 SOLID: D - Dependency Inversion Principle (DIP)


📈 34.6 Punkte
🔧 Programmierung

🔧 Dependency Inversion Principle


📈 34.6 Punkte
🔧 Programmierung

🔧 D - Dependency Inversion Principle(DIP)


📈 34.6 Punkte
🔧 Programmierung

🔧 Disadvantages of Dependency Inversion Principle(DIP)


📈 34.6 Punkte
🔧 Programmierung

🔧 Disadvantages of Dependency Inversion Principle(DIP)


📈 34.6 Punkte
🔧 Programmierung

🔧 How to Implement Data Validation in NestJS Using nestjs-joi and joi-class-decorators


📈 32.67 Punkte
🔧 Programmierung

🔧 NestJS Dependency Injection - Overview


📈 31.33 Punkte
🔧 Programmierung

🔧 Understand Dependency Injection in NestJs in a simple way


📈 31.33 Punkte
🔧 Programmierung

🔧 Queuing jobs in NestJS using @nestjs/bullmq package


📈 31.05 Punkte
🔧 Programmierung

🔧 NestJS tip: how to use Node.js built-in .env file reader with NestJS CLI


📈 31.05 Punkte
🔧 Programmierung

🔧 Website for NestJS-Mod - https://nestjs-mod.com


📈 31.05 Punkte
🔧 Programmierung

🔧 Discover the magic of custom decorators in NestJS #nestjs


📈 31.05 Punkte
🔧 Programmierung

🔧 Fix long import paths in your NestJS project #nestjs


📈 31.05 Punkte
🔧 Programmierung

🔧 Integrating Firebase Authentication into NestJS with nestjs-firebase-auth


📈 31.05 Punkte
🔧 Programmierung

🔧 FastAPI Beyond CRUD Part 6 - CRUD With Async SQLModel (An Introduction to Dependency Injection)


📈 25.08 Punkte
🔧 Programmierung

📰 Samsung says the only cure for tech dependency is more tech dependency


📈 24.75 Punkte
📰 IT Nachrichten

🔧 🐍Goodbye Dependency Hell: Discover Pipx, the Python Package Manager that Solves Dependency Conflicts


📈 24.75 Punkte
🔧 Programmierung

🐧 [$] Utilization inversion and proxy execution


📈 23.85 Punkte
🐧 Linux Tipps

📰 Meet In-N-Out: A Face Video Inversion and Editing Framework with Volumetric Decomposition


📈 23.85 Punkte
🔧 AI Nachrichten

🔧 Singleton pattern in PHP and IOC (Inversion Of Control) container in laravel


📈 23.85 Punkte
🔧 Programmierung

🔧 Inversion Control - The difference between a library and a framework.


📈 23.85 Punkte
🔧 Programmierung

matomo