「高凝集」の意味は何ですか?


28

私はインターンとしてソフトウェア開発会社に最近入社した学生です。大学に戻って、私の教授の一人は、「低結合と高凝集」を達成するために努力しなければならないと言っていました。

低結合の意味を理解しています。これは、ある場所での変更が別の場所でコードを壊さないように、別々のコンポーネントのコードを別々に保持することを意味します。

しかし、高い凝集性が意味するもの。同じコンポーネントのさまざまな部分を互いにうまく統合することを意味する場合、それがどのように有利になるか理解できません。

凝集力が高いとはどういう意味ですか?その利点を理解するために例を説明できますか?



1
ウィキペディアの記事はあなたの質問に十分に答えていませんか? en.wikipedia.org/wiki/Cohesion_(computer_science)
Eoinキャロル

これに関する良い記事があります:msdn.microsoft.com/en-us/magazine/cc947917.aspx
NoChance

1
@EoinCarroll:残念ながら、現時点でのウィキペディアの記事では、新しいプログラマーが使用できる具体的な例は提供されていません。理論は優れており、すべてですが、結束性が低いことをめぐる過ちを犯すまで、実際には固執しません。高い結束性は、私が数年のプログラミングを費やして、なぜそれが重要で、どのようにそれを達成するのかを完全に理解してきたトピックの1つです。
スポイケ

Clean Codeを読むまでCohesionを本当に理解していませんでした。あなたもすべき。
セバスチャンレッド

回答:


25

OOの観点から凝集度を調べる1つの方法は、クラスのメソッドがプライベート属性のいずれかを使用している場合です。この回答で gnatが指摘したように、LCOM4(Cohesive Methodsの欠如)などのメトリックを使用します。、リファクタリングできるクラスを特定できます。メソッドまたはクラスをよりまとまりのあるものにリファクタリングする理由は、他の人がそれを使用するためのコード設計を簡単にするためです。私を信じて; これらの問題を解決するとき、ほとんどの技術リーダーと保守プログラマーはあなたを愛しています。

Sonarなどのビルドプロセスでツールを使用して、コードベースの低い凝集度を特定できます。「凝集性」が低い方法について考えることができる非常に一般的なケースがいくつかあります。

ケース1:メソッドがクラスにまったく関連していない

次の例を考えてみましょう。

public class Food {
   private int _foodValue = 10;

   public void Eat() {
     _foodValue -= 1;
   }

   public void Replenish() {
     _foodValue += 1;
   }

   public void Discharge() {
     Console.WriteLine("Nnngghhh!");
   }
}

メソッドの1つであるにDischarge()は、クラスのプライベートメンバーのいずれにも触れないため、凝集性がありません。この場合、プライベートメンバーは1人のみです_foodValue。クラス内部で何もし​​ない場合、それは本当にそこに属しますか?このメソッドは、たとえばという名前の別のクラスに移動できますFoodDischarger

// Non-cohesive function extracted to another class, which can
// be potentially reused in other contexts
public FoodDischarger {
  public void Discharge() {
    Console.WriteLine("Nnngghhh!");
  }
}

JavaScriptで実行している場合、関数はファーストクラスのオブジェクトであるため、放電は自由な関数になります。

function Food() {
    this._foodValue = 10;
}
Food.prototype.eat = function() {
    this._foodValue -= 1;
};
Food.prototype.replenish = function() {
    this._foodValue += 1;
};

// This
Food.prototype.discharge = function() {
    console.log('Nnngghhh!');
};
// can easily be refactored to:
var discharge = function() {
    console.log('Nnngghhh!');
};
// making it easily reusable without creating a class

ケース2:ユーティリティクラス

これは実際、凝集性を破壊する一般的なケースです。誰もユーティリティクラスを愛していますが、これらは通常、設計上の欠陥を示しており、ほとんどの場合、(ユーティリティクラスに関連する高い依存性のために)コードベースの保守が難しくなります。次のクラスを検討してください。

