Tytułem wstępu

Treści tu zawarte odpowiadają całkowicie tym zawartym w prezentacji dołączonej do archiwum, a nawet można tu znaleźć nieco więcej przykładzików i komentarzy których w prezentacji nie ma. Jednakże poniższy tekst nie był docelowo wersją mającą wyjść na światło dzienne, nie ręcze więc za wszelkiego typu błędy językowe czy składniowe.

Dla orientacji: można mieć pewność że wszystko co pisane jest czcionką taką jak ten wstęp, istnieje tylko i wyłącznie w tych notatkach (odwrotnie się to jednak nie sprawdza - niektórych niewyróżnionych informacji w slajdach też nie będzie)

Zwłaszcza w pierwszej części można znaleźć dużo linków do przykładów refaktoryzacji prostych, których ze względów na ograniczony czas prezentacji, w slajdach nie umieściłem.

Tyle tytułem wstępu, jeśli powyższy tekst Cie nie przestraszył to zapraszam do ,,lektury"

Jednoczesnie pragne zaznaczyc, iż material zamieszczony w rozdziale 3 "Trudności napotykane podczas refaktoryzacji Javy", stanowi streszczenie fragmentu pracy magisterskiej p. Adama Kieżuna (link na dole strony)

Adam Mazur


Konspekt

  1. Co to jest refaktoryzacja
  2. Rodzaje refaktoryzacji
  3. Trunosci napotykane przy refaktoryzacji (na przykladzie Javy)
  4. Narzedzia (wyszczególnienie dostępnych narzędzi, oraz co potrafia)
  5. Linki

Co to jest refaktoryzacja

Refaktoryzacja, to zmiana organizacji struktury kodu programu, jednak z zachowaniem integralności jego działania.

Ładnie to widać w matyce - mając liczbę 6432 można ja reprezentować jako 32 * 3 * 67. Refaktoryzując ja do 8 * 12 * 67 otrzymamy dokładnie ten sam produkt (6432) ale o innej strukturze.


Do czego to?

Dostosowanie istniejących programów komputerowych do nowych lub zmieniających się wymagań jest trudne i czasochłonne. Jednym ze sposobów radzenia sobie z tym zadaniem jest refaktoryzacja - proces przekształcania kodu źródłowego niezmieniający działania programu. Ułatwia on budowę i pielęgnację oprogramowania, umożliwiając utrzymanie systemu komputerowego w stanie pozwalającym na łatwą rozbudowę. Refaktoryzacja jest jednak procesem czasochłonnym i podatnym na błędy, wobec czego pożądana jest jej automatyzacja. Stworzenie niezawodnych i wydajnych narzędzi wspierających programistów w tym zadaniu jest niezbędnym warunkiem do tego, by refaktoryzacja mogła stać się powszechnie przyjętą techniką tworzenia i pielęgnacji programów.

Ułatwia on budowę i pielęgnację oprogramowania, umożliwiając utrzymanie systemu komputerowego w stanie pozwalającym na łatwą rozbudowę.

Poza tym refaktoryzacja jest znacznie tansza niz przepisywanie kodu od nowa


Języki...


Rodzaje refaktoryzacji:

Refaktoryzacje proste mozna to podzielić na: Podzial ten nie jest absolutnie scisly, wrecz troszke sztuczny, a wzial sie z http://c2.com/cgi/wiki?RefactoringLanguage oraz z ksiazki Martina Flower'a "Refactoring: Improving the Design of Existing Code"
Bardziej bierzaca lista refaktoryzacji jest na http://www.refactoring.com/catalog/

Organizacja klas:

wiecej nie ma, np. przenoszenie klasy w gore/w dol hierarchii jest w "postepowaniu z uogolnieniami" pod postacia "extract subclass" i "extract superclass"

Składanie metod:

Within methods

Organizing Data: Making Method Calls Simpler: Dealing With Generalization: MetaRefactoring: BigRefactorings: (originally described by MartinFowler) RefactoringLegacyCode: JavaLanguage Specific: (RefactoringIdioms?)

