Dependency


依存とは?

  • あるクラスAが別のクラス(またはインタフェース)Bを使用する場合、AはBに依存する.
  • AはBがないと作動せず、B Aを再利用しなくても再利用できない.
  • ここでAクラスをDependent、BクラスをDependenceと呼ぶ.
  • は自分の依存に依存している.
  • 相互に利用される2つのレベルは、それぞれ結合と呼ばれる.
  • クラス間の結合は、緩和結合であっても緊縮結合であってもよい.
  • 気密度は連続している.
  • 依存性も強い/弱いと表現できる.
  • タイトなカップル指輪は強い依存性を生じ、ゆとりのあるカップル指輪は弱い依存性や依存性を生じない可能性がある.
  • 依存性、カップル対戒に方向性がある.
    AがBに依存しているからといって、BもAに依存しているわけではない.
  • 高度な依存性が悪い原因


    高度な依存性により、モジュールの重複使用が減少します.独立せず、他の場所での使用が困難です.

    依存規則


    すべてのソースコード依存性は、外部から内部へ、低レベルから高レベルのポリシーへ移行する必要があります.
    고수준 : 상위 수준의 개념, 추상화된 개념
        ex. 업무로직: 데이터를 저장한다, 견적을 계산한다
    저수준 : 추상화된 개념을 실제 어떻게 구현할지에 대한 세부적인 개념
        ex. 세부사항: MySQL에 데이터를 저장한다, 선택 프로젝트의 견적을 계산한다

    依存ルールの説明の追加説明


  • 高度なモジュールは、低レベルのモジュールに依存することはできません.この2つのモジュールは、他の抽象に依存する必要があります.

  • 抽象的なものは具体的なものに頼ってはいけない.具体的な抽象に頼らなければならない.

  • 頻繁に変更されるインプリメンテーションクラスに依存しないでください.クラスの参照が必要な場合は、参照されるクラスが抽象クラスとして作成されます.関数を呼び出す必要がある場合は、呼び出された関数が抽象関数として作成されます.

  • 通常、抽象クラスとインタフェースの変化は、自身から導かれる特定のクラスよりもずっと小さい.
  • これらの依存性ルールを遵守するには、「What dataが境界を越える」や「Crossing境界」など、各レイヤの境界で注意すべきことを理解する必要があります.

    What Data crosses the boundaries


    :境界間でデータを渡す場合、何を渡す必要がありますか?
  • は、単純で独立したデータ構造
  • を必要とする.
  • DB形式のデータ構造またはFrameworkに依存するデータ構造を使用する場合は、下位レベルのデータ型を上位レベルで理解する必要があります.これは依存ルールに違反します.
  • Crossing boundaries


    :「制御フローは内部から外部に流れることができ、依存性ルールに違反するため、依存性逆転の原則を利用してこの問題を解決する必要があります.」
    例えば、
  • が高い依存性から低い依存性を制御する場合、
  • .
  • 依存性逆転原則を適用して修正した例
    1)抽象的なRepositoryインタフェースを使用すると,サービスはこれを参照する.
    2)具体的なRDB Repositoryは、抽象的なRepositoryインタフェースを参照するために、これらのインタフェースを実装する
    3)1),2)によってソースコードの依存性を逆転させることができ,サービスはデータベースの詳細を知らないため,データベースの変更も影響を受けない.

  • 依存注入とは何ですか?


    用語

  • 依存性

  • //수정필요
     B 클래스에서
    A 클래스를 내부에 변수로 사용하게 됨으로써
    B 클래스는 A 클래스에 의존관계가 생기게 됩니다.

  • ちゅうにゅう


    内部ではなく外部からオブジェクトを作成して挿入

  • 依存性注入


    依存性注入は、パラメータに依存性を渡すと、モジュールへの依存性のロードや作成を回避するモードです.
  • DIのメリット

  • モジュールは、独立して
  • を作成することができる.
    簡略化
  • コード
  • 試験用
  • を再利用
    依存コード
  • を減らす
  • 依存関係の減少>コード変更の容易さ
  • の毒性増強(使用理由の理解が容易)
  • の結合度を低減するとともに、柔軟性と拡張性を向上させる
  • オブジェクト間で依存関係を確立できる
  • オブジェクト間の依存関係を解消または減少する

  • 依存性注入方法

  • 依存注入のいくつかのモード
    https://getchan.github.io/til/node_DI/
  • 依存性注入前vs後


    関連項目:https://velog.io/@moongq/Dependency-Injection
    次のコードは依存注入前の従来のコードです.
    //user-service.js
    const User = require('./User_);
    const UsersRepository = require('./users-repository);
                         
    async function getUsers() {
      return UserRepository.findAll();
    }
    
    async function addUser(userData) {
      const user = new User(userData);
      
      return UserRepository.addUser(user):
    }
    
    module.exports = {
      getUsers,
      addUser
    }
    以上のコードのuser-service.jsは業務ロジックを担当し、ユーザーリポジトリはデータを担当する.しかし、2つの問題があります.

  • サービスは、特定のリポジトリに関連付けられます.
    他のリポジトリに変更した場合は、すべてのコードを変更する必要があります>拡張性が低いことを意味します.

  • モジュールのテストが難しくなりました.
    外部ライブラリを使用してテストする必要があります>依存性の注入により、外部ライブラリの使用を最小限に抑えることができます.
  • 次のコードは,依存注入(ユーザレポートをパラメータとして渡す)を記述するコードである.
    const User = require('./User);
    
    function UsersService(usersRepository) {
      async function getUsers() {
        return usersRepository.findAll();
      }
      
      async function addUser(userData) {
        const user = new User(userData);
        
        return usersRepository.addUser(user);
      }
      
      return {
        getUsers,
        addUser
      };
    }
    
    module.exports = UsersService

    注入依存性:Class vs function


    関連項目:https://velog.io/@moongq/Dependency-Injection

    1.クラス形式の依存性注入


    :クラスのコンストラクション関数(constructor)に依存性を注入します.単一の依存性を単一のパラメータとして渡すよりも、オブジェクトを囲み、一度に渡すほうがいいです.
    class UsersService {
      constructor({ usersRepository, mailer, logger }) {
        this.usersRepository = usersRepository;
        this.mailer = mailer;
        this.logger = logger;
      }
      async findAll() {
        return this.usersRepository.findAll();
      }
      async addUser(user) {
        await this.usersRepository.addUser(user);
        this.logger.info(`User created ${user}`);
        await this.mailer.sendConfirmationLink(user);
        this.logger.info(`Confirmation link sent!: ${user}`);
      }
    }
    
    module.exports = UsersService;
    
    //ex. userController.js
    require('./userService.js)
    const usersService = new UsersService({
      usersRepository,
      mailer,
      logger
    }); 

    2.関数形式の依存注入

    export const userService = ({ usersRepository, mailer, logger }) => {
      const fildAll  = () => usersRepository.findAll();
      addUser = (user) => {
        await usersRepository. addUser(user);
        logger.info(`User created: ${user}`);
        await mailer.sendConfirmationLink(user);
        logger.info(`Confirmation link sent ${user}`);
      };
      
      return {
        findAll,
        addUser
      };
    }
    
    const service = usersService({
      usersRepository,
      mailer,
      logger})       

    依存関係の設定


    依存性注入の欠点は,利用すべきすべての依存性を予め設定し,構造化することである.
    userServiceを生成する前に、依存性が集中している場所をcontainerと呼びます.次のコードに示します.
    //container.js
    const UsersRepository = require('./users-repository');
    const Mailer = require('./mailer');
    const Logger = require('./logger');
    const UsersService = require('./users-service');
    const InMemoryDataSource = require('./users-repository/data-source/in-memory');
    
    const logger = new Logger({
      level: process.env || 'dev'
    });
    
    const dataSource = new InMemoryDataSource();
    
    const mailer = new Mailer({
      templates: '/emails',
      logger
    });
    
    const usersRepository = new UsersRepository({
      logger,
      dataSource
    });
    
    const usersService = new UsersService({
      usersRepository,
      mailer,
      logger
    });
    
    module.exports = {
      usersService
    }
    上記のコードに示すように、コンテナを1つずつ設定する必要がある場合、ライブラリAwilixまたはTypeDIを使用して依存性を検索および取得することができる.

    リファレンス


    用語参照


    抽象クラス、定義実装クラス:https://zetawiki.com/wiki/%EC%B6%94%EC%83%81%ED%81%B4%EB%9E%98%EC%8A%A4,_%EA%B5%AC%EC%B2%B4%ED%81%B4%EB%9E%98%EC%8A%A4
  • 抽象クラス(abstrate class)
    :抽象クラス.インスタンス化できません
    :ex.移動ツール
  • 実施類(具体類)
    :具体的なカテゴリ.インスタンス化可能
    トラック、自転車、船、飛行機...
  • :抽象クラス
    https://itewbm.tistory.com/entry/%EC%B6%94%EC%83%81%ED%81%B4%EB%9E%98%EC%8A%A4abstract-class%EC%9D%98-%EC%A1%B4%EC%9E%AC-%EC%9D%B4%EC%9C%A0

    依存性リファレンス


    https://medium.com/@jang.wangsu/di-dependency-injection-%EC%9D%B4%EB%9E%80-1b12fdefec4f
    https://getchan.github.io/til/node_DI/
    https://velog.io/@moongq/Dependency-Injection
    https://getchan.github.io/til/node_DI/