web-dev-qa-db-ja.com

オブジェクト指向パラダイムにおける疎結合と密結合の違いは何ですか?

オブジェクト指向パラダイムで、疎結合と密結合の違いを正確に説明できる人はいますか。

242
Jim

密結合は、クラスのグループが互いに強く依存している場合です。

このシナリオは、クラスがあまりにも多くの責任を引き受けるとき、または1つの懸念が独自のクラスを持つのではなく、多くのクラスにわたって広がるときに発生します。

疎結合は、単一責任と懸念の分離を促進する設計によって達成されます。

疎結合クラスは、他の(具体的な)クラスとは無関係に消費およびテストできます。

インターフェースは、デカップリングに使用するための強力なツールです。クラスは他の具象クラスではなくインタフェースを介して通信できます。また、インタフェースを実装するだけで、任意のクラスをその通信の反対側に置くことができます。

密結合の例

class CustomerRepository
{
    private readonly Database database;

    public CustomerRepository(Database database)
    {
        this.database = database;
    }

    public void Add(string CustomerName)
    {
        database.AddRow("Customer", CustomerName);
    }
}

class Database
{
    public void AddRow(string Table, string Value)
    {
    }
}

疎結合の例:

class CustomerRepository
{
    private readonly IDatabase database;

    public CustomerRepository(IDatabase database)
    {
        this.database = database;
    }

    public void Add(string CustomerName)
    {
        database.AddRow("Customer", CustomerName);
    }
}

interface IDatabase
{
    void AddRow(string Table, string Value);
}

class Database : IDatabase
{
    public void AddRow(string Table, string Value)
    {
    }
}

別の例 ここ

302
Jonathan

ANYコードなしの簡単な説明

要約の例:

帽子は体と「ゆるく結合」しています。つまり、人や体に何も変更を加えることなく帽子を簡単に外すことができます。あなたがそれをすることができるとき、あなたはそれから「疎結合」を持ちます。詳しくは下記をご覧ください。

The Hat is "loosely coupled" to the body. This means you can easily take then hat off without making any changes to the the person/body. Picture Attribution: https://pixabay.com/en/greeting-cylinder-chapeau-dignity-317250/

タイトカップリング(詳細例)

あなたの肌を考えてください。体にくっついています。手袋のようにフィットします。しかし、もしあなたが肌の色を例えば白から黒に変えたいとしたら?肌をはがして染めてから貼り付けるなどの作業がどれほど痛みを伴うか想像できますか。それはあなたの体に密接に結合されているのであなたの肌を変えることは困難です。簡単に変更することはできません。これを可能にするためには、基本的に人間を再設計しなければならないでしょう。

  • キーポイント#1:言い換えれば、あなたがスキンを変更したいのなら、あなたはまた持っているでしょうあなたの体のデザインを変えなさい同様に2つが一緒に結合されるので - それらは密接に結合されている。

神は良いオブジェクト指向プログラマーではありませんでした。

ルースカップリング(詳細例)

今度は朝服を着ることを考えなさい。あなたは青が好きではありませんか?問題ありません。代わりに赤いシャツをかぶることができます。シャツはあなたの肌と同じようにあなたの体に実際に接続されていないため、あなたはこれを簡単かつ楽に行うことができます。 シャツは自分の体がどうなっているのかわからないし気にもしていません。つまり、体を変えることなく、自分の服を変えることができます。

  • それがキーポイント#2です。 シャツを変えても、体を変える必要はありません - できるときそれで、あなたは疎結合を持っています。それができないときは、密接な関係がある。

それが一言で言えば基本的な概念です。

なぜこれらすべてが重要なのでしょうか。

ソフトウェアは常に変化するので重要です。一般的に言って、あなたはあなたのコードを簡単に修正できるようにしたいのです。 (これは別のコーディングのベストプラクティス、つまり開閉の原則と結び付いています。つまり、基本的に何も変更することなくコードに簡単に追加できるはずです(インターフェイスを使用することでこれが可能なことは可能です)。別の日のために)。

計算における結合の実際的な例

  • 誰かがJSONなどではなくCSVファイルに出力したい場合、またはMySQLからPostGreSQLに切り替えたい場合は、クラス全体を書き直すことなく、コード内でこれらの変更を非常に簡単に行うことができるはずです。つまり、アプリケーションを特定のデータベース実装(Mysqlなど)や特定の出力(CSVファイルなど)に密接に結び付けたくはありません。なぜなら、ソフトウェアでは避けられないことですが、変化が起こるからです。それらが来るとき、あなたのコードのあなたの部分が疎結合されているなら、それははるかに簡単です。

