En introduksjon til refactoring med IntelliJ IDEA

1. Oversikt

Å holde koden ryddig er ikke alltid lett. Heldigvis for oss er IDEene våre ganske smarte i dag og kan hjelpe oss med å oppnå dette. I denne opplæringen skal vi fokusere på IntelliJ IDEA, JetBrains Java-kodeditor.

Vi ser noen få funksjoner som redaktøren tilbyr for å refaktorkode, fra å gi nytt navn til variabler til å endre en metodesignatur.

2. Gi nytt navn

2.1. Grunnleggende omdøping

La oss først begynne med det grunnleggende: gi nytt navn. IntelliJ gir oss muligheten til å gi nytt navn til forskjellige elementer i koden vår: typer, variabler, metoder og til og med pakker.

For å gi nytt navn til et element, må vi følge disse trinnene:

  • Høyreklikk på elementet
  • Utløs Refactor> Gi nytt navn alternativ
  • Skriv inn det nye elementnavnet
  • trykk Tast inn

Forresten, vi kan erstatte de to første trinnene ved å velge elementet og trykke Skift + F6.

Når den utløses, vil omdøpshandlingen søk på tvers av koden for hver bruk av elementet, og endre dem deretter med den oppgitte verdien.

La oss forestille oss en SimpleClass klasse med en dårlig navngitt tilleggsmetode, someAdditionMethod, kalt inn hoved- 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; }}

Dermed, hvis vi velger å gi nytt navn til denne metoden til legge til, IntelliJ vil produsere følgende kode:

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

2.2. Avansert omdøping

Imidlertid gjør IntelliJ mer enn å søke etter kodebruk av elementene våre og gi dem nytt navn. Faktisk er noen flere alternativer tilgjengelige. IntelliJ kan også søke etter hendelser i kommentarer og strenger, og til og med i filer som ikke inneholder kildekode. Når det gjelder parametere, kan den endre navn på dem i klassehierarkiet i tilfelle overstyrte metoder.

Disse alternativene er tilgjengelige ved å trykke Skift + F6 en gang til før du omdøper elementet vårt, og en popup vil vises:

De Søk i kommentarer og strenger alternativet er tilgjengelig for ethvert navn. Når det gjelder Søk etter tekstforekomster alternativet, er det ikke tilgjengelig for metodeparametere og lokale variabler. Til slutt, Gi nytt navn til parametere i hierarki alternativet er bare tilgjengelig for metodeparametere.

Så, hvis noen samsvar er funnet med ett av disse to alternativene, vil IntelliJ vise dem og tilby oss muligheten til å velge bort noen av endringene (si, hvis det samsvarer med noe som ikke er relatert til omdøpet vårt).

La oss legge til litt Javadoc i metoden vår, og deretter gi den første parameteren nytt navn, en:

/ ** * Legger til a og b * @param a det første tallet * @param b det andre tallet * / public int add (int a, int b) {...}

Ved å sjekke det første alternativet i bekreftelsesvinduet, samsvarer IntelliJ med omtale av parametrene i Javadoc-kommentaren til metoden, og tilbyr også å gi dem navn:

/ ** * Legger til firstNumber og b * @param firstNumber the first number * @param b the second number * / public int add (int firstNumber, int b) {...}

Til slutt må vi merke oss det IntelliJ er smart og søker hovedsakelig etter bruksområder i det omdøpte elementet. I vårt tilfelle vil det bety at en kommentar ligger utenfor metoden (bortsett fra Javadoc) og inneholder en omtale til en ville ikke blitt vurdert for å gi nytt navn.

3. Utpakking

La oss nå snakke om utvinning. Ekstraksjon gjør at vi kan hente et stykke kode og sette det i en variabel, en metode eller til og med en klasse. IntelliJ håndterer dette ganske smart når det søker etter lignende kodestykker og tilbyr å trekke dem ut på samme måte.

Så i denne delen vil vi lære hvordan du kan utnytte ekstraksjonsfunksjonen som tilbys av IntelliJ.

3.1. Variabler

Først, la oss begynne med ekstraksjon av variabler. Det betyr lokale variabler, parametere, felt og konstanter. For å trekke ut en variabel, må vi følge disse trinnene:

  • Velg et uttrykk som passer i en variabel
  • Høyreklikk det valgte området
  • Utløs Refactor> Extract> Variable / Parameter / Field / Constant alternativ
  • Velg mellom Erstatt bare denne forekomsten eller Erstatt alle x-forekomster alternativer, hvis foreslått
  • Skriv inn et navn for det ekstraherte uttrykket (hvis det valgte ikke passer oss)
  • trykk Tast inn

Når det gjelder å gi nytt navn, er det mulig å bruke hurtigtaster i stedet for å bruke menyen. Standard snarveier er henholdsvis Ctrl + Alt + V, Ctrl + Alt + P, Ctrl + Alt + F og Ctrl + Alt + C.

