En introduktion til refactoring med IntelliJ IDEA

1. Oversigt

Det er ikke altid let at holde koden pæn. Heldigvis for os er vores IDE'er ret smarte i dag og kan hjælpe os med at opnå dette. I denne vejledning vil vi fokusere på IntelliJ IDEA, JetBrains Java-kodeditor.

Vi ser et par funktioner, der tilbydes af redaktøren til refaktorkode, fra omdøbning af variabler til ændring af en metodesignatur.

2. Omdøbning

2.1. Grundlæggende omdøbning

Lad os først starte med det grundlæggende: omdøbning. IntelliJ giver os muligheden for at omdøbe forskellige elementer i vores kode: typer, variabler, metoder og endda pakker.

For at omdøbe et element skal vi følge disse trin:

  • Højreklik på elementet
  • Udløs Refactor> Omdøb mulighed
  • Skriv det nye elementnavn
  • Trykke Gå ind

I øvrigt, Vi kan erstatte de to første trin ved at vælge elementet og trykke på Skift + F6.

Når den udløses, vil omdøbningshandlingen søg på tværs af koden for hver brug af elementet, og skift dem derefter med den angivne værdi.

Lad os forestille os en SimpleClass klasse med en dårligt navngivet tilføjelsesmetode, someAdditionMethod, kaldes i vigtigste metode:

public class SimpleClass {public static void main (String [] args) {new SimpleClass (). someAdditionMethod (1, 2); } public int someAdditionMethod (int a, int b) {return a + b; }}

Således, hvis vi vælger at omdøbe denne metode til tilføje, IntelliJ vil producere følgende kode:

public class SimpleClass () {public static void main (String [] args) {new SimpleClass (). tilføj (1, 2); } public int add (int a, int b) {return a + b; }}

2.2. Avanceret omdøbning

Imidlertid gør IntelliJ mere end at søge efter kodeanvendelse af vores elementer og omdøbe dem. Faktisk er der et par flere muligheder tilgængelige. IntelliJ kan også søge efter forekomster i kommentarer og strenge og endda i filer, der ikke indeholder kildekode. Med hensyn til parametre kan den omdøbe dem i klassehierarkiet i tilfælde af tilsidesatte metoder.

Disse muligheder er tilgængelige ved at trykke Skift + F6 endnu en gang før du omdøber vores element, og der vises en popup:

Det Søg i kommentarer og strenge mulighed er tilgængelig for enhver omdøbning. hvad angår Søg efter tekstforekomster mulighed, det er ikke tilgængeligt for metodeparametre og lokale variabler. Endelig blev Omdøb parametre i hierarki mulighed er kun tilgængelig for metodeparametre.

Så, hvis der findes nogen match med en af ​​disse to muligheder, viser IntelliJ dem og giver os muligheden for at fravælge nogle af ændringerne (sig, hvis det matcher noget, der ikke er relateret til vores omdøbning).

Lad os tilføje noget Javadoc til vores metode og derefter omdøbe den første parameter, -en:

/ ** * Tilføjer a og b * @param a det første nummer * @param b det andet nummer * / public int add (int a, int b) {...}

Ved at kontrollere den første mulighed i pop op-bekræftelsesvinduet matcher IntelliJ enhver omtale af parametrene i Javadoc-kommentaren til metoden og tilbyder også at omdøbe dem:

/ ** * Tilføjer firstNumber og b * @param firstNumber det første nummer * @param b det andet nummer * / public int add (int firstNumber, int b) {...}

Endelig skal vi bemærke det IntelliJ er smart og søger mest efter anvendelser inden for det omdøbte element. I vores tilfælde vil det betyde, at en kommentar ligger uden for metoden (undtagen Javadoc) og indeholder en omtale til -en ville ikke have været overvejet at omdøbe.

3. Uddrag

Lad os nu tale om ekstraktion. Ekstraktion gør os i stand til at få fat i et stykke kode og sætte det i en variabel, en metode eller endda en klasse. IntelliJ håndterer dette ret smart, da det søger efter lignende stykker kode og tilbyder at udtrække dem på samme måde.

Så i dette afsnit lærer vi, hvordan man udnytter ekstraktionsfunktionen, der tilbydes af IntelliJ.

3.1. Variabler