他の例:自動車部品とスペア部品

  • 誰かが 自分の車 in を望んでいるのなら、それをするために車全体を再設計する必要はないはずです。自動車とそのスペアパーツは、疎結合アーキテクチャの好例です(@ mnmopazemのコメントに従って)。あなたがより良いものとあなたのエンジンを交換したいならば、あなたはあまり多くの努力なしであなたのエンジンを単に取り除いて、より良いものとそれを交換することができるはずです。あなたの車がRolls Royce 1234エンジンと他のエンジンで動かないだけであるならば - あなたの車はそのエンジン(Rolls Royce 1234)と密接に結びついています。あなたはそれがそのコンポーネントともう少し緩やかに結合されるように、それがanyエンジンで動作するようにあなたの車のデザインを変更した方が良いでしょう。あなたの車がまったくエンジンを必要とせずに働くことができればさらに良いでしょう!ある程度のカップリングが起こりますが、できる限り最小化するように努力する必要があります。どうして?要件が変化しても、高品質のソフトウェアを迅速に提供できるはずであるため、疎結合によってその目標を支援します。

概要

つまり、疎結合によってコードの変更が容易になります。上記の答えはこの時点で読む価値があるいくつかのコードを提供します。

写真の帰属

140
BKSpurgeon

オブジェクト指向設計では、結合量は、あるクラスの設計が別のクラスの設計にどれだけ依存するかを表します。言い換えれば、クラスAの変更はクラスBの変更に関連した変更をどのくらいの頻度で実行するのでしょうか。タイトカップリングは、2つのクラスがしばしば一緒に変わることを意味し、ルーズカップリングは、それらがほとんど独立していることを意味します。一般に、テストと保守が容易なため、疎結合をお勧めします。

あなたは Martin Fowlerによるこの論文(PDF) が役に立つかもしれません。

65
Don Kirkby

一般的にタイトカップリングは悪いですが、ほとんどの場合、コードの柔軟性と再利用性を低下させるため、変更をはるかに困難にし、テスト容易性を妨げます。

密結合オブジェクトは、互いについてかなりよく知っておく必要があるオブジェクトであり、通常、他のインターフェースに大きく依存しています。密結合アプリケーションで1つのオブジェクトを変更するには、他の多くのオブジェクトを変更する必要があります。小さなアプリケーションでは、変更を簡単に識別でき、何も見逃す可能性が少なくなります。しかし、大規模なアプリケーションでは、これらの相互依存関係がすべてのプログラマーに常に知られているとは限らず、変更を見逃す可能性があります。しかし、疎結合オブジェクトの各セットは他のオブジェクトに依存しません。

つまり、疎結合は、あるコンポーネントの変更が他のコンポーネントの変更を必要とするリスクを減らすことを目的として、システムのコンポーネント間の相互依存性を減らすことを目的とした設計目標です。疎結合は、システムの柔軟性を高め、保守性を高め、フレームワーク全体をより「安定的」にすることを目的とした、より一般的な概念です。

カップリングとは、ある要素が別の要素に持っている直接的な知識の程度のことです。例:AとB、BのみがAの動作を変更した場合にのみその動作を変更します。疎結合システムは、定義可能な要素に簡単に分割できます。

13
Jom George

2つのオブジェクトが疎結合の場合、それらは相互作用することができますが、お互いの知識はほとんどありません。

疎結合設計により、変化を処理できる柔軟なOOシステムを構築できます。

オブザーバデザインパターンは、クラスを疎結合にする良い例です。 Wikipedia で見ることができます。

9
Ahmed_Gad

私が理解しているように、密結合アーキテクチャーは、疎結合アーキテクチャーと比較した場合、変更に対する柔軟性があまりありません。

しかし、疎結合アーキテクチャー、メッセージフォーマット、オペレーティングプラットフォーム、ビジネスロジックの見直しが相手先に影響を与えることはありません。システムが刷新のために停止された場合、もちろんもう一方の端はしばらくサービスにアクセスすることができないでしょうがそれ以外は、変更されていない端は刷新の前のようにメッセージ交換を再開できます。

5
Amit Kumar

カップリングについての私の ブログ記事 からの抜粋:

タイトカップリングとは何ですか: -