IntelliJ vil prøve å gjette et navn på det ekstraherte uttrykket vårt, basert på hva uttrykket returnerer. Hvis det ikke samsvarer med våre behov, kan vi endre det før vi bekrefter utvinningen.

La oss illustrere med et eksempel. Vi kunne tenke oss å legge til en metode i vår SimpleClass klasse som forteller oss om dagens dato er mellom to gitte datoer:

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

La oss si at vi vil endre implementeringen vår fordi vi bruker LocalDate.now () to ganger, og vi vil sørge for at den har nøyaktig samme verdi i begge evalueringene. La oss bare velge uttrykket og trekke det ut i en lokal variabel, nå:

Så, vår LocalDate.now () samtalen fanges i en lokal variabel:

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

Ved å sjekke Bytt ut alle alternativet, sørget vi for at begge uttrykkene ble erstattet samtidig.

3.2. Metoder

La oss nå sjekke hvordan du trekker ut metoder ved hjelp av IntelliJ:

  • Velg uttrykket eller kodelinjene som passer til metoden vi vil lage
  • Høyreklikk det valgte området
  • Utløs Refactor> Extract> Method alternativ
  • Skriv inn metodeinformasjonen: navnet, synligheten og parametrene
  • trykk Tast inn

Treffer Ctrl + Alt + M. etter å ha valgt metode fungerer kroppen også.

La oss bruke vårt forrige eksempel på nytt og si at vi vil ha en metode som sjekker om noen dato er mellom til andre datoer. Da må vi bare velge vår siste linje i isNowBetween metode og utløse funksjonen for utvinning av metoden.

I den åpnede dialogen kan vi se at IntelliJ allerede har oppdaget de tre nødvendige parameterne: startdato, sluttdato og . Siden vi vil at denne metoden skal være så generisk som mulig, omdøper vi parameter inn i Dato. Og for samholdsformål plasserer vi det som den første parameteren.

Til slutt gir vi metoden vår et navn, isDateBetween, og avslutt utvinningsprosessen:

Vi vil da få følgende kode:

public static boolean isNowBetween (LocalDate startingDate, LocalDate endingDate) {LocalDate now = LocalDate.now (); retur isDateBetween (nå, startingDate, endingDate); } privat statisk boolsk isDateBetween (LocalDate date, LocalDate startingDate, LocalDate endingDate) {return date.isBefore (endingDate) && date.isAfter (startingDate); }

Som vi kan se, utløste handlingen etableringen av det nye isDateBetween metoden, som også kalles i isNowBetween metode. Metoden er privat, som standard. Selvfølgelig kunne dette ha blitt endret ved hjelp av synlighetsalternativet.

3.3. Klasser

Når alt kommer til alt, vil vi kanskje få våre daterelaterte metoder i en bestemt klasse, fokusert på datahåndtering, la oss si: DateUtils. Igjen, dette er ganske enkelt:

  • Høyreklikk i klassen som har elementene vi vil flytte
  • Utløs Refactor> Extract> Delegate alternativ
  • Skriv inn klasseinformasjonen: navnet, pakken, elementene som skal delegeres, synligheten til disse elementene
  • trykk Tast inn

Som standard er ingen hurtigtast tilgjengelig for denne funksjonen.

La oss si, før vi utløser funksjonen, at vi kaller våre dato-relaterte metoder i hoved- metode:

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

Deretter delegerer vi de to metodene til a DateUtils klasse ved hjelp av delegatalternativet:

Trigger funksjonen vil produsere følgende kode:

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

Vi kan se at isDateBetween metoden er laget offentlig. Det er resultatet av synlighetsalternativet, som er satt til eskalere som standard. Eskaler betyr at synligheten vil bli endret for åsikre at gjeldende samtaler til de delegerte elementene fortsatt kompileres.

I vårt tilfelle, isDateBetween brukes i hoved- Metode av 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 derfor nødvendig å gjøre den ikke privat.

Det er imidlertid mulig å gi spesifikk synlighet til elementene våre ved å velge de andre alternativene.

4. Innfelling

Nå som vi dekket utvinning, la oss snakke om motstykket: innfelling. Inlining handler om å ta et kodeelement og erstatte det med det det er laget av. For en variabel vil dette være uttrykket det er tildelt. For en metode ville det være kroppen. Tidligere så vi hvordan vi skulle lage en ny klasse og delegere noen av kodeelementene våre til den. Men det er tider kan det være lurt å delegere en metode til en eksisterende klasse. Det er hva denne delen handler om.

For å integrere et element, må vi høyreklikke på dette elementet - enten dets definisjon eller en referanse til det - og utløse Refactor>På linje alternativ. Vi kan også oppnå dette ved å velge elementet og trykke på Ctrl + Alt + N. nøklene.