Trudności napotykane podczas refaktoryzacji Javy

Dlaczego wybralem Jave?
Python nie jest az tak popularny
SmallTalku ma swoje wlasne narzedzie do refaktoryzacji
C i C++ w porownaniu z Java sa duzo bardziej skomplikowanymi i "zasmieconymi skladniowo" jezkami (choc narzedzi do nich jest troche)

Wielokrotne dziedziczenie interfejsów oraz efekt fali

  1. Jak wyglada dziedziczenie interfejsow w Javie

    • ze wielodziedziczenie, bez cykli
    • podklasy tez musza implementowac interfejs nadklasy (lub dziedziczyc)
    • metody z interfejsow musza byc instancyjne i publiczne
  2. Zmiana nazwy metody w SmallTalku (pojedyncze dziedziczenie)

    1. Sprawdź, czy metoda o nowej nazwie (sygnaturze) nie jest już zadeklarowana w hierarchii danego typu - jeśli tak, to zmiana nazwy nie jest możliwa.
    2. Znajdź najbardziej abstrakcyjny typ deklarujący daną metodę.
    3. Zmień nazwę metody we wszystkich podtypach znalezionego typu.
  3. Przyklad w Javie

    Poprzedni algorytm jest niewystarczajacy, np:
    
    	interface I1{
    	    public void m();
    	}
    	interface I2{
    	    public void m();
    	}
    	class A implements I1, I2{
    	    public void m(){}
    	}
    	
    Zmiana nazwy metody I1::m() musi pociągać za sobą zmianę nazwy A::m() - w przeciwnym razie powstanie błąd kompilacji. Zauważmy także, że również nazwa I2::m() musi ulec zmianie.
  4. Efekt fali

    • Jak widać na poprzednim przykladzie zmiana nazwy metody jest przenoszona po grafie typów.
    • takie zjawisko można nazwać efektem fali (ang. ripple effect)
    • fala może się rozchodzić po wielu klasach i interfejsach.
    • algorytm wyszukiwania metod, których nazwy należy zmienić, powinien przeglądać graf typów w górę i w dół począwszy od maksymalnie abstrakcyjnego typu deklarującego daną metodę.
    • Nie tylko zmiana nazwy metody powoduje efekt fali.
      Powyzszy algorytm stosowac mozna (należy!) niemal przy kazdej refaktoryzacji (np. dodanie/usuniecie parametru metody, usuniecie metody, zmiana kolejnosci parametrow metody...)
  5. Dodatkowe problemy:

    1. Nie wszystkie typy wzdłuż fali muszą deklarować metodę o sygnaturze takiej, jak sygnatura metody, której nazwę chcemy zmienić.
      Rozważmy następujący przykład pokazujący, że wystarczy, by metoda taka była odziedziczona z nadklasy:
      
      			interface I{
      			    public void m();
      			}
      			class A{
      			    public void m(){}
      			}
      			class B extends A implements I{
      			}
      		
      Po zmianie nazwy metody I::m() również nazwa metody A::m() musi zostać zmieniona.
    2. W pewnych sytuacjach fala zatrzymuje się - metody niewirtualne nie zastępują metod wirtualnych i wobec tego zatrzymują falę.
      Podobny do poprzedniego przykład:
      
      		interface I{
      		    public void m();
      		}
      		class A{
      		    private void m(){}
      		}
      		class B extends A implements I{
      		    public void m() {}
      		}
      		
      Zmianie nazwy metody I::m() musi towarzyszyć zmiana nazwy metody B::m(), natomiast metoda A::m() może pozostać nieprzemianowana.
  6. Jeszcze o interfejsach

    Opublikowane interfejsy: publicznie dostepne
    • jezeli inni ludzie korzystaja z opublikowanego przez nas interfejsu:
      jego refaktoryzacja wymusza pozostawienie starych nazw i sygnatur w celu zachowania zgodnosci wstecz
    • jezeli my korzysatmy z opublikowanego przez innych interfejsu:
      lepiej jest stworzyc wlasny interfejs nad ktorym mamy pelna kontrole (i mozemy go refaktoryzowac) a ktory bedzie ewentualnie wykorzystywal obce interfejsy

