凝集度と結合度の違いは何ですか?
結合と凝集度は、どのようにしてソフトウェア設計の良し悪しにつながるのでしょうか。
2つの違いと、全体的なコード品質への影響を概説するいくつかの例は何ですか?
凝集度と結合度の違いは何ですか?
結合と凝集度は、どのようにしてソフトウェア設計の良し悪しにつながるのでしょうか。
2つの違いと、全体的なコード品質への影響を概説するいくつかの例は何ですか?
結束とは、クラス(またはモジュール)が実行できることを指します。凝集度が低いということは、クラスがさまざまなアクションを実行することを意味します。つまり、クラスは幅広く、何をすべきかについて焦点が当てられていません。凝集度が高いということは、クラスが何をすべきかに焦点を合わせていることを意味します。つまり、クラスの意図に関連するメソッドのみです。
低凝集度の例:
-------------------
| Staff |
-------------------
| checkEmail() |
| sendEmail() |
| emailValidate() |
| PrintLetter() |
-------------------
高凝集度の例:
----------------------------
| Staff |
----------------------------
| -salary |
| -emailAddr |
----------------------------
| setSalary(newSalary) |
| getSalary() |
| setEmailAddr(newEmail) |
| getEmailAddr() |
----------------------------
結合に関しては、2つのクラス/モジュールが互いにどの程度関連または依存しているかを示します。低結合クラスの場合、一方のクラスでメジャーなものを変更しても、もう一方のクラスには影響しません。結合度が高いと、コードの変更と保守が困難になります。クラスは緊密に連携しているため、変更を加えるには、システム全体の刷新が必要になる可能性があります。
優れたソフトウェア設計では、凝集度が高く、結合度が低くなります。
モジュール内の高い凝集度とモジュール間の低い結合度は、オブジェクト指向プログラミング言語の高品質に関連していると見なされることがよくあります。
たとえば、各Javaクラス内のコードは、高い内部凝集度を持っている必要がありますが、他のJavaクラス内のコードと可能な限り緩く結合されている必要があります。
Meyerのオブジェクト指向ソフトウェア構築(第2版)の第3章は、これらの問題の優れた説明です。
凝集度は、ソフトウェア要素の責任がどの程度関連し、集中しているかを示します。
結合とは、ソフトウェア要素が他の要素にどれだけ強く接続されているかを指します。
ソフトウェア要素は、クラス、パッケージ、コンポーネント、サブシステム、またはシステムである可能性があります。また、システムを設計する際には、凝集度が高く、結合度が低いソフトウェア要素を使用することをお勧めします。
凝集度が低いと、モノリシッククラスが生成され、維持、理解が困難になり、再利用性が低下します。同様に、高結合は、密に結合されたクラスをもたらし、変更は非ローカルではなく、変更が難しく、再利用を減らします。
ConnectionPool
次の要件を備えた典型的なモニター可能を設計しているという架空のシナリオをとることができます。のような単純なクラスには多すぎるように見えるかもしれませんConnectionPool
が、基本的な目的は、いくつかの単純な例を使用して低結合度と高凝集度を示すことであり、役立つと思います。
凝集度が低い場合はConnectionPool
、以下のように、このすべての機能/責任を1つのクラスに強制的に詰め込むことでクラスを設計できます。この単一のクラスが接続管理、データベースとの対話、および接続統計の維持を担当していることがわかります。
高い凝集度により、クラス全体にこれらの責任を割り当て、保守性と再利用性を高めることができます。
低結合を示すために、上記の高凝集度ConnectionPool
図を続けます。高い凝集度をサポートしているにもかかわらず上の図を見ると、はクラスとConnectionPool
緊密に結合されており、それらと直接相互作用します。代わりに、結合を減らすために、インターフェースを導入し、これら2つのクラスにインターフェースを実装させ、クラスに登録させることができます。そして、はこれらのリスナーを反復処理し、接続の取得イベントと解放イベントを通知し、結合を少なくします。ConnectionStatistics
PersistentStore
ConnectionListener
ConnectionPool
ConnectionPool
注/単語または注意:この単純なシナリオでは、やり過ぎのように見えるかもしれませんが、アプリケーションがトランザクションを完了するために複数のサードパーティサービスと対話する必要があるリアルタイムシナリオを想像すると、コードをサードパーティサービスと直接結合しますつまり、サードパーティのサービスを変更すると、複数の場所でコードが変更される可能性があります。代わりにFacade
、これらの複数のサービスと内部で相互作用し、サービスの変更がローカルになりFacade
、サードパーティとの結合が少なくなる可能性があります。サービス。
簡単に言うと、Cohesionは、コードベースの一部が論理的に単一のアトミックユニットを形成する度合いを表します。一方、結合は、単一のユニットが他のユニットに依存している度合いを表します。つまり、2台以上のユニット間の接続数です。数値が小さいほど、カップリングは低くなります。
本質的に、高い凝集度とは、相互に関連するコードベースの部分を1か所に保持することを意味します。同時に、低結合とは、コードベースの無関係な部分を可能な限り分離することです。
凝集度と結合度の観点からのコードの種類:
ガイドラインに従ったコードが理想的です。それは緩く結合され、非常にまとまりがあります。このようなコードは、次の図で説明できます。
神オブジェクトは、高い凝集度と高い結合度を導入した結果です。これはアンチパターンであり、基本的にすべての作業を一度に実行する単一のコードを表します。
異なるクラスまたはモジュール間の境界が適切に選択されていない場合、不適切に選択されます。
破壊的なデカップリングは最も興味深いものです。プログラマーがコードベースを切り離そうとして、コードが完全にフォーカスを失った場合に発生することがあります。
詳細はこちら
凝集度の増加と結合の減少は、優れたソフトウェア設計につながります。
Cohesionは機能を分割して、関連するデータに簡潔かつ最も近くなるようにします。一方、デカップリングは、機能の実装がシステムの他の部分から分離されることを保証します。
デカップリングを使用すると、ソフトウェアの他の部分に影響を与えることなく、実装を変更できます。
結束性により、実装が機能に固有であると同時に、保守が容易になります。
結合を減らし、凝集度を上げる最も効果的な方法は、インターフェースによる設計です。
つまり、主要な機能オブジェクトは、それらが実装するインターフェースを介してのみお互いを「知る」必要があります。インターフェイスの実装は、自然な結果として結束をもたらします。
一部のシナリオでは現実的ではありませんが、それを実行することは設計上の目標である必要があります。
例(非常に大ざっぱです):
public interface IStackoverFlowQuestion
void SetAnswered(IUserProfile user);
void VoteUp(IUserProfile user);
void VoteDown(IUserProfile user);
}
public class NormalQuestion implements IStackoverflowQuestion {
protected Integer vote_ = new Integer(0);
protected IUserProfile user_ = null;
protected IUserProfile answered_ = null;
public void VoteUp(IUserProfile user) {
vote_++;
// code to ... add to user profile
}
public void VoteDown(IUserProfile user) {
decrement and update profile
}
public SetAnswered(IUserProfile answer) {
answered_ = answer
// update u
}
}
public class CommunityWikiQuestion implements IStackoverflowQuestion {
public void VoteUp(IUserProfile user) { // do not update profile }
public void VoteDown(IUserProfile user) { // do not update profile }
public void SetAnswered(IUserProfile user) { // do not update profile }
}
コードベースの他の場所に、質問が何であるかに関係なく、質問を処理するモジュールを含めることができます。
public class OtherModuleProcessor {
public void Process(List<IStackoverflowQuestion> questions) {
... process each question.
}
}
結束の最も良い説明は、ボブおじさんのクリーンコードから来ています:
クラスには少数のインスタンス変数が必要です。クラスの各メソッドは、これらの変数の1つ以上を操作する必要があります。一般に、メソッドが操作する変数が多いほど、そのメソッドはそのクラスに対してよりまとまりがあります。各変数が各メソッドで使用されるクラスは、最大限にまとまりがあります。
一般に、このような最大限にまとまりのあるクラスを作成することはお勧めできません。一方で、凝集力を高くしたい。凝集力が高い場合、それはクラスのメソッドと変数が相互に依存しており、論理的な全体として一緒にぶら下がっていることを意味します。
関数を小さく保ち、パラメーターリストを短くするという戦略は、メソッドのサブセットによって使用されるインスタンス変数の急増につながる場合があります。これが発生した場合、ほとんどの場合、より大きなクラスから抜け出そうとしている他のクラスが少なくとも1つあることを意味します。新しいクラスがよりまとまりのあるものになるように、変数とメソッドを2つ以上のクラスに分割するようにしてください。
ソフトウェアエンジニアリングにおける凝集度は、特定のモジュールの要素が一緒に属する程度です。したがって、これは、ソフトウェアモジュールのソースコードによって表現される各機能がどれほど強く関連しているかを示す尺度です。
簡単に言えば、結合とは、あるコンポーネント(必ずしもそうではないが、クラスを想像してください)が別のコンポーネントの内部動作または内部要素についてどれだけ知っているか、つまり、他のコンポーネントについてどれだけの知識を持っているかです。
例や図面を使ってもう少し詳しく知りたい場合は、これについてブログに投稿しました。私はそれがあなたの質問のほとんどに答えると思います。
結束とは、単一のクラスがどのように設計されているかを指します。結束は、クラスが単一の、焦点を絞った目的で設計されていることを確認することに最も密接に関連するオブジェクト指向の原則です。クラスに焦点を合わせるほど、そのクラスのまとまりが増します。高凝集度の利点は、そのようなクラスは、低凝集度のクラスよりも保守がはるかに簡単である(そして変更の頻度が少ない)ことです。高い凝集度のもう1つの利点は、目的に焦点を合わせたクラスが他のクラスよりも再利用可能になる傾向があることです。
上の画像では、凝集度が低い場合、1つのクラスだけが、共通ではない多くのジョブを実行する責任があり、再利用と保守の可能性が低くなっていることがわかります。ただし、凝集度が高い場合は、すべてのジョブに個別のクラスがあり、特定のジョブを実行するため、使いやすさとメンテナンスが向上します。
Cohesion(Co-hesion):一緒を意味するCo、固執することを意味するhesion。異なる物質の粒子をくっつけるシステム。
実際の例の場合:img礼儀
全体はパーツの合計よりも大きい-アリストテレス。
凝集度は通常のタイプの測定であり、通常は「高凝集度」または「低凝集度」と呼ばれます。高い凝集度は、堅牢性、信頼性、再利用性、理解性など、ソフトウェアのいくつかの望ましい特性に関連しているため、高い凝集度のモジュールが好ましい傾向があります。対照的に、凝集度が低いと、保守、テスト、再利用、さらには理解が困難になるなど、望ましくない特性が発生します。ウィキ
結合は通常、凝集とは対照的です。低結合はしばしば高凝集度と相関し、逆もまた同様です。低結合は、多くの場合、適切に構造化されたコンピューターシステムと優れた設計の兆候であり、高凝集度と組み合わせると、高い可読性と保守性という一般的な目標をサポートします。ウィキ
違いは次のように言えます。
このブログ投稿では、それについてさらに詳しく書いています。
凝集度は、モジュールの相対的な機能強度を示します。
従来のビュー:
モジュールの「ひたむきさ」
OOビュー:
凝集度とは、コンポーネントまたはクラスが、相互に、およびクラスまたはコンポーネント自体に密接に関連する属性と操作のみをカプセル化することを意味します。
凝集度のレベル
機能的
レイヤー
コミュニケーション
シーケンシャル
手続き型
一時的
ユーティリティ
結合は、モジュール間の相対的な相互依存性を示します。
結合は、モジュール間のインターフェイスの複雑さ、モジュールへのエントリまたは参照が行われるポイント、およびインターフェイスを通過するデータによって異なります。
従来の見方:コンポーネントが他のコンポーネントや外界に接続されている度合い
OOビュー:クラスが相互に接続されている程度の定性的尺度
結合のレベル
コンテンツ
共通
制御
スタンプ
データ
定期的な電話
タイプの使用
包含またはインポート
外部#
凝集度という用語は、ソフトウェア設計での意味に対して、実際には少し直感に反しています。
凝集の一般的な意味は、分子の引力のような強い結合を特徴とする、しっかりとくっついているものが結合していることです。ただし、ソフトウェア設計では、理想的には1つのことだけを実行するクラスを目指して努力することを意味するため、複数のサブモジュールは含まれません。
おそらく、私たちはそれをこのように考えることができます。パーツは、それが唯一のパーツである場合に最も凝集性があります(1つのことだけを実行し、それ以上分解することはできません)。これがソフトウェア設計で望まれることです。結束は、単に「単一責任」または「関心の分離」の別名です。
一方、結合という用語は非常に直感的です。つまり、モジュールが他のモジュールにあまり依存せず、接続するモジュールを簡単に置き換えることができます。たとえば、リスコフの置換原則に従います。
結合=相互作用/2つのモジュール間の関係... 凝集=モジュール内の2つの要素間の相互作用。
ソフトウェアは多くのモジュールで構成されています。モジュールは要素で構成されています。モジュールがプログラムであると考えてください。プログラム内の関数は要素です。
実行時に、プログラムの出力は別のプログラムの入力として使用されます。これは、モジュール間相互作用またはプロセス間通信と呼ばれます。これは、カップリングとも呼ばれます。
単一のプログラム内で、関数の出力は別の関数に渡されます。これは、モジュール内の要素の相互作用と呼ばれます。これは凝集とも呼ばれます。
例:
結合=2つの異なる家族間のコミュニケーション... 凝集=家族内の父-母-子間のコミュニケーション。
簡単に言えば、凝集度とは、クラスが単一の概念を表す必要があることを意味します。
すべてのクラス機能がクラスが表す概念に関連している場合、クラスのパブリックインターフェイスはまとまりがあります。たとえば、CashRegisterクラスを使用する代わりに、CashRegisterとCoinの機能を統合すると、CashRegisterクラスとCoinクラスの2つのクラスになります。
結合では、クラスのオブジェクトを使用するため、あるクラスは別のクラスに依存します。
高結合の問題は、副作用が発生する可能性があることです。1つのクラスで1つの変更を行うと、他のクラスで予期しないエラーが発生し、コード全体が破損する可能性があります。
一般に、高凝集度と低結合度は高品質のOOPと見なされます。
1.偶然2.論理的3.時間的4.手続き的5.コミュニケーション6.順次7.機能的
結合はモジュール内の関係を表し、結合はモジュール間の関係を示します。凝集力の増加はソフトウェアにとっては良いことですが、結合の増加はソフトウェアにとっては避けられます。凝集力は、モジュールの機能強度を表します。結合は、モジュール間の独立性を表します。結束して、モジュールは単一のものに焦点を合わせます。結合では、モジュールは他のモジュールに接続されます。したがって、設計中は、高い凝集度と低い結合度を追求する必要があります。