På dette punktet vil IntelliJ tilby oss flere alternativer, enten vi ønsker å integrere en variabel eller en metode, enten vi valgte en definisjon eller en referanse. Disse alternativene er:

  • Sett alle referansene inn og fjern elementet
  • Sett inn alle referansene, men behold elementet
  • Bare legg inn den valgte referansen og behold elementet

La oss ta vår isNowBetween metode og kvitte seg med variabel, som nå virker litt overkill:

Ved å innlemme denne variabelen ville vi oppnå følgende resultat:

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

I vårt tilfelle var det eneste alternativet å fjerne alle referansene og fjerne elementet. Men la oss forestille oss at vi også vil bli kvitt isDateBetween ring og velg å legge den inn. Deretter vil IntelliJ tilby oss de tre mulighetene vi snakket om før:

Hvis du velger den første, erstattes alle samtaler med metodeteksten og sletter metoden. Når det gjelder den andre, vil den erstatte alle samtaler med metodekroppen, men beholde metoden. Og til slutt, den siste ville bare erstatte den nåværende samtalen 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); }}

Våre hoved- metoden i SimpleClass forblir urørt også.

5. Flytte

Tidligere så vi hvordan vi skulle lage en ny klasse og delegere noen av kodeelementene våre til den. Men det er tider kan det være lurt å delegere en metode til en eksisterende klasse. Det er hva denne delen handler om.

For å flytte et element, må vi følge disse trinnene:

  • Velg elementet du vil flytte
  • Høyreklikk på elementet
  • Utløs Refactor> Flytt alternativ
  • Velg mottakerklassen og metodens synlighet
  • trykk Tast inn

Vi kan også oppnå dette ved å trykke F6 etter at du har valgt elementet.

La oss si at vi legger til en ny metode i vår SimpleClass, isDateOutstide (), som vil fortelle oss om en dato ligger utenfor et intervall av datoer:

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

Vi innser da at stedet skal være i vårt DateUtils klasse. Så vi bestemmer oss for å flytte det:

Metoden vår er nå i DateUtils klasse. Vi kan se at henvisningen til DateUtils inne i metoden har forsvunnet ettersom den ikke lenger er nødvendig:

offentlig statisk boolsk isDateOutside (LocalDate date, LocalDate startingDate, LocalDate endingDate) {return! isDateBetween (date, startingDate, endingDate); }

Eksemplet vi nettopp gjorde fungerer bra da det gjelder en statisk metode. Imidlertid, når det gjelder en instansemetode, er ting ikke så rett frem.

Hvis vi vil flytte en forekomstmetode, IntelliJ vil søke etter klasser det refereres til i feltene i gjeldende klasse og tilby å flytte metoden til en av disse klassene (forutsatt at de er våre å endre).

Hvis det ikke er referert til noen modifiserbar klasse i feltene, foreslår IntelliJ å lage metoden statisk før du flytter den.

6. Endring av metodesignatur

Til slutt vil vi snakke om en funksjon som lar oss endre en metodesignatur. Hensikten med denne funksjonen er å manipulere alle aspekter av en metodesignatur.

Som vanlig må vi gå gjennom noen få trinn for å utløse funksjonen:

  • Velg metoden du vil endre
  • Høyreklikk metoden
  • Utløs Refactor> Endre signatur alternativ
  • Ta med endringer i metodesignaturen
  • trykk Tast inn

Hvis vi foretrekker å bruke hurtigtaster, det er mulig å bruke Ctrl + F6 også.

Denne funksjonen åpner en dialog som er veldig lik funksjonen for utvinning av metoder. Og så vi har de samme mulighetene som når vi trekker ut en metode: endre navn, synlighet og legge til / fjerne parametere og finjustere dem.

La oss forestille oss at vi vil endre implementeringen av isDateBetween å enten betrakte datagrenser som inkluderende eller eksklusive. For å gjøre det ønsker vi å legge til en boolsk parameter til vår metode:

Ved å endre metodesignaturen kan vi legge til denne parameteren, gi den navn og gi den en standardverdi:

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

Etter det er det bare å tilpasse metodekroppen etter våre behov.

Hvis vi ville, kunne vi ha sjekket Delegere via overbelastningsmetode alternativet for å lage en annen metode med parameteren i stedet for å endre den nåværende.

7. Trekk opp og skyv ned

Java-koden vår har vanligvis klassehierarkier - avledede klasser utvider en basisklasse.

Noen ganger ønsker vi å flytte medlemmer (metoder, felt og konstanter) mellom disse klassene. Det er her den siste refactoring er nyttig: det lar oss trekk opp medlemmer fra en avledet klasse inn i basisklassen eller skyv dem ned fra en baseklasse til hver avledede klasse.

