Jeg er student som nylig begynte i et programvareutviklingsselskap som praktikant. Tilbake på universitetet pleide en av professorene mine å si at vi må streve for å oppnå «Lav kobling og høy kohesjon».
Jeg forstår betydningen av lav kobling. Det betyr å holde koden til separate komponenter separat, slik at en endring på et sted ikke bryter koden på et annet.
Men hva menes med høy kohesjon. Hvis det betyr å integrere de forskjellige delene av den samme komponenten godt med hverandre, forstår jeg ikke hvordan det blir fordelaktig.
Hva menes med høy kohesjon? Kan et eksempel forklares for å forstå fordelene?
Kommentarer
- mulig duplikat av Finnes det Metrics For Cohesion And Coupling?
- Svarer ikke Wikipedia-artikkelen tilstrekkelig på spørsmålet ditt? no.wikipedia.org/wiki/Cohesion_(computer_science)
- Det er en god artikkel om dette på: msdn.microsoft.com/en-us/magazine/cc947917.aspx
- @EoinCarroll: Dessverre gir ikke Wikipedia-artikkelen for øyeblikket noe godt konkrete eksempler som nye programmerere kan jobbe med. Teorien er bra og alt, men holder ikke ' til du ' har gjort feilene rundt lav samhørighet. Høy kohesjon er et av de emnene som har tatt meg flere år med programmering for å forstå fullt ut hvorfor det er viktig og hvordan å oppnå det.
- Jeg forstod egentlig ikke kohesjon før jeg leste Ren kode. Du burde også gjøre det.
Svar
En måte å se på kohesjon i forhold til OO er hvis metodene i klassen bruker noen av de private attributtene. Ved å bruke beregninger som LCOM4 (Mangel på sammenhengende metoder), som påpekt av gnat i dette svaret her , kan du identifisere klasser som kan omformeres. Årsaken til at du vil refaktorere metoder eller klasser for å være mer sammenhengende er at det gjør kodedesign enklere for andre å bruke det . Stol på meg; de fleste tekniske potensielle kunder og vedlikeholdsprogrammerere vil elske deg når du løser disse problemene.
Du kan bruke verktøy i byggeprosessen din, for eksempel Ekkolodd til identifisere lav kohesjon i kodebasen. Det er et par veldig vanlige tilfeller som jeg kan tenke på hvor metodene har lite «sammenheng» :
Sak 1: Metoden er ikke relatert til klassen i det hele tatt
Vurder følgende eksempel:
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 metodene , Discharge()
, mangler sammenheng, fordi den ikke berører noen av klassens private medlemmer. I dette tilfellet er det bare ett privat medlem: _foodValue
. Hvis det ikke gjør noe med klassen internt, så hører det virkelig til der? Metoden kan flyttes til en annen klasse som kan bli kalt f.eks. 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 deg «gjør du det i Javascript, siden funksjoner er førsteklasses objekter, utladningen kan være en gratis funksjon:
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
Sak 2: Utility Class
Dette er faktisk en vanlig sak som bryter sammenhold. Alle elsker bruksklasser, men disse indikerer vanligvis designfeil, og det meste gjør kodebasen vanskeligere å opprettholde (på grunn av den høye avhengigheten forbundet med nytteklasser). Tenk på følgende 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; } }
Her kan vi se at verktøyklassen trenger for å få tilgang til en eiendom i klassen Food
. Metodene i nytteklassen har ingen sammenheng i dette tilfellet fordi det trenger eksterne ressurser for å gjøre det. I dette tilfellet ville det ikke være bedre å ha metodene i klassen de jobber med seg selv ( omtrent som i det første tilfellet)?
Tilfelle 2b: Skjulte objekter i verktøyklasser
Det er et annet tilfelle av nytteklasser der det er urealiserte domeneobjekter. Den første kneppet reaksjonen en programmerer har når programmering av strengmanipulering er å skrive en verktøyklasse for den.Som den her som validerer et par vanlige strengrepresentasjoner:
public static class StringUtils { public static bool ValidateZipCode(string zipcode) { // validation logic } public static bool ValidatePhoneNumber(string phoneNumber) { // validation logic } }
Hva de fleste vet ikke her at et postnummer, et telefonnummer eller en hvilken som helst annen strengrepresentasjon kan være et objekt i seg selv:
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 } }
Forestillingen om at du ikke» skal «håndtere strenger» er detaljert i dette blogginnlegget av @codemonkeyism , men er nært beslektet med samhørighet fordi måten programmerere bruker strenger ved å legge logikk i verktøyklasser.
Kommentarer
- Nå hvis vi bare kunne få våre ORMer for å håndtere våre tilpassede ZipCode- og PhoneNumber-klasser riktig: |
- +1 gode eksempler. For det siste punktet, se også sourcemaking.com/refactoring/primitive-obsession
- @Pete Din ORM vil håndtere det hvis du gir konvertering operatører fra streng til din definerte type (ZipCode, PhoneNumber): msdn.microsoft.com/en-us/library/85w54y0a.aspx
Svar
Høy kohesjon betyr å holde lignende og relaterte ting sammen, for å koble sammen eller smelte deler som deler innhold, funksjonalitet, grunn eller mål . Med andre ord kan lav kohesjon for eksempel bety en funksjon / klasse / kodeenhet som tjener flere formål i stedet for å være « til poenget «. En av de bærende ideene er å gjøre en ting og gjøre det bra . Andre kan inkludere det åpenbare faktum at du ikke replikerer lignende funksjonalitet mange steder. Dette forbedrer også lokalitet av kodebasen, visse typer ting finnes på et bestemt sted (fil, klasse, sett av funksjoner, …) i stedet for å være spredt rundt.
Som et eksempel kan du vurdere en klasse som tjener to eller tre formål: Laster inn / lagrer ressurser (for eksempel en fil) og analyserer og viser deretter innhold. En slik klasse har lav kohesjon fordi den administrerer minst to separate oppgaver som ikke er relatert i det hele tatt (fil I / O, analyse og visning). Et design med høy kohesjon kan bruke forskjellige klasser for å laste og lagre ressursen, analysere den og deretter vise den. så lite som mulig som deretter reduserer kompleksiteten og forenkler designet.
Svar
Det betyr at delene av et objekt er nært knyttet til objektets funksjon. Dette betyr at det er veldig lite eller ingen avfall innenfor objektet når det gjelder funksjon eller ansvar. Dette kan igjen forbedre forståelsen av hva det aktuelle objektet skal brukes til.
Kommentarer
- ikke ' t gjelder det også et høyere nivå enn bare objekter? for eksempel å gruppere objekter / funksjoner relatert til en oppgave i navnerom?