what is refactoring?b3ad%204/2%20refactoring.pdf · refactoring - 1 what is refactoring? •...
TRANSCRIPT
Refactoring - 1
What Is Refactoring?
• Definition:
– The process of changing software in a way that the external behavior is not alteredbut the internal structure is improved.
– Or, an instance of such a change.(E.g. “I carried out a refactoring….”)
• Cleaning up code. Improving design.But after the code works.
– Fights against software entropy
Refactoring - 2
Why Refactor?
• Continuous improvement of design– “Tidying up.” Avoids decay.
– Needed if “make it work” is first priority
– Best design choices may not evident at first
• Makes software easier to understand– Refactoring done to clean up hacks
– Done after reflection.
– May be done to remove ambiguity, misleading code, a hack, etc.
– If you can change it successfully, you understand it
Refactoring - 3
Why Refactor? (2)
• Helps you find bugs
– A change to improve structure may reveal a flaw in old implementation
• Helps you developing working code more quickly
– Counter-intuitive!
– Short cycles of add-functionality then improve-design. (Kent Beck’s “two hats” idea).
Refactoring - 4
But Hold On…
• Possible objections….
– Touching the design is asking for trouble!
– Once it’s working, why bother?
– After I think it’s working, don’t I have to re-verify the design changes again?
• What we need to make refactoring successful is
– Unit tests
Refactoring - 5
Unit Testing in TDD
• Motto: “Clean code that works.” (Ron Jeffries)
• Unit testing has “broader goals” that just insuring quality
– Improve developers lives (coping, confidence)
– Support design flexibility and change
– Allow iterative development with working code early
Refactoring - 6
Unit Testing Benefits
• Developers can work in a predictable way
of developing code
• Programmers write their own unit tests
• Get rapid response for testing small
changes
• Build many highly-cohesive loosely-
coupled modules to make unit testing
easier
Refactoring - 7
Red/Green/Refactor
• The TDD mantra of how to code:
– Red: write a little test that doesn’t work,
perhaps even doesn’t compile
– Green: Write code to make the test work
quickly (perhaps not the best code)
– Refactor: Eliminate duplication and other
problems that you did to just make the test
work
Refactoring - 8
When Should Refactor?
• Remember: afterwards! (After what?)
• “The Rule of Three”
– First, just do it. Second time, do it badly but tolerate it. Third time, do it well: refactor.
• Some guidelines:
– When you need to add a function. Existing design makes this hard. Improve it.
– When you need to fix a bug.
– As part of a code review.
Refactoring - 9
Refactoring and Design Smells
• Fowler, design smells, and catalog of
refactorings
– The book
– http://www.refactoring.com/
– List of smells on the web:
http://wiki.java.net/bin/view/People/SmellsTo
Refactorings
Refactoring - 10
Tool Support for Refactoring
• Refactorings: standard re-structurings to
solve common problems
– Can do them by hand
– Put might be tricky
• IDEs and separate tools support this
– IntelliJ, ReSharper, JRefactory, C# Refactory
– Eclipse, JBuilder, next release of Visual
Studio
Refactoring - 11
Why tools? Ponder these:
• In Java, you decide to change a class’s
name. What needs to changed?
• In Java, you want to change the name of
a method. What needs to be changed?
Refactoring - 12
Java Refactorings in Eclipse
• Renaming resources
– classes, methods, fields
– moving to another package
– inner and anonymous classes
• Class hierarchy modifications
– includes make an interface from a class
• Code level mods
– make a code segment a function
Refactoring - 13
Refactoring
• JDT has actions for refactoring Java
code
Refactoring - 14
Refactoring
• Refactoring actions rewrite source code
– Within a single Java source file
– Across multiple interrelated Java source
files
• Refactoring actions preserve program
semantics
– Does not alter what program does
– Just affects the way it does it
Refactoring - 15
Refactoring
• Full preview of all ensuing code changes– Programmer can veto individual changes
List of changes
“before” vs. “after”
Refactoring - 16
Refactoring
• JDT has actions for refactoring Java
code
Refactoring - 17
Refactoring
• Growing catalog of refactoring
actions
– Organize imports
– Rename {field, method, class,
package}
– Move {field, method, class}
– Extract method
– Extract local variable
– Inline local variable
– Reorder method parameters
Refactoring - 18
Cechy języka utrudniające refaktoryzację
• Mechanizm refleksji
• określenie klasy danego obiektu,
• uzyskanie informacji nt. modyfikatorów klasy, pól, metod, konstruktorów i nadklasy,
• odkrycie, jakie stałe i deklaracje metod należą do danego interfejsu,
• stworzenie instancji klasy, której nazwa nie jest znana do chwili uruchomienia programu,
• pobranie i ustawienie wartości pola obiektu, nawet jeśli nazwa pola nie jest znana aż do uruchomienia programu,
• wywołanie metody obiektu, nawet bez uprzedniej znajomości jej nazwy,
• stworzenie tablicy, której rozmiar i typ przechowywanych obiektów nie jest znany aż do chwili wykonania programu, a następnie modyfikowanie przechowywanych w niej obiektów.
Refactoring - 19
Wymagania stawiane narzędziom oraz algorytmom
• Zasada niezmienionego zachowania
• Samodzielne pozyskiwanie maksymalnej ilości potrzebnych danych
• Niemożność polegania na użytkowniku w sprawie bezpieczeństwa refaktoryzacji
• Udostępnianie użytkownikowi listy problemów
• Maksymalnie dobra jakość generowanego kodu
• Prostota i łatwość modyfikacji wygenerowanego kodu
• Brak kompilacji kodu w trakcie refaktoryzacji w celu sprawdzenia jego poprawności
Refactoring - 20
Wpływ dodania klasy na
zachowanie
• Przed
• import java.util.*;
• class A { HashMap m = new HashMap();}
• Po
• import java.util.*;
• class HashMap {}
• class A { HashMap m = new HashMap();}
Refactoring - 21
Refaktoryzacje (1)
• Zmiana nazwy (Rename)
• Przemieszczenie klasy (Move class)
• Przemieszczenie pola statycznego (Move static field)
• Przemieszczenie pola (Move field)
• Przemieszczenie metody statycznej (Move static method)
• Przemieszczenie metody nie-statycznej (Move non-static method)
• Ekstrakcja metody (Extract Method)
• Rozwinięcie wywołań metody (Inline method)
• Rozwinięcie odwołań do zmiennej (Inline variable)
• Wprowadzenie zmiennej objaśniającej (Introduce explaining variable)
• Awansowanie zmiennej do pola (Promote temporary to field)
• Zmiana nagłówka metody (Change method signature)
• Ekstrakcja interfejsu (Extract Interface)
• Ekstrakcja nadklasy (Extract Superclass)
Refactoring - 22
Refaktoryzacje (2)
• Przemieszczenie metody/pola w dół hierarchii dziedziczenia (Push down method/field)
• Przemieszczenie metody/pola w górę hierarchii dziedziczenia (Pull up method/field)
• Enkapsulacja dostępu do pola (Encalpsulate field)
• Użycie typu nadrzędnego gdzie to możliwe (Use Supertype where possible)
• Dodanie metod delegujących (Add delegate methods)
• Oczyszczenie deklaracji import (Clean imports)
• Minimalizowanie praw dostępu (Minimize Access Rights)
• Stworzenie metody fabrycznej (Create factory method)
• Wprowadzenie stałej (Introduce constant)
• Ustatycznienie metody (Make method static)
• Bezpieczne usunięcie (Safe delete)
• Zamiana klasy anonimowej na zagnieżdżoną (Convert anonymous to inner)
• Zastąpienie zmiennej wyrażeniem (Replace temp with query)
• Wyodrębnienie na zewnątrz łańcuchów tekstowych (Externalize Strings)
Refactoring - 23
Wprowadzenie Obiektu Null
• Przed
• class ZamykaczOkien {void pozamykaj() {
Okno o = znajdźOkno();if (o != null) {
o.zamknij();}
}Okno znajdźOkno() {
return null;}
}
• Po
• class ZamykaczOkien {void pozamykaj() {
Okno o = znajdźOkno();o.zamknij();
}
Okno znajdźOkno() {return new OknoNull();
}}
class OknoNull extends Okno {public void zamknij() {}
}
Refactoring - 24
Redukcja zakresu zmiennej
• Przed
• int i=1; zróbCoś(); zróbCośInnego();
obliczJeszczeCośInnego();
pierwszeUżycie(i);...
• Po
• zróbCoś(); zróbCośInnego();
obliczJeszczeCośInnego(); int i = 1;
pierwszeUżycie(i);
Refactoring - 25
Wprowadzenie Klasy
Wyliczeniowej (1)• Przed
• public class Person {
• public static final int BLOOD_GROUP_0 = 0;
• public static final int BLOOD_GROUP_A = 1;
• public static final int BLOOD_GROUP_B = 2;
• public static final int BLOOD_GROUP_AB = 3;
• private int bloodGroup;
• public Person(int bg) {
• bloodGroup = bg;
• }
• }
• Po
• public class Person {
• private BloodGroup bloodGroup;
• public Person(BloodGroup bg) {
• bloodGroup = bg;
• }
• }
• public class BloodGroup {
• public static final int 0 = new BloodGroup(0);
• public static final int A = new BloodGroup(1);
• public static final int B = new BloodGroup(2);
• public static final int AB = new BloodGroup(3);
• private int bloodGroup;
• private BloodGroup(int bg) {
• bloodGroup = bg;
• }
• }
Refactoring - 26
Wprowadzenie Klasy
Wyliczeniowej (2)
Refactoring - 27
Refaktoryzacja w Eclipse
Refactoring - 28
Refaktoryzacja w Eclipse
Refactoring - 29
Refaktoryzacja w Visual Studio