Lad os starte med ekstraktion af variabler. Det betyder lokale variabler, parametre, felter og konstanter. For at udtrække en variabel skal vi følge disse trin:

  • Vælg et udtryk, der passer ind i en variabel
  • Højreklik på det valgte område
  • Udløs Refactor> Extract> Variable / Parameter / Field / Constant mulighed
  • Vælg mellem Udskift kun denne forekomst eller Erstat alle x forekomster optioner, hvis de foreslås
  • Indtast et navn til det udpakkede udtryk (hvis det valgte ikke passer os)
  • Trykke Gå ind

Med hensyn til omdøbning er det muligt at bruge tastaturgenveje i stedet for at bruge menuen. Standardgenveje er henholdsvis Ctrl + Alt + V, Ctrl + Alt + P, Ctrl + Alt + F og Ctrl + Alt + C.

IntelliJ vil forsøge at gætte et navn på vores ekstraherede udtryk, baseret på hvad udtrykket returnerer. Hvis det ikke svarer til vores behov, kan vi ændre det, før vi bekræfter udvindingen.

Lad os illustrere med et eksempel. Vi kunne forestille os at tilføje en metode til vores SimpleClass klasse fortæller os, om den aktuelle dato er mellem to givne datoer:

public static boolean isNowBetween (LocalDate startingDate, LocalDate endingDate) {return LocalDate.now (). isAfter (startingDate) && LocalDate.now (). isBefore (endingDate); }

Lad os sige, at vi vil ændre vores implementering, fordi vi bruger LocalDate.now () to gange, og vi vil gerne sikre os, at den har nøjagtig samme værdi i begge evalueringer. Lad os bare vælge udtrykket og udtrække det i en lokal variabel, nu:

Så vores LocalDate.now () opkald fanges i en lokal variabel:

public static boolean isNowBetween (LocalDate startingDate, LocalDate endingDate) {LocalDate now = LocalDate.now (); returner nu.isAfter (startingDate) && now.isBefore (endingDate); }

Ved at kontrollere Udskift alle valgmulighed, sørgede vi for, at begge udtryk er blevet erstattet på én gang.

3.2. Metoder

Lad os nu kontrollere, hvordan man udpakker metoder ved hjælp af IntelliJ:

  • Vælg det eller de kodelinjer, der passer til den metode, vi vil oprette
  • Højreklik på det valgte område
  • Trigger Refactor> Uddrag> Metode mulighed
  • Indtast metodeoplysningerne: navn, synlighed og parametre
  • Trykke Gå ind

At ramme Ctrl + Alt + M efter valg af metode fungerer kroppen også.

Lad os genbruge vores tidligere eksempel og sige, at vi vil have en metode til at kontrollere, om en dato er mellem til andre datoer. Derefter skulle vi bare vælge vores sidste linje i isNowBetween metode og udløse metodeudvindingsfunktionen.

I den åbnede dialog kan vi se, at IntelliJ allerede har set de tre nødvendige parametre: start dato, slutter dato og nu. Da vi ønsker, at denne metode skal være så generisk som muligt, omdøber vi nu parameter ind i dato. Og til samhørighedsformål placerer vi det som den første parameter.

Endelig giver vi vores metode et navn, isDateBetween, og færdiggør ekstraktionsprocessen:

Vi får derefter følgende kode:

public static boolean isNowBetween (LocalDate startingDate, LocalDate endingDate) {LocalDate now = LocalDate.now (); returnere erDateBetween (nu, startdato, slutdato); } privat statisk boolsk isDateBetween (LocalDate date, LocalDate startingDate, LocalDate endingDate) {return date.isBefore (endingDate) && date.isAfter (startingDate); }

Som vi kan se, udløste handlingen oprettelsen af ​​det nye isDateBetween metode, som også kaldes i isNowBetween metode. Metoden er som standard privat. Selvfølgelig kunne dette have været ændret ved hjælp af synlighedsindstillingen.

3.3. Klasser

Efter alt dette vil vi muligvis få vores dato-relaterede metoder i en bestemt klasse med fokus på datahåndtering, lad os sige: DateUtils. Igen er dette ret let:

  • Højreklik i den klasse, der har vores elementer, vi vil flytte
  • Udløs Refactor> Uddrag> Delegeret mulighed
  • Indtast klasseoplysningerne: dens navn, dens pakke, de elementer, der skal delegeres, synligheden af ​​disse elementer
  • Trykke Gå ind

Som standard er ingen tastaturgenvej tilgængelig for denne funktion.

