[Nest]DIとIoCって何?


「最近」を勉強していると、よくこんな言葉に遭遇します.
DIとIOCです.この2つはjava springやAngularなどのフレームワークによく登場し,非常に重要な概念である.

DI (Dependency Injection)


DIは依存注入,依存注入の意味である.
依存性注入とは何ですか?うん.そう思ってもいいです.
初めてDIに触れたときは、Importの違いさえ知らなかった.(恥ずかしい…)
また,事実上,最新のプロジェクトを行う際にはDIを完全に理解し制定していない.(時間の圧迫…)
ウィキペディアの5歳の学生にDIについて説明しましょう.
<5살에게 DI 설명하기>

너가 스스로 냉장고로 가서 무언가를 꺼내오려고 할 때 문을 닫지 않고 열어두거나 
엄마나 아빠가 너가 안먹었으면 좋겠다고 생각하는 것들을 갖게 되는 문제가 생길 수 있어.
아니면 유통기한이 지난 것이나 갖고 있지 않는 것을 찾을 수 있지.

그럴 때 너가 해야할 일은 "점심 먹을 때 마실 게 필요해요"라고 우리에게 말한다면 
너가 점심을 먹으려고 할 때 우유를 가져다 줄게. - 위키피디아 -
つまり、DIが何か(声明)が必要だと言ったら、プログラムが持ってきます.
リクエスト・プログラムが任意のオブジェクトを使用することで、オブジェクト間の依存性を低減できます.

DIのメリット