7.1. Trekk opp

La oss først trekke opp en metode til basisklassen:

  • Velg et medlem av en avledet klasse å trekke opp
  • Høyreklikk medlemmet
  • Utløs Refactor> Trekk medlemmene opp ... alternativ
  • Trykk på Refactor knapp

Som standard er ingen hurtigtast tilgjengelig for denne funksjonen.

La oss si at vi har en avledet klasse kalt Avledet. Den bruker en privat doubleValue () metode:

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

Baseklassen Utgangspunkt er tom.

Så, hva skjer når vi trekker opp doubleValue () inn i Utgangspunkt?

To ting skjer med doubleValue () når vi trykker på "Refactor" i dialogboksen ovenfor:

  • den beveger seg til Utgangspunkt klasse
  • synligheten endres fra privat til beskyttet slik at Avledet klassen kan fortsatt bruke den

De Utgangspunkt klasse etterpå har nå metoden:

offentlig klasse Base {beskyttet int doubleValue (int nummer) {retur nummer + nummer; }}

Dialogen for å trekke opp medlemmer (bildet ovenfor) gir oss noen flere alternativer:

  • vi kan velge andre medlemmer og trekke dem opp samtidig
  • vi kan forhåndsvise endringene våre med "Preview" -knappen
  • bare metoder har en avkrysningsrute i kolonnen "Lag abstrakt". Hvis dette er avmerket, vil dette alternativet gi basisklassen en abstrakt metodedefinisjon under opptrekket. Den faktiske metoden vil forbli i den avledede klassen, men få en @Overstyring kommentar. Følgelig vil andre avledede klasser ikke kompilere lenger da fordi de mangler implementering av den nye, abstrakte basemetoden

7.2. Presse ned

Til slutt, la oss presse et medlem ned til den avledede klassen. Dette er motsatt av trekkingen vi nettopp utførte:

  • Velg et medlem av en basisklasse for å presse ned
  • Høyreklikk medlemmet
  • Utløs Refactor> Push Members Down… alternativ
  • Trykk på Refactor knapp

Som med å trekke medlemmene opp, er ingen tastatursnarvei tilgjengelig for denne funksjonen som standard.

La oss presse ned metoden igjen som vi nettopp trakk opp. De Utgangspunkt klassen så slik ut på slutten av forrige avsnitt:

offentlig klasse Base {beskyttet int doubleValue (int nummer) {retur nummer + nummer; }}

La oss presse doubleValue () ned til Avledet klasse:

Dette er Avledet klasse etter å ha trykket "Refactor" i dialogboksen ovenfor.De doubleValue () metoden er tilbake:

offentlig klasse Derived utvider Base {private int theField = 5; public static void main (String [] args) {Derived subject = new Derived (); System.out.println ("Dobling 21. Resultat:" + subject.doubleValue (21)); } beskyttet int doubleValue (int nummer) {retur nummer + nummer; }}

Nå både den Utgangspunkt klasse og Avledet klassen er tilbake til der de startet i forrige "Pull Up" -del. Nesten, det er - doubleValue () beholdt beskyttet synlighet den hadde i Utgangspunkt (det var privat opprinnelig).

IntelliJ 2019.3.4 gir faktisk en advarsel når du skyver ned doubleValue (): “Pressede medlemmer vil ikke være synlige fra visse anropssider”. Men som vi kan se i Avledet klasse over, doubleValue () er faktisk synlig for hoved() metode.

Dialogen for å presse medlemmene ned (bildet ovenfor) gir oss også flere alternativer:

  • hvis vi har flere avledede klasser, vil IntelliJ skyve medlemmene inn i hver avledede klasse
  • vi kan presse flere medlemmer ned
  • vi kan forhåndsvise endringene våre med "Preview" -knappen
  • bare metoder har en avkrysningsrute i "Behold abstrakt" -kolonnen. I motsetning til å trekke opp medlemmer, vil dette alternativet plassere metodeimplementeringer i alle avledede klasser. Disse metodene vil også få en @Overstyring kommentar

8. Konklusjon

I denne artikkelen hadde vi sjansen til å dykke dypt inn i noen av refactoring-funksjonene som tilbys av IntelliJ. Selvfølgelig dekket vi ikke alle mulighetene, da IntelliJ er et veldig kraftig verktøy. For å lære mer om denne redaktøren, kan vi alltid referere til dokumentasjonen.

Vi så noen få ting som å endre navn på kodeelementene våre og hvordan vi kan hente ut noen atferd i variabler, metoder eller klasser. Vi lærte også hvordan vi kunne legge inn noen elementer hvis vi ikke trengte dem å stå alene, flytte litt kode andre steder eller til og med endre en eksisterende metodesignatur.


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