Seminarium för dig som tittat i Refactoring-menyn och känner på dig att det finns betydligt mer bortom "Rename". Genom konkreta demo och praktiska övningar bekantar vi oss närmare med konkreta handgrepp och tar dessa som utgångspunkt för diskussioner om pragmatik och filosofi.
Tid: 4h
Labbkoden finns i form av ett maven-projekt definierat av pom.xml
För att öppna i IntelliJ: välj "Import Project" och markera biblioteket "refactoring-lab", importera som Maven-projekt
Kör enhetstestet i CustomerTest.
Vi ärver en halvrörig kod. Vad kan vi göra för att göra koden enklare och lättare att förstå?
Som huvudmål i denna del vill vi extrahera en metod för prisberäkning: charge().
Kodlukter:
- Lång metod
- Stor klass
- Funktionsavundsjuka
- Tillfälliga variabler
- Bryt ut
switch
-satsen ur loopen till en egen metod. Testa skillnaden med att göra det själv och att låta ditt IDE göra det åt dig.
- Flytta den nya metoden till Rental
- Byt namn på den nya metoden till exempelvis
charge()
Varför gjorde vi denna refaktorisering?
- Gör inline på anropet till den nya metoden
charge()
iCustomer::statement
. - Byt ++ mot +=
- Summera till en temp-variabel (
tmpPoints
) och lägg till temp-variabeln till summan - Bryt ut beräkningen av
frequentRenterPoints
till en egen metod. - Namnge metoden exempelvis
getFrequentRenterPoints
- Gör inline på
tmpPoints
variabeln - Flytta den nya metoden till
Rental
- Summera till en temp-variabel (
tmpResult
) och lägg till temp-variabeln till summan - Bryt ut beräkningen av
result
till en egen metod. - Namnge metoden exempelvis
getRentalFigures
- Gör inline på
tmpResult
variabeln - Flytta den nya metoden till
Rental
- Pilla isär loopen till en loop per beräkning.
- Bryt ut varje loop till en egen metod. Glöm inte att få med den lokala variabeln
- EXTRA: Bygg om looparna till att använda streams.
Vi får reda på att butiken kommer att vilja ha fler typer av priser och kunna byta prissättning på filmerna efterhand. Kan vi förändra koden så att det blir lättare att stödja en sådan funktion?
- Introducera en ny variabel för
getDaysRented()
(Vi behöver baradaysRented
från rental.) - Extrahera en ny metod som exempelvis heter
chargeForDaysRented()
- Flytta metoden
chargeForDaysRented()
vidare från Rental till Movie. - Bli av med Rental parameter beroendet i
chargeForDaysRented()
- Extrahera
getPriceCode()
till en lokal variabel - Extrahera tillfällig metod
chargeForDaysAndPriceCode(int daysRented, int priceCode)
- Gör inline på
thisAmount
- Extrahera metoden till delegate PriceCalculatorImpl
- Flytta initiering till konstruktor-parameter. Hur ser testet ut nu?
- Skapa interface
PriceCalculator
- Kopiera
PriceCalculatorImpl
och döp tillRegularPriceCalculator
- Gör
chargeForDaysRentedAndPriceCode
iPriceCalculatorImpl
publik - Ta bort delar som ej har med REGULAR_PRICE_CODE ur
switch
-satsen - Byt ut medlemsvariabeln
PriceCalculatorImpl
motPriceCalculator
interfacet iMovie
- Byt ut till
RegularPriceCalculator
i test-konstruktor
- Gör motsvarande för Children och New Release som gjordes för Regular
- Kör testerna
- Lägg till metod för att ändra calculator
- Ta bort switch statement
- Safe delete på priceCode
Kodlukter:
- Switch-sats (https://refactoring.guru/smells/switch-statements)
- Onödig intimitet
- Tillfälliga variabler
- Martin Fowler: Refactoring: Improving the Design of Existing Code (2nd Edition)
- https://refactoring.com/catalog
- Joshua Kerievsky: Refactoring to Patterns 1st Edition
- https://refactoring.guru