Indpak kode

Den aktuelle version af siden er endnu ikke blevet gennemgået af erfarne bidragydere og kan afvige væsentligt fra den version , der blev gennemgået den 17. februar 2021; checks kræver 7 redigeringer .

Lugtkode ( lugtkode , ildelugtende kode engelsk kode lugt ) er en betegnelse for kode med tegn (lugte) på problemer i systemet. Det blev introduceret af Kent Beck [1] og brugt af Martin Fowler i sin bog Refactoring. Forbedring af eksisterende kode [1] .  

Kodelugte  er nøgletegn på behovet for refaktorisering [2] . Der er lugte, der er specifikke for både programmeringsparadigmer og specifikke sprog . Det største problem, som udviklere står over for, når de beskæftiger sig med kodelugte, er, at kriterierne for aktualitet af refactoring ikke kan formaliseres klart uden at appellere til æstetik og en konventionel skønhedssans. Kodelugte er ikke et sæt klare regler, men en beskrivelse af steder, som du skal være opmærksom på ved refactoring [3] . De er lette at opdage, men indikerer ikke i alle tilfælde problemer [1] .

Lugtekode fører til kodebrud, udviklere bør stræbe efter at eliminere lugte ved at anvende enkelte eller flere refactorings [4] . Processen med refactoring fjerner kodelugte, hvilket gør det muligt for applikationen at fortsætte med at udvikle sig med samme eller højere hastighed. Mangel på regelmæssig refactoring kan fuldstændig lamme et projekt over tid, så kodelugte skal elimineres tidligt [2] . Der findes værktøjer til at finde og rette kodelugte [5] , men erfaringen viser, at intet scorekort kan konkurrere med informationsbaseret menneskelig intuition [6] .

Kode lugter

Generelt lugter af objektorienteret kode

Kode duplikering

Kodeduplikering er brugen af ​​de samme kodestrukturer flere steder. Kombination af disse strukturer vil forbedre programkoden [6] .

Eksempler på duplikering og metoder til deres eliminering:

  • Det samme udtryk er til stede i to metoder af samme klasse: du skal anvende "Extract Method" og kalde koden for den oprettede metode fra begge punkter;
  • Det samme udtryk findes i to underklasser på samme niveau: du skal anvende Extract Method på begge klasser efterfulgt af Pull Up Field eller Form Template Method , hvis koden er ens, men ikke helt den samme. Hvis begge metoder gør det samme ved at bruge forskellige algoritmer, kan du vælge den klareste af disse algoritmer og anvende "Substitution Algorithm" (Substitution Algorithm);
  • Duplikatkoden er i to forskellige klasser: du skal anvende Extract Class i én klasse og derefter bruge den nye komponent i en anden [6] .
Lang metode

Blandt objektprogrammer lever programmer med korte metoder længst . Jo længere proceduren er, jo sværere er den at forstå. Hvis metoden har et godt navn, så behøver du ikke se på dens krop [3] .

En heuristik bør følges: hvis du føler behov for at kommentere noget, skal du skrive en metode. Det giver mening at adskille blot en linje i en metode, hvis den har brug for afklaring [7] .

  • For at reducere metoden er det nok at anvende ekstraktmetoden;
  • Hvis lokale variabler og parametre forhindrer metodeudtræk, kan du bruge Replace Temp with Query, Introduce Parameter Object og Preserve Whole Object [3] ;
  • Betingede udsagn og loops angiver muligheden for at adskille i en separat metode. Decompose Conditional er velegnet til at arbejde med betingede udtryk. At arbejde med cyklussen - "Extract Method" (Extract Method) [7] .
Stor klasse

