Zpo-9-lab

From Studia Informatyczne

Spis treści

Ćwiczenie 9. Refaktoryzacja oprogramowania w Javie za pomocą Eclipse IDE

Informacje wstępne

Ćwiczenie jest realizowane w języku Java w środowisku Eclipse 3.2. Przed przystąpieniem do realizacji ćwiczenia należy zapozanać się z nt. refaktoryzacji w Eclipse IDE Celem ćwiczenia jest wykonanie przekształceń refaktoryzacyjnych wybranych fragmentów kodu znajdujących się w załączonym projekcie

Instalacja

Przygotowanie do ćwiczenia polega na zainstalowaniu JDK 5.0 [1] oraz środowiska Eclipse [2] w wersji 3.2 Po uruchomieniu środowiska należy zaimportować (menu File->Import->Existing projects into workspace) projekt Sudoku autorstwa Henninga Vittinga, dostępny w serwisie SourceForge.net.

Ponadto należy zaimportować projekt zpo-9-lab.zip, niezbędny do prezentacji przekształcenia rozwinięcia zmiennej.

Zadanie

Na podstawie załączonego kodu programu przeprowadź następujące zmiany w programie, korzystając z mechanizmów refaktoryzacyjnych obecnych w Eclipse IDE.

Wyłączenie metody

