web-dev-qa-db-ja.com

カップリング。ベストプラクティス

私が始めたこのスレッドから続いて

シングルトンパターン

クラスがどのように結合されているか、疎結合を実現するための最良の方法について考えさせられました。私は新しいプログラマー(私の最初の仕事に4か月)であり、これは本当に私がこれに与えた最初の考慮事項であり、概念を理解することに非常に熱心です。

それでは、厳密な結合と重い結合を正確に構成するものは何ですか?私の現在の(そして最初のプロジェクト)では、c#winformsプロジェクトに取り組んでいます。GUIセクションはオブジェクトを作成し、そのイベントにサブスクライブします。トリガーされると、GUIは別のオブジェクトを作成します(この例では、datagridview(クラス標準のデータグリッドビューをラップし、追加機能を追加して作成したもの)をGUIにアタッチします。これは悪いカップリングですか、それとも良いですか?

私は本当に悪い習慣に陥ってコーディングをうまく始めたくないので、私はあなたの応答に感謝します。

11
Darren Young

私はASP.NET開発者なので、WinFormsカップリングについてはあまり知りませんが、UI、ドメイン、データアクセスレイヤー(DAL)の3層アプリケーションアーキテクチャを想定して、N層Webアプリからは少し知っています。

疎結合は抽象化についてです。

@MKOは、アセンブリを別のものに置き換えることができるかどうかを示しているため(たとえば、ドメインプロジェクトを使用する新しいUIプロジェクト、データベースではなくスプレッドシートに保存する新しいDAL)、疎結合があります。ドメインとDALがチェーンのさらに下のプロジェクトに依存している場合、カップリングが緩くなる可能性があります。

疎結合されているものの1つの側面は、オブジェクトを同じインターフェースを実装する別のものに置き換えることができるかどうかです。 実際のオブジェクトには依存しませんが、オブジェクトの動作の抽象的な説明(そのインターフェース)。
疎結合、インターフェース、ディペンデンシーインジェクター(DI)および制御の反転(IoC)は、テスト容易性の設計の分離の側面に役立ちます。

例えば。 UIプロジェクトのオブジェクトは、ドメインプロジェクトのリポジトリオブジェクトを呼び出します。
テスト対象のコードが使用するリポジトリと同じインターフェイスを実装するfakeオブジェクトを作成し、テスト用の特別な動作を記述できます(stubs for prevent呼び出される保存/削除/取得するプロダクションコード、およびスタブとして機能するmocksおよび偽の状態を追跡するテスト目的のオブジェクト)。
つまり、呼び出されている唯一のプロダクションコードがUIオブジェクト内にのみ存在することを意味します。テストはそのメソッドのみに対して行われ、テストが失敗すると、そのメソッドの欠陥が特定されます。

また、VSの[分析]メニュー(使用しているバージョンによって異なります)には、プロジェクトのコードメトリックを計算するためのツールがあり、その1つがクラスカップリングです。これについては、MSDNのドキュメントで詳しく説明しています。