Lad os sige, før vi udløser funktionen, at vi kalder vores dato-relaterede metoder i vigtigste metode:

isNowBetween (LocalDate.MIN, LocalDate.MAX); isDateBetween (LocalDate.of (2019, 1, 1), LocalDate.MIN, LocalDate.MAX);

Derefter delegerer vi disse to metoder til a DateUtils klasse ved hjælp af delegeret valgmulighed:

Udløs funktionen vil producere følgende kode:

public class DateUtils {public static boolean isNowBetween (LocalDate startingDate, LocalDate endingDate) {LocalDate now = LocalDate.now (); returnere erDateBetween (nu, startdato, slutdato); } offentlig statisk boolsk isDateBetween (LocalDate date, LocalDate startingDate, LocalDate endingDate) {return date.isBefore (endingDate) && date.isAfter (startingDate); }}

Vi kan se, at isDateBetween metoden er lavet offentlig. Det er resultatet af synlighedsindstillingen, der er indstillet til eskalere som standard. Eskalere betyder, at synligheden ændres for atsikre, at aktuelle opkald til de delegerede elementer stadig kompileres.

I vores tilfælde isDateBetween bruges i vigtigste metode til SimpleClass:

DateUtils.isNowBetween (LocalDate.MIN, LocalDate.MAX); DateUtils.isDateBetween (LocalDate.of (2019, 1, 1), LocalDate.MIN, LocalDate.MAX);

Når du flytter metoden, er det således nødvendigt at gøre den ikke privat.

Det er dog muligt at give vores elementer specifik synlighed ved at vælge de andre muligheder.

4. Inline

Nu hvor vi dækkede udvinding, lad os tale om dets modstykke: inlining. Inlining handler om at tage et kodeelement og erstatte det med det, det er lavet af. For en variabel ville dette være det udtryk, den er tildelt. For en metode ville det være dets krop. Tidligere så vi, hvordan man opretter en ny klasse og delegerer nogle af vores kodeelementer til den. Men der er tidspunkter Vi vil måske delegere en metode til en eksisterende klasse. Det er, hvad dette afsnit handler om.

For at integrere et element skal vi højreklikke på dette element - enten dets definition eller en henvisning til det - og udløse Refactor>Inline mulighed. Vi kan også opnå dette ved at vælge elementet og trykke på Ctrl + Alt + N. nøgler.

På dette tidspunkt vil IntelliJ tilbyde os flere muligheder, uanset om vi ønsker at integrere en variabel eller en metode, uanset om vi har valgt en definition eller en reference. Disse muligheder er:

  • Inline alle referencer, og fjern elementet
  • Indsæt alle referencer, men hold elementet
  • Indsæt kun den valgte reference og bevar elementet

Lad os tage vores isNowBetween metode og slippe af med nu variabel, som nu virker lidt overkill:

Ved at indlejre denne variabel opnår vi følgende resultat:

public static boolean isNowBetween (LocalDate startingDate, LocalDate endingDate) {return isDateBetween (LocalDate.now (), startingDate, endingDate); }

I vores tilfælde var den eneste mulighed at fjerne alle referencer og fjerne elementet. Men lad os forestille os, at vi også vil slippe af med isDateBetween ring og vælg at integrere det. Derefter ville IntelliJ tilbyde os de tre muligheder, vi talte om før:

Hvis du vælger den første, erstattes alle opkald med metodens brødtekst og slettes. Hvad angår den anden, ville den erstatte alle opkald med metodekroppen, men beholde metoden. Og endelig ville den sidste kun erstatte det aktuelle opkald med metodekroppen:

public class DateUtils {public static boolean isNowBetween (LocalDate startingDate, LocalDate endingDate) {LocalDate date = LocalDate.now (); return date.isBefore (endingDate) && date.isAfter (startingDate); } offentlig statisk boolsk isDateBetween (LocalDate date, LocalDate startingDate, LocalDate endingDate) {return date.isBefore (endingDate) && date.isAfter (startingDate); }}

Vores vigtigste metode i SimpleClass forbliver også uberørt.

5. Flytter

Tidligere så vi, hvordan vi opretter en ny klasse og delegerer nogle af vores kodeelementer til den. Men der er tidspunkter Vi vil måske delegere en metode til en eksisterende klasse. Det er, hvad dette afsnit handler om.