Wyłączanie metody (ang. Extract Method) jest najprostszym przekształceniem refaktoryzacyjnym. Jest stosowane zwykle w stosunku do metod o zbyt dużej złożoności lub zbyt długich.

  1. W projekcie SuDoKu znajdź metodę o dużej złożoności (o wysokiej wartości złożoności McCabe'a), np. com.vitting.rcpsudoku.model.SudokuDocument.load().
  2. Zaznacz fragment metody, w którym nie są wykorzystywane zmienne lokalne (np. linie 65-71 w klasie SudokuDocument)
  3. Następnie z menu kontekstowego wybierz opcję Refactor->ExtractMethod. Pojawi się okienko, w którym należy wprowadzić nazwę metody (np. canReadVerification w przypadku klasy SudokuDocument) oraz jej zakres widoczności. Zwróć uwagę, że parametry metody są obliczane automatycznie na podstawie zmiennych zdefiniowanych poza zaznaczonym fragmentem, a do których istnieją odwołania wewnątrz niego.
  4. Możesz kliknąć klawisz Preview - zostanie wówczas wyświetlona nowotworzona metoda.
  5. Kliknij klawisz OK - wówczas zostanie utworzona nowa metoda o podanej nazwie, a w miejscu zaznaczonego fragmentu kodu zostanie umieszczone wywołanie tej metody.

image:extract-method.png

Jednak wyłączenie metody nie zawsze jest wykonalne. Spróbuj wyłączyć fragment tej samej metody pomiędzy liniami 138 i 145. Tym razem Eclipse zgłosi brak możliwości wykonania przekształcenia. Wytłumacz, dlaczego?

Zmiana sygnatury metody

Przekształcenie to jest złożeniem dwóch refaktoryzacji: dodania parametru i usunięcia parametru, a także pozwala zmieniać typ metody i zasięg jej widoczności. Służy właśnie do modyfikowania tych elementów metody, w tym przede wszystkim listy parametrów przekazywanych metodzie.

  1. Wskaż kursorem sygnaturę metody save() w klasie com.vitting.rcpsudoku.jfc.actions.SaveAction()
  2. Z menu kontekstowego wybierz opcję Refactor->Change Method Signature
  3. Pojawi się okienko, w którym możesz zmodyfikować wspomniane wcześniej wartości
  4. Dodaj do sygnatury nowy parametr typu Object o nazwie obj. Domyślną wartością może być dowolne wyrażenie, którego wartość jest określonego typu (w tym przypadku Object), np. new Object().
  5. Kliknij klawisz Preview. Pojawi się okienko z listą plików, które zostaną zmodyfikowane, oraz zakres zmian w każdym pliku.
  6. Kliknij OK. Sygnatura metody zostanie zmodyfikowana, a wszystkie wywołania tej metody zostaną poszerzone o nowy argument o wartości new Object().

Jednak istnieją sytuacje, w których to przekształcenie nie może zostać poprawnie zakończone.

  1. Wskaż kursorem metodę, która jest wymagana przez interfejs (np. metodę controlEnabled() w klasie com.vitting.rcpsudoku.jfc.actions.SaveAction()).
  2. Z menu kontekstowego wybierz opcję Refactor->Change Method Signature.
  3. Pojawi się ostrzeżenie. Co jest jego przyczyną?

image:change-signature.png

Przeniesienie składowej

Przekształcenie to służy do przeniesienia składowej (pola lub metody) do innej klasy. Stosowane jest zwykle w sytuacji, gdy odwołania do tej składowej w większości pochodzą z innej klasy.

W przypadku składowej statycznej może ona zostać przeniesiona do dowolnej klasy.

  1. Wskaż kursorem dowolną składową statyczną (np. pole PROPERTY_FILE_NAME w klasie com.vitting.sudoku.jfc.GuiPersistence.
  2. Z menu kontekstowego wybierz opcję Refactor->Move
  3. Pojawi się okienko z prośbą o wskazanie klasy, do której składowa ma zostać przeniesiona
  4. Kliknij Preview. Pojawi się okienko podglądu z listą modyfikowanych klas oraz zakresem zmian.
  5. Kliknij OK. Składowa zostanie przeniesiona

image:move-static.png

Natomiast w przypadku składowych niestatycznych (tzn. należących do instancji klasy) składowa może zostać przeniesiona do obiektu, który jest polem klasy źródłowej (jest to jedyna możliwość w przypadku przenoszenia pól) lub argumentem przenoszonej metody (w przypadku przenoszenia metody).

Przeniesienie metody powoduje również przekazanie w metodzie referencji do obiektu źródłowego.

  1. Wskaż kursorem metodę isEditMode() w klasie com.vitting.sudoku.jfc.MainWindow
  2. Z menu kontekstowego wybierz opcję Refactor->Move
  3. Pojawi się okienko, w którym zostaną wyświetlone potencjalne klasy docelowe (w tym przypadku będą to wyłącznie pola klasy źródłowej, ponieważ przenoszona metoda nie posiada argumentów). Okienko to pozwala na zmianę nazwy metody podczas przenoszenia oraz określenie nazwy parametru z obiektem źródłowym
  4. Kliknij Preview. Zostanie wyświetlone ostrzeżenie o zmiane zasięgu widoczności pola editMode. Kliknij Continue
  5. Zostanie wyświetlona lista modyfikowanych klas wraz z zakresem zmian. Przeanalizuj je.
  6. Kliknij OK. Metoda zostanie przeniesiona

image:move-nonstatic-target.png

Rozwinięcie

Przekształcenie to służy do rozwinięcia zmiennej (ang. Inline Temp) lub metody (ang. Inline Method), czyli jest komplementarne np. w stosunku do przekształcenia Extract Method

  1. Wskaż kursorem wywołanie metody setMessage(message, NORMAL) w metodzie setMessage(String) w klasie com.vitting.sudoku.jfc.MainWindow
  2. Z menu kontekstowego wybierz opcję Refactor->Inline
  3. Pojawi się okienko, w którym należy dokonać wyboru pomiędzy zastąpieniem wszystkich wywołań tej metody jej ciałem, czy tylko wskazanego wywołania. W przypadku wyboru wszystkich wywołań metoda setMessage(String, int) stanie się nie wykorzystywana i będzie mogła być usunięta. Wybierz opcję All Invocations
  4. Pojawi się okienko podglądu z listą modyfikowanych klas i zmianami, jakie zostaną wprowadzone. Przeanalizuj je. Zauważ, że rozwijana metoda została usunięta (jeżeli w poprzednim kroku zaznaczono opcję usunięcia metody).

image:inline-scope.png

Podobnie jak w poprzednich przypadkach, przekształcenie to nie zawsze może być poprawnie wykonane. W celu zaobserwowania takiego zachowania, zaimportuj projekt media:zpo-9-lab.zip i spróbuj wykonać rozwinięcie zmiennej st. Eclipse wykona przekształcenie, jednak wynik działania programu będzie inny. Dlaczego?

Przeniesienie składowych w obrębie hierarchii dziedziczenia

Do tej kategorii należą przekształcenia Pull up i Push down. Służą one odpowiednio do przeniesienia składowej do nadklasy lub do podklasy. W obu przypadkach podstawowym warunkiem wykonania przekształcenia jest istnienie w projekcie odpowiednio nadklasy (lub implementowanego interfejsu) i podklasy w postaci źródłowej.

  1. Wskaż kursorem metodę save() w klasie com.vitting.sudoku.jfc.actions.SaveAction
  2. Z menu kontekstowego wybierz opcję Refactor->Pull Up
  3. Pojawi się okienko, w którym należy wskazać docelowy typ, do którego ma być przeniesiona metoda. W tym przypadku jedynym dopuszczalnym typem jest interfejs IAction, ponieważ pozostałe (klasa JButton oraz interfejs ActionListener są dostępne jedynie jako binaria. Za pomocą klawisza Set Required można dołączyć inne składowe, które są wykorzystywane przez przenoszoną metodę, i które także mogą być przeniesione wraz z nią. Klawisz Set Action służy do określenia typu wykonywanej akcji.
  4. Klikając kolejno klawisze Next wykonaj przekształcenie, analizując poszczególne etapy.

Hermetyzacja pola

Za pomocą środowiska Eclipse wykonaj przekształcenie hermetyzacji pola (ang. Encapsulate Field) na zmiennej saveFile w klasie com.vitting.sudoku.model.SudokuDocument

Wyłączenie nadklasy

Za pomocą środowiska Eclipse wykonaj przekształcenie utworzenia nadklasy klasy com.vitting.sudoku.model.SudokuDocument. Przenieś do niej wszystkie metody z klasy com.vitting.sudoku.model.SudokuDocument.

Literatura

  1. D. Gallardo "Refactoring for everyone" IBM DeveloperWorks