Når en klasse implementerer for meget funktionalitet, kan du overveje at underklassificere noget af koden. Dette vil spare udviklere fra et for stort antal attributter, som en klasse har, og duplikerende kode [7] .

  • For at reducere en klasse skal du bruge Extract Class eller Extract Subclass. Samtidig bør man være opmærksom på fællesheden i navnene på attributterne og på, om klassen bruger dem alle på samme tid [3] ;
  • Hvis den store klasse er en GUI -klasse , vil du måske flytte dens data og adfærd til et separat domæneobjekt. Det kan dog være nødvendigt at gemme kopier af nogle data to steder og sikre deres konsistens. Duplicate Observed Data foreslår en måde, hvorpå dette kan gøres [8] .
Lang liste over muligheder

Lange parameterlister er svære at forstå, inkonsekvente og svære at bruge. Brugen af ​​objekter tillader, i tilfælde af ændringer i de transmitterede data, kun at ændre selve objektet. Når du arbejder med objekter, bør du bestå lige nok til, at metoden kan få de data, den skal bruge [8] .

  • "Erstat parameter med metode" bruges, når du kan få data ved at kalde en metode på et objekt. Dette objekt kan være et felt eller en anden parameter.
  • Bevar hele objektet giver dig mulighed for at tage en gruppe data modtaget fra et objekt og erstatte det med selve objektet.
  • "Introducer Parameter Object" bruges, hvis der er flere dataelementer uden et logisk objekt [8] .
Afvigende ændringer

Problemet opstår, når det ved ændring af systemet er umuligt at tildele et bestemt sted, der skal ændres. Dette er en konsekvens af dårlig softwarestruktur [8] eller copy-paste programmering .

  • Hvis sættet af metoder skal ændres, hver gang der foretages visse ændringer af koden, anvendes Extract Class (for eksempel ændres tre metoder hver gang en ny database tilsluttes , og fire, når et finansielt instrument tilføjes) [3 ] .
Haglgeværskydning

Enhver ændring involverer mange små ændringer i et stort antal klasser. Haglgevær ligner Divergent Modification, men er det modsatte. En divergerende modifikation opstår, når der er én klasse, der laver mange forskellige ændringer, mens Shotgun er én ændring, der påvirker mange klasser [9] .

  • Flyt alle ændringer til én klasse vil tillade "Move Method" (Move Method) og "Move Field" (Move Field);
  • Hvis der ikke er en passende klasse, skal der oprettes en ny klasse;
  • Brug om nødvendigt Inline Class [3] .
Misundelsesfunktioner

Metoden tilgår et andet objekts data oftere end dets egne data [3] .

  • "Flytmetode" bruges, hvis metoden eksplicit skal flyttes til et andet sted;
  • Uddrag Metode gælder kun for en metodedel, hvis denne del får adgang til et andet objekts data;
  • Metoden bruger funktionerne i flere klasser: det bestemmes hvilken klasse der indeholder flest data, og metoden placeres i klassen sammen med disse data, eller ved hjælp af Extract Method opdeles metoden i flere dele og de placeres i forskellige steder [10] .

En grundlæggende tommelfingerregel er, at ting, der ændrer sig på samme tid, skal opbevares ét sted. Dataene og funktionerne, der bruger disse data, ændres normalt sammen, men der er undtagelser [10] .

Datagrupper

Grupper af data, der forekommer sammen, bør omdannes til en separat klasse [10] .

  • "Extract Method" bruges til felter;
  • "Introducer Parameter Object" eller "Preserve Whole Object" for metodeparametre [11] .

En god test er at fjerne en af ​​dataværdierne og se, om de andre stadig giver mening. Hvis ikke, er det et sikkert tegn på, at dataene beder om at blive flettet ind i et objekt [10] .

Besættelse af elementære typer

Problemet er relateret til brugen af ​​elementære typer i stedet for små objekter til små opgaver, såsom valuta, intervaller, specielle strenge til telefonnumre mv.

  • "Erstat dataværdi med objekt";
  • "Erstatning af et array med et objekt" (Erstat array med objekt);
  • Hvis det er en typekode, så brug Erstat typekode med klasse, Erstat typekode med underklasser eller Erstat typekode med tilstand/strategi) [3] .