For at flytte et element skal vi følge disse trin:

  • Vælg det element, der skal flyttes
  • Højreklik på elementet
  • Udløs Refactor> Flyt mulighed
  • Vælg modtagerklassen og metodens synlighed
  • Trykke Gå ind

Vi kan også opnå dette ved at trykke på F6 efter valg af elementet.

Lad os sige, at vi tilføjer en ny metode til vores SimpleClass, isDateOutstide (), der fortæller os, om en dato ligger uden for et datointerval:

public static boolean isDateOutside (LocalDate date, LocalDate startingDate, LocalDate endingDate) {return! DateUtils.isDateBetween (date, startingDate, endingDate); }

Vi indser derefter, at dets plads skal være i vores DateUtils klasse. Så vi beslutter at flytte det:

Vores metode er nu i DateUtils klasse. Vi kan se, at henvisningen til DateUtils inde i metoden er forsvundet, da det ikke længere er nødvendigt:

public static boolean isDateOutside (LocalDate date, LocalDate startingDate, LocalDate endingDate) {return! isDateBetween (date, startingDate, endingDate); }

Eksemplet, vi lige har gjort, fungerer godt, da det vedrører en statisk metode. I tilfælde af en instansmetode er tingene imidlertid ikke så ligetil.

Hvis vi vil flytte en instansmetode, IntelliJ vil søge efter klasser der henvises til i felterne i den aktuelle klasse og tilbyde at flytte metoden til en af ​​disse klasser (forudsat at de er vores at ændre).

Hvis der ikke henvises til nogen modificerbar klasse i felterne, foreslår IntelliJ at lave metoden statisk inden du flytter den.

6. Ændring af en metodesignatur

Endelig vil vi tale om en funktion, der giver os mulighed for at ændre en metodesignatur. Formålet med denne funktion er at manipulere alle aspekter af en metodesignatur.

Som sædvanligt skal vi gennemgå et par trin for at udløse funktionen:

  • Vælg den metode, du vil ændre
  • Højreklik på metoden
  • Udløs Refactor> Skift signatur mulighed
  • Medbring ændringer i metodesignaturen
  • Trykke Gå ind

Hvis vi foretrækker at bruge tastaturgenveje, det er muligt at bruge Ctrl + F6 såvel.

Denne funktion åbner en dialog, der minder meget om metodeudvindingsfunktionen. Også vi har de samme muligheder, som når vi ekstraherer en metode: ændre navn, dets synlighed og tilføje / fjerne parametre og finjustere dem.

Lad os forestille os, at vi vil ændre vores implementering af isDateBetween enten at betragte datagrænserne som inkluderende eller eksklusive. For at gøre det ønsker vi at tilføje en boolsk parameter til vores metode:

Ved at ændre metodesignaturen kan vi tilføje denne parameter, navngive den og give den en standardværdi:

public static boolean isDateBetween (LocalDate date, LocalDate startingDate, LocalDate endingDate, boolean inclusive) {return date.isBefore (endingDate) && date.isAfter (startingDate); }

Derefter er vi bare nødt til at tilpasse metoden kroppen efter vores behov.

Hvis vi ville, kunne vi have kontrolleret Delegere via overbelastningsmetode mulighed for at oprette en anden metode med parameteren i stedet for at ændre den aktuelle.

7. Træk op og skub ned

Vores Java-kode har typisk klassehierarkier - afledte klasser udvider en basisklasse.

Nogle gange ønsker vi at flytte medlemmer (metoder, felter og konstanter) mellem disse klasser. Det er her, den sidste refactoring er praktisk: det giver os mulighed for det træk medlemmer fra en afledt klasse ind i basisklassen eller skub dem ned fra en basisklasse til hver afledt klasse.

7.1. Træk op

Lad os først trække en metode op til basisklassen:

  • Vælg et medlem af en afledt klasse, der skal trækkes op
  • Højreklik på medlemmet
  • Udløs Refactor> Træk medlemmer op ... mulighed
  • Skub Refactor knap

Som standard er der ingen tastaturgenvej til denne funktion.

Lad os sige, at vi har en afledt klasse kaldet Afledt. Det bruger en privat dobbeltværdi () metode:

public class Derived extends Base {public static void main (String [] args) {Derived subject = new Derived (); System.out.println ("Fordobling 21. Resultat:" + subject.doubleValue (21)); } privat int doubleValue (int-nummer) {returnummer + nummer; }}

