疎結合システムでは、コンポーネントを同じサービスを提供する代替実装に置き換えることができます。疎結合システムでは、コンポーネントは同一のプラットフォーム、言語、オペレーティングシステム、またはビルド環境に制約されることが少なくなります。
システムが時間的に分離されている場合、トランザクションの整合性を確保することは困難であり、追加の調整プロトコルが必要となります。異なるシステム間でのデータ複製は、可用性の面では疎結合を実現しますが、一貫性(データ同期)の維持に問題が生じます。
より広範な分散システム設計における疎結合は、トランザクション、メッセージ指向ミドルウェアによって提供されるキュー、および相互運用性標準の使用によって実現されます。 [ 2 ]
疎結合を促進する4種類の自律性は、参照自律性、時間自律性、フォーマット自律性、プラットフォーム自律性である。[ 3 ]
疎結合は、サービス指向アーキテクチャにおけるアーキテクチャの原則および設計目標です。疎結合の11の形式と、それに対応する密結合の形式が[ 4 ]にリストされています。
エンタープライズサービスバス(ESB)ミドルウェアは、複数の次元で疎結合を実現するために考案されました。[ 5 ]しかし、過剰設計され配置が不適切なESBは、逆の効果をもたらし、望ましくない密結合や中心的なアーキテクチャ上のホットスポットを生み出す可能性もあります。
イベント駆動型アーキテクチャは疎結合を促進することも目的としている。[ 6 ]
インターフェースの疎結合は、データを標準フォーマット(XMLやJSONなど)で公開することで強化できます。
プログラムコンポーネント間の疎結合は、パラメータに標準データ型を使用することで強化できます。カスタムデータ型やオブジェクトを渡す場合は、両方のコンポーネントがカスタムデータ定義を認識している必要があります。
サービス間の疎結合性を高めるには、サービスに渡す情報を重要なデータのみに絞り込むことが有効です。例えば、手紙を送るサービスの場合、顧客識別子だけを渡して、顧客住所はサービス内で取得するようにすれば、再利用性は最大限に高まります。こうすることで、サービスを特定の順序(例:GetCustomerAddress、SendLetter)で呼び出す必要がなくなり、サービスの疎結合性が高まります。
結合度とは、あるコンポーネントが別のコンポーネントについてどの程度直接的な知識を持っているかを示すものです。コンピューティングにおける疎結合は、カプセル化と非カプセル化の対比として解釈されます。
密結合の例としては、依存クラスが必要な動作を提供する具象クラスへのポインタを直接保持している場合が挙げられます。依存クラスを変更せずに、依存関係を置き換えたり、その「シグネチャ」を変更したりすることはできません。疎結合は、依存クラスがインターフェースへのポインタのみを保持し、そのインターフェースを1つまたは複数の具象クラスで実装できる場合に発生します。これは依存性逆転と呼ばれます。依存クラスの依存関係は、インターフェースによって指定された「契約」、つまり実装クラスが提供しなければならないメソッドやプロパティの定義済みリストです。インターフェースを実装するクラスは、クラスを変更することなく、依存クラスの依存関係を満たすことができます。これにより、ソフトウェア設計の拡張性が向上します。依存クラスを変更することなく、インターフェースを実装する新しいクラスを作成して、一部またはすべての状況で現在の依存関係を置き換えることができます。新しいクラスと古いクラスは自由に交換できます。密結合では、このようなことはできません。
これは、依存クラスと、必要な動作を提供する一連の具象クラスとの間の疎結合の例を示すUML図です。
比較のために、依存クラスとプロバイダ間の結合が強い代替設計を図に示します。
関数をコアモジュールとする(関数型プログラミングを参照)か、関数をオブジェクトとする概念を持つコンピュータプログラミング言語は、疎結合プログラミングの優れた例となります。関数型言語には、継続、クロージャ、ジェネレータなどのパターンがあります。関数型プログラミング言語の例としては、 ClojureとLispを参照してください。SmalltalkやRubyのようなオブジェクト指向言語にはコードブロックがあり、Eiffelにはエージェントがあります。基本的な考え方は、関数を他の囲んでいる概念から独立してオブジェクト化(オブジェクトとしてカプセル化)することです(たとえば、オブジェクト関数を囲んでいるオブジェクトに関する直接的な知識から切り離すなど)。関数をオブジェクトとして扱うことについてさらに詳しく知りたい場合は、「第一級関数」を参照してください。これは第一級関数の1つの形式に該当します。
例えば、オブジェクト指向言語では、オブジェクトの関数がオブジェクトとして参照されると(つまり、関数がそれを囲むホストオブジェクトについて何も知らなくても済むようになると)、新しい関数オブジェクトは受け渡し、保存、そして後で呼び出すことができます。これらの関数オブジェクトを受け取るオブジェクトは、囲むホストオブジェクトについて直接知ることなく、都合の良いときに安全にその関数を実行(呼び出し)できます。このようにして、プログラムは関数オブジェクトの連鎖やグループを実行しながら、囲むホストオブジェクトへの直接的な参照から安全に切り離された状態を維持できます。
電話番号は優れた類推であり、この乖離の度合いを容易に示すことができる。
例えば、ある組織が別の組織に特定の仕事を依頼するための電話番号を提供するとします。その番号に電話がかかってきたとき、発信元の組織は実質的に「この仕事を私にやってください」と言っていることになります。この分離、あるいは疎結合はすぐに明らかになります。番号を受け取る組織は、その番号がどこから来たのか(例えば、番号の提供元など)を知らない可能性があります。一方、発信側は、誰に電話をかけているのか、自分がどこにいるのか、そして電話を受ける側の内部的な仕組みなど、具体的な情報から切り離されています。
この例をさらに発展させると、発信者は着信者に対して「この仕事をしてください。終わったらこの番号に折り返し電話してください」と言うかもしれません。着信者に提示されるこの「番号」は「コールバック」と呼ばれます。ここでも、この機能オブジェクトの疎結合性、あるいは分離性が明らかです。コールバックの受信者は、何に、あるいは誰に電話がかかっているのかを知りません。着信者は、電話をかけることができることだけを知っており、いつ電話をかけるかを自分で決定します。実際には、コールバックは、最初にコールバックを提供した相手にさえ届かない可能性があります。このような間接性こそが、関数オブジェクトを疎結合プログラムを実現するための優れた技術にしているのです。
疎結合コンポーネント間の通信は、前述の非同期通信スタイルや同期メッセージパッシングスタイルなどのさまざまなメカニズムに基づいている可能性があります[ 7 ]。
疎結合の度合いは、送信システムまたは受信システムで発生する可能性のあるデータ要素の変更数を記録し、コンピュータが引き続き正しく通信できるかどうかを判断することによって測定できます。これらの変更には、次のような項目が含まれます。