web-dev-qa-db-ja.com

クリーンアーキテクチャ:クラスの内側の円のインスタンスを外側の円から取得する

これは、経験豊富なソフトウェアエンジニアにとっては簡単な質問です。

私は現在、ボブおじさんによる本 Clean Architecture を読んでおり、Javaプロジェクトにクリーンアーキテクチャを実装しようとしています。

さて、私のプロジェクトでは、本の第17章で説明されているのとまったく同じ状況に遭遇しました。

enter image description here

赤い線は、高レベルのビジネスルールコンポーネントと低レベルのデータベースコンポーネントの境界です。高レベルコンポーネントの一部であるDatabaseInterfaceのおかげで、低レベルコンポーネントに実装されているため、依存関係ルールは満たされています。

ただし、BusinessRulesは、依存関係ルールに違反せずにDatabaseInterfaceを実装するオブジェクトのインスタンスをどのように取得できますか?

実装クラスDatabaseAccessは低レベルコンポーネントにあり、高レベルコンポーネントは低レベルコンポーネントのクラスについて何も認識していません。

言い換えると、DatabaseAccess内でBusinessRulesオブジェクトをインスタンス化することはできません。これは、依存関係ルールに違反するためです。

この問題は通常どのように解決されますか?

注:

同じ状況が第18章でも説明されています。

enter image description here

そしてここでも、依存関係ルールに違反せずにClientServiceImplのインスタンスを取得する方法を教えてください。

この本は、これが実際にどのように行われるかについてのヒントを与えていません。この状況を解決するための正しい戦略を知りたいと思います。

4
weibeld

アプリケーション構造には、他のすべてのコンポーネント/ライブラリについて「認識する」1つの「エントリポイント」コンポーネント(mainメソッドを使用)が必要です。
エントリポイントコンポーネントの責任は、高レベルの抽象化と低レベルの実装を接着することです。

.----------------.       .----------------<I>-.       .-----------------.   
| Business rules | ----> | Database interface | <|--- | Database access |  
'----------------'       '--------------------'       '-----------------'  
        ^                         ^                            ^  
        |                         |                            |  
        |                         |                            |  
        |                  .-------------.                     |  
         ----------------  | Entry point |  -------------------  
                           '-------------'  

エントリポイントでは、ビジネスルールオブジェクトをインスタンス化して、実装の詳細を知るビジネスルールなしでデータベースインターフェースの実装を渡すことができます。

public void main()
{
    // MyDatabase implements IDataAccess
    IDataAccess dataAccess = new MyDatabase(connectionString); 

    // BusinessRules expect an instance of IDataAccess as constructor parameter
    MyBusinessRule rule = new MyBusinessRule(dataAccess);
}

このアプローチは、依存性注入としてよく知られています。このプロセスを自動化する依存性注入フレームワークがたくさんあります。ただし、学習のためには、手動で行い、考えられる問題を自分で解決するとよいでしょう。

7
Fabio

典型的なアプローチは、ある種のファクトリーを使用することです(Wikipedia:Factory Method Pattern)。高レベルのコードはファクトリからオブジェクトを要求し、ファクトリはオブジェクトを作成する必要がある具体的なクラスを認識しています。

編集:(インターフェースではなく)ファクトリーの実装はアプリケーションに固有であり、構成の一部です。ビジネスロジックと下位層を「接着」しますが、どちらにも含まれていません。

ファクトリアプローチは、下位層のオブジェクトを構築する必要がある決定、いつ、どのくらいの頻度でビジネスロジックを実行する必要がある場合に役立ちます。他の場合では、ビジネスロジックの起動時にオブジェクトにビジネスロジックを提供するなど、制御メカニズムの他の反転を使用できます(Fabioからの回答を参照)。

1
Dirk Herrmann