1.依存性の減少.
2.再利用可能なコードとなる.
3.テストに適したコードとなる.
4.可読性を高める.
Nestでは@InjectableなどのデータレコーダでDIを行うことができます.
@Injectable()
export class ArticlesService {
  constructor(
    @InjectRepository(ArticleRepository)
    private articleRepository: ArticleRepository,
     (...생략)
最後に,DIの目的をよりよく理解するためには,ソフトウェア設計の「SOLID法則」を理解した方がよい.
1. 단일 책임 원칙(SRP; Single Responsibility Principle)

객체는 단 하나의 책임만을 가져야한다.
어떤 클래스를 변경해야 하는 이유는 오직 하나뿐이어야 한다.
어느 한 객체가 책임을 많이 진다는 것은 클래스 내부에서 서로 다른 역할을 수행하는 코드끼리 강하게 결합될 가능성이 높아지는 것이다.
이는 곧 변경이 일어날 때 영향범위가 커지게 되는 것으로 나쁜 설계로 볼 수 있다.

설계할 때의 기본 원칙은 응집도는 높이고 결합도는 낮추는 것으로 세우는 것이 좋다. 관련된 것들을 한 곳에 두어 응집도를 높이면 결합도는 낮아진다. 
2. 개방-폐쇄 원칙(OCP; Open-Closed Principle)

기존의 코드를 변경하지 않으면서(closed) 기능을 추가(open)할 수 있어야 한다.
소프트웨어 엔티티가 확장에 대해서는 개방(open)되어야 하지만, 변경에 대해서는 폐쇄(closed)되어야 한다. 
클래스 자체를 변경하지 않고도(closed) 그 클래스를 둘러싼 환경을 바꿀 수 있어야 한다.

OCP를 위반하지 않는 설계를 위해서는,무엇이 변하는 것인지, 무엇이 변하지 않는 것인지를 구분해야 한다. 
변해야 하는 것은 쉽게 변할 수 있게 하고, 변하지 않아야 할 것은 변하는 것에 의해 영향을 받지 않게 해야 한다.
3. 리스코프 치환 원칙(LSP; Liskov Substitution Principle) 

부모 클래스와 자식 클래스 사이의 행위가 일관성이 있어야 한다.
부모 클래의 인스턴스를 자식 클래스의 인스턴스로 대체해도 프로그램의 의미는 변화되지 않는다.

자식클래스는 최소한 자신의 부모 클래스에서 가능한 행위는 수행할 수 있어야 한다는 뜻으로, 가장 직접적이고 직관적인 방법은 
부모 클래스에서 상속받은 메소드들이 자식클래스에 오버라이드(재정의) 되지 않도록 하면 된다.

피터 코드의 상속 규칙이라는 것이 있는데, 상속의 오용을 막기 위해 상속을 사용해서 안되는 5가지 규칙을 만들었는데 
그 중 "자식 클래스가 부모 클래스의 책임을 무시하거나 재정의하지 않고 확장만 수행해야 한다"라는 원칙이 있는데, 
  이것이 바로 LSP를 만족시키는 방법이다.
4. 인터페이스 분리 원칙(ISP; Interface Segregation Principle) 

인터페이스를 클라이언트에 특화되도록 분리시켜라.
클라이언트는 자신이 사용하지 않는 메소드에 의존 관계를 맺으면 안된다.

클라이언트와 무관하게 발생한 변화로 클라이언트 자신이 영향을 받지 않으려면, 범용(general)의 인터페이스보다는 
특화된 인터페이스를 사용해야 한다. ISP는 즉, 인터페이스를 클라이언트에 특화되도록 분리시키라는 의미이다.
5. 의존 역전 원칙(DIP; Dependency Inversion Principle)

의존 관계를 맺을 때, 변화하기 쉬운 것 또는 자주 변화하는 것보다는 변화하기 어려운 것, 거의 변화가 없는 것에 의존하라.
자주 변경되는 구체 클래스 대신 인터페이스나 추상 클래스에 의존하라.

- 변하기 어려운 것
정책, 전략과 같은 어떤 큰 흐름이나 개념 같은 추상적인 것

- 변하기 쉬운 것
구체적인 방식, 사물 등

DIP를 만족하면, 의존성 주입(Dependency Injection)을 통해 변화를 쉽게 수용할 수 있는 코드를 작성할 수 있다. 
의존성 주입을 이용하면, DIP를 만족하는 변화에 유연한 시스템이 된다.

- 만약 어떤 클래스에서 상속받아야 한다면, 부모 클래스를 추상 클래스로 만든다.
- 어떤 클래스의 참조(reference)를 가져야 한다면, 참조 대상이 되는 클래스를 추상 클래스로 만든다.
- 어떤 메소드를 호출해야 한다면, 호출되는 메소드를 추상 메소드로 만든다.

最近のDI実施例


サービスに必要な方法をRepositoryに接続し,Singletonへの依存性を投射可能データレコーダにより実現した.
@Injectable()
export class LikesService {
  constructor(
    @InjectRepository(LikesRepository)
    private likesRepository: LikesRepository,
    @InjectRepository(ArticleRepository)
    private articleRepository: ArticleRepository,
  ) {}

  async likeUnlike(likesDto: LikesDto): Promise<any> {
    ...
  }
内部メソッドを使用するためにコントローラソースからLikesServiceをLikesServiceに注入します.
@Controller('likes')
export class LikesController {
  // 의존성(Dependency)
  constructor(private likesService: LikesService) {}

    @Post()
    @UseGuards(AuthGuard)
    likeUnlike(
      @Body() likesDto: LikesDto,
    ): Promise<object> {
      return this.likesService.likeUnlike(likesDto);
    }
}
(...생략)
constructor(
    private articlesService: ArticlesService,
  (...생략)

IoC (Inversion of Control)


' Don't call us, we'll call you '
△私たちに連絡しないでください.私たちはあなたに連絡します.
IOCはコントロール反転(Inversion Control)です.
プログラマによって作成されたプログラムは、再利用ライブラリのストリームによって制御されるソフトウェア設計モードを受ける.( ウィキペディア )
IoC=IoC containerは、オブジェクトの管理、オブジェクトの作成、依存性の管理を担当するコンテナであり、非常に良い友人と言えます.
つまり、私たちがしなければならないことに代わってプログラムを譲ります.

IoCの目標

  • タスクを実現する方法は、実行自体とは別である.
  • モジュールを作成する際、モジュールと外部プログラムの結合を考慮する必要がなく、モジュールの目的に専念することができる.
  • は、他のシステムがどのように動作するかを考慮する必要はなく、事前に決定されたプロトコルに従って操作すればよい.
  • モジュールを交換しても、他のシステムには副作用はありません.
  • ---関連内容は引き続き学習し、完備します!---
    キラキラ!

    Reference

  • [NestJS]プロバイダの概念と実践
  • ウィキペディア
  • ソフトウェア設計テクニック:SOLIDとは何ですか?
  • 「依存注入」(Dependency Injection)の理解が容易