上記の定義と同様に、密結合オブジェクトは他のオブジェクトについて知る必要があるオブジェクトであり、通常は互いのインターフェースに大きく依存しています。

密結合アプリケーションで1つのオブジェクトを変更すると、他の多くのオブジェクトも変更する必要があります。小さなアプリケーションでも問題はありません。変更を簡単に識別できます。しかし、大規模なアプリケーションの場合、これらの相互依存関係がすべてのコンシューマや他の開発者に常に知られているわけではないか、将来変更される可能性が多くあります。

密結合を理解するために、ショッピングカートのデモコードを見てみましょう。

namespace DNSLooseCoupling
{
    public class ShoppingCart
    {
        public float Price;
        public int Quantity;

        public float GetRowItemTotal()
        {
            return Price * Quantity;
        }
    }

    public class ShoppingCartContents
    {
        public ShoppingCart[] items;

        public float GetCartItemsTotal()
        {
            float cartTotal = 0;
            foreach (ShoppingCart item in items)
            {
                cartTotal += item.GetRowItemTotal();
            }
            return cartTotal;
        }
    }

    public class Order
    {
        private ShoppingCartContents cart;
        private float salesTax;

        public Order(ShoppingCartContents cart, float salesTax)
        {
            this.cart = cart;
            this.salesTax = salesTax;
        }

        public float OrderTotal()
        {
            return cart.GetCartItemsTotal() * (2.0f + salesTax);
        }
    }
}

上記の例の問題

タイトカップリングはいくつかの問題を引き起こします。

ここでは、OrderTotal()メソッドは、カートの現在の商品の全額を表示します。このカートシステムに割引機能を追加したい場合。上記のコードでは、クラスが非常に密接に関連しているため、クラスごとに変更を加える必要があるため、実行するのは非常に困難です。

4
Anil Sharma

それらのライブラリを通して依存性注入を提供する特定のツールがあります。例えば、.netには ninject Library があります。

もしあなたがJavaでさらに進んでいるのであれば spring はこの機能を提供します。

疎結合オブジェクトは、コードにインタフェースを導入することで作成できます。それが、これらのソースが行うことです。

あなたが書いているあなたのコードで言う

Myclass m = new Myclass();

あなたのメソッドのこのステートメントはmyclassに依存していると言っています。これは密結合と呼ばれます。今、あなたはいくつかのコンストラクタインジェクション、またはプロパティインジェクションとインスタンス化オブジェクトを提供し、それは疎結合になります。

3
Vishal Sharma

疎結合は、2つの要素間の依存度が非常に低いことを意味します。
例:GSM SIM

密結合は、2つのコンポーネント間の依存度が非常に高いことを意味します。
例:CDMAモバイル

3
govind satpute

疎結合は、古いスタイルのハードコードされた依存関係や、変更があった場合の頻繁な再コンパイルやコードの再利用などの関連する問題の問題への回答です。それは、コンポーネントにワーカーロジックを実装し、そこでソリューション固有のコードを配線することを避けることを強調しています。

疎結合= IoC 説明を簡単にするために this を参照してください。

2
MSIL

密結合は、あるクラスが別のクラスに依存していることを意味します。
疎結合は、1つのクラスがクラスではなくインターフェースに依存していることを意味します。

密結合では、メソッド内で宣言されたハードコーディングされた依存関係があります。
疎結合では、ハードコードではなく実行時に依存関係を外部に渡す必要があります。 (疎結合システムでは、クラスとの依存関係を減らすためにインタフェースが使用されます。)

たとえば、JSON出力、CSV出力など、複数の方法で出力を送信できるシステムがあります。

タイトカップル

public interface OutputGenerator {
    public void generateOutput();
}

public class CSVOutputGenerator implements OutputGenerator {
    public void generateOutput() {
        System.out.println("CSV Output Generator");
    }
}

public class JSONOutputGenerator implements OutputGenerator {
    public void generateOutput() {
        System.out.println("JSON Output Generator");
    }
}

// In Other Code, we write Output Generator like...
public class Class1 {
    public void generateOutput() {
        // Here Output will be in CSV-Format, because of hard-coded code.
        // This method tightly coupled with CSVOutputGenerator class, if we want another Output, we must change this method.
        // Any method, that calls Class1's generateOutput will return CSVOutput, because Class1 is tight couple with CSVOutputGenerator.
        OutputGenerator outputGenerator = new CSVOutputGenerator();
        output.generateOutput();
    }
}

