it-swarm.com.de

Was bedeutet "hoher Zusammenhalt"?

Ich bin ein Student, der kürzlich als Praktikant in eine Softwareentwicklungsfirma eingetreten ist. Zurück an der Universität pflegte einer meiner Professoren zu sagen, dass wir uns bemühen müssen, "niedrige Kopplung und hohe Kohäsion" zu erreichen.

Ich verstehe die Bedeutung von niedriger Kopplung. Es bedeutet, den Code einzelner Komponenten separat aufzubewahren, damit eine Änderung an einer Stelle den Code an einer anderen Stelle nicht beschädigt.

Aber was ist mit hohem Zusammenhalt gemeint? Wenn es bedeutet, die verschiedenen Teile derselben Komponente gut miteinander zu integrieren, verstehe ich nicht, wie vorteilhaft dies wird.

Was ist mit hohem Zusammenhalt gemeint? Kann ein Beispiel erklärt werden, um seine Vorteile zu verstehen?

28
Max

Eine Möglichkeit, die Kohäsion in Bezug auf OO] zu betrachten, besteht darin, dass die Methoden in der Klasse eines der privaten Attribute verwenden. Verwenden Sie Metriken wie LCOM4 (Mangel an kohäsiven Methoden), wie von gnat in diese Antwort hier können Sie Klassen identifizieren, die umgestaltet werden könnten. Der Grund, warum Sie Methoden oder Klassen umgestalten möchten, um kohärenter zu sein, ist, dass sie den Code erstellen Das Design ist für andere einfacher zu verwenden . Vertrauen Sie mir, die meisten technischen Leiter und Wartungsprogrammierer werden Sie lieben, wenn Sie diese Probleme beheben.

Sie können in Ihrem Erstellungsprozess Tools wie Sonar verwenden, um eine geringe Kohäsion in der Codebasis zu identifizieren. Es gibt einige sehr häufige Fälle, in denen ich mir vorstellen kann, dass die Methoden in "Kohäsivität" niedrig sind:

Fall 1: Die Methode ist überhaupt nicht mit der Klasse verbunden

Betrachten Sie das folgende Beispiel:

public class Food {
   private int _foodValue = 10;

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

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

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

Einer der Methoden, Discharge(), fehlt der Zusammenhalt, da sie keines der privaten Mitglieder der Klasse berührt. In diesem Fall gibt es nur ein privates Mitglied: _foodValue. Wenn es mit den Klasseneinbauten nichts zu tun hat, gehört es dann wirklich dorthin? Die Methode könnte in eine andere Klasse verschoben werden, die beispielsweise .FoodDischarger heißen könnte.

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

Da Sie dies in Javascript tun, kann die Entladung eine freie Funktion sein, da Funktionen erstklassige Objekte sind:

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

Fall 2: Gebrauchsklasse

Dies ist tatsächlich ein häufiger Fall, der den Zusammenhalt bricht. Jeder liebt Utility-Klassen, aber diese weisen normalerweise auf Designfehler hin und machen die Pflege der Codebasis meistens schwieriger (aufgrund der hohen Abhängigkeit, die mit Utility-Klassen verbunden ist). Betrachten Sie die folgenden Klassen:

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;
    }

}

Hier sehen wir, dass die Utility-Klasse auf eine Eigenschaft in der Klasse Food zugreifen muss. Die Methoden in der Utility-Klasse haben in diesem Fall überhaupt keinen Zusammenhalt, da sie externe Ressourcen benötigen, um ihre Arbeit zu erledigen. Wäre es in diesem Fall nicht besser, die Methoden in der Klasse zu haben, mit der sie selbst arbeiten (ähnlich wie im ersten Fall)?

Fall 2b: Versteckte Objekte in Dienstprogrammklassen

Es gibt einen anderen Fall von Dienstprogrammklassen, in denen nicht realisierte Domänenobjekte vorhanden sind. Die erste Reaktion eines Programmierers beim Programmieren der String-Manipulation besteht darin, eine Utility-Klasse dafür zu schreiben. Wie die hier, die einige gängige Zeichenfolgendarstellungen validiert:

public static class StringUtils {

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

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

}

Was die meisten hier nicht erkennen, ist, dass eine Postleitzahl, eine Telefonnummer oder eine andere Zeichenfolgendarstellung selbst ein Objekt sein kann:

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
    }
}

Die Vorstellung, dass Sie Strings nicht direkt "behandeln" sollten, wird in dieser Blogpost von @codemonkeyism beschrieben, hängt jedoch eng mit dem Zusammenhalt zusammen, da Programmierer Strings verwenden, indem sie Logik in Dienstprogrammklassen einfügen.

26
Spoike

Hoher Zusammenhalt bedeutet, ähnliche und verwandte Dinge zusammenzuhalten, Teile zu koppeln oder zu verschmelzen, die Inhalt, Funktionalität, Grund oder Ziel gemeinsam haben. Mit anderen Worten, eine geringe Kohäsion könnte beispielsweise eine Funktion/Klasse/Code-Entität bedeuten, die mehreren Zwecken dient, anstatt "auf den Punkt" zu sein. Eine der tragenden Ideen ist mache eine Sache und mache es gut. Andere könnten die offensichtliche Tatsache beinhalten, dass Sie ähnliche Funktionen an vielen Stellen nicht replizieren. Dies verbessert auch Lokalität der Codebasis, bestimmte Arten von Dingen befinden sich an einem bestimmten Ort (Datei, Klasse, Funktionssatz, ...), anstatt verstreut zu sein.

Stellen Sie sich als Beispiel eine Klasse vor, die zwei oder drei Zwecken dient: Lädt/speichert Ressourcen (z. B. eine Datei) und analysiert und zeigt den Inhalt an. Eine solche Klasse hat niedrig Zusammenhalt, weil sie mindestens zwei separate Aufgaben verwaltet, die überhaupt nicht miteinander verbunden sind (Datei-E/A, Analyse und Anzeige). Bei einem Entwurf mit hoher Kohäsion können unterschiedliche Klassen zum Laden und Speichern der Ressource, zum Analysieren und anschließenden Anzeigen verwendet werden.

Andererseits zielt eine niedrige Kopplung darauf ab, unterschiedliche Dinge getrennt zu halten - damit sie so wenig wie möglich miteinander interagieren, was dann die Komplexität verringert und das Design vereinfacht.

9
zxcdw

Dies bedeutet, dass die Teile eines bestimmten Objekts eng mit der Funktion des Objekts verbunden sind. Dies bedeutet, dass das Objekt in Bezug auf Funktion oder Verantwortung nur sehr wenig oder gar keinen Abfall enthält. Dies kann wiederum das Verständnis dafür verbessern, wofür das betreffende Objekt verwendet werden soll.

7
World Engineer