Przestrzenie nazw typów

  1. Java - przestrzenie nazw typów

    • nazwy proste (np. Object) i unikatowe kanoniczne (np. java.lang.Object)
    • nazwy proste przewazaja (wygoda, czytalnosc kodu)
    • jesli w ktoryms fragmencie kodu wystepuja dwie takie same nazwy proste to
      1. nazwa jednego z tych typów przesłania (lub ukrywa) pozostałe
      2. dwie lub więcej nazw pozostaje w konflikcie i powstaje błąd kompilacji
  2. Java - deklaracje importu

    • w celu uzycia nazwy prostej trzeba wczesniej zaimportowac dany typ
    • import pojedynczego typu (pelna nazwa typu: pakiet.nadtypy.typ) kontra import na zadanie (pakiet z koncowka .* - wszystkich publicznych, niezagnieżdżonych typów zdefiniowanych w tym pakiecie)
    • import na żądanie nigdy nie przesłania żadnych deklaracji, natomiast import pojedynczego typu przesłania deklaracje typów importowanych na żądanie oraz typów importowanych domyślnie (tzn. typów zdefiniowanych w pakiecie, w którym znajduje się importująca jednostka kompilacji oraz typów zdefiniowanych w wyróżnionym pakiecie o nazwie java.lang)
    • jesli odniesienia nie są jednoznaczne, to zgłaszany jest błąd kompilacji
      szerzej: jeśli jednostka kompilacji importuje dwa lub wiecej typów (import na żądanie) o tej samej nazwie prostej i występują wewnątrz niej odniesienia do jednego z tych typów używające jego nazwy prostej, to jest zgłaszany błąd kompilacji (odniesienia nie są jednoznaczne).
  3. import - przykład zachowania (1)

    
    	"A.java"
    	package p1;
    	public class A{}
    
    	"B.java"
    	package p2;
    	public class B{}
    
    	"Test.java"
    	package test;
    	import p1.A;
    	import p2.B;
    	class Test{
    	    B b;
    	}
    	
    Zmiana nazwy typu A na B (wraz z aktualizacją odniesień) daje w rezultacie błąd kompilacji w ostatniej jednostce kompilacji - która importuje wówczas (import pojedynczego typu) dwa typy o tej samej nazwie prostej (tj. B)
  4. import - przykład zachowania (2)

    
    	"A.java"
    	package p;
    	public class A{}
    
    	"Test.java"
    	package test;
    	import java.util.*; //zawiera typ List
    	import p.*;
    	class Test{
    	    A a;
    	    List l; /*1*/
    	}
    	
    Jeśli zmienimy nazwę typu A na List, to odniesienie w wierszu oznaczonym przez /*1*/ stanie się niejednoznaczne, co spowoduje błąd kompilacji
  5. import - przykład zachowania (3)

    
    	"B.java"
    	package p1;
    	public class B{
    	    public static int x= 42;
    	}
    
    	"A.java"
    	package p;
    	public class A{
    	    public static int x= 0;
    	}
    
    	"Test.java"
    	package p;
    	import p1.B;
    	class Test{
    	    static int i;
    	    static {
    	        i= A.x;
    	    }
    	}
    	
    zmieniając nazwe p1.B na A, działanie programu ulega zmianie (bez wystąpienia błędów kompilacji) przez przesłonięcie widoczności typu zdefiniowanego w tym samym pakiecie, ale innej jednostce kompilacji.

    Jeśli jedynie zmienimy nazwę typu p1.B na A (wraz z aktualizacją wszystkich odniesień do tego typu), to pole i w klasie Test zostanie zainicjalizowane wartością 42, a nie 0, jak poprzednio. Pomimo zmiany w działaniu programu, pozostaje on poprawny, tzn. nie powstają błędy kompilacji. Zauważmy, że działanie programu się zmienia, mimo, że w klasie Test nie ma odniesień do typu p1.B, którego nazwę zmieniamy. Importowanie typu (i związane z tym przesłanianie) wystarcza, by w istotny sposób zmienić funkcjonowanie programu.

  6. import - przykład zachowania (4)

    
    	package p;
    	import java.util.*; // zawiera klase ArrayList
    	class A{
    	    public Object m(){
    	        return new ArrayList();
    	    }
    	}
    	
    Samo stworzenie w pakiecie p klasy o nazwie ArrayList spowoduje, że metoda A::m() przekaże obiekt klasy innej niż dotychczas, zmieniając w ten sposób działanie programu (bez powodowania błędów kompilacji).
  7. Typy zagnieżdżone

    Nazwy typów zagnieżdżonych przesłaniają widoczność nazw innych typów oraz zaciemniają widoczność nazw pakietów. Spójrzmy na przykład:
    
    		import java.util.*; //zawiera typ Stack
    		class A{
    		    class B{
    		        Object m(){
    		            return new Stack{};
    		        }
    		    }
    		}
    		
    Zmiana nazwy klasy dowolnej z klas A lub B na Stack spowoduje zmianę działania programu - bez powstania błędów kompilacji.
  8. Typy zagnieżdżone

    • równie ważną konsekwencją używania typów zagnieżdżonych jest niejednoznaczność nazw typów, jaka się wówczas pojawia
    • w pewnych warunkach, liczba sposobów, na jakie możemy się odnosić do jednego, zagnieżdżonego typu, jest nieograniczona (kolejny przyklad - jest bardzo zawily)
    • ta cecha języka wpływa na znaczne zwiększenie możliwych przesłonięć nazw typów

    Każda z podanych nazw może być przesłaniana (lub zaciemniana) niezależnie od innych. Podczas refaktoryzacji musimy, po pierwsze, odszukać je wszystkie jako odniesienia to danego typu, a po drugie analizować każdą z nich oddzielnie. Zmiana nazwy lub położenia typu, dodanie nowego typu do systemu oraz wszelkie zmiany w hierarchiach dziedziczenia, czy zawierania) to kilka przykładów refaktoryzacji, które mogą być niepoprawne, jeśli nie zostaną poprzedzone analizą przypadków przedstawionych w tym punkcie (tych a'propo przeslaniania typow zagniezdzonych).

  9. Typy zagniezdzone - przyklad

    wszystkie zmienne oznaczone /**/ sa tego samego typu (o kanonicznej nazwie p.O.I.J)
    
    	package p; 
    	public class O{
    	    public class I{
    	        public class J{} 
    	        J j; /**/ 
    	    } 
    	    I.J ij; /**/ 
    	} 
    	class O1 extends O{ 
    	    class O2 extends O.I{ 
    	        O2(O o){ o.super(); }
    	    } 
    	    O2.J o2j; /**/
    	} 
    	class Test{ 
    	    O.I.J oij; /**/ 
    	    p.O.I.J poij; /**/ 
    	    O1.I.J o1ij; /**/ 
    	    p.O1.I.J po1ij; /**/ 
    	    O1.O2.J o1o2j; /**/
    	    p.O1.O2.J po1o2j; /**/ 
    	} 
    	
  10. Typy lokalnie zdefiniowane

    • Typy można deklarować w dowolnym miejscu metody - tak, jak zmienne lokalne.
    • Nazwy typow lokalnie zdefiniowanych przesłaniają widoczność nazw innych typów począwszy od miejsca deklaracji.
    • przyklad: zmiana typu o kanonicznej nazwie p.X na A spowoduje ze metoda Test::m() przekaże obiekt innego typu.
      
      	package p; 
      	class X{}
      	class Test{ 
      	    Object m(){
      	        class A{};
      	        return new X(); /*1*/
      	    }
      	}
      	
  11. Postępowanie w wypadku wystąpienia konfliktu nazw typów

    narzędzie do refaktoryzacji może posłużyć się jedną z dwóch strategii:
    1. tarać się naprawić kod
      tzn. rozwiązać konflikt przez zamianę nazw prostych na nazwy kanoniczne
    2. uznać wystąpienie takiej sytuacji za niepożądane i zabronić refaktoryzacji
    Trzeba jednak pamietac ze próba naprawy kodu moze okazac sie nieskuteczna (...i byc moze trzeba bedzie jeszcze dodatkowych zmian)
    Dodatkowo, dlugie nazwy raczej psuja niz poprawiaja estetyke kodu

Przesłanianie, ukrywanie i zaciemnianie nazw (w Javie)

  1. Przesłanianie

    • przesłanianie (ang. shadowing) opisane jest w punkcie 6.3.1 specyfikacji języka Java tymbardziej wiec nie jest niepoprawną technika programowania
    • deklaracje mogą być przesłaniane w częściach swych zasięgów przez inne deklaracje o tej samej nazwie
    • przykład: jak przesłanianie wpłynie na zmianę nazwy pola:
      
      	class S{
      		protected int g;
      	}
      	class A extends S{
      		public int m(int p){
      			return g + p;
      		}
      	}
      	
      zmiana nazwy pola g na p powoduje, że jego deklaracja zostaje przesłonięta przez nazwę parametru w treści metody A::m()
  2. Ukrywanie

    • ukrywania (ang. hiding) odnosi się do elementów, które byłyby odziedziczone z nadtypów - jednak nie są, z powodu istnienia deklaracji w podtypie
    • przykład procesu refaktoryzacji:
      
      	class A{
      		protected int f;
      	}
      	class B extends A{
      		void m(){
      			f= 42; /*1*/
      		}
      	}
      	
      po dodaniu do klasy B nowego pola typu int, o nazwie f, należałoby wiersz oznaczony przez /*1*/ zmienić na: ((A)this).f= 42; /*1*/
  3. Zaciemnianie

    • specyfikacja języka stwierdza, że nazwy proste mogą występować w różych kontekstach - w takich sytuacjach zmienna ma pierwszeństwo przed typem, a typ przed pakietem
    • przykład refaktoryzacji:
      
      	class X {
      		static int length(){
      			return 42;
      		};
      	}
      	class Test {
      		String s= "hello";
      		int m(){
      			return X.length(); /*1*/
      		}
      	}
      	
      Zmiana nazwy typu X na s nie powoduje błędów kompilacji, a działanie programu zostanie zmienione.
      ...wywołanie metody Test::m() przekazuje wartość 5, a nie 42, jak poprzednio.
      Analogicznie istnieja inne rodzaje zaciemniania - nazwa zmiennej zaciemniająca nazwę pakietu, nazwa typu zaciemniająca nazwę pakietu.
  4. Postępowanie w przypadku wystąpienia przesłaniania, ukrywania lub zaciemniania

    Ogolnie sa dwie strategie:
    1. mozemy starać się odpowiednio zmodyfikować kod
      zaleznie od sytuacji - w niektórych przypadkach niezbędne jest wprowadzenie rzutowania (ang. downcast), w innych użycie w pełni kwalifikowanych nazw typów itd.
    2. lub tez zabronic refaktoryzacji (ew. zmienic jej parametry)

Przeciążanie nazw metod (w Javie)

  1. Refaktoryzacje mogą prowadzić zarówno do eliminowania, jak i do powstawania przeciążania
  2. powstawanie przeciążenia:
    
    	class Foo{
    		void a(String s){}
    		void b(Object s){}
    	}
    	...
    	void cos( Foo f ) {
    		f.a("hello");
    		f.b("hello");
    	}
    	
    Zmiana nazwy metody Foo::b na Foo::a powoduje, że wczesniejsze wywołanie b("hello") musi zostać zastąpione przez a((Object)"hello").
  3. eliminowanie przeciążenia:
    
    	class Foo{
    		void a(String s){}
    		void a(Object s){}
    	}
    	...
    	void cos( Foo f ) {
    		f.a("hello");
    		f.a((Object)"hello");
    		f.a( f );
    	}
    	
    Zmieniając nazwe metody Foo::a(Object) na Foo::b, musimy dla każdego wołania przeciążonej metody Foo::a badać typ przekazywanego parametru (może się zdarzyć że przekazywany parametr bedzie niejawnie rzutowany na typu parametru, lub z niego dziedziczy)

Przypadki specjalne (Java)

  1. metoda toString()
    • jest zadeklarowana w klasie java.lang.Object
    • wywoływana domyślnie przez użycie operatora + wtedy, gdy co najmniej jeden z argumentów jest obiektem klasy java.lang.String
      dozwolona jest więc konstrukcja np. String f= "a" + new Exception();
    • zagrożenie dla refaktoryzacji jest takie, że zmiana nazwy tej metody lub jej położenia może prowadzić do niepożadanych sytuacji
  2. Pakiet java.lang
    • wszystkie publiczne typy z pakietu java.lang są zawsze importowane niejawnie (import na żądanie)
      - należy o tym pamietać zwłaszcza przy refaktoryzacji
    • ponadto nazwy wielu typów zadeklarowanych w tym pakiecie są na stałe zakodowane w maszynie wirtualnej Javy
    • możemy więc założyć, że nie wolno:
      1. zmienić nazwy ani położenia żadnego typu zadeklarowanego w tym pakiecie,
      2. zmienić nazwy tego pakietu
  3. (!) metoda main
    • nie jest możliwa, bez zmiany zachowania programu, zmiana nazwy, położenia, typu wyniku, typu i liczby argumentów tej metody, jak również jej modyfikatorów (...)
    • nie można także zmienić nazwy i położenia typu, w którym jest zadeklarowana (ani żadnego z zawierających go typów)
    • zmiana nazwy pakietu, w którym znajduje się typ deklarujący taką metodę również spowoduje błąd
    Przy wprowadzaniu jednej z powyższych refaktoryzacji należy pamietać o aktualizacji zewnętrznych programów uruchamiających refaktoryzowany program w Javie (skryptów, programów wsadowych i innych)
  4. niejawne dziedziczenie z java.lang.Object

    W specyfikacji języka napisano ([JLS2 9.2]), że: ,,jeżeli interfejs nie ma żadnych bezpośrednich nadinterfejsów, wówczas niejawnie deklaruje
    publiczną, abstrakcyjną metodę m o sygnaturze s, typie wyniku r oraz klauzuli throws t
    odpowiadającą każdej z
    publicznych metod instancyjnych m o sygnaturze s, typie wyniku r oraz klauzuli throws t
    zadeklarowanych w klasie java.lang.Object, chyba, że
    metoda o tej samej sygnaturze, typie wyniku i odpowiadającej klauzuli throws
    jest jawnie zadeklarowana w tym interfejsie.''

    Wynika z tego, że zgłaszany jest błąd kompilacji, jeżeli interfejs deklaruje metodę o tej samej sygnaturze i odmiennym typie wyniku bądź nieodpowiadającej klauzuli throws.

    z tej reguły wynika pewna liczba ograniczeń dla niektórych refaktoryzacji

  5. mechanizm odbicia
    • pozwala na dynamiczny dostęp do elementów programu używając ich nazw, które mogą być określone dopiero podczas działania systemu
    • Przykładowo, tak też można wywołać metodę m obiektu o:
      o.getClass().getMethod("m", null).invoke(o)
      Zmiana nazwy metody m spowoduje, że efektem wykonania podanego fragmentu kodu będzie zgłoszenie wyjątku

Narzędzia do refaktoryzacji

  1. Ewolucja

    • Jeszcze 4 lata temu rzadko ktore narzedzie obslugiwalo wiecej niz 15 refaktoryzacji.
    • Obecnie modne stalo sie "extreme programming" - a refaktoryzacja jest jedynym sposobem aby utrzymac i rozwijac poprawne programy
    • niemal wszystkie wymienione narzedzia dedykowane są conajmniej platformom Windows, Linux i MacOS
    • znacznie poprawił się interfejs uzytkownika
  2. JRefactory

    (darmowe)
    http://jrefactory.sourceforge.net/
    • The software is free, and was provided "as is". (If you use it and find any bugs, then don't report them to us, add them to the JRefactory bug list on SourceForge. The backlog of bugs is gradually being worked on, but don't expect a fix the same day. Similarly, request for enhancements should be made to the Feature Requests tracker.
    • The following IDEs are supported. Versions numbers of the IDEs are those that JavaStyle has been tested on.
      • jEdit (4.1final and 4.2pre11) - good support in latest version of JavaStyle.
      • Netbeans (3.6) - partial support, but not yet fully integrated.
      • JBuilder X - partial support, but not yet fully integrated
      • Ant (1.5.4) - pretty printing only
      • Stand-alone application - works well but has very limited editing support, its more a demonstration than anything else.
      • there is partial support for several other IDEs in CVS (Cafe, elixir, jDeveloper, jooda and kawa)
      This tool comes as a command line option with GUI or without, and as a plugin for the JEdit (still under development), JBuilder, NetBeans, and Elixir IDEs.
      For JBuilder and Elixir you can switch from the UML diagram to the source code.
    • JRefactory is a tool that allows you to perform the following refactorings:
      • Move class between packages (repackage)
      • Rename class
      • Add abstract parent class
      • Add child class
      • Remove empty class
      • Extract interface
      • Push up field
      • Push down field
      • Rename Field
      • Push up method
      • Push up abstract method
      • Push down method
      • Move method
      • Extract method
      • Rename Parameter
  3. TransMogrify

    (darmowe)
    http://transmogrify.sourceforge.net/
    http://sourceforge.net/projects/transmogrify/
    • At this time, Transmogrify is available as a plug-in for two IDEs: Borland's JBuilder, and Sun's Forte4Java.
    • Had been written in Java
    • In addition to reference and definition finding, it can perform the following refactorings:
      • Rename Symbol--like Rename Variable except it (sort of) works for methods, too. Care must be taken when renaming interface or overridden methods.
      • Extract Method
      • Replace Temp With Query
      • Inline Temp
      • Pull up field
  4. Eclipse

    (darmowe)
    http://www.eclipse.org/
    http://www-106.ibm.com/developerworks/opensource/library/os-ecref/
    • Eclipse is a kind of universal tool platform - an open extensible IDE for anything and nothing in particular.
    • Eclipse's refactoring tools can be grouped into three broad categories:
      1. Changing the name and physical organization of code, including renaming fields, variables, classes, and interfaces, and moving packages and classes
      2. Changing the logical organization of code at the class level, including turning anonymous classes into nested classes, turning nested classes into top-level classes, creating interfaces from concrete classes, and moving methods or fields from a class to a subclass or superclass
      3. Changing the code within a class, including turning local variables into class fields, turning selected code in a method into a separate method, and generating getter and setter methods for fields
      Several refactorings don't fit neatly into these three categories
    • Short summary: one of the bests tool
  5. JavaRefactor for jEdit

    (darmowe)
    http://www.jedit.org/
    • JavaRefactor is a plugin for jEdit
    • jEdit - edytor tekstowy, wspomaga ponad 80 jezykow programowania
    • Written in Java, so it runs on MacOS X, OS/2, Unix, VMS and Windows.
    • extensible plugin architecture. Dozens of macros and plugins available.
    • Refaktoryzacje:
      • class, field, method, and package renaming
      • PushDown and PullUp of methods and fields in an inheritance hierarchy
  6. Borland JBuilder 2005 (Foundation/Developer/Enterprise)

    (komercyjne)
    http://www.borland.com/jbuilder/pdf/jb2005_feature_matrix.pdf
    • Features (not all!):
      • extract interface/method
      • introduce a variable/field
      • add/remove/reorder parameters
      • convert existing loops to enhanced loops (JDK 5.0)
      • surround with try/catch a code selection and automatically add specific catch blocks for all detected and selected exceptions
      • rename packages/classes/methods/fields/methods arguments/local variables
      • move classes
      • pull up/push down methods/fields
      • introduce superclass from multiple classes
      • delegate to instance
      • invoke refactoring from UML diagrams
  7. Xrefactory

    (komercyjne... ale licencje od 29$, a licencja na 8 dni za darmo)
    http://xref-tech.com/xrefactory-java/main.html
    • also known as Xref, X-ref and Xref-Speller
    • a professional development tool for C and Java providing code completion, source browsing and refactoring - it's a Refactoring Browser for Emacs, XEmacs and jEdit.
      (eg. full undo is only under Emacs and XEmacs)
    • Designed to work with the largest projects.
      Xrefactory indexes all JDK 1.4 classes (1 million lines of code) in 2 minutes and the Linux kernel 2.4.7 sources (3 millions lines) in 15 minutes.
    • Refactorings for:
      • method (function) extraction
      • renaming of packages, classes, parameters, variables, fields (structure records) and methods (functions);
      • insertion, deletion and moving of parameters, fields and methods;
      • pushing down and pulling up fields and methods;
      • encapsulate field;
      • and more...
      Refactorings are safe with detection of possible conflicts
  8. RefactorIT

    (komercyjne, 30€ za okrojona wersje "Personal")
    http://www.refactorit.com/
    • it's plugin for Eclipse, JDeveloper, NetBeans and JBuilder. RefactorIT comes also with a stand-alone edition for users of other IDEs or text-oriented editors (e.g. EMACS)
    • refactorings:
      • Rename method, field, type, Package Prefix
      • Move Class, Method/Field; Pull up/Push down in Hierarchy
      • Extract, Method, Superclass/Interface
      • Create Factory Method, Constructor; Add Delegate Methods; Override/Implement Methods
      • Inline Variable, Method
      • Introduce Explaining Variable
      • Change Method Signature
      • Clean Imports
      • Convert Temp To Field
      • Encapsulate Field
      • Minimize Access Rights
      • Use Supertype Where Possible
  9. jFactor™ for VisualAge Java

    (komercyjne)
    http://www.instantiations.com/jfactor/
    • works only with Windows, and IBM VisualAge version 3.0 and higher
    • Refactorings:
      • methods: extract, rename, inline, pull up, push down, save delete, introduce foreign
      • fields: rename, pull up, push down, encapsulate
      • extract superclass/interface
      • rename method arguments and local variables
      • introduce explaining variable
      • inline temp
      • replace magic number with symbolic links
    • W porownaniu z poprzednimi oraz z cena (prawie 700$) - troszke malo mozliwosci
  10. IntelliJ IDEA

    (komercyjne, Academic License - 99$)
    http://www.jetbrains.com/idea/
    • Wspomagane refaktoryzacje:
      • Inline constant, Local Variable, method
      • Extract subclass (rename the original class and make it an implementation of the newly created superclass. IDEA will alter all original class usages to the usages of the implementing class only where it is still necessary)
      • Replace Method Code Duplicates (locate all places in the current file where the selected method code is fully repeated and turn all such code blocks into the corresponding method calls)
      • Convert To Instance Method
      • Renaming of packages, classes, methods, fields, method parameters and local variables
      • Moving classes, packages; also moving static methods, fields or inner classes
      • Move Inner Class to Upper Level
      • Change Method Signature (add/remove/reorder parameter, change return/parameter type)
      • Make Method Static
      • Copy/Clone Class
      • Extract Method, Interface, Superclass
      • Introduce Variable, Field, Constant, Parameter
      • Use Interface Where Possible (replacing particular class usages with references to its superclass or interface. It is especially useful after the Pull Members Up refactoring)
      • pull up / puch down class members
      • Replace Inheritance with Delegation
      • Convert Anonymous Class to Inner
      • Encapsulate Fields
      • Replace Temp With Query
      • replace Constructor With Factory Method
  11. jeszcze jedno porownanie kilku narzędzi

    porownanie paru najpopularniejszych narzedzi oraz
    opis/tlumaczenie do tegoz porownania

Linki