switch statements

Et indlysende kendetegn ved objektorienteret kode er den relativt sjældne brug af switch- (eller case)-sætninger . Ofte ender den samme omskifterblok spredt forskellige steder i programmet. Når du tilføjer en ny mulighed, skal du kigge efter alle disse switch-blokke og ændre dem. Som regel, når du bemærker en omskifterblok, bør du tænke på polymorfi [12] .

  • Hvis switchen skifter efter typekode, skal du bruge "Erstat typekode med underklasser" eller "Erstat typekode med tilstand/strategi";
  • Du skal muligvis "Extract Method" og "Move Method" for at isolere switchen og placere den i den rigtige klasse;
  • Efter opsætning af arvestrukturen skal du bruge Erstat betinget med polymorfi [3] .
Parallelle arvehierarkier

I kode med denne lugt, hver gang du underklasser en af ​​klasserne, skal du oprette en underklasse af en anden klasse [12] .

  • En almindelig deduplikeringsstrategi er at få forekomster af et hierarki til at henvise til forekomster af et andet hierarki, og derefter fjerne hierarkiet i den henvisende klasse ved hjælp af Flytmetode og Flytfelt [12] .
Dovne klasse

En klasse, hvis eksistensomkostninger ikke er dækket af de funktioner, den udfører, bør elimineres [12] .

  • Hvis der er underklasser med utilstrækkelig funktionalitet, prøv Collapse Hierarchy;
  • Næsten ubrugelige komponenter bør underkastes Inline Class [12] .
Teoretisk almenhed

Dette tilfælde opstår, når der på et eller andet tidspunkt i et programs levetid leveres et sæt mekanismer, som en fremtidig funktionalitet kan have behov for. Som følge heraf bliver programmet sværere at forstå og vedligeholde [13] .

  • For ubrugte abstrakte klasser, brug Collapse Hierarchy;
  • Unødvendig delegering kan fjernes ved hjælp af Inline Class;
  • Metoder med ubrugte parametre skal underkastes en "Fjern parameter" [3] .
Tidsfelt

Midlertidige felter er felter, som et objekt kun har brug for under visse omstændigheder. Denne tilstand er svær at forstå, da en genstand forventes at have brug for alle dens felter [14] .

  • Midlertidige felter og al kode, der arbejder med dem, skal placeres i en separat klasse ved hjælp af Extract Class;
  • Du kan fjerne betinget eksekverbar kode ved at bruge Introduce Null Object for at oprette en alternativ komponent [13] .
Opkaldskæde

En kæde af kald opstår, når en klient anmoder om et andet objekt fra et objekt, et andet objekt anmoder om et andet objekt osv. Sådanne kaldssekvenser betyder, at klienten er forbundet med at navigere i klassestrukturen. Enhver ændring af de mellemliggende links betyder behovet for at ændre klienten [13] .

  • For at fjerne kæden af ​​opkald, bruges Hide Delegate-teknikken [13] .
Mellemmand

Overdreven brug af delegering kan føre til klasser, hvor de fleste af metoderne kun består i at kalde en metode af en anden klasse [13] .

  • Hvis en klasse uddelegerer de fleste af metoderne til en anden klasse, skal du bruge "Remove Middle Man" [15] .
Misplaceret nærhed

"Misplaceret nærhed" opstår, når klasser er oftere, end de burde være nedsænket i lukkede dele af hinanden [15] .

  • Du kan slippe af med "Upassende nærhed" ved at bruge "Flytmetode" (Flytmetode) og "Flyt felt" (Flyt felt);
  • Hvis det er muligt, bør du ty til "Change Todirectional Association to Unidirectional", "Extract Class" eller brug "Hide Delegate" [15] .
Alternative klasser med forskellige grænseflader

To klasser, hvor en del af funktionaliteten er fælles, men metoderne, der implementerer den, har forskellige parametre [16] .

  • Anvend "Omdøb metode" på alle metoder, der udfører de samme handlinger, men som adskiller sig i signaturer [15] .
