Jag är en student som nyligen gick med i ett mjukvaruutvecklingsföretag som praktikant. Tillbaka på universitetet brukade en av mina professorer säga att vi måste sträva efter att uppnå ”Låg koppling och hög sammanhållning”.
Jag förstår innebörden av låg koppling. Det betyder att hålla koden för separata komponenter separat så att en förändring på ett ställe inte bryter koden på en annan.
Men vad menas med hög sammanhållning. Om det innebär att integrera de olika delarna av samma komponent väl med varandra, förstår jag inte hur det blir fördelaktigt.
Vad menas med hög sammanhållning? Kan ett exempel förklaras för att förstå fördelarna?
Kommentarer
- möjlig duplikat av Finns det Mätvärden för sammanhållning och koppling?
- Svarar inte Wikipedia-artikeln tillräckligt på din fråga? sv.wikipedia.org/wiki/Cohesion_(computer_science)
- Det finns en bra artikel om detta på: msdn.microsoft.com/en-us/magazine/cc947917.aspx
- @EoinCarroll: Tyvärr ger Wikipedia-artikeln för närvarande inte något bra konkreta exempel som nya programmerare kan arbeta med. Teorin är bra och allt, men fastnar inte ' tills du ' har gjort misstagen kring låg sammanhållning. Hög sammanhållning är ett av de ämnen som har tagit mig flera år av programmering för att förstå varför det är viktigt och hur att uppnå det.
- Jag förstod aldrig sammanhållningen förrän jag läste Ren kod. Du borde också göra det.
Svar
Ett sätt att titta på sammanhållning i termer av OO är om metoderna i klassen använder någon av de privata attributen. Med hjälp av mått som LCOM4 (Brist på sammanhängande metoder), som påpekas av gnat i detta svar här , kan du identifiera klasser som kan omformas. Anledningen till att du vill omforma metoder eller klasser för att vara mer sammanhängande är att det gör koddesignen enklare för andra att använda den . Lita på mig; de flesta tekniska leads och underhållsprogrammerare kommer att älska dig när du åtgärdar dessa problem.
Du kan använda verktyg i din byggprocess som Sonar för att identifiera låg sammanhållning i kodbasen. Det finns ett par mycket vanliga fall som jag kan tänka på där metoderna är låga i ”sammanhållning” :
Fall 1: Metoden är inte relaterad till klassen alls
Tänk på följande exempel:
public class Food { private int _foodValue = 10; public void Eat() { _foodValue -= 1; } public void Replenish() { _foodValue += 1; } public void Discharge() { Console.WriteLine("Nnngghhh!"); } }
En av metoderna , Discharge()
, saknar sammanhållning eftersom den inte rör någon av klassens privata medlemmar. I det här fallet finns det bara en privat medlem: _foodValue
. Om det inte gör något med klassinterna, hör det verkligen där? Metoden kan flyttas till en annan klass som skulle kunna heter t.ex. FoodDischarger
.
// Non-cohesive function extracted to another class, which can // be potentially reused in other contexts public FoodDischarger { public void Discharge() { Console.WriteLine("Nnngghhh!"); } }
I dig ”gör du det i Javascript, eftersom funktioner är förstklassiga objekt, urladdningen kan vara en fri funktion:
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: Utility Class
Detta är faktiskt ett vanligt fall som bryter sammanhållningen. Alla älskar verktygsklasser, men dessa indikerar vanligtvis designfel och för det mesta gör kodbasen svårare att upprätthålla (på grund av det höga beroendet i samband med verktygsklasser). Tänk på följande klasser:
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; } }
Här kan vi se att verktygsklassen behöver för att komma åt en egendom i klassen Food
. Metoderna i verktygsklassen har ingen sammanhållning alls i det här fallet eftersom det behöver externa resurser för att göra det. I det här fallet skulle det inte vara bättre att ha metoderna i den klass de arbetar med sig själv ( ungefär som i det första fallet)?
Fall 2b: Dolda föremål i verktygsklasser
Det finns ett annat fall av verktygsklasser där det finns orealiserade domänobjekt. en programmerare har när programmering av strängmanipulation är att skriva en verktygsklass för den.Som den här som validerar ett par vanliga strängrepresentationer:
public static class StringUtils { public static bool ValidateZipCode(string zipcode) { // validation logic } public static bool ValidatePhoneNumber(string phoneNumber) { // validation logic } }
Vad de flesta inser inte här att ett postnummer, ett telefonnummer eller någon annan strängrepresentation kan vara ett objekt i sig:
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 } }
Uppfattningen att du inte” ska ”hantera strängar” beskrivs i detta blogginlägg av @codemonkeyism , men är nära relaterat till sammanhållning eftersom sättet som programmerare använder strängar genom att lägga logik i verktygsklasser.
Kommentarer
- Nu om vi bara kunde få våra ORM för att hantera våra anpassade ZipCode- och PhoneNumber-klasser ordentligt: |
- +1 bra exempel. För den sista punkten, se även sourcemaking.com/refactoring/primitive-obsession
- @Pete Din ORM hanterar det om du ger konvertering operatörer från sträng till din definierade typ (ZipCode, PhoneNumber): msdn.microsoft.com/en-us/library/85w54y0a.aspx
Svar
Hög sammanhållning betyder att hålla liknande och relaterade saker tillsammans, att koppla ihop eller smälta delar som delar innehåll, funktionalitet, anledning eller mål . Med andra ord kan låg sammanhållning till exempel betyda en funktion / klass / kodenhet som tjänar flera syften snarare än att vara ” till punkten ”. En av de bärande idéerna är att göra en sak och göra det bra . Andra kan inkludera det uppenbara faktum att du inte replikerar liknande funktioner på många ställen. Detta förbättrar också lokalitet för kodbasen, vissa typer av saker finns på en viss plats (fil, klass, uppsättning av funktioner, …) snarare än att vara utspridda.
Tänk som exempel på en klass som tjänar två eller tre syften: Läser in / lagrar resurser (till exempel en fil) och analyserar och visar sedan Innehåll. En sådan klass har låg sammanhållning eftersom den hanterar minst två separata uppgifter som inte är relaterade alls (fil I / O, analys och visning). En hög sammanhållningsdesign kan använda olika klasser för att ladda och lagra resursen, analysera den och sedan visa den.
Å andra sidan syftar låg koppling till att hålla åtskilda saker åtskilda – så att de interagerar med varandra så lite som möjligt vilket sedan minskar komplexiteten och förenklar designen.
Svar
Det betyder att delarna av ett objekt är nära relaterade till objektets funktion. Detta innebär att det finns mycket lite eller inget avfall inom objektet när det gäller funktion eller ansvar. Detta kan i sin tur förbättra förståelsen för vad objektet i fråga ska användas till.
Kommentarer
- inte ' t gäller det också en högre nivå än bara objekt? t.ex. gruppera objekt / funktioner relaterade till en uppgift i namnområden?