問題タブ [dependency-inversion]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
java - 依存性逆転の原則 (Java に適用される場合)
私は SOLID オブジェクト指向プログラミングに関連する原則を独学で学んでいますが、文字 D (依存関係反転の原則) のすべての詳細を理解するのに苦労しています。
ウィキペディア ( http://en.wikipedia.org/wiki/Dependency_inversion_principle ) でそのエントリを読んでいますが、図に示されているすべてのことを理解していません:
http://en.wikipedia.org/wiki/Dependency_inversion_principle#/media/File:DIPLayersPattern_v2.png )
2 種類の矢印があることに気付きました。1 つは破線で、もう 1 つは実線です。
私の現在の理解に基づいて、破線は Java の「implements」キーワードに相当するものを表し、実線はキーワード「extends」を表します。
これは正しい解釈ですか?
solid-principles - モジュール間の依存関係反転の原則を使用して設計を修正しますか?
単一のモジュール内で作業する場合の依存関係の反転は理解していますが、モジュール間の依存関係がある場合にも適用したいと考えています。次の図では、既存のアプリケーションがあり、参照データ サービスのいくつかの新しい要件を実装する必要があります。新しい jar を作成しようと思いました (将来的にはスタンドアロン サービスになる可能性があります)。最初の図は、私が過去にそのようなことに取り組んできた通常の方法を示しています。referencedataservices jar には、アプリがそれを呼び出すために使用するインターフェイスがあります。
2 番目の図は、DIP を使用しようとした私の試みを示しています。現在、アプリはその抽象化を所有しているため、参照データ サービスが変更されたからといって変更されることはありません。ただし、循環依存関係が作成されるため、これは間違った設計のようです。MyApp は referencedataservices jar に依存し、referencedataservices jar は MyApp に依存します。
したがって、3 番目の図は、追加の抽象化レイヤーを作成することによって、より通常の依存関係に戻ります。私は正しいですか?それとも、これは本当に DIP が意図したものではないのでしょうか? 他のアプローチやアドバイスについて聞くことに興味があります。
spring - Maven と Spring を使用した依存関係逆転の原則の実装
このウィキペディアの記事によると、依存関係逆転原則の実装は、次の 2 つの方法で実行できます。
- 高レベル コンポーネントと低レベル コンポーネントの両方が依存する別のパッケージに、低レベル コンポーネントを抽象化すること。
- 低レベル コンポーネントの抽象化を高レベル コンポーネントの同じパッケージに配置します。
次の図は、2 つのアプローチを使用した DIP 前後の依存関係を示しています。
DIP
の前: リポジトリは別の Maven モジュールに存在し、インターフェイスを持たず、サービスはリポジトリの実装に直接依存します。
アプローチ 1:リポジトリのインターフェース (抽象化) を導入します。そのインターフェースの実装は別のモジュールであり、サービスとリポジトリの実装の両方がインターフェースに直接依存しています。
アプローチ 2:このアプローチでは、インターフェイスはサービスの同じパッケージに存在します。Fowler がSeparated Interfaceパターンを説明するために使用した図も、このアプローチの例のようです。
私はApproach1に従ってきました。Spring の JavaConfig を使用したため、サービス モジュールにはインフラストラクチャ インターフェイスと実装モジュールの両方への maven 依存関係が必要でした。私のファイルを除けば、@Configuration
インフラストラクチャの具体的な実装への参照はまったくありません。
私は現在Approach2 への切り替えを検討していますが、コード内でインターフェイス実装モジュールへの直接参照が発生し、循環依存関係が発生するため、明らかに JavaConfig では機能しません。maven などのビルドツールでは処理できません。 .
問題は、Spring と Maven を構成してApproach2を実現する方法です。Maven 依存関係として追加されていないコンポーネントをスキャンするように春に依頼する方法はありますか? Maven の使用方法を変更する必要がありますか?
r - R6 クラスの多重継承
実際の質問
R6が多重継承をサポートしていないという事実を回避するためのオプションは何ですか?
免責事項
R は基本的に関数型言語であることは知っています。ただし、非常に強力なオブジェクト指向も組み込まれています。さらに、OOD の原則/動作を模倣することの何が問題なのかわかりません。
C#、Java などのオブジェクト指向言語のプロトタイピングを行っていることを知っています。
アプリのプロトタイプは、自己完結型である必要があります(DB バックエンド、ビジネス ロジック、フロントエンド/UI を含む「フル スタック」)。
あなたはR6のような素晴らしい「プロトタイピング技術」を持っていて、自由に使うことができます
環境
Web アプリ用の私の R プロトタイプは、「フル スタック」/自己完結型であり、本番環境言語( C#/.ネット)。
その点で、コード モジュールを切り離し、OOD の SOLID 原則のD (依存性反転の原則)に準拠するために、インターフェイス (または抽象クラス) の使用が非常に好きになりました( 「ボブおじさん」による詳細な説明)。 )。
R6 はインターフェイスを明示的にサポートしていませんが、「抽象メソッド」のみを定義する R6 クラスで完全に模倣できます(以下の例を参照)。これは、R にあまり詳しくない OO プログラマーに私のソフトウェア設計を伝えるのに非常に役立ちます。
ただし、実際に他の具象から継承したい場合(「 abstractのような」模倣されたインターフェイス クラスとは対照的に) には、少し問題になるinherit
inの値を放棄する必要があります。しかし、 の 2 つのクラス。R6Class
inherit
例
依存関係の反転前:
Foo
具体的なクラスに依存しBar
ます。OOD 原則の観点からは、コードが密結合になるため、これはかなり悪いことです。
依存関係の反転後:
Foo
Bar
現在は切り離されています。どちらも、 class によって模倣されるインターフェースに依存していますIBar
。実行時に のインスタンスにプラグインするインターフェイスの実装を決定できFoo
ます (プロパティ インジェクション: のフィールドbar
によって実現Foo
)
これがOODに関して理にかなっている理由について少し詳しく説明します。フィールドに格納されたオブジェクトが実装Foo
される方法に完全に依存しない必要があります。知る必要があるのは、そのオブジェクトで呼び出すことができるメソッドだけです。それを知るには、 field 内のオブジェクトが実装するインターフェース(私たちの場合は method ) を知るだけで十分です。bar
bar
IBar
doSomething()
基本クラスからの継承を使用して設計を簡素化する:
ここまでは順調ですね。ただし、他の具象クラスの一部が継承できる特定の具象基本クラスを定義することで、設計を簡素化したいとも考えています。
「インターフェースの実装」と基本クラスの継承を組み合わせる:
これは、多重継承が必要な場所なので、次のようなものが機能します (PSEUDO CODE):
現在、私の値inherit
は、インターフェイスの実装を模倣するために「ちょうど」使い果たされているため、実際の具象クラスの継承の「実際の」利点を失います。
別の考え:
あるいは、インターフェイス と具象クラスの区別を何らかの形で明示的にサポートすることは素晴らしいことです。たとえば、このようなもの
oop - 具体的な実装は、実装するインターフェイスに存在しないパブリック API を提供する必要がありますか?
「インターフェースへのコード」は良い習慣と考えられています。このようなコードは単体テストが容易で、疎結合が可能です。ユーザーはインターフェイスだけを知っており、具体的なオブジェクトを配線する責任は最上位レベルにあります (これは、いくつかの初期化コードで、またはフレームワークの助けを借りて行うことができます)。
私の質問は、インターフェースへのコードの実践に従うことについてです:具象クラスは、そのインターフェースに存在しないパブリックメソッドを決して宣言できないことを意味しますか?
そうしないと、ユーザーは具体的な実装に依存することになります。これにより、そのようなメソッドの単体テストが難しくなります。テストが失敗した場合、呼び出し元コードの問題が原因で失敗したのか、具体的なメソッドが原因で失敗したのかを判断するには、余分な労力が必要です。これは、依存関係逆転の原則にも違反します。これは、悪い習慣と見なされる型チェックとダウンキャストを引き起こします。
c# - これは DIP (SOLID) の有効な使用法ですか?
そのクラスの実装が依存性逆転の原則に違反してGenotypes
いるかどうかを尋ねたいですか? Individual
もしそうなら、それを修正する方法は?
コードは次のとおりです。
javascript - ノード内の Javascript 依存性注入 & DIP: 要求対コンストラクター注入
私は .NET の世界から来た NodeJs 開発に不慣れです。Javascript で DI / DIP を再構築するベスト プラクティスを Web で検索しています。
.NET では、コンストラクターで依存関係を宣言しますが、javascript では、require ステートメントを介してモジュール レベルで依存関係を宣言するという一般的なパターンが見られます。
私にとっては、 require を使用すると、特定のファイルに結合されているように見えますが、コンストラクターを使用して依存関係を受け取る方がより柔軟です。
JavaScript のベスト プラクティスとして何をすることをお勧めしますか? (IOC 技術ソリューションではなく、アーキテクチャ パターンを探しています)
Web を検索すると、このブログ投稿にたどり着きました (コメントで非常に興味深い議論が行われています): https://blog.risingstack.com/dependency-injection-in-node-js/
それは私の対立をかなりうまく要約しています。私が話していることを理解できるように、ブログ投稿のコードを次に示します。
簡単なテストは次のようになります。
VS DI:
テスト:
xcode - XCTestCases を外部テスト バンドルに公開する方法は?
Whiteboard
ビジネス ロジックをカプセル化するフレームワークがあります。私は依存関係を逆にして分離したままにしようとしているのでWhiteboard
、リポジトリに依存しているため、 protocol を宣言し、リンクするクライアントがの実装を提供するWhiteboardRepository
ことを期待しています。Whiteboard
WhiteboardRepository
これは、以下のスクリーン ショットで確認できます。クラスとそれ自身のテスト サブクラスWhiteboardTests
を含むグループにも注意してください。WhiteboardRepositoryTests
WhiteboardRepositoryFake
の実装がWhiteboardRepository
期待どおりに動作することを確認するために、WhiteboardTests
テスト バンドルは のWhiteboardRepositoryTests
サブクラスを定義しXCTestCase
ます。
のクライアントが のWhiteboard
実装をテストするWhiteboardRepository
ために、実装のテスト クラスは をサブクラス化し、WhiteboardRepositoryTests
実装のインスタンスをテスト サブクラスに提供します。テスト サブクラスは、テストの実行時にそのインスタンスを使用します。
たとえば、次のWhiteboardRepositoryFakeTests
ようになります。
もちろん、これWhiteboardRepositoryFakeTests
はWhiteboardTests
バンドルに含まれているため、正常に機能WhiteboardRepositoryTests
しWhiteboardRepositoryFakeTests
ます。
問題は、リンクするアプリは、独自の実装をテストするWhiteboard
ために独自のサブクラスを作成する必要がありますが、テスト バンドルにアクセスできないため、クラスを認識せず、サブクラス化できないことです。 .WhiteboardRepositoryTests
WhiteboardTests
WhiteboardRepositoryTests
複数のクライアントがを消費しているため、クラスを各クライアントにWhiteboard
単純にコピーすることはできません。理想的な世界では、のテスト バンドルをクライアントのテスト バンドルにリンクまたは挿入して、クライアントのテストに公開することができますが、これを行う方法がわかりません。WhiteboardRepositoryTests
Whiteboard
WhiteboardRepository
WhiteboardRepositoryTests
Whiteboard
Whiteboard
WhiteboardRepositoryTests
この障害を回避する方法はありますか? の実装が期待どおりに動作WhiteboardRepositoryTests
することをクライアントが確認できるように、クライアント テスト バンドル内のテストに公開するにはどうすればよいですか?WhiteboardRepository
solid-principles - OCP と DIP は YAGNI を壊しますか?
私が理解YAGNI
しているように、必要な場合にのみインターフェイスを抽出する必要があると言っています。したがって、ポリモーフィズムが不要で、現在実装が 1 つしかない場合は、インターフェイスを使用する必要はありません。しかし、次のDIP
ように述べています。
A. 高レベル モジュールは低レベル モジュールに依存すべきではありません。どちらも抽象化に依存する必要があります。
B. 抽象化は詳細に依存すべきではありません。詳細は抽象化に依存する必要があります。
YAGNI
とオプション B. の間に不一致があるようですDIP
。また、適用したい場合はOCP
、依存関係の制御を反転し、抽象化を抽出して、その型を変更せずに型を拡張できるようにする必要があります。
また、一部のテクノロジでは、型クライアントを単体テストできるように抽象化を抽出する必要があります。しかし、たとえばJavaでは必要ありません。ですから、現在実装が 1 つしかない場合、抽象化を抽出する必要があるかどうかを知りたいですか?