public class Food {
    public int FoodValue { get; set; }
}

public static class FoodHelper {

    public static void EatFood(Food food) {
        food.FoodValue -= 1;
    }

    public static void ReplenishFood(Food food) {
        food.FoodValue += 1;
    }

}

ここで、ユーティリティクラスがクラスのプロパティにアクセスする必要があることがわかります。 Food。ユーティリティクラスのメソッドは、作業を行うために外部のリソースを必要とするため、この場合は凝集性がありません。この場合、それ自体で動作しているクラスにメソッドを含める方が良いとは思いませんか(最初のケースのように)?

ケース2b:ユーティリティクラスの非表示オブジェクト

未実現のドメインオブジェクトがあるユーティリティクラスの別のケースがあります。文字列操作をプログラミングする際にプログラマが最初に感じる不意打ちの反応は、そのためのユーティリティクラスを記述することです。いくつかの一般的な文字列表現を検証する次のようなものです。

public static class StringUtils {

  public static bool ValidateZipCode(string zipcode) {
    // validation logic
  }

  public static bool ValidatePhoneNumber(string phoneNumber) {
    // validation logic
  }

}

ここでほとんど理解していないのは、郵便番号、電話番号、またはその他の文字列表現がオブジェクトそのものになる可能性があることです。

public class ZipCode {
    private string _zipCode;
    public bool Validates() {
      // validation logic for _zipCode
    }
}

public class PhoneNumber {
    private string _phoneNumber;
    public bool Validates() {
      // validation logic for _phoneNumber
    }
}

直接「文字列を処理する」べきではないという概念は、このブログ投稿で@codemonkeyismによって詳しく説明されていますが、ユーティリティクラスにロジックを入れて文字列を使用する方法のため、結束と密接に関連しています。


ORMがカスタムZipCodeクラスとPhoneNumberクラスを適切に処理できるようになった場合のみ:
ピート14

良い例を+1。最後の点については、sourcemaking.com
refactoring /

:あなたは、文字列から、あなたの定義型(郵便番号、のPhoneNumber)に変換演算子を提供する場合あなたのORMはそれを処理する@Pete msdn.microsoft.com/en-us/library/85w54y0a.aspx
マーカス

9

高い凝集力とは、コンテンツ、機能、理由、または目標を共有するパーツを結合または融合するために、類似した関連するものをまとめて保持することを意味します。言い換えれば、低い凝集度とは、たとえば、「ポイントに」ではなく、複数の目的に役立つ機能/クラス/コードエンティティを意味します。持ち運びのアイデアの1つは 1つのことをしてそれをうまくやることです。その他には、多くの場所で同様の機能を複製しないという明らかな事実を含めることができます。これにより、局所性も向上しますにより、コードベースの。特定の種類のものは、散らばるのではなく、特定の場所(ファイル、クラス、関数のセットなど)で見つかります。

例として、2つまたは3つの目的を果たすクラスを考えます。リソース(ファイルなど)をロード/保存し、コンテンツを分析して表示します。そのようなクラスは低い、少なくとも管理するため、凝集度なります。まったく関係のない 2つの個別のタスク(ファイルI / O、分析、表示)をなります。凝集度の高い設計では、リソースのロードと保存、分析、表示に個別のクラスを使用できます。

一方、低カップリングは、明確なものを分離することを目的としているため、相互作用をできる限り少なくして、複雑さを軽減し、設計を簡素化します。


7

これは、特定のオブジェクトの部分がオブジェクトの機能に密接に関連していることを意味します。これは、機能または責任の面でオブジェクト内の無駄がほとんどまたはまったくないことを意味します。これにより、問題のオブジェクトの使用目的の理解が向上します。


オブジェクトよりも高いレベルにも適用されませんか?たとえば、名前空間内のタスクに関連するオブジェクト/関数をグループ化しますか?
stijn
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.