[〜#〜] too [〜#〜]は、緩い結合の細部に行き詰まってはいけません。再利用する場合(たとえば、複数のUIを持つドメインプロジェクト)、製品の寿命が短い場合、疎結合の優先度は低くなります(それでも考慮されます)が、それでも設計者の責任になります/あなたのコードをレビューする技術リーダー。

6
StuperUser

5 [〜#〜] solid [〜#〜] の原則をご覧ください。 SRPに準拠すると、ISPとDIPの結合が大幅に低下し、DIPが圧倒的に強力です。これは、すでに述べた [〜#〜] di [〜#〜] の下の基本原理です。

また、 [〜#〜] grasp [〜#〜] も一見の価値があります。それは抽象的な概念(最初は実装するのが難しいと思う)と具体的なパターン(実際に役立つかもしれません)の間の奇妙な組み合わせですが、美しさはおそらく今のところあなたの懸念の最も少ないものです。

そして最後に、一般的な手法へのエントリポイントとして IoCのこのセクション が非常に役立つことがあります。

実際、私は stackoverflowに関する質問 を見つけました。ここで、具体的な問題でのSOLID)の適用を示します。興味深い読みである可能性があります。

3
back2dos

カップリングは、あるクラスが別のクラスに持っている直接的な知識の程度を指します。これは、カプセル化対非カプセル化として解釈されることを意図していません。これは、あるクラスの別のクラスの属性や実装に関する知識への参照ではなく、他のクラス自体に関する知識への参照です。依存関係のあるクラスに、必要な動作を提供する具象クラスへの直接ポインタが含まれている場合、強い結合が発生します。依存関係は、依存クラスの変更を必要とせずに、置換したり、「署名」を変更したりすることはできません。 疎結合は、依存クラスにインターフェイスへのポインターのみが含まれる場合に発生します。これは、1つまたは複数の具象クラスによって実装できます。依存クラスの依存関係はインターフェースで指定された「契約」に。実装クラスが提供しなければならないメソッドやプロパティの定義済みリスト。したがって、インターフェースを実装するクラスは、クラスを変更する必要なく、依存クラスの依存関係を満たすことができます。これにより、ソフトウェア設計の拡張性が可能になります。インターフェイスを実装する新しいクラスを記述して、依存するクラスを変更することなく、一部またはすべての状況で現在の依存関係を置き換えることができます。新旧のクラスは自由に入れ替えることができます。強い結合はこれを可能にしません。 参照リンク

3
Amir Rezaei

依存性注入、戦略パターン、およびイベントを使用します。一般的には、設計パターンを読んでください。これらはすべて、疎結合と依存関係の削減に関するものです。イベントは、依存関係の注入と戦略パターンがいくつかのインターフェースを必要とする一方で、イベントはあなたが得るのと同じくらい疎結合です。

良いトリックは、クラスを別のライブラリ/アセンブリに配置し、それらが他のライブラリにできるだけ依存しないようにすることです。これにより、依存関係を少なくするようにリファクタリングする必要があります。

1
Homde

ウィキペディアによると:

コンピューティングとシステムの設計では、疎結合システムとは、そのコンポーネントのそれぞれが、他の個別のコンポーネントの定義に関する知識をほとんど、またはまったく持たないシステムです。

密結合の問題により、変更が困難になります。 (多くのライターは、これが主にメンテナンス中に問題を引き起こすことを示唆しているようですが、私の経験では、初期開発中にも関連しています。)密結合システムで発生する傾向があるのは、システム内の1つのモジュールを変更すると、追加の変更が必要になることです。結合されているモジュール内。多くの場合、これには他のモジュールでの変更などが必要になります。

対照的に、疎結合システムでは、変更は比較的分離されています。したがって、それらはより安価であり、より大きな自信を持って作ることができます。

あなたの特定の例では、イベント処理のものは、GUIと基礎となるデータをある程度分離します。ただし、探索できる分離の他の領域があるかのように聞こえます。特定の状況の詳細がなければ、特定することは困難です。ただし、次のような3層アーキテクチャから始めることもできます。

  • データの保存と検索のロジック
  • ビジネスの論理
  • UIを実行するために必要なロジック

考慮すべきことは、1人の開発者がいる小規模な1回限りのアプリケーションの場合、すべてのレベルで疎結合を適用することの利点は、努力に値しない場合があるということです。一方、複数の開発者がいる大規模で複雑なアプリケーションは必須です。最初は、抽象化の導入と、そのアーキテクチャーに関するコードに不慣れな開発者の教育には、コストがかかります。ただし、長期的には、疎結合にはコストをはるかに上回る利点があります。

疎結合システムの設計に真剣に取り組んでいる場合は、SOLIDの原理と設計パターンを読んでください。

ただし、重要なことは、これらのパターンと原則はパターンと原則にすぎないということです。それらはnotルールです。これは、実用的かつインテリジェントに適用する必要があることを意味します

パターンが関係している場合、パターンの単一の「正しい」実装は存在しないことを理解することが重要です。また、独自の実装を設計するためのcookie-cutterテンプレートもありません。それらは、優れたソリューションがどのような形をとるかを伝え、設計の決定を他の開発者と伝達するための共通言語を提供するためにあります。

ではごきげんよう。

1
Kramii

別の見方をさせてください。これは、各クラスが優れたAPIであると考えるだけです。メソッドが呼び出される順序は明白です。彼らが何をするかは明らかです。メソッドの数を必要最小限に減らしました。たとえば、

init、open、close

versus

setTheFoo、setBar、initX、getConnection、close

1つ目は明白で、Nice APIのように見えます。 2番目は、間違った順序で呼び出された場合にエラーを引き起こす可能性があります。

呼び出し元を変更して再コンパイルする必要があることについてはあまり心配していません。私はコードの多くを新しいものから15年前のものまで維持しています。通常、変更を加えるとコンパイラエラーが発生します。そのため、意図的にAPIを破壊することがあります。それは私に各呼び出し側の影響を検討する機会を与えてくれます。私は依存関係注入の大ファンではありません。ブラックボックスなしでコードを視覚的にトレースできるようにしたいので、コンパイラーにできるだけ多くのエラーをキャッチさせたいのです。

0
Sean McEligot