Baseklassen Grundlag er tom.

Så hvad sker der, når vi trækker op dobbeltværdi () ind i Grundlag?

To ting sker med dobbeltværdi () når vi skubber "Refactor" i ovenstående dialog:

  • det bevæger sig til Grundlag klasse
  • dens synlighed ændres fra privat til beskyttet så at Afledt klasse kan stadig bruge det

Det Grundlag klasse bagefter har nu metoden:

public class Base {beskyttet int doubleValue (int nummer) {retur nummer + nummer; }}

Dialogen for at trække medlemmer op (billedet ovenfor) giver os nogle flere muligheder:

  • vi kan vælge andre medlemmer og trække dem op på én gang
  • vi kan få vist vores ændringer med "Preview" -knappen
  • kun metoder har et afkrydsningsfelt i kolonnen "Lav abstrakt". Hvis dette er markeret, giver denne mulighed basisklassen en abstrakt metodedefinition under pull-up. Den aktuelle metode forbliver i den afledte klasse, men får en @Override kommentar. Derfor kompileres andre afledte klasser ikke længere så fordi de mangler implementeringen af ​​den nye, abstrakte basemetode

7.2. Tryk ned

Endelig lad os skubbe et medlem ned til den afledte klasse. Dette er det modsatte af det træk, vi lige har udført:

  • Vælg et medlem af en basisklasse for at skubbe ned
  • Højreklik på medlemmet
  • Udløs Refactor> Skub medlemmer ned ... mulighed
  • Skub Refactor knap

Som med at trække medlemmer op, er der som standard ingen tastaturgenvej til denne funktion.

Lad os skubbe metoden ned igen, som vi lige trak op. Det Grundlag klasse så sådan ud i slutningen af ​​forrige afsnit:

public class Base {beskyttet int doubleValue (int nummer) {retur nummer + nummer; }}

Lad os nu skubbe dobbeltværdi () ned til Afledt klasse:

Dette er Afledt klasse efter at have skubbet "Refactor" i ovenstående dialog.Det dobbeltværdi () metoden er tilbage:

public class Derived udvider Base {private int theField = 5; public static void main (String [] args) {Afledt emne = nyt Afledt (); System.out.println ("Fordobling 21. Resultat:" + subject.doubleValue (21)); } beskyttet int doubleValue (int nummer) {retur nummer + nummer; }}

Nu både den Grundlag klasse og Afledt klasse er tilbage til det sted, hvor de startede i den forrige “Pull Up” sektion. Næsten det er - dobbeltværdi () beholdt beskyttet synlighed det havde i Grundlag (det var privat oprindeligt).

IntelliJ 2019.3.4 giver faktisk en advarsel når du skubber ned dobbeltværdi (): “Pushede medlemmer vil ikke være synlige fra bestemte opkaldssider”. Men som vi kan se i Afledt klasse over, dobbeltværdi () er faktisk synlig for hoved () metode.

Dialogen for at skubbe medlemmer ned (billedet ovenfor) giver os også nogle flere muligheder:

  • hvis vi har flere afledte klasser, så skubber IntelliJ medlemmer ind i hver afledt klasse
  • vi kan skubbe flere medlemmer ned
  • vi kan få vist vores ændringer med "Preview" -knappen
  • kun metoder har et afkrydsningsfelt i kolonnen "Behold abstrakt" - Det svarer til at trække medlemmer op: Hvis dette er markeret, vil denne mulighed efterlade en abstrakt metode i basisklassen. I modsætning til at trække medlemmer op, placerer denne mulighed metodeimplementeringer i alle afledte klasser. Disse metoder får også en @Override kommentar

8. Konklusion

I denne artikel havde vi chancen for at dybe dybt ned i nogle af de refactoring-funktioner, der tilbydes af IntelliJ. Selvfølgelig dækkede vi ikke alle mulighederne, da IntelliJ er et meget kraftfuldt værktøj. For at lære mere om denne editor kan vi altid henvise til dens dokumentation.

Vi så et par ting som hvordan man omdøber vores kodeelementer og hvordan man udtrækker nogle adfærd i variabler, metoder eller klasser. Vi lærte også, hvordan man integrerer nogle elementer, hvis vi ikke har brug for dem, der står alene, flytter noget kode et andet sted eller endda fuldt ud ændrer en eksisterende metodesignatur.


$config[zx-auto] not found$config[zx-overlay] not found