Ich bin ein Student, der kürzlich als Praktikant in eine Softwareentwicklungsfirma eingetreten ist. Zurück an der Universität sagte einer meiner Professoren, 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 hoher Kohäsion gemeint? Wenn es bedeutet, die verschiedenen Teile derselben Komponente gut miteinander zu integrieren, verstehe ich nicht, wie das vorteilhaft wird.
Was ist mit hoher Kohäsion gemeint? Kann ein Beispiel erklärt werden, um seine Vorteile zu verstehen?
Kommentare
- mögliches Duplikat von Gibt es Metriken für Kohäsion und Kopplung?
- Beantwortet der Wikipedia-Artikel Ihre Frage nicht ausreichend? en.wikipedia.org/wiki/Cohesion_(computer_science)
- Es gibt einen guten Artikel dazu unter: msdn.microsoft.com/en-us/magazine/cc947917.aspx
- @EoinCarroll: Leider gibt der Wikipedia-Artikel im Moment nichts Gutes konkrete Beispiele , mit denen neue Programmierer arbeiten können. Die Theorie ist gut und alles, aber ' bleibt nicht wirklich bestehen, bis Sie ' die Fehler im Zusammenhang mit geringem Zusammenhalt gemacht haben. Hohe Kohäsion ist eines dieser Themen, bei denen ich mehrere Jahre lang programmiert habe, um zu verstehen, warum es wichtig ist und wie ich es erreichen kann.
- Ich habe Kohäsion erst wirklich verstanden, als ich gelesen habe Code reinigen. Das sollten Sie auch.
Antwort
Eine Möglichkeit, den Zusammenhalt in Bezug auf OO zu betrachten, besteht darin, ob die Methoden in Die Klasse verwendet eines der privaten Attribute. Mithilfe von Metriken wie LCOM4 (Mangel an kohäsiven Methoden), auf die gnat in dieser Antwort hier hingewiesen hat, können Sie Klassen identifizieren, die überarbeitet werden könnten. Der Grund, warum Sie Methoden oder Klassen so umgestalten möchten, dass sie zusammenhängender sind, ist, dass das Code-Design für andere einfacher macht, es zu verwenden . Vertrau 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 Identifizieren Sie eine geringe Kohäsion in der Codebasis. Es gibt einige sehr häufige Fälle, in denen ich mir vorstellen kann, dass Methoden eine geringe „Kohäsivität“ aufweisen :
Fall 1: Methode ist überhaupt nicht mit der Klasse verwandt
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!"); } }
Eine der Methoden , Discharge()
, fehlt der Zusammenhalt, da es 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
.
// Non-cohesive function extracted to another class, which can // be potentially reused in other contexts public FoodDischarger { public void Discharge() { Console.WriteLine("Nnngghhh!"); } }
Wenn Sie dies in Javascript tun, da Funktionen erstklassige Objekte sind, wird die Entladung kann eine freie Funktion sein:
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: Dienstprogrammklasse
Dies ist tatsächlich ein häufiger Fall, der den Zusammenhalt bricht. Jeder liebt Dienstprogrammklassen, aber diese weisen normalerweise auf Konstruktionsfehler hin und machen die Pflege der Codebasis meistens schwieriger (aufgrund der hohen Abhängigkeit, die mit Dienstprogrammklassen 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 benötigt um auf eine Eigenschaft in der Klasse Food
zuzugreifen. Die Methoden in der Utility-Klasse haben in diesem Fall überhaupt keinen Zusammenhalt, da sie externe Ressourcen benötigen, um ihre Arbeit zu erledigen. In diesem Fall wäre es 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 Knie-Ruck-Reaktion Ein Programmierer hat beim Programmieren der String-Manipulation die Aufgabe, eine Utility-Klasse dafür zu schreiben.Wie die hier, die einige gängige Zeichenfolgendarstellungen überprüft:
public static class StringUtils { public static bool ValidateZipCode(string zipcode) { // validation logic } public static bool ValidatePhoneNumber(string phoneNumber) { // validation logic } }
Was Die meisten wissen hier nicht, dass eine Postleitzahl, eine Telefonnummer oder eine andere Zeichenfolgendarstellung ein Objekt selbst 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 nicht direkt mit Zeichenfolgen umgehen sollten, wird in diesem Blogpost von @codemonkeyism beschrieben. Dies hängt jedoch eng mit der Kohäsion zusammen, da Programmierer Zeichenfolgen verwenden, indem sie Logik in Dienstprogrammklassen einfügen.
Kommentare
- Wenn wir nur unsere ORMs erhalten könnten Um unsere benutzerdefinierten ZipCode- und PhoneNumber-Klassen richtig zu handhaben: |
- +1 gute Beispiele. Für den letzten Punkt siehe auch sourcemaking.com/refactoring/primitive-obsession
- @Pete Ihr ORM wird dies behandeln, wenn Sie eine Konvertierung bereitstellen Operatoren von der Zeichenfolge bis zu Ihrem definierten Typ (Postleitzahl, Telefonnummer): msdn.microsoft.com/en-us/library/85w54y0a.aspx
Antwort
Hoher Zusammenhalt bedeutet, ähnliche und verwandte Dinge zusammenzuhalten, Teile zu koppeln oder zu verschmelzen, die Inhalt, Funktionalität, gemeinsam haben Grund oder Ziel . Mit anderen Worten, eine geringe Kohäsion könnte beispielsweise eine Funktions- / Klassen- / Code-Entität bedeuten, die mehreren Zwecken dient, anstatt „ auf den Punkt “ zu sein. Eine der tragenden Ideen ist, eine Sache zu tun und sie gut zu machen . Andere könnten die offensichtliche Tatsache beinhalten, dass Sie an vielen Stellen keine ähnlichen Funktionen replizieren. Dies verbessert auch die Lokalität der Codebasis, bestimmte Arten von Dingen werden an einem bestimmten Ort gefunden (Datei, Klasse, Menge von Funktionen, …) anstatt verstreut zu sein.
Betrachten Sie als Beispiel eine Klasse, die zwei oder drei Zwecken dient: Lädt / speichert Ressourcen (zum Beispiel eine Datei) und analysiert und zeigt dann die an Eine solche Klasse weist eine geringe Kohäsion auf, da sie mindestens zwei separate Aufgaben verwaltet, die überhaupt nicht miteinander zusammenhängen (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 miteinander interagieren so wenig wie möglich, was dann die Komplexität reduziert und das Design vereinfacht.
Antwort
Dies bedeutet, dass die Teile eines 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.
Kommentare
- nicht ' gilt das nicht auch für eine höhere Ebene als nur für Objekte? zB Gruppieren von Objekten / Funktionen, die sich auf eine Aufgabe beziehen, in Namespaces?