Bibliotekets ufuldstændighed

Biblioteker holder op med at opfylde brugernes krav efter et stykke tid. Den naturlige løsning er at ændre nogle ting i bibliotekerne, men ikke at ændre biblioteksklasserne. Du bør bruge refactoring-metoder, der er specielt designet til dette formål [16] .

  • Hvis du skal tilføje et par metoder, så brug "Introducer udenlandsk metode";
  • Hvis du seriøst har brug for at ændre klassens adfærd, skal du bruge "Introducer Local Extension" (Introducer Local Extension) [16] .
Dataklasser

Dataklasser er klasser, der kun indeholder felter og metoder til at få adgang til dem, de er simpelthen containere for data, der bruges af andre klasser [16] .

  • Anvend Encapsulate Field og Encapsulate Collection [3] .
Afkald på arv

Hvis barnet kun bruger en lille del af forælderens nedarvede metoder og egenskaber, er det tegn på et dårligt hierarki.

  • Du skal oprette en ny klasse på samme niveau som barnet og bruge Push Down Method og Push Down Field til at skubbe alle inaktive metoder ind i den. Dette sikrer, at den overordnede klasse kun indeholder det, der deles [17] .
Kommentarer

Ofte spiller kommentarer rollen som en "deodorant" af kode, som kun vises i den, fordi koden er dårlig. Når du føler behov for at skrive en kommentar, så prøv at omstrukturere din kode, så eventuelle kommentarer bliver overflødige [17] .

  • Hvis du stadig har brug for en kommentar til at forklare blokkens handlinger, så prøv at bruge udtræksmetoden;
  • Hvis en metode allerede er fremhævet, men du stadig har brug for en kommentar for at forklare dens funktion, skal du bruge Rename Method;
  • Hvis du vil angive nogle regler om den påkrævede tilstand af systemet, skal du bruge Introducer Assertion [17] .

Se også

  • Antimønster
  • Kategori:Programmeringsprincipper
  • Værktøjer til statisk kodeanalyse

Noter

  1. 1 2 3 Martin, 1999 .
  2. 1 2 Kraftig Hive_CodeSmell .
  3. 1 2 3 4 5 6 7 8 9 10 11 Ildelugtende kode .
  4. Counsell_Code Smells, 2010 .
  5. devconf .
  6. 1 2 3 Martin Fowler_Refactoring, 2003 , s. 54.
  7. 1 2 3 Martin Fowler_Refactoring, 2003 , s. 55.
  8. 1 2 3 4 Martin Fowler_Refactoring, 2003 , s. 56.
  9. Martin Fowler_Refactoring, 2003 , s. 56-57.
  10. 1 2 3 4 Martin Fowler_Refactoring, 2003 , s. 57.
  11. Ildelugtende kode , s. 57.
  12. 1 2 3 4 5 Martin Fowler_Refactoring, 2003 , s. 58.
  13. 1 2 3 4 5 Martin Fowler_Refactoring, 2003 , s. 59.
  14. Midlertidigt felt .
  15. 1 2 3 4 Martin Fowler_Refactoring, 2003 , s. 60.
  16. 1 2 3 4 Kode refactoring .
  17. 1 2 3 Martin Fowler_Refactoring, 2003 , s. 61.

Litteratur

  • Fowler, M. Kapitel 3. Ildelugtende kode // Refactoring. Forbedring af eksisterende kode = Refactoring: Forbedring af design af eksisterende kode / Pr. fra engelsk. S. Makkaveeva. - 1. udg. - Sankt Petersborg. : Symbol-Plus, 2003. - S. 54-62. - 432 s. — ISBN 5-93286-045-6 .

Links

  • CodeSmell  (engelsk) . Martinfowler.com. Hentet: 13. oktober 2013.
  • Code Smell  (engelsk) . Cunningham & Cunningham Inc. (c2.com). Hentet: 23. november 2013.