上の例で、JSONの出力を変更したい場合は、Class1がCSVOutputGeneratorクラスと密接に関連しているため、コード全体を見つけて変更する必要があります。

緩いカップル

public interface OutputGenerator {
    public void generateOutput();
}

public class CSVOutputGenerator implements OutputGenerator {
    public void generateOutput() {
        System.out.println("CSV Output Generator");
    }
}

public class JSONOutputGenerator implements OutputGenerator {
    public void generateOutput() {
        System.out.println("JSON Output Generator");
    }
}

// In Other Code, we write Output Generator like...
public class Class1 {
    public void generateOutput(OutputGenerator outputGenerator) {
        // if you want to write JSON, pass object of JSONOutputGenerator (Dependency will be passed externally to this method)
        // if you want to write CSV, pass object of CSVOutputGenerator (Dependency will be passed externally to this method)

        // Due to loose couple with class, we don't need to change code of Class1, because Class1 is loose coupled with CSVOutputGenerator or JSONOutputGenerator class
        // Any method, that calls Class1's generateOutput will desired output, because Class1 does not tight couple with CSVOutputGenerator or JSONOutputGenerator class
        OutputGenerator outputGenerator = outputGenerator;
        output.generateOutput();
    }
}
2
Milan Vaghasiya

それはクラスについてです依存率疎結合でとても低く、密結合でとても高い別のクラス。 サービス指向アーキテクチャーで明確になるように、サービスは互いに疎結合ですモノリシックお互いに対してどのクラスの依存関係が意図的であるかに対して

1

疎結合は、密結合が直接的に与えられる場合には、依存関係のすべての情報を提供せずに間接的にクラスが必要とする依存関係を与えるプロセスです。これはコーディングの良い方法ではありません。

1
David William

あるオブジェクトの作成/存在が、調整できない別のオブジェクトに依存している場合、その密接な関係があります。そして、依存関係を調整することができれば、それは疎結合です。 Javaの例を考えます。

class Car {

    private Engine engine = new Engine( "X_COMPANY" ); // this car is being created with "X_COMPANY" engine
    // Other parts

    public Car() { 
        // implemenation 
    }

}

Carクラスのクライアントは「X_COMPANY」エンジンのみでそれを作成することができます。

それを変える能力でこのカップリングを壊すことを考えなさい:

class Car {

    private Engine engine;
    // Other members

    public Car( Engine engine ) { // this car can be created with any Engine type
        this.engine = engine;
    }

}

Carは型で作成できるため、 "X_COMPANY"のエンジンには依存しません。

Java特有の注意:デカップリングの目的でJavaインターフェースを使用することは、適切な設計方法ではありません。 Javaでは、インターフェースは目的を持っています - 本質的に分離の振舞い/利点を提供するコントラクトとして機能すること。

承認された回答でのBill Rosmusのコメントには、良い説明があります。

0
lupchiazoem

アナロジーを使ってここにたくさんのいい答えがあります、しかし仕事の友人は私がここに述べられたもののすべてより好きであるという例を私に与えました...目とメガネ!

タイトカップリング

タイトカップリングが目になります。私が自分のビジョンを直したいのなら、私は目の移植を受けるのは非常に高価で、かなりのリスクを抱えています。しかし、デザイナー(人類)がより良い方法を見つけたらどうなるでしょう。それは簡単に変更することができるように体に疎結合されている機能を追加してください! (はい。メガネ)

疎結合

私は私の基本的な視野を壊すことなく私の眼鏡を簡単に交換することができます。私はメガネをはずすことができます、そして、私のビジョンはそれが以前であった方法になるでしょう(良くも悪くもありません)。異なるペアのメガネを使用すると、リスクとメンテナンス性がほとんどなく、私たちの目を通して世界を見る方法が変わります。

要約

それで、次回は「誰かが私のコードが密結合されているかどうかを気にかけていますか」とあなたに尋ねます。その答えは、変化への努力、維持への努力、そして変化のリスクです。

では、これはC#でどのように行われるのでしょうか。インターフェースと依存性注入

EDIT

これはDecoratorパターンの良い例でもあります。ここでは目が私たちがインターフェース要件を満たすことによって装飾しているクラスであるが、異なる機能を与えるクラスです(例:サングラス、老眼鏡、宝石商用虫眼鏡e.t.c)。

0
JohnChris