Jak odmienić sposób programowania używając refaktoryzacji

Nie będzie tu kwiecistych wyjaśnień wszystkich możliwych refaktoryzacji, nie będzie przykładów wyrwanych z kontekstu. W

729 133 585KB

Polish Pages [55] Year 2009

Report DMCA / Copyright

DOWNLOAD FILE

Polecaj historie

Jak odmienić sposób programowania używając refaktoryzacji

Table of contents :
Przedmowa
Wstep
Zaczac od siebie
Wstep
Dla kogo jest ta ksiazka
Wstep
Podziekowania
Refaktoryzacja - o co tyle krzyku
Refaktoryzacja - o co tyle krzyku
Czym jest refaktoryzacja?
Postulaty nowoczesnej inzynierii oprogramowania, czyli odpowiedz na pytanie ,,Dlaczego?''
Postulaty dotyczace współczesnej inzynierii oprogramowania
Refaktoryzacja - o co tyle krzyku
Postulaty nowoczesnej inzynierii oprogramowania, czyli odpowiedz na pytanie ,,Dlaczego?''
Koszt wytwarzania oprogramowania
Entropia wzrasta
Refaktoryzacja - o co tyle krzyku
Postulaty nowoczesnej inzynierii oprogramowania, czyli odpowiedz na pytanie ,,Dlaczego?''
Refaktoryzacja w locie
Refaktoryzacja - o co tyle krzyku
Postulaty nowoczesnej inzynierii oprogramowania, czyli odpowiedz na pytanie ,,Dlaczego?''
Refaktoryzacja ewolucyjna
Najwazniejsza ze wszystkich zasad - wydzielanie odpowiedzialnosci
Refaktoryzacja - o co tyle krzyku
Antywzorce w kodzie
Don't repeat yourself (DRY) - likwiduj powtórzenia
Długie metody i duze klasy
Refaktoryzacja - o co tyle krzyku
Antywzorce w kodzie
Zmiana lub dodanie funkcjonalnosci powoduje koniecznosc wielu zmian w systemie
Metoda danej klasy wykonuje zbyt wiele operacji na innych klasach
Analogiczne instrukcje warunkowe w róznych miejscach w projekcie
Nie twórz bytów ponad miare
Pola tymczasowe
Refaktoryzacja - o co tyle krzyku
Antywzorce w kodzie
Klasa przechowujaca tylko i wyłacznie dane
Komentarze
Refaktoryzacja - o co tyle krzyku
Testowanie
Kod, który czyta sie jak ksiazke - techniki, które całkowicie odmienia twoje zycie programisty
Kod, który czyta sie jak ksiazke - techniki, które całkowicie odmienia twoje zycie programisty
Co to znaczy - czytac jak ksiazke
Przykład
Kod, który czyta sie jak ksiazke - techniki, które całkowicie odmienia twoje zycie programisty
Przykład
Bardzo krótkie wprowadzenie do wyrazen regularnych
Kod, który czyta sie jak ksiazke - techniki, które całkowicie odmienia twoje zycie programisty
Przykład
Analiza struktury strony
Kod, który czyta sie jak ksiazke - techniki, które całkowicie odmienia twoje zycie programisty
Podstawowa zasada - wydzielanie odpowiedzialnosci
Kod, który czyta sie jak ksiazke - techniki, które całkowicie odmienia twoje zycie programisty
Refaktoryzacja: Wydzielenie metody
Kod, który czyta sie jak ksiazke - techniki, które całkowicie odmienia twoje zycie programisty
Refaktoryzacja: Zmiana nazwy klasy, metody, atrybutu lub zmiennej
Kod, który czyta sie jak ksiazke - techniki, które całkowicie odmienia twoje zycie programisty
Refaktoryzacja: Wydzielenie zmiennej tymczasowej
Kod, który czyta sie jak ksiazke - techniki, które całkowicie odmienia twoje zycie programisty
Refaktoryzacja: Wydzielenie zmiennej tymczasowej
Nazywanie warunków
Kod, który czyta sie jak ksiazke - techniki, które całkowicie odmienia twoje zycie programisty
Złote reguły refaktoryzacji
Kod, który czyta sie jak ksiazke - techniki, które całkowicie odmienia twoje zycie programisty
Kod trudny w testowaniu prawdopodobnie nadaje sie do refaktoryzacji

Citation preview

R Mistrz Programowania BNS IT, http://www.bnsit.pl

Mariusz Sieraczkiewicz

R Ksia˙ zka z serii Mistrz Programowania ,

Jak calkowicie odmieni´c spos´ob programowania uz˙ ywaja,c refaktoryzacji Przedmowa Michal Bartyzel

c 2009 BNS IT

c Copyright for Polish edition by BNS IT s. c.

Data: 09.03.2009 Wersja 151 Tytul: Jak calkowicie odmieni´c spos´ob programowania u˙zywajac , refaktoryzacji Autor: Mariusz Sieraczkiewicz Wszystkie znaki firmowe bad´ ace scie sa, zastrze˙zonymi , z towarowe wystepuj , , w tek´ znakami firmowymi bad´ scicieli. , z towarowymi ich wla´ Pierwsze trzy rozdzialy tej ksia˙ bezplatnie. Pozostale rozdzialy ,zki sa, udostepniane , dostepne sa, w platnej wersji ksia˙ , ,zki. Zabronione sa, jakiekolwiek zmiany w zawarto´sci publikacji bez pisemnej zgody BNS IT s. c. Zabrania sie, jej odsprzeda˙zy.

Aby dowiedzie´c sie, wie, cej o pelnej wersji, kliknij tutaj Autor oraz BNS IT s. c. dolo˙zyli wszelkich stara´n, aby zawarte w tej ksia˙ ,zce informacje byly kompletne i rzetelne. Nie biora, jednak z˙ adnej odpowiedzialno´sci za ich wykorzystanie, ani za zwiazane z tym ewentualne naruszenie praw patentowych , lub autorskich. Autor oraz BNS IT s. c. nie ponosza, r´ownie˙z z˙ adnej odpowiedzialno´sci ze ewentualne szkody wynikle z wykorzystania informacji zawartych w ksia˙ ,zce. BNS IT s. c. ul. Wyszy´nskiego 22 lok. 17 94 - 042 L´od´z www.bnsit.pl [email protected] Wszelkie prawa zastrze˙zone. All rights reserved.

R Mistrz Programowania BNS IT, http://www.bnsit.pl

Mojej najwspanialszej z˙ onie Kamili i c´orce Poli, kt´ora, ju˙z niedlugo zobacze,

Mariusz Sieraczkiewicz Trener, konsultant, mened˙zer projekt´ow IT, coach. Zalo˙zyciel zespolu programist´ow Equilibrium. Wsp´olinicjator JUGa L´od´z. Autor artykul´ow o in˙zynierii oprogramowania. Wsp´olwla´sciciel firmy szkoleniowej BNS IT. Z jezykiem Java ma do czynienia od dziewieciu lat na stanowiskach programisty, , , projektanta, architekta, analityka biznesowego, kierownika projekt´ow i kierownika zespolu. Jego pasja, jest programowanie i aspekty psychologiczne pracy programist´ow. Poszukuje wyznacznik´ow efektywno´sci programisty szczeg´olnie w obszarze zarza, dzania czasem, inteligencji emocjonalnej, przekona´n, pracy w zespole, motywacji i ich wplywu na codzienna, prace. ,

R Mistrz Programowania BNS IT, http://www.bnsit.pl

´ SPIS TRESCI

Spis tre´sci Przedmowa

7

Wstep ,

9

Zacza´ ,c od siebie . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

9

Dla kogo jest ta ksia˙ ,zka . . . . . . . . . . . . . . . . . . . . . . . . . 10 Podziekowania . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 , 1 Refaktoryzacja - o co tyle krzyku

13

Czym jest refaktoryzacja? . . . . . . . . . . . . . . . . . . . . . . . . 14 Postulaty nowoczesnej in˙zynierii oprogramowania, czyli odpowied´z na pytanie Dlaczego?” . . . . . . . . . . . . . . . . . . . . . . . . 14 ” Postulaty dotyczace olczesnej in˙zynierii oprogramowania . . . 14 , wsp´ Koszt wytwarzania oprogramowania . . . . . . . . . . . . . . . . 15 Entropia wzrasta . . . . . . . . . . . . . . . . . . . . . . . . . . 15 Refaktoryzacja w locie . . . . . . . . . . . . . . . . . . . . . . . 16 Refaktoryzacja ewolucyjna . . . . . . . . . . . . . . . . . . . . . 17 Najwa˙zniejsza ze wszystkich zasad - wydzielanie odpowiedzialno´sci 17 Antywzorce w kodzie . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 Don’t repeat yourself (DRY) - likwiduj powt´orzenia

. . . . . . . 19

Dlugie metody i du˙ze klasy . . . . . . . . . . . . . . . . . . . . 19 Zmiana lub dodanie funkcjonalno´sci powoduje konieczno´s´c wielu zmian w systemie . . . . . . . . . . . . . . . . . . . . . 20 Metoda danej klasy wykonuje zbyt wiele operacji na innych klasach 20 Analogiczne instrukcje warunkowe w r´oz˙ nych miejscach w projekcie 20 Nie tw´orz byt´ow ponad miare, . . . . . . . . . . . . . . . . . . . 20 Pola tymczasowe . . . . . . . . . . . . . . . . . . . . . . . . . . 20 Klasa przechowujaca tylko i wylacznie dane . . . . . . . . . . . . 21 , , Komentarze . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 Testowanie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22

R Mistrz Programowania BNS IT, http://www.bnsit.pl

´ SPIS TRESCI

2 Kod, kt´ ory czyta sie, jak ksia˙ zke - techniki, kt´ ore calkowicie , , odmienia, twoje z˙ ycie programisty

23

Co to znaczy - czyta´c jak ksia˙ ,zke, . . . . . . . . . . . . . . . . . . . . 24 Przyklad . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24 Bardzo kr´otkie wprowadzenie do wyra˙ze´n regularnych

. . . . . . 30

Analiza struktury strony . . . . . . . . . . . . . . . . . . . . . . 31 Podstawowa zasada - wydzielanie odpowiedzialno´sci . . . . . . . . . . 36 Refaktoryzacja: Wydzielenie metody . . . . . . . . . . . . . . . . . . . 37 Refaktoryzacja: Zmiana nazwy klasy, metody, atrybutu lub zmiennej . . 41 Refaktoryzacja: Wydzielenie zmiennej tymczasowej . . . . . . . . . . . 47 Nazywanie warunk´ow . . . . . . . . . . . . . . . . . . . . . . . 49 Zlote reguly refaktoryzacji . . . . . . . . . . . . . . . . . . . . . . . . 51 Kod trudny w testowaniu prawdopodobnie nadaje sie, do refaktoryzacji

52

3 Jak u˙zywa´ c refaktoryzacji do tworzenia w pelni obiektowych aplikacji

55

Nawyki skutecznej refaktoryzacji . . . . . . . . . . . . . . . . . . . . 55 Aby zrozumie´c, musisz do´swiadczy´c . . . . . . . . . . . . . . . . 55 To nie techniki dzialaja, — to ludzie dzialaja, . . . . . . . . . . . 56 Racjonalizacja . . . . . . . . . . . . . . . . . . . . . . . . . . . 56 Przekonania . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57 Co nagle, to po diable . . . . . . . . . . . . . . . . . . . . . . . . . . 58 Dlugie metody nie sa, wcale dobre . . . . . . . . . . . . . . . . . . . . 58 Refaktoryzacja: Zastapienie metody przez obiekt reprezentujacy , , metode, 60 Refaktoryzacja: Zmiana algorytmu na pisany ludzkim jezykiem . . . . . 62 , Refaktoryzacja: Wprowadzenie klarownej obslugi wyjatk´ , ow . . . . . . . 66 Dlawienie wyjatk´ , ow . . . . . . . . . . . . . . . . . . . . . . . . 66 Refaktoryzacja: Zmiana nazwy metody . . . . . . . . . . . . . . . . . 69 Refaktoryzacja: Zastapienie metody poruszania sie, po zlo˙zonej struk, turze wzorcem Iteratora . . . . . . . . . . . . . . . . . . . . . . 74 Refaktoryzacja: Przeniesienie metody i przeniesienie pola . . . . . . . . 74 Ko´ncowe porzadki czyli refaktoryzacja: Zmie´n implementacje, algorytmu 80 , Strategia najlepszych programist´ow: Male kroki . . . . . . . . . . . . . 83

R Mistrz Programowania BNS IT, http://www.bnsit.pl

´ SPIS TRESCI

4 Tajemnica mistrz´ ow refaktoryzacji Refaktoryzacja: Wydzielenie interfejsu . . . . . . . . . . . Kierunek wprowadzania interfejs´ow . . . . . . . . . . . . Inny przyklad . . . . . . . . . . . . . . . . . . . . . . . . Strategia skutecznych programist´ow: Usuwaj powt´orzenia Refaktoryzacja: Wydzielenie klasy abstrakcyjnej . . . . . . Najwa˙zniejsze odkrycie! . . . . . . . . . . . . . . . . . . Mistrzostwo . . . zobacz co sie, zmienilo . . . . . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

85 85 86 87 90 90 91 92

5 Pragmatyzm przede wszystkim 95 Dlaczego refaktoryzacja nie jest dobra na wszystko . . . . . . . . . . . 95 Dziesie´ n dotyczacych refaktoryzacji . . . . . . . . . . . . . . 96 , c przykaza´ , 6 I co dalej . . . - inne ´ zr´ odla Warsztaty . . . . . . . . . . Szkolenia . . . . . . . . . . . Trening indywidualny . . . . Ksia˙ ,zki . . . . . . . . . . . . Inne ´zr´odla w sieci . . . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

R Mistrz Programowania BNS IT, http://www.bnsit.pl

. . . . .

. . . . .

. . . . .

97 97 97 97 98 98

Przedmowa Wiekszo´ s´c programist´ow wie, co to refaktoryzacja, zna zalety wynikajace z jej , , stosowania, zna r´ownie˙z konsekwencje zaniedbywania refaktoryzacji. Jednocze´snie wielu programist´ow uwa˙za, z˙ e refaktoryzacja to bardzo kosztowny proces, wymaga wysilku i brak na nia, czasu w szybko zmieniajacych sie, warunkach biz, nesowych. W tej niesamowitej ksia˙ ,zce, Mariusz zaprezentuje Ci kilka bardzo prostych sposob´ow refaktoryzacji kodu. Dowiesz sie, ob stosowa´c refak, jak w latwy spos´ toryzacje, w twoim projekcie. Ostrzegam, z˙ e legna, w gruzach twoje z trudem wypracowane przekonania. By´c mo˙ze zaczniesz uwa˙za´c, z˙ e refaktoryzacja jest niezwykle prosta, zajmuje bardzo malo czasu i nie sprawia trudno´sci. Ze zdziwieniem bedziesz sie, zastanawia´c, jak to sie, stalo, z˙ e wcze´sniej nie u˙zywale´s tych , technik. Powodzenia! Michal Bartyzel

7

R Mistrz Programowania BNS IT, http://www.bnsit.pl

PRZEDMOWA

8 R Mistrz Programowania BNS IT, http://www.bnsit.pl

Wstep , Na plycie nagrobnej pewnego anglika´nskiego biskupa (ok. 1100 r.) spoczywaja, cego w krypcie Opactwa Westminsterskiego widnieja, nastepuj ace s lowa: , , Kiedy bylem mlody i wolny, a moja wyobra´znia nie znala granic, marzylem o tym, by zmieni´c ´swiat. Gdy wzroslem w latach i madro´ sci, zrozumialem, z˙ e ´swiata nie da sie, zmieni´c. , Wiec ocilem nieco swe zamiary i postanowilem zmieni´c jedynie sw´oj , przykr´ kraj. Lecz i on tak˙ze pozostal niezmienny. Gdy do˙zylem swego zmierzchu, w ostatnim, rozpaczliwym zrywie zdecydowalem zmieni´c cho´c swoja, rodzine, , istoty mi najbli˙zsze. Lecz niestety! Na nic sie, to zdalo! Teraz za´s, gdy spoczywam na lo˙zu ´smierci, nagle zdalem sobie sprawe, , z˙ e je´slibym zmienil najpierw tylko samego siebie, to by´c mo˙ze swym przykladem zmienilbym i swa, rodzine. c , Przy jej inspiracji i wsparciu bylbym w stanie ulepszy´ sw´oj kraj, i kto wie, mo˙ze zmienilbym w´owczas caly ´swiat.

Zacza´ ,c od siebie Rzeczywisto´s´c projektowa jest zlo˙zona. • Zazwyczaj brakuje czasu. 9

R Mistrz Programowania BNS IT, http://www.bnsit.pl

WSTEP ,

• Trzeba pracowa´c na starym kodzie, kt´ory pozostawia wiele do z˙ yczenia. • Koledzy z biurka obok nie kwapia, sie, do tego, z˙ eby zacza´ c ,c lepiej pisa´ programy. • Klienci nie widza, czego chca., • Szefowi zale˙zy tylko i wylacznie na najszybszym wykonywaniu zada´n. , • Biblioteki sa, ´zle udokumentowane i zawieraja, bledy. , • Narzedzia nie dzialaja, do ko´nca tak jak powinny. , Jest wiele przeszk´od, kt´ore utrudniaja, tworzenie oprogramowania i niestety zawsze tak bedzie. Chcieliby´smy, z˙ eby wszystko dookola nas sie, zmienilo, z˙ eby´smy , mogli w ko´ncu zacza´ c w przyzwoity spos´ob. Czy nie przypomina to ,c programowa´ troche, sytuacji biskupa z Opactwa Westminsterskiego?

Dla kogo jest ta ksia˙ ,zka Je´sli z jakiegokolwiek powodu temat refaktoryzacji wydaje ci sie, interesujacy , - ta ksia˙ ob, aby ka˙zdy kto nie mial ,zka jest dla ciebie. Zostala napisana w taki spos´ do tej pory styku z tym tematem, m´ogl sie, go nauczy´c i rozpocza´ ,c stosowanie techniki refaktoryzacji. Jest to ksia˙ zka dla os´ ob poczatkuj acych w temacie , , , refaktoryzacji, wystarczy tylko, z˙ e znasz obiektowy jezyk programowania , i mo˙zesz zaczyna´ c. Ksia˙ ora, masz w reku oparta jest o jezyk programowania Java, jednak ,zka kt´ , , wiele z przedstawionych technik mo˙zna zastosowa´c z powodzeniem w innych jezykach. Refaktoryzacja jest tematem uniwersalnym i niezale˙znym od jezyka , , programowania. Uwaga! Je´sli znasz dobrze inny jezyk programowania i chcialby´s opracowa´c , wersje, tej ksia˙ napisz do nas na [email protected] — ,zki w tym jezyku , staniesz sie, wsp´olautorem.

10 R Mistrz Programowania BNS IT, http://www.bnsit.pl

PODZIEKOWANIA ,

Dla os´ob, kt´ore znaja, ju˙z te, technike, mo˙ze ona stanowi´c punkt odniesienia dla stosowanych przez siebie metod. Je´sli zdecydowale´s sie, na dalsze czytanie tej ksia˙ sbe, s zasta,zki, mam pro´ , aby´ nowil sie, nad celem, intencja,, kt´ora ma towarzyszy´c jej przeczytaniu. By´c mo˙ze bedziesz chcial zwiekszy´ c swoja, efektywno´s´c, by´c mo˙ze bedziesz chcial dopro, , , wadzi´c do tego, aby tw´oj kod ´zr´odlowy stal sie, czytelny, a by´c mo˙ze po prostu bedziesz chcial spedzi´ c milo czas. Zapisz sobie ten cel i niech ci towarzyszy pod, , czas lektury.

Moja intencja

Podzie, kowania Stworzenie ksia˙ ,zki wymaga sporo wysilku, wsparcia i pomocy innych. Chcialbym podziekowa´ c mojej wspanialej z˙ onie Kamili za ogromne wsparcie , w zrealizowaniu tego szale´nczego dziela. Chcialbym podziekowa´ c Michalowi Bartyzelowi. Dlugie dyskusje z nim dopro, wadzily do wielu wniosk´ow zawartych w tej ksia˙ ,zce. Chcialbym podziekowa´ c osobom, kt´ore krytycznym okiem spojrzaly na te, , ksia˙ ,zke, , przyczyniajac , sie, do jej rozwoju — Piotrowi Majowi, Jackowi Laskowskiego, Piotrowi Str´oz˙ ykowi, Marcinowi Kasi´nskiemu, Grzegorzowi Smoragowi, Maciejowi Kubiszowi i Teresie Sas. Chcialbym podziekowa´ c wszystkim osobom z zespolu Equilibrium, gdy˙z to , dzieki c i odkrywa´c tajniki pracy programist´ow. , nim, moglem sie, tak wiele nauczy´

11 R Mistrz Programowania BNS IT, http://www.bnsit.pl

WSTEP ,

12 R Mistrz Programowania BNS IT, http://www.bnsit.pl

Rozdzial 1

Refaktoryzacja - o co tyle krzyku Dawno, dawno temu, tworzylem swoje pierwsze zaawansowane programy. Sprawialo mi to niesamowita, przyjemno´s´c, moglem stworzy´c co´s z niczego, a tworzone przeze mnie aplikacje byly u˙zyteczne. Mimo tej ogromnej rado´sci tworzenia oprogramowania, wewnetrznie pojawial sie, pewien niedosyt. Tworzony kod z cza, sem stawal sie, coraz bardziej skomplikowany, podobne konstrukcje sie, powtarzaly i mialem wra˙zenie, z˙ e trace, kontrole, nad tym, co robie. , Zazwyczaj wyglada , lo to tak, i˙z przez wiele godzin programowalem swoje dzielo, a nastepnie modlilem sie, ob i , , z˙ eby zadzialalo. Najcze´ , sciej nie dzialalo. Metoda, pr´ bled´ ecia. Ciagle towarzyszyla , ow po dlugim czasie naprawialem kolejne niedociagni , , , mi my´sl: Obym nie musial niczego p´o´zniej zmienia´c w tym, co napisalem”. ” W tym czasie wydawalo mi sie, snie taka jest specyfika pracy programi, z˙ e wla´ sty. Programowanie to dziedzina in˙zynieryjna, ludzie tworza, jedne z najbardziej skomplikowanych twor´ow. Tak musi by´c!” — my´slalem, cho´c przeczucie m´owilo ” mi, z˙ e jest inny spos´ob. Od tego czasu wiele wody w rzekach uplyne, lo i poznalem wiele wspanialych obiektowych technik tworzenia oprogramowania, i˙z teraz ju˙z wiem, z˙ e programowanie mo˙ze by´c prostsze. A co najwa˙zniejsze mam pewno´s´c, z˙ e nad tworzonym oprogramowaniem mo˙zna mie´c pelna, kontrole, c napisane czytelnie i , mo˙ze by´ mo˙ze by´c przygotowane do dalszego rozwoju. Jedna, z technik, kt´ora przybli˙za do wypracowania dobrego stylu pracy, jest refaktoryzacja.

13

R Mistrz Programowania BNS IT, http://www.bnsit.pl

ROZDZIAL 1. REFAKTORYZACJA - O CO TYLE KRZYKU

Czym jest refaktoryzacja? Czym zatem jest refaktoryzacja i w czym mo˙ze pom´oc? Jednym z najwiekszych , wyzwa´n programisty zwiazanych z tworzeniem kodu, jest jego czytelno´ s´c i la, two´s´c modyfikacji. Mo˙zna powiedzie´c, z˙ e obecnie nie jest sztuka, umiejetno´ s´c , napisania rozwiazania w wybranym jezyku programowania. Ze wzgledu na zlo˙zo, , , no´s´c wsp´olczesnych system´ow informatycznych, wa˙zniejsze jest, aby latwo bylo je przeanalizowa´c, zrozumie´c i zmodyfikowa´c. Nade wszystko - czytelno´s´c. Definicja Refaktoryzacja to zmiana dokonana w wewnetrznej strukturze opro, gramowania w celu jego latwiejszego zrozumienia i modyfikacji bez zmiany obserwowalnego zachowania.

Postulaty nowoczesnej inz˙ ynierii oprogramowania, czyli odpowied´z na pytanie Dlaczego?” ” Czesto zdarza mi sie, slysze´c stwierdzenie, z˙ e na refaktoryzacje, nie ma czasu lub z˙ e , to kosztuje zbyt wiele. Dlaczego zmiana struktury rozwiazania ma takie znaczenie , i czy warto po´swieca´ , c na tego typu dzialania bezcenny czas programisty?

Postulaty dotyczace olczesnej in˙zynierii oprogramowania , wsp´ Kiedy my´slimy o tworzeniu oprogramowania, najcze´ sl sam , sciej nasuwa sie, na my´ etap implementowania kodu. Tymczasem jest to tylko jeden z element´ow ukladanki nazywanej wytwarzaniem oprogramowania. Najwa˙zniejsze dwa postulaty 1 zwiazane z in˙zynieria, oprogramowania brzmia, nastepuj aco : , , , • kod oprogramowania jest cze´ sciej czytany ni˙z pisany — samo napisa, nie rozwiazania to tylko cze´ c wysilku potrzebnego do tego, aby rozwiazanie , , s´ , moglo dziala´c, i aby bylo rozwijane np. programista poprawiajac b l edy w , , swoim fragmencie, musi go wielokrotnie czyta´c; kod jest czytany podczas 1

Kent Beck, Implementation Patterns, Addison Wesley Publishing Company, 2007

14 R Mistrz Programowania BNS IT, http://www.bnsit.pl

˙ ´ NA PYTANIE DLACZEGO?” POSTULATY NOWOCZESNEJ INZYNIERII OPROGRAMOWANIA, CZYLI ODPOWIEDZ ”

przeglad´ , ow (ang. review); kod jest poddawany testowaniu; jest analizowany w momencie potrzeby wprowadzenia zmiany; • w procesie wytwarzania oprogramowania czesto nie istnieje stwier, dzenie zrobione” — oprogramowanie ciagle sie, rozwija, je´sli powstala , ” wersja pierwsza, prawdopodobnie powstanie wersja druga, system wdro˙zony w przedsiebiorstwie, w banku czy innej organizacji bedzie ciagle rozwijany, , , , aby dostosowa´c sie, do zmieniajacej sie, rzeczywisto´sci; szacuje sie, , , z˙ e ok. 80−90% profesjonalnych programist´ow pracuje w projektach, kt´ore polegaja, na rozwoju istniejacych rozwiaza´ ow ma mo˙zli, , n; niewielu programist´ wo´s´c brania udzialu w projekcie tworzonym calkowicie od poczatku. ,

Koszt wytwarzania oprogramowania Koszt wytworzenia oprogramowania (od momentu rozpoczecia prac implementa, cyjnych) to ´srednio w 30% koszt samego programowania, a w 70% koszt utrzy2 mania rozwiazania . Koszt utrzymania to miedzy innymi koszt poprawy bled´ , , , ow, analizy rozwiazania, zmiany, przetestowania i wdro˙zenia. , Niezwykle istotne jest, aby zadba´c o owe 70%. Obni˙zenie tego kosztu mo˙zna osiagn sci: , a´ ,c da˙ ,zac , do realizacji trzech warto´ • komunikatywno´s´ c — tworzenie rozwiaza´ ob, aby byly czy, n w taki spos´ telne i mo˙zliwie latwe w analizie; • prostota — dobre rozwiazania sa, zazwyczaj proste; , • elastyczno´s´ c – stworzony kod powinien by´c przygotowany na zmiany, tam gdzie te zmiany sa, realne i wynikaja, z wymaga´n. Dzieki refaktoryzacji mo˙zemy w usystematyzowany spos´ob da˙ c do realizacji , ,zy´ tych warto´sci.

Entropia wzrasta Istnieje w fizyce II zasada termodynamiki o wzro´scie entropii w ukladzie zamknie, tym, kt´ora, mo˙zemy sparafrazowa´c do zastosowania w in˙zynierii oprogramowania. 2

Kent Beck, Implementation Patterns, Addison Wesley Publishing Company, 2007

15 R Mistrz Programowania BNS IT, http://www.bnsit.pl

ROZDZIAL 1. REFAKTORYZACJA - O CO TYLE KRZYKU

Wa˙zne Z uplywem czasu stopie´n nieuporzadkowania w projekcie informatycz, nym wzrasta.

C´oz˙ to oznacza? Im dlu˙zej jest realizowany projekt, tym wiecej pojawia sie, w , nim rozwiaza´ ore nie sa, ju˙z u˙zywane lub realizuja, zadania w bardziej skom, n, kt´ plikowany spos´ob ni˙z by mogly. Pojawia sie, mn´ostwo nazw w projekcie, kt´ore nie sa, ju˙z adekwatne lub wrecz sa, mylne. W projekcie istnieje mn´ostwo obej´s´c, kt´ore , umo˙zliwiaja, dopasowanie nowych rozwiaza´ , n do starych. Pojawiaja, sie, rozwiaza, nia tymczasowe, kt´ore ostatecznie nie sa, nigdy poprawiane. Mo˙zna by tak dlugo wymienia´c. Entropia ukladu, jakim jest system informatyczny, z czasem wzrasta i potrzeba planowanego dzialania, aby temu przeciwdziala´c. Tak jak ka˙zdy dom wymaga sprzatania, tak samo sprzatania wymaga sys, , tem informatyczny. Mo˙zna oczywi´scie przez pewien czas nie robi´c porzadk´ , ow i akceptowa´c pewien poziom balaganu, ale z czasem poruszanie sie, po projekcie staje sie, coraz bardziej nieprzyjemne, a nawet niemo˙zliwe. Bylem ´swiadkiem wielu sytuacji, w kt´orych komercyjne systemy wymagaly przepisania, wla´snie dlatego, z˙ e nie stosowano w og´ole refaktoryzacji. Dzieki c system do stanu u˙zy, refaktoryzacji mo˙zemy posprzata´ , c i doprowadzi´ walno´sci.

Refaktoryzacja w locie W tym momencie mo˙ze pojawi´c sie, pytanie: W takim razie mam teraz zaprzesta´c ” prac i zrobi´c porzadki w ca lym systemie?” W du˙zej cze´ ow mo˙ze to , , sci przypadk´ by´c albo nierealne, albo nierozsadne. Jest niewiele projekt´ow, kt´ore nagle mo˙zna , przerwa´c i rozpocza´ ,c dlu˙zszy proces refaktoryzacji. Najwa˙zniejsze jest to, aby refaktoryzacja stala sie, stalym elementem realizowanych projekt´ow informatycznych, z˙ eby stala sie, nawykiem. Je´sli programista posiadzie umiejetno´ sci dokonywania refaktoryzacji na wysokim poziomie, bedzie , , , potrafil dokonywa´c tzw. refaktoryzacji w locie — w momencie tworzenia rozwiazania bedzie rozpoznawal miejsca, kt´ore nale˙zy skonstruowa´c inaczej, aby , ,

16 R Mistrz Programowania BNS IT, http://www.bnsit.pl

˙ ´ NA PYTANIE DLACZEGO?” POSTULATY NOWOCZESNEJ INZYNIERII OPROGRAMOWANIA, CZYLI ODPOWIEDZ ”

rozwiazanie w najbli˙zszej przyszlo´sci nie wymagalo refaktoryzacji (czyli aby bylo , zrefaktoryzowane w momencie tworzenia). Cho´c wydaje sie, to brzmie´c nieco abstrakcyjnie, zapewniam, i˙z taki stan osiaga sie, po kilku tygodniach intensywnego , stosowania refaktoryzacji. Umiejetno´ s´c refaktoryzacji w locie, jest o tyle wa˙zna, z˙ e refaktoryzacja w , naszym rozumieniu to proces, kt´ory musi trwa´c bezustannie, aby projekt plynnie sie, rozwijal.

Refaktoryzacja ewolucyjna Co zatem w sytuacji, gdy istnieje kod, kt´ory wyra´znie wymaga refaktoryzacji, a nie ma takiej mo˙zliwo´sci, aby po´swieci´ , c cala, energie, na jego zmiane. , Proponujemy podej´scie ewolucyjne. Proces ten nazywam Czteroetapowym modelem refaktoryzacji ewolucyjnej: 1. zidentyfikuj miejsca, kt´ore ulegaja, najczestszym zmianom , 2. okre´sl rodzaj refaktoryzacji, kt´ory chcialby´s wprowadzi´c 3. je´sli nie masz testu danego fragmentu, stw´orz go 4. zrefaktoryzuj lokalnie — dokonaj najmniejszej mo˙zliwej zmiany Gl´owna, idea, tego modelu jest zmiana tych element´ow systemu, kt´ore sa, najcze´ , sciej modyfikowane, gdy˙z to koszt modyfikacji jest w tym przypadku najwy˙zszy. Szczeg´olnie, je´sli stworzone rozwiazane nie posiada konstrukcji ulatwiajacych , , ich dalszy rozw´oj.

Najwa˙zniejsza ze wszystkich zasad - wydzielanie odpowiedzialno´sci Proces refaktoryzacji jest najbardziej efektywny, je´sli bedzie oparty o najwa˙zniej, sza, zasade, zwiazan a, z programowaniem obiektowym - wydzielaniem odpowie, dzialno´sci. Odpowiedzialno´s´ c to pojecie pierwotne, za pomoca, kt´orego mo˙zna , sformulowa´c niemal wszystkie inne zasady stojace za technikami refaktoryzacji, , 3 za wzorcami implementacyjnymi czy projektowymi . 3

Jedna z definicji brzmi nastepuj aco: Pow´od wprowadzenia zmian w klasie. Jednak jest , , to tak skondesowana definicja, i˙z w naszych rozwa˙zaniach jest bezu˙zyteczna

17 R Mistrz Programowania BNS IT, http://www.bnsit.pl

ROZDZIAL 1. REFAKTORYZACJA - O CO TYLE KRZYKU

Wa˙zne Odpowiedzialno´s´c to najwa˙zniejsze pojecie zwiazane z obiektowo´scia., , , Je´sli odpowiednio nauczysz poslugiwa´c sie, odpowiedzialno´scia, w praktyce, ka˙zda dziedzina in˙zynierii oprogramowania stanie przed toba, otworem. Osobi´scie traktuje, to pojecie bardzo szeroko. Mo˙zemy je lapidarnie zdefinio, wa´c jako to, czym dany element sie, zajmuje”. ” Definicja Odpowiedzialno´s´c okre´sla to, czym dany element sie, zajmuje Odpowiedzialno´s´c dotyczy ka˙zdego aspektu tworzonego systemu: • klasy - za co odpowiada klasa, jakie metody i atrybuty z tego wynikaja,, • metody - za co odpowiada metoda i jaki wynik zwraca, • zmiennej, pola klasy, stalej - za co odpowiada zmienna, jakie informacje przechowuje, • pakietu - jakiego typu elementy powinny sie, w nim znale´z´c, • podsystem, modul - z jakim procesem biznesowym jest zwiazany. , W przypadku klas z odpowiedzialno´sci jasno musi wynika´c, co z obiektem danej klasy mo˙zna zrobi´c, a czego nie. Odpowiedzialno´s´c jest ´sci´sle powiazana z , nazwa., Je´sli nazwa klasy nie oddaje tego, za co klasa jest odpowiedzialna, to mamy dwie mo˙zliwo´sci: albo nazwa klasy jest nieprawidlowa, albo klasa realizuje co´s innego ni˙z powinna. Je´sli nazwa metody nie odzwierciedla tego, co robi dana metoda i jaki wynik zwraca, to albo nazwa metody jest nieprawidlowa, albo odpowiedzialno´s´c metody wymkne, la sie, spod kontroli. Analogiczne rozumowanie mo˙zna by przenie´s´c na pozostale elementy systemu — zmienne, pola klasy, stale, pakiety i moduly.

18 R Mistrz Programowania BNS IT, http://www.bnsit.pl

ANTYWZORCE W KODZIE

Antywzorce w kodzie Jak zatem rozpoznawa´c miejsca w systemie, kt´ore nale˙zy zrefaktoryzowa´c? Po pierwsze intuicja. By´c mo˙ze nie jest to przekonujace scislych umysl´ow progra, dla ´ mist´ow, ale zapewniam cie, sli masz odczucie, z˙ e rozwiazanie, kt´ore stwo, z˙ e je´ , rzyle´s jest nienajlepsze, albo z˙ e trudno ci sie, nad nim pracuje, albo nie chcialby´s do niego zaglada´ to najprawdopodobniej nadaje sie, do refak, c za dwa miesiace, , toryzacji. Z drugiej strony programowanie to dziedzina techniki, zatem przyda sie, kilka regul, kt´ore pomoga, zlokalizowa´c fragmenty kodu, kt´ore nale˙zy zrefaktoryzowa´c. Tego typu reguly i wskaz´owki sa, nazywane zapachami kodu (ang. code smells). Poni˙zej znajduja, sie, zapachy kodu, kt´ore w ten czy inny spos´ob wynikaja, z nienajlepszej realizacji zasady odpowiedzialno´sci.

Don’t repeat yourself (DRY) - likwiduj powt´orzenia Powt´orzenia to wr´og numer jeden programisty. Wynikaja, najcze´ , sciej ze stosowania metody kopiuj-wklej lub powielania podobnych rozwiaza´ oz˙ nych miej, n w r´ scach. Je´sli znajdujesz w swoim kodzie fragmenty, kt´ore niewiele sie, r´oz˙ nia, od siebie — prawdopodobnie warto je zrefaktoryzowa´c np. poprzez wyodrebnienie , nowej metody.

Dlugie metody i du˙ze klasy Zbyt dlugie metody (kilkadziesiat , lub co gorsza kilkaset wierszy), to zazwyczaj zly znak — sygnal, z˙ e odpowiedzialno´s´c metody nie jest dobrze zdefiniowana. Analogicznie wystepowanie du˙zych klas z du˙za, ilo´scia, metod lub du˙za, ilo´scia, , p´ol, to r´ownie˙z sygnal alarmowy ostrzegajacy przed nieodpowiednio wydzielona, , odpowiedzialno´scia, klasy.

19 R Mistrz Programowania BNS IT, http://www.bnsit.pl

ROZDZIAL 1. REFAKTORYZACJA - O CO TYLE KRZYKU

Zmiana lub dodanie funkcjonalno´sci powoduje konieczno´s´c wielu zmian w systemie Kiedy wprowadzasz zmiany do systemu np. dodajesz nowa, funkcjonalno´s´c albo rozszerzasz istniejac c zmian w wielu miejscach, warto sie, , a, i musisz dokonywa´ przyjrze´c tym miejscom. Prawdopodobnie mo˙zna za pomoca, wzorc´ow projektowych wyodrebni´ c i odizolowa´c to, co jest zmienne. ,

Metoda danej klasy wykonuje zbyt wiele operacji na innych klasach Je´sli metoda danej klasy pracuje przede wszystkim na obiekcie innej klasy, prawdopodobnie powinna znajdowa´c sie, w tej drugiej klasie.

Analogiczne instrukcje warunkowe w r´oz˙ nych miejscach w projekcie Je´sli w kilku miejscach w systemie, przebieg operacji jest zale˙zny od typu obiektu (seria instrukcji if lub konstrukcja switch), zamiast instrukcji warunkowych warto u˙zy´c polimorfizmu.

Nie tw´orz byt´ow ponad miare, Programowanie obiektowe wia˙ acy pro,ze sie, z dwoma zagro˙zeniami. Poczatkuj , , grami´sci obiektowi, obawiaja, sie, nieco klas i wychodza, z zalo˙zenia, i˙z powinno by´c ich niewiele, co czesto prowadzi do zbyt dlugich metod lub zbyt du˙zych klas. , Kiedy programista nabierze ju˙z sprawno´sci w poslugiwaniu sie, obiektowo´scia,, nierzadko wpada w druga, skrajno´s´c - tworzy nowe klasy przy ka˙zdej nadarzajacej sie, , okazji. Je´sli nowe klasy niewiele r´oz˙ nia, sie, od innych, zlikwiduj je.

Pola tymczasowe W klasie istnieja, atrybuty, kt´ore potrzebne sa, tylko w pewnych okoliczno´sciach, np. do wykonania jednej konkretnej metody. Przechowywanie takiej jednorazowej informacji nie powinno le˙ze´c w odpowiedzialno´sci klasy, wiec c , nie powinno by´ r´ownie˙z polem w klasie.

20 R Mistrz Programowania BNS IT, http://www.bnsit.pl

ANTYWZORCE W KODZIE

Klasa przechowujaca tylko i wylacznie dane , , Szczeg´olnie w Javie jest to sytuacja, kt´ora pojawia sie, do´s´c czesto. Tworzone , sa, klasy, kt´ore maja, tylko i wylacznie pola oraz metody dostepowe (ang. set, , ters, getters), bez wzgledu na to, czy bed , , a, potrzebne czy nie. Konwencja Java Beans wymaga od programisty stworzenia metod dostepowych do p´ol w klasie, , do tego stopnia, i˙z w wielu narzedziach istnieje mechanizm, kt´ory generuje je , automatycznie. W ten spos´ob powstaja, klasy, kt´ore poprzez metody dostepowe , udostepniaj a stan obiektu na zewn atrz i przechowuj a wy l acznie dane. Klasa taka , , , , , nie jest odpowiednio hermetyzowana oraz mamy do czynienia z tzw. anemicznymi obiektami modelu. Powstaja, w systemie dwie niezale˙zne warstwy klas: • klasy modelu - przechowujace , dane, na przyklad User, • klasy uslugowe - wykonujace , operacje na tych danych, na przyklad UserManager. Nastepuje nadmierne mno˙zenie klas, zaburzenie odpowiedzialno´sci obiekt´ow oraz , wiele obiekt´ow jest ze soba, trwale powiazanych. ,

Komentarze Komentarze sa, zle. Tak powiedzialby konserwatywny zwolennik metodyki Extreme Programming. Komentarzy nikt nie lubi pisa´c, a jak ju˙z napisze, to p´o´zniej nikt ich nie aktualizuje. Nie wiadomo co jest gorsze - brak komentarza czy nieaktualny komentarz. Najlepszy jest samodokumentujacy , sie, kod. Poza pierwszym zdaniem, zdecydowanie zgadzam sie, z tym stanowiskiem. Komentarze nie sa, z natury zle, ale sa, bardzo trudnym narzedziem i rzadko , znajduje sie, odpowiednia motywacja, z˙ eby z niego dobrze korzysta´c. Poza tym w du˙zych projektach utrzymywanie dokumentacji implementacyjnej jest bardzo drogim przedsiewzi eciem. Je´sli to tylko mo˙zliwe, nale˙zy tworzy´c kod, , , kt´ory sam sie, dokumentuje. Do kt´orego nie potrzeba slownego wyja´snienia, aby go zrozumie´c. Je´sli przeczytasz w calo´sci nastepny rozdzial, to zobaczysz na , z˙ ywym przykladzie, jak to robi´c.

21 R Mistrz Programowania BNS IT, http://www.bnsit.pl

ROZDZIAL 1. REFAKTORYZACJA - O CO TYLE KRZYKU

Wa˙zne Je´sli masz ochote, napisa´c komentarz tekstowy, najpierw zastan´ow sie, czy wprowadzajac , prosta, refaktoryzacje, (taka, jak zmiana nazwy zmiennej, pola, klasy, wyodrebnienie metody) nie uzyskasz podob, nego, latwiejszego w utrzymaniu efektu.

Testowanie Na koniec do´s´c istotna uwaga dotyczaca refaktoryzacji. Technika ta polega na , zmianie struktury kodu, stad Wtedy , istnieje du˙ze ryzyko, i˙z popelnimy blad. , refaktoryzacja mo˙ze przynie´s´c wiecej szkody ni˙z po˙zytku. Dlatego nieodlacznym , , ˙ towarzyszem tej techniki sa, testy jednostkowe. Zeby bezpiecznie refaktoryzowa´c, powiniene´s mie´c testy, kt´ore weryfikuja, poprawno´s´c zmienionego rozwiazania. , Dla os´ob kt´ore w projekcie nie posiadaja, wystarczajacej liczby test´ow, jest , dobra wiadomo´s´c — wiele wsp´olczesnych ´srodowisk programistycznych automatyzuje proste refaktoryzacje, dzieki czemu mo˙zemy wykonywa´c je bezpiecznie, , nawet je´sli nie posiadamy test´ow. W tej ksia˙ Jest to jedna z pozycji serii ,zce aspekt testowania zostal pominiety. , R

Mistrz Programowania .

22 R Mistrz Programowania BNS IT, http://www.bnsit.pl

Rozdzial 2

Kod, kt´ ory czyta sie, jak ksia˙ zke , , techniki, kt´ ore calkowicie odmienia, twoje z˙ ycie programisty R Gl´ownym celem serii Mistrz Programowania jest wskazanie najwa˙zniejszych 20% umiejetno´ sci, kt´ore pozwola, zrealizowa´c 80% codziennych zada´n. Ten roz, dzial dotyczy czterech najwa˙zniejszych technik zwiazanych z refaktoryzacja., Je´sli , chcesz po´swieci´ c najbardziej praktyczne , c mo˙zliwie najmniej czasu po to, by pozna´ elementy refaktoryzacji, to powiniene´s przeczyta´c ten rozdzial. Zawiera on przyklady, kt´ore pokazuja,, jak kilka prostych, wdro˙zonych w z˙ ycie nawyk´ow, mo˙ze mie´c ogromne konsekwencje w codziennej pracy. Pierwszym krokiem, kt´ory przybli˙zy nas do celu opanowania umiejetno´ sci re, faktoryzacji, bedzie sztuka tworzenia kodu, kt´ory czyta sie, jak ksia˙ , ,zke, , kodu, kt´ory sie, sam dokumentuje.

23

R Mistrz Programowania BNS IT, http://www.bnsit.pl

´ ˙ E - TECHNIKI, KTORE ´ ˙ ROZDZIAL 2. KOD, KTORY CZYTA SIE, JAK KSIA,ZK CALKOWICIE ODMIENIA, TWOJE ZYCIE PROGRAMISTY ,

Co to znaczy - czyta´c jak ksia˙ ,zke, Jest pewne powiedzenie, kt´ory brzmi mniej wiecej nastepuj aco: , , , Wa˙zne Nie jest sztuka, stworzenie dzialajacego kodu, kt´ory bedzie zrozumialy , , dla komputera. Sztuka, jest stworzenie dzialajacego kodu, kt´ory bedzie , , zrozumialy dla czlowieka.

Majac spotykasz sie, z niezro, do czynienia z programowaniem zapewne czesto , zumialym kodem. Czesto masz do czynienia z metodami zlo˙zonymi z kilkudzie, sieciu lub nawet kilkuset wierszy, z ogromna, ilo´scia, zmiennych i zagnie˙zd˙zonymi , instrukcjami sterujacymi. Zrozumienie takiego zapisu jest niezwykle trudnym za, daniem, a modyfikacja jeszcze trudniejszym. Jest to antyprzyklad kodu, kt´ory ” czyta sie, jak ksia˙ ,zke” , . Je´sli masz do czynienia z kodem, kt´orego metody sa, niezbyt rozbudowane, na podstawie zastosowanych nazw jeste´s w stanie szybko zorientowa´c, jak stworzone rozwiazanie realizuje swoje zadanie. Je´sli spos´ob, w jakim napisane sa, metody, , jest przejrzystym zapisem u˙zytego algorytmu, to mo˙zna powiedzie´c, z˙ e“kod czyta sie, jak ksia˙ scia, nie wyczerpuje tego stwierdzenia. ,zke” , . Powy˙zszy opis z pewno´ Najlepszy bedzie konkretny przyklad. ,

Przyklad Jestem zwolennikiem praktycznego dzialania, dlatego idee, refaktoryzacji oraz idee, “kodu, kt´ory czyta sie, jak ksia˙ ,zke” , poka˙ze, na przykladowym projekcie. Zajmiemy sie, prostym systemem, kt´orego zadaniem bedzie tlumaczenie po, jedynczych wyraz´ow z u˙zyciem internetowych slownik´ow jezyka angielskiego. Za , pomoca, stworzonego programu u˙zytkownik bedzie m´ogl znale´z´c odpowiednik po, szukiwanego slowa w innym jezyku i wykorzystania do wlasnych cel´ow. , Na poczatku system bedzie mial nastepuj ace sci: , , , , funkcjonalno´ • u˙zytkownik za pomoca, menu wybiera opcje dostepne w systemie, ,

24 R Mistrz Programowania BNS IT, http://www.bnsit.pl

PRZYKLAD

• u˙zytkownik wpisuje wyraz w jezyku angielskim, system z u˙zyciem wybra, nego internetowego slownika znajdzie jego tlumaczenia i wy´swietli na ekranie, • u˙zytkownik mo˙ze zapamieta´ n, , c w systemie jedno ze znalezionych tlumacze´ • u˙zytkownik mo˙ze wy´swietli´c zapamietane slowa, , • u˙zytkownik mo˙ze wy´swietli´c slowa znalezione w ostatnim zapytaniu. System dla uproszczenia bedzie poslugiwal sie, interfejsem opartym o konsole. , , Osoby mniej zorientowane zachecam do zapoznania si e z tematem strumieni w , , jezyku Java, w szczeg´ o lno´ s ci z klas a java.util.Scanner, kt´ora bedzie gl´ownym , , , narzedziem pobierania danych. , Uwaga! Kody zamieszczone poni˙zej dostepne sa, w wersji komercyjnej ksia˙ , ,zki oraz sa, dolaczane do warsztat´ow multimedialnych. Szczeg´oly mo˙zna , znale´z´c na stronie http://www.bnsit.pl

W celu zorganizowania interfejsu u˙zytkownika u˙zyjemy narzedzi dostepnych , , w standardowej bibliotece jezyka Java. Pracujac c tech, , nad kodem b ed , e, stosowa´ nike, Malych krok´ow tak, aby kolejne elementy aplikacji powstawaly etapami niewielkimi fragmentami. Wa˙zne Technika Malych krok´ ow jest zasadniczym sposobem pracy skutecznych programist´ow - dzielac , zadanie na mniejsze cze´ , sci latwiej jest opanowa´c zmiany zachodzace w kodzie i pro´sciej jest odnale´z´c , ewentualne bledy. , Poni˙zej znajduje sie, kod, kt´ory bedzie baza, dla konsolowego interfejsu u˙zyt, kownika. package pl . bnsit . webdictionary ; import java . util . Scanner ;

25 R Mistrz Programowania BNS IT, http://www.bnsit.pl

´ ˙ E - TECHNIKI, KTORE ´ ˙ ROZDZIAL 2. KOD, KTORY CZYTA SIE, JAK KSIA,ZK CALKOWICIE ODMIENIA, TWOJE ZYCIE PROGRAMISTY ,

public class ConsoleSample {

public static void main ( String [] args ) { boolean ok = true ; Scanner s = new Scanner ( System . in ) ; System . out . println ( " Welcome to Web Dictionary System . " ) ; while ( ok ) { System . out . print ( " dictionary > " ) ; String c = s . nextLine () ; if ( c . equals ( " hello " ) ) { System . out . println ( " Welcome to Web Dictionary System . " ) ; } else if ( c . startsWith ( " search " ) ) { String f = c . split ( " " ) [ 1 ]; // TODO wyszukaj } else if ( c . startsWith ( " save " ) ) { // TODO zapisz } else if ( c . equals ( " showFound " ) ) { // TODO znalezione } else // } else ok }

if ( c . equals ( " showSaved " ) ) { TODO zachowane if ( c . equals ( " exit " ) ) { = false ;

} s . close () ; } }

Wa˙zne Je´sli nie znasz szczeg´ol´ow dotyczacych u˙zytkowania strumieni w je, , zyku Java, znajdziesz je na stronie: http://java.sun.com/docs/books/tutorial/essential/io/

Naszym gl´ownym zadaniem jest odczytanie zawarto´sci strony internetowej,

26 R Mistrz Programowania BNS IT, http://www.bnsit.pl

PRZYKLAD

zawierajacej dostepne tlumaczenia wybranego slowa z jezyka angielskiego. Pro, , , ponuje, w formie ´cwiczenia wybra´c dowolny slownik online i przygotowa´c oparte na nim rozwiazanie. W tej ksia˙ , ,zce u˙zyjemy strony http://www.dict.pl. Wa˙zne Pamietajmy, z˙ e witryny ze slownikami internetowymi dzialaja, komer, cyjnie i sa, posiadaczami praw autorskich zwiazanych ze slownikiem lub , posiadaja, odpowiednie prawa u˙zytkowania. W tej ksia˙ ,zce u˙zywamy ich tylko do cel´ow zobrazowania technik refaktoryzacji. Nie nale˙zy wykorzystywa´c tych witryn do wlasnych cel´ow (np. do dzialalno´sci komercyjnej) bez upewnienia sie, , z˙ e jest to zgodne z prawem. Poni˙zej znajduje sie, kod, kt´ory umo˙zliwia odczytanie zawarto´sci strony internetowej o zadanym adresie i wy´swietlenie go na konsoli. package pl . bnsit . webdictionary ; import import import import import

java . io . BufferedReader ; java . io . IOException ; java . io . I n p u t S t r e a m R e a d e r ; java . net . M a l f o r m e d U R L E x c e p t i o n ; java . net . URL ;

public class WebDictionary { public static void main ( String [] args ) { BufferedReader r = null ; try { r = new BufferedReader ( new I n p u t S t r e a m R e a d e r ( new URL ( " http :// www . dict . pl / dict ? word = " + " boy " + " & words =& lang = PL " ) . openStream () ) ) ; String t = null ; while ( ( t = r . readLine () ) != null ) { System . out . println ( t ) ; } } catch ( M a l f o r m e d U R L E x c e p t i o n ex ) { ex . p rin tSta ckTr ace () ;

27 R Mistrz Programowania BNS IT, http://www.bnsit.pl

´ ˙ E - TECHNIKI, KTORE ´ ˙ ROZDZIAL 2. KOD, KTORY CZYTA SIE, JAK KSIA,ZK CALKOWICIE ODMIENIA, TWOJE ZYCIE PROGRAMISTY ,

} catch ( IOException ex ) { ex . p rintSta ckTrace () ; } finally { try { if ( r != null ) { r . close () ; } } catch ( IOException ex ) { ex . p rintSta ckTrace () ; } } } }

W celu pobrania zawarto´sci strony u˙zywamy obiektu klasy java.net.URL. Za jego pomoca, otrzymujemy dostep z pobierana, , do strumienia danych zwiazanych , strona, URL.openStream(). Je´sli nie u˙zywale´s wcze´sniej tych klas, proponuje, po´swieci´ c. , c chwile, , aby z nimi poeksperymentowa´ Je´sli przyjrzymy sie, bli˙zej efektowi dzialania powy˙zszej metody, zauwa˙zymy, z˙ e polskie wyrazy nie sa, wy´swietlane prawidlowo. Dzieje sie, tak, gdy˙z strona, z kt´orej korzystamy, jest zapisana z u˙zyciem kodowania UTF−8. Te, kwestie, mo˙zemy rozwiaza´ , c u˙zywajac , specjalnego konstruktora klasy String:

String encodedString = new String ( line . getBytes () , " UTF8 " ) ;

Trzecim elementem, kt´ory bedzie potrzebny do zrealizowania zadania, jest , mechanizm wyra˙ze´n regularnych. Z jego pomoca, odnajdziemy te wiersze kodu HTML strony internetowej, kt´ore zawieraja, tlumaczenia poszukiwanego wyrazu. Aby wykona´c to zadanie, najpierw nale˙zy przeanalizowa´c strukture, kodu HTML, aby doszuka´c sie, schemat´ow charakterystycznych dla danych, kt´ore nas interesuja.,

28 R Mistrz Programowania BNS IT, http://www.bnsit.pl

PRZYKLAD

Wa˙zne Poni˙zej podano przyklady, kt´ore sa, aktualne w momencie pisania tej ksia˙ s czas generowany kod HTML mo˙ze wyglada´ ,zki. Za jaki´ , c inaczej. Nale˙zy przede wszystkim zrozumie´c zasade, przedstawiona, poni˙zej tak, aby samodzielnie m´oc dostosowa´c podany przyklad do wlasnych potrzeb. Zajmijmy sie, zatem analiza, struktury strony slownika www.dict.pl. Mo˙zemy zauwa˙zy´c, z˙ e pojedynczy wiersz zawierajacy slowo z polskim odpowiednikiem , wyglada nastepuj aco: , , , ... class = " resWordCol " > ch´L,opiec { m }

Za´s pojedynczy wiersz z angielskim odpowiednikiem wyglada nastepuj aco: , , , ... class = " resWordCol " > < font style = " background : # E3ECFB ; color : black " > boy

Ponadto najpierw nastepuje wiersz ze slowem polskim, p´o´zniej wiersz dla nas , nieistotny, a nastepnie wiersz ze slowem angielskim. , ... class = " resWordCol " > ch´L,opiec ... () ;

boolean ok = true ; Scanner s = new Scanner ( System . in ) ; System . out . println ( " Welcome to Web Dictionary System . " ) ; while ( ok ) { System . out . print ( " dictionary > " ) ; String c = s . nextLine () ; if ( c . equals ( " hello " ) ) { System . out . println ( " Welcome to Web Dictionary System . " ) ; } else if ( c . startsWith ( " search " ) ) { list2 . clear () ; BufferedReader r = null ; String plW = null ; String enW = null ; int i = 1; try { r = new BufferedReader ( new I n p u t S t r e a m R e a d e r ( new URL ( " http :// www . dict . pl / dict ? word = "

34 R Mistrz Programowania BNS IT, http://www.bnsit.pl

PRZYKLAD

+ c . split ( " " ) [1] + " & words =& lang = PL " ) . openStream () ) ) ; boolean polish = true ; String t = null ; Pattern pat = Pattern . compile ( " .* < a href =\" dict \\? words ?=(.*) & lang .* " ) ; while ( ( t = r . readLine () ) != null ) { Matcher matcher = pat . matcher ( t ) ; if ( matcher . find () ) { String t2 = matcher . group ( matcher . groupCount () ) ; if ( polish ) { System . out . print ( i + " ) " + t2 + " => " ); plW = new String ( t2 . getBytes () , " UTF8 " ) ; polish = false ; } else { System . out . println ( t2 ) ; polish = true ; enW = new String ( t2 . getBytes () , " UTF8 " ) ; list2 . add ( new DictionaryWord ( plW , enW , new Date () ) ) ; i ++; } } } } catch ( M a l f o r m e d U R L E x c e p t i o n ex ) { ex . prin tSta ckTr ace () ; } catch ( IOException ex ) { ex . prin tSta ckTr ace () ; } finally { try { if ( r != null ) { r . close () ; } } catch ( IOException ex ) { ex . p rin tSta ckTr ace () ; } } } else if ( c . startsWith ( " save " ) ) { int num = new Integer ( c . split ( " " ) [1] ) ; list1 . add ( list2 . get ( num - 1 ) ) ; } else if ( c . equals ( " showFound " ) ) { int i = 1; for ( DictionaryWord el : list2 ) { System . out . println ( i ++ + " ) " + el ) ;

35 R Mistrz Programowania BNS IT, http://www.bnsit.pl

´ ˙ E - TECHNIKI, KTORE ´ ˙ ROZDZIAL 2. KOD, KTORY CZYTA SIE, JAK KSIA,ZK CALKOWICIE ODMIENIA, TWOJE ZYCIE PROGRAMISTY ,

} } else if ( c . equals ( " showSaved " ) ) { for ( DictionaryWord el : list1 ) { System . out . println ( el ) ; } } else if ( c . equals ( " exit " ) ) { ok = false ; } } s . close () ; } }

Analizujac c kilka rzeczy. Program nie jest prawie , powy˙zszy kod, warto zauwa˙zy´ wcale napisany obiektowo, gdy˙z caly zawiera sie, w metodzie main (wyjatkiem jest tu , wprowadzona klasa DictionaryWord). Ponadto przytoczony kod klasy WebDictionary i metody main to przyklad antywzorca Zbyt dluga metoda. Odpowiedzialno´s´ c metody main jest w tym momencie bardzo szeroka - zajmuje sie, obsluga, interfejsu u˙zytkownika, obsluga, zewnetrznego , portalu slownikowego, przechowywaniem i przetwarzaniem danych tymczasowych. To wszystko w jednej metodzie. Taka, metode, bardzo trudno sie, czyta. Trzeba ja, cala, przeanalizowa´c, z˙ eby zrozumie´c, jakie zadania realizuje.

Podstawowa zasada - wydzielanie odpowiedzialno´sci W celu refaktoryzacji metody main, zastan´owmy sie, ownych cze´ , z jakich gl´ , sci sie, sklada. Jak wyglada c mo˙ze w taki spos´ob: , lby slowny zapis algorytmu? By´ 1. inicjuj zmienne 2. przetwarzaj menu: (a) pobierz komende, od u˙zytkownika; (b) je´sli wybrana komenda to hello, wypisz tekst powitalny; (c) je´sli wybrana komenda rozpoczyna sie, od slowa search, to pobierz dane ze strony, wypisz i zapamietaj; , (d) je´sli wybrana komenda to showFound, to wy´swietl wyniki ostatniego wyszukiwania; (e) je´sli wybrana komenda to showSaved, to wy´swietl zapamietane slowa; ,

36 R Mistrz Programowania BNS IT, http://www.bnsit.pl

REFAKTORYZACJA: WYDZIELENIE METODY

(f) je´sli wybrana komenda to exit, to zako´ ncz program. Dlaczego nie da˙ c do tego, aby kod, kt´ory tworzymy, odpowiadal powy˙zszemu ,zy´ zapisowi, wydzielajac , cze´ , sci algorytmu do osobnych metod. Wa˙zne By´c mo˙ze znasz odpowied´z na pytanie, jak zje´s´c slonia. Dzielac , go na mniejsze kawalki . . . Wa˙zne Zbyt dlugie metody dziel na mniejsze, tak aby odzwierciedlaly kroki algorytmu oraz stanowily jego dokumentacje, poprzez odpowiednio dobrane nazwy.

Refaktoryzacja: Wydzielenie metody Wydzielenie metody to jedna z najwa˙zniejszych refaktoryzacji. Polega na przeniesieniu pewnego zestawu instrukcji do osobnej metody. Poprzez odpowiednia, nazwe, mo˙zemy sprawi´c, z˙ e powstanie samodokumentujacy sie, kod. , Kiedy wydziela´c nowe metody? Jedna z zasad m´owi, z˙ e metoda powinna sie, mie´sci´c na jednym ekranie. Obecnie ekrany maja, r´oz˙ ne wymiary i rozdzielczo´sci, zatem jest to miara niejednoznaczna. Sugerowalbym zatem dlugo´s´c metod ograniczy´c do mniej wiecej 40 wierszy, gdy˙z ´srednio taki rozmiar jeste´smy w stanie jednorazowo obja´ , ,c swoim wzrokiem i przeanalizowa´c. W klasie WebDictionary i metodzie main wydzielmy metody odpowiadajace za: , • wy´swietlanie komunikatu powitalnego (printInfo()), • przetwarzanie menu (processMenu()), • wyszukiwanie danych w slowniku internetowym (searchWord()), • zapisanie wybranego slowa (saveWord()), • wy´swietlanie wynik´ ow ostatniego wyszukiwania (showAll()) i zapamietanych , sl´ ow (showSaved()).

37 R Mistrz Programowania BNS IT, http://www.bnsit.pl

´ ˙ E - TECHNIKI, KTORE ´ ˙ ROZDZIAL 2. KOD, KTORY CZYTA SIE, JAK KSIA,ZK CALKOWICIE ODMIENIA, TWOJE ZYCIE PROGRAMISTY ,

Poniewa˙z pojawia, sie, dodatkowe metody, kt´ore wsp´oldziela, dane, tote˙z listy przechowujace wyrazy uczynimy polami klasy. , Kod po refaktoryzacji wyglada nastepuj aco: , , , package pl . bnsit . webdictionary ; import import import import import import import import import import import

java . io . BufferedReader ; java . io . IOException ; java . io . In pu tS tr ea mR ea de r ; java . net . M a l f o r m e d U R L E x c e p t i o n ; java . net . URL ; java . util . ArrayList ; java . util . Date ; java . util . List ; java . util . Scanner ; java . util . regex . Matcher ; java . util . regex . Pattern ;

public class WebDictionary { private static List < DictionaryWord > list1 = new ArrayList < DictionaryWord >() ; private static List < DictionaryWord > list2 = new ArrayList < DictionaryWord >() ; public static void main ( String [] args ) { processMenu () ; } private static void processMenu () { boolean ok = true ; Scanner s = new Scanner ( System . in ) ; printInfo () ; while ( ok ) { System . out . print ( " dictionary > " ) ; String c = s . nextLine () ; if ( c . equals ( " hello " ) ) { printInfo () ; } else if ( c . startsWith ( " search " ) ) { searchWord ( c ) ; } else if ( c . startsWith ( " save " ) ) { saveWord ( c ) ; } else if ( c . equals ( " showFound " ) ) {

38 R Mistrz Programowania BNS IT, http://www.bnsit.pl

REFAKTORYZACJA: WYDZIELENIE METODY

showFound () ; } else if ( c . equals ( " showSaved " ) ) { showSaved () ; } else if ( c . equals ( " exit " ) ) { ok = false ; } } s . close () ; } private static void showSaved () { for ( DictionaryWord el : list1 ) { System . out . println ( el ) ; } } private static void showFound () { int i = 1; for ( DictionaryWord el : list2 ) { System . out . println ( i ++ + " ) " + el ) ; } } private static void saveWord ( String c ) { int num = new Integer ( c . split ( " " ) [1] ) ; list1 . add ( list2 . get ( num - 1 ) ) ; } private static void searchWord ( String c ) { list2 . clear () ; BufferedReader r = null ; String plW = null ; String enW = null ; int i = 1; try { r = new BufferedReader ( new I n p u t S t r e a m R e a d e r ( new URL ( " http :// www . dict . pl / dict ? word = " + c . split ( " " ) [1] + " & words =& lang = PL " ) . openStream () ) ) ; boolean polish = true ; String t = null ; Pattern pat = Pattern . compile ( " .* < a href =\" dict \\? words ?=(.*) & lang .* " ) ; while ( ( t = r . readLine () ) != null ) {

39 R Mistrz Programowania BNS IT, http://www.bnsit.pl

´ ˙ E - TECHNIKI, KTORE ´ ˙ ROZDZIAL 2. KOD, KTORY CZYTA SIE, JAK KSIA,ZK CALKOWICIE ODMIENIA, TWOJE ZYCIE PROGRAMISTY ,

Matcher matcher = pat . matcher ( t ) ; if ( matcher . find () ) { String t2 = matcher . group ( matcher . groupCount () ) ; if ( polish ) { System . out . print ( i + " ) " + t2 + " => " ); plW = new String ( t2 . getBytes () , " UTF8 " ) ; polish = false ; } else { System . out . println ( t2 ) ; polish = true ; enW = new String ( t2 . getBytes () , " UTF8 " ) ; list2 . add ( new DictionaryWord ( plW , enW , new Date () ) ) ; i ++; } } } } catch ( M a l f o r m e d U R L E x c e p t i o n ex ) { ex . p rintSta ckTrace () ; } catch ( IOException ex ) { ex . p rintSta ckTrace () ; } finally { try { if ( r != null ) { r . close () ; } } catch ( IOException ex ) { ex . p rintSta ckTrace () ; } } } private static void printInfo () { System . out . println ( " Welcome to Web Dictionary System . " ) ; } }

Widzimy kilka pozytywnych efekt´ow tego dzialania: 1. kod nie jest ju˙z monolityczny 2. powstalo kilka mniejszych metod, kt´ore sa, latwiejsze w zrozumieniu

40 R Mistrz Programowania BNS IT, http://www.bnsit.pl

REFAKTORYZACJA: ZMIANA NAZWY KLASY, METODY, ATRYBUTU LUB ZMIENNEJ

3. nazwy nowych metody dokumentuja, ich odpowiedzialno´s´c 4. osoba analizujaca na podstawie analizy metody pro, kod mo˙ze tylko i wylacznie , cessMenu() zrozumie´c gl´owna, my´sl algorytmu 5. je´sli czytelnik kodu chce pozna´c szczeg´oly danego kroku algorytmu, mo˙ze przeanalizowa´c konkretna, metode, 6. kod zaczyna sie, czyta´c jak ksia˙ ,zke, . . . ciagle pozostaje kilka wad. Wszystkie metody sa, statyczne, co w konsekwencji , oznacza, i˙z program jest nieobiektowy. Elementy statyczne sa, zwiazane z klasami, , maja, zatem charakter globalny wzgledem obiekt´ow. Rozwiazanie, kt´ore stworzyli´smy , , wpisuje sie, w konwencje, programowania proceduralnego. Zr´ obmy maly krok, kt´ ory uczyni nasz program bardziej obiektowym i zbuduje podwaliny dla dalszego rozwoju systemu - wydzielone metody oraz atrybuty uczy´ nmy niestatycznymi, za´s w metodzie main stworzymy obiekt klasy WebDictionary. Efekt tej zmiany mo˙zesz obejrze´c na listingu zamieszczonym pod koniec nastepnego podroz, dzialu. Wa˙zne Unikaj element´ ow statycznych. Sa, nieobiektowe, gdy˙z maja, charakter globalny. W szczeg´ olno´sci w odniesieniu do metod statycznych warto pamieta´ , c, z˙ e w ich przypadku nie dziala mechanizm polimorfizmu.

Refaktoryzacja: Zmiana nazwy klasy, metody, atrybutu lub zmiennej Przed nami kolejny wa˙zny krok w strone, czytelnego kodu - zmiana nazw metod, atrybut´ ow i zmiennych. Jak ju˙z wcze´sniej wspominalem, nazwy odzwierciedlaja, odpowiedzialno´s´c elementu, dlatego warto po´swieci´ c swojej energii. Jest to jeden z , c im cze´ , s´ najwa˙zniejszych no´snik´ ow informacji w tworzonym kodzie. Sp´ ojrzmy na przykladowy kod ´zr´odlowy. Jak odr´oz˙ nimy atrybuty list1 i list2? Na pierwszy rzut oka nie ma niczego, co by podpowiedzialo, jaka intencja przy´swiecala autorowi. W konsekwencji oznacza to, z˙ e bedziemy musieli przeanalizowa´c kod i ,

41 R Mistrz Programowania BNS IT, http://www.bnsit.pl

´ ˙ E - TECHNIKI, KTORE ´ ˙ ROZDZIAL 2. KOD, KTORY CZYTA SIE, JAK KSIA,ZK CALKOWICIE ODMIENIA, TWOJE ZYCIE PROGRAMISTY ,

zapamieta´ oz˙ nice, miedzy jedna, lista, a druga., Dodatkowy wysilek. Je´sli takich przy, c r´ , padk´ow w tworzonym kodzie mamy kilka . . . kilkana´scie . . . kilkaset - latwo mo˙zna sobie wyobrazi´c, jak trudno bedzie zrozumie´c i przeanalizowa´c taki kod. , Milo´snicy komentarzy moga, mie´c ochote, zmodyfikowa´c nieco kod na przyklad w taki spos´ ob: // saved words private List < DictionaryWord > list1 = new ArrayList < DictionaryWord >() ; // last search words private List < DictionaryWord > list2 = new ArrayList < DictionaryWord >() ;

Jednak taki komentarz niewiele zmienia: • komentarz wystepuje w miejscu deklaracji, zatem nie wida´c go najcze´ , , sciej w miejscu, gdzie dany element jest u˙zywany; • je´sli zmieni sie, nieco odpowiedzialno´s´c, latwo zapomnie´c o zmianie komentarza; • komentarze sa, dla ludzi - nie sa, analizowane ani interpretowane przez kompilator, nie istnieja, narzedzia, kt´ore pozwalaja, automatycznie nimi zarzadza´ c (np. , , zmienia´c powiazane komentarze wystepuj ace w wielu miejscach systemu). , , , A czy nie pro´sciej byloby zmieni´c nazwy zmiennych w nastepuj acy spos´ob? , , private List < DictionaryWord > savedWords = new ArrayList < DictionaryWord >() ; private List < DictionaryWord > l ast Sear chWo rds = new ArrayList < DictionaryWord >() ;

Zauwa˙zmy, z˙ e uzyskujemy ten sam efekt, kt´ory sie, pojawil w przypadku komentarza, lecz tym razem to nazwa pola jest komentarzem. Komentarz ten pojawia sie, nie tylko w miejscu deklaracji, ale r´ ownie˙z tam, gdzie pole jest u˙zywane: private void showSaved () { for ( DictionaryWord el : savedWords ) { System . out . println ( el ) ; } } private void showFound () { int i = 1; for ( DictionaryWord el : last Sea rchW ords ) {

42 R Mistrz Programowania BNS IT, http://www.bnsit.pl

REFAKTORYZACJA: ZMIANA NAZWY KLASY, METODY, ATRYBUTU LUB ZMIENNEJ

System . out . println ( i ++ + " ) " + el ) ; } } private void saveWord ( String c ) { int num = new Integer ( c . split ( " " ) [1] ) ; savedWords . add ( las tSea rchW ords . get ( num - 1 ) ) ; }

W momencie, kiedy stwierdzimy, z˙ e odpowiedzialno´s´c nie zostala precyzyjnie wyra˙zona poprzez nazwe, c nazwe, s automatyczne narzedzia dokonaja, , mo˙zemy zmieni´ , za´ , 1. zmian w ka˙zdym miejscu w projekcie, gdzie taka nazwa wystepuje , W przytoczonym przykladzie pojawia sie, wiele przypadk´ow, w kt´orych nazwy zmiennych niewiele m´ owia,, sa, skr´ otowe, nie odzwierciedlaja, znaczenia i utrudniaja, zrozumienie kodu. Nazwa ok jest lakoniczna, mo˙ze oznacza´c niemal˙ze wszystko, podobnie z nazwami c, s, el, plW, enW, t, r . . . . Co sie, dzieje kiedy nagle w kodzie dostrzegamy wiersz s . close () ;

Albo musimy pamieta´ z´c , c co jest przechowywane pod nazwa, s, albo musimy odnale´ miejsce deklaracji pola, zmiennej lub parametru. W obu przypadkach jest to dodatkowy wysilek. Je´sli takich zmiennych w niewielkim fragmencie kodu jest kilkana´scie, ka˙zdy przypadek kosztuje dodatkowa, energie, ora, musimy na niego wydatkowa´c. , kt´ Czy zastanawiale´s sie, , dlaczego po kilku minutach czytania kodu, stajesz sie, bardzo zmeczony? , Chcialbym podkre´sli´c, z˙ e nazwy klas, p´ol, metod, zmiennych sa, jak awers monety, kt´orej rewersem jest odpowiedzialno´s´c. Nazwy musza, by´c jednoznaczne, mo˙zliwie kr´otkie, ale na tyle dlugie, aby odda´c sens i odpowiedzialno´s´c nazywanego elementu. Czesto , mam wra˙zenie, z˙ e programi´sci boja, sie, nadawa´c nieco dlu˙zsze nazwy swoim klasom lub zmiennym, ale c´ oz˙ za zysk z napisania String w = "slowo"; zamiast String word = " slowo";, list1

zamiast

savedWords, list2

zamiast

lastSearchWords

itd. Wiele wsp´olczesnych

´srodowisk programistycznych podpowiada nazwy zmiennych, klas i p´ol, zatem i tak najcze´ Kr´otko m´owiac, otkich nazwach nie oszcze, sciej nie wpisujemy ich recznie. , , na kr´ , dzamy. 1

Obecnie wiele ´srodowisk programistycznych (np. Eclipse, NetBeans, Visual Studio) wspiera proces refaktoryzacji i dzieki czemu wielu zmia mo˙zna dokonywa´c u˙zywajac , , automat´ ow, kt´ ore zadbaja, o wprowadzane zmiany.

43 R Mistrz Programowania BNS IT, http://www.bnsit.pl

´ ˙ E - TECHNIKI, KTORE ´ ˙ ROZDZIAL 2. KOD, KTORY CZYTA SIE, JAK KSIA,ZK CALKOWICIE ODMIENIA, TWOJE ZYCIE PROGRAMISTY ,

Poni˙zej znajduje sie, analizowany przyklad WebDictionary, tym razem ju˙z ze zmodyfikowanymi nazwami zmiennych: package pl . bnsit . webdictionary ; import import import import import import import import import import import

java . io . BufferedReader ; java . io . IOException ; java . io . In pu tS tr ea mR ea de r ; java . net . M a l f o r m e d U R L E x c e p t i o n ; java . net . URL ; java . util . ArrayList ; java . util . Date ; java . util . List ; java . util . Scanner ; java . util . regex . Matcher ; java . util . regex . Pattern ;

public class WebDictionary { private List < DictionaryWord > savedWords = new ArrayList < DictionaryWord >() ; private List < DictionaryWord > l ast Sear chWo rds = new ArrayList < DictionaryWord >() ;

public static void main ( String [] args ) { WebDictionary webDictionary = new WebDictionary () ; webDictionary . start () ; } public void start () { processMenu () ; } private void processMenu () { boolean running = true ; Scanner scanner = new Scanner ( System . in ) ; printInfo () ; while ( running ) { System . out . print ( " dictionary > " ) ; String command = scanner . nextLine () ; if ( command . equals ( " hello " ) ) { printInfo () ; } else if ( command . startsWith ( " search " ) ) {

44 R Mistrz Programowania BNS IT, http://www.bnsit.pl

REFAKTORYZACJA: ZMIANA NAZWY KLASY, METODY, ATRYBUTU LUB ZMIENNEJ

searchWord ( command ) ; } else if ( command . startsWith ( " save " ) ) { saveWord ( command ) ; } else if ( command . equals ( " showFound " ) ) { showFound () ; } else if ( command . equals ( " showSaved " ) ) { showSaved () ; } else if ( command . equals ( " exit " ) ) { running = false ; } } scanner . close () ; } private void showSaved () { for ( DictionaryWord d i c t i o n a r y E l e m e n t : savedWords ) { System . out . println ( d i c t i o n a r y E l e m e n t ) ; } } private void showFound () { int counter = 1; for ( DictionaryWord d i c t i o n a r y E l e m e n t : l astS earc hWor ds ) { System . out . println ( counter ++ + " ) " + d i c t i o n a r y E l e m e n t ) ; } } private void saveWord ( String command ) { int wordNumber = new Integer ( command . split ( " " ) [1] ) ; savedWords . add ( las tSea rchW ords . get ( wordNumber - 1 ) ) ; } private void searchWord ( String command ) { las tSe arch Word s . clear () ; BufferedReader bufferedReader = null ; String polishWord = null ; String englishWord = null ; int counter = 1; try { bufferedReader = new BufferedReader ( new I n p u t S t r e a m R e a d e r ( new URL ( " http :// www . dict . pl / dict ? word = " + command . split ( " " ) [1] + " & words =& lang = PL " ) . openStream () ) ) ;

45 R Mistrz Programowania BNS IT, http://www.bnsit.pl

´ ˙ E - TECHNIKI, KTORE ´ ˙ ROZDZIAL 2. KOD, KTORY CZYTA SIE, JAK KSIA,ZK CALKOWICIE ODMIENIA, TWOJE ZYCIE PROGRAMISTY ,

boolean polish = true ; String line = null ; Pattern pat = Pattern . compile ( " .* < a href =\" dict \\? words ?=(.*) & lang .* " ) ; while ( ( line = bufferedReader . readLine () ) != null ) { Matcher matcher = pat . matcher ( line ) ; if ( matcher . find () ) { String foundWord = matcher . group ( matcher . groupCount () ) ; if ( polish ) { System . out . print ( counter + " ) " + foundWord + " => " ); polishWord = new String ( foundWord . getBytes () , " UTF8 " ) ; polish = false ; } else { System . out . println ( foundWord ) ; polish = true ; englishWord = new String ( foundWord . getBytes () , " UTF8 " ) ; lastSe arch Word s . add ( new DictionaryWord ( polishWord , englishWord , new Date () ) ) ; counter ++; } } } } catch ( M a l f o r m e d U R L E x c e p t i o n ex ) { ex . p rintSta ckTrace () ; } catch ( IOException ex ) { ex . p rintSta ckTrace () ; } finally { try { if ( bufferedReader != null ) { bufferedReader . close () ; } } catch ( IOException ex ) { ex . p rintSta ckTrace () ; } } } private void printInfo () { System . out . println ( " Welcome to Web Dictionary System . " ) ;

46 R Mistrz Programowania BNS IT, http://www.bnsit.pl

REFAKTORYZACJA: WYDZIELENIE ZMIENNEJ TYMCZASOWEJ

} }

Refaktoryzacja: Wydzielenie zmiennej tymczasowej Kod naszego systemu tlumaczacego poddany refaktoryzacji zawiera coraz wiecej ele, , ment´ ow, kt´ ore powoduja,, z˙ e metody sa, coraz bli˙zsze rozumowania czlowieka. Stosujac , kilka prostych zabieg´ ow kod staje sie, bardziej samodokumentujacy. Na co jeszcze mo, z˙ emy zwr´ oci´c uwage? acemu fragmentowi: , Przyjrzyjmy sie, nastepuj , , bufferedReader = new BufferedReader ( new I n p u t S t r e a m R e a d e r ( new URL ( " http :// www . dict . pl / dict ? word = " + command . split ( " " ) [1] + " & words =& lang = PL " ) . openStream () ) ) ;

Dzieje sie, tu wiele rzeczy jednocze´snie. Powstaja, trzy nowe obiekty, nastepuje kon, katenacja napis´ ow. Jeden z czlon´ow konkatenacji to zlo˙zone wyra˙zenie command.split(" ") [1]

wyluskujace c ten fragment trzeba po´swieci´ , wyraz do wyszukiwania. Aby zrozumie´ , c

sporo czasu (kilka lub kilkana´scie sekund). Dokonajmy prostych zmian w kilku krokach, stosujac ora towarzyszyla refaktoryzacji Wydzielenie zmiennej , te, sama, zasade, , kt´ - podzielmy konstrukcje na mniejsze skladowe. Zacznijmy od ciagu napisowego: , String urlString = " http :// www . dict . pl / dict ? word = " + command . split ( " " ) [1] + " & words =& lang = PL " ; bufferedReader = new BufferedReader ( new I n p u t S t r e a m R e a d e r ( new URL ( urlString ) . openStream () ) ) ;

Atmosfera wok´ ol tworzenia obiektu klasy BufferedReader ju˙z nie jest tak zagesz, czona. Nie jest skondensowana w jednym wierszu - latwiej ja, zrozumie´c, tym bardziej, z˙ e wprowadzili´smy niejawnie komentarz w formie nazwy zmiennej urlString. Caly czas jednak konstrukcja

command.split(" ")[1]

jest bardzo tajemnicza. By´c mo˙ze domy-

´slasz sie, o co chodzilo autorowi, ale mo˙zna te, itencje, wyrazi´c du˙zo ja´sniej. String wordToFind = command . split ( " " ) [1]; String urlString = " http :// www . dict . pl / dict ? word = " + wordToFind + " & words =& lang = PL " ; bufferedReader = new BufferedReader ( new I n p u t S t r e a m R e a d e r (

47 R Mistrz Programowania BNS IT, http://www.bnsit.pl

´ ˙ E - TECHNIKI, KTORE ´ ˙ ROZDZIAL 2. KOD, KTORY CZYTA SIE, JAK KSIA,ZK CALKOWICIE ODMIENIA, TWOJE ZYCIE PROGRAMISTY ,

new URL ( urlString ) . openStream () ) ) ;

Ciekawe czy jeste´s w stanie zrozumie´c ten fragment kodu, w sytuacji, gdy nie znasz dobrze efektu dzialania metody split. Oczywi´scie nic nie stoi na przeszkodzie, z˙ eby dociekliwie zbada´c, jak dokladnie przebiega wykonanie konstrukcji command.split(" ")[1]. Mo˙zna by sie, jednak pokusi´c o wprowadzenie do kodu dodatkowej informacji: String [] commandParts = command . split ( " " ) ; String wordToFind = commandParts [1];

Teraz sprawa jest jeszcze prostsza, gdy˙z zmienna commandParts informuje o tym, co jest w tym przypadku efektem dzialania metody String.split. Wa˙zne Tam gdzie mo˙ze to upro´sci´c analize, kodu, wydzielaj zmienne, kt´ore podziela, zlo˙zone konstrukcje na mniejsze i udokumentuja, program.

Wydzielajac c sie, zdrowym rozsadkiem. Nie chcialbym, aby´s , zmienne nale˙zy kierowa´ , Czytelniku odni´ osl wra˙zenie, z˙ e ka˙zda skladowa zlo˙zonego wyra˙zenia powinna zosta´c wydzielona. Czesto nie ma to wiekszego sensu. Na przyklad we fragmencie , , System . out . print ( counter + " ) " + foundWord + " = > " ) ;

wprowadzenie pomocniczych zmiennych nic by nie wnioslo do kodu. Wrecz mogloby , zmniejszy´c jego czytelno´s´c. Nale˙zy wydziela´c zmienne tam, gdzie zlo˙zono´s´c wyra˙zenia utrudnia jego analize. olnie widoczne podczas poszukiwania przyczyn , Jest to szczeg´ wyjatk´ sli w wierszu o postaci: , ow lub bled´ , ow. Je´ bufferedReader = new BufferedReader ( new I n p u t S t r e a m R e a d e r ( new URL ( " http :// www . dict . pl / dict ? word = " + command . split ( " " ) [1] + " & words =& lang = PL " ) . openStream () ) ) ;

pojawi sie, wyjatek, nie bedzie oczywista, sprawa,, gdzie le˙zy jego przyczyna. Je´sli za´s ten , , wiersz rozbijemy na kilka cze´ , sci i wydzielimy zmienne, to w momencie pojawienia sie, wyjatku lub bledu, bedzie oczywiste, kt´ore wyra˙zenie spowodowalo jego wystapienie. , , , ,

48 R Mistrz Programowania BNS IT, http://www.bnsit.pl

REFAKTORYZACJA: WYDZIELENIE ZMIENNEJ TYMCZASOWEJ

Wa˙zne Wydzielanie zmiennych ze zlo˙zonych wyra˙ze´ n mo˙ze ulatwi´c odnajdywanie przyczyn wystapienia wyjatk´ , , ow lub bled´ , ow.

Nazywanie warunk´ow Szczeg´ olna, odmiana, refaktoryzacji Wydzielenie zmiennej tymczasowej lub Wydzielenie metody jest Nazywanie warunk´ow. Przyjrzymy sie, wierszowi: String line = null ; while ( ( line = bufferedReader . readLine () ) != null ) {

Dzieje sie, tu wiele rzeczy jednocze´snie - jest przypisanie warto´sci, jest sprawdzenie warunku. To trudny wiersz do analizy. W tym przypadku nie udalo mi sie, znale´z´c jednego prostego przej´scia, dlatego proponuje, nastepuj ace zmiany: , , // ... String line = bufferedReader . readLine () ; while ( hasNextLine ( line ) ) { // ... line = bufferedReader . readLine () ; } // ... private boolean hasNextLine ( String line ) { return ( line != null ) ; }

Pojawila sie, pomocnicza metoda hasNextLine oraz odczyt kodu HTML zostal przesuniety do osobnych wierszy. Pojawia sie, w zamian pewna nadmia, z warunku p etli , rowo´s´c (dwukrotnie w kodzie wystepuje odczyt line = bufferedReader.readLine();). , Chcialbym zwr´ oci´c uwage, w tym przykladzie na metode, hasNextLine, gdy˙z ona jest tu gl´ ownym bohaterem. Czesto w kodach ´zr´odlowych pojawiaja, sie, skompliko, wane konstrukcje definiujace , warunki wykonywania przeplywu. Sa, one trudne w interpretacji i rzadko wyra˙zaja, bezpo´srednio intencje, autora. Taki warunek lepiej zapisa´c w postaci nowej zmiennej pomocniczej (refaktoryzacja Wydzielenie zmiennej tymczasowej) lub nowej metody pomocniczej (refaktoryzacja Wydzielenie metody ). Dzieki ,

49 R Mistrz Programowania BNS IT, http://www.bnsit.pl

´ ˙ E - TECHNIKI, KTORE ´ ˙ ROZDZIAL 2. KOD, KTORY CZYTA SIE, JAK KSIA,ZK CALKOWICIE ODMIENIA, TWOJE ZYCIE PROGRAMISTY ,

temu posunieciu dodatkowo dokumentujemy warunek i jest on prostszy w interpreta, cji. Zapis hasNextLine zawiera informacje, o tym, jaka byla intencja autora, czego z pewno´scia, w spos´ ob bezpo´sredni nie zawiera konstrukcja (line = bufferedReader.readLine()) != null). Innym przykladem (kt´ ory nie wystepuje w realizowanym w tej ksia˙ , ,zce projekcie) mo˙ze by´c sprawdzenie, czy ciag , znakowy zawiera przynajmniej jeden znak niepusty. String text = readFromFile ( filename ) ; if ( text != null && text . trim () . equals ( " " ) == false ) { System . out . println ( text ) ; }

Oczywi´scie ka˙zdy wprawiony programista jezyka Java rozszyfruje ten zapis po pew, nym czasie, jednak potrzebna bedzie na to dodatkowa energia. , String text = readFromFile ( filename ) ; boolean textNotEmpty = ( text != null && text . trim () . equals ( " " ) == false ) ; if ( textNotEmpty ) { System . out . println ( text ) ; }

Warunek if ( textNotEmpty ) jest napisany niemal˙ze ludzkim jezykiem. Pro, gramista mo˙ze oczywi´scie sprawdzi´c, co kryje sie, za nazwa, textNotEmpty, ale tylko wtedy, kiedy jest mu to potrzebne. Nie musi analizowa´c warunku, aby zrozumie´c dany fragment kodu. Wa˙zne U˙zywaj nazwanych warunk´ ow, aby w prosty i bezpo´sredni spos´ob wyrazi´c intencje, zwiazan a, z danym fragmentem kodu. , Czesto sie, zdarza, z˙ e pod konkretna, postacia, warunku mo˙ze sta´c intencja, kt´ora, , warto zapisa´c. W jednym z szkielet´ ow aplikacyjnych do tworzenia aplikacji sieciowych w jezyku Java, u˙zywa sie, czesto warunku w postaci: , , if ( person . getId () != null ) { // ... } else { // ... }

50 R Mistrz Programowania BNS IT, http://www.bnsit.pl

ZLOTE REGULY REFAKTORYZACJI

Sprawa niby prosta i oczywista. Z tym, z˙ e za zapisem person.getId() != null stoi pewna intencja. Warunek ten slu˙zy do sprawdzenia, czy w danym momencie naste, puje edycja istniejacego obiektu person.getId() != null czy te˙z tworzenie nowego , obiektu person.getId() == null. Mo˙zna by powy˙zszy kod zapisa´c w nastepuj aco: , , boolean editMode = ( person . getId () != null ) ; if ( editMode ) { // ... } else { // ... }

W ten spos´ ob u˙zywajac sni, refaktoryzacji Wydzielenie zmiennej tymczasowej rozja´ li´smy intencje, stojac s´c oczywistym warunkiem. Refaktoryzacja slu˙zy , a, za pozornie do´ przede wszystkim temu, aby osoba, kt´ora bedzie czytala dany fragment kodu za kilka , tygodni lub miesiecy, w ciagu mo˙zliwie kr´otkiego czasu mogla zorientowa´c sie, , , , co jest intencja, danego fragmentu kodu oraz kt´ore miejsce nale˙zy zmodyfikowa´c, aby wprowadzi´c zmiany. Dokonujac smy do bardziej uporzadkowanego rozwiaza, zmian w systemie, dotarli´ , , nia. Caly czas aplikacja nie ma zbyt wielu znamion kodu obiektowego. I bardzo dobrze! Oznacza to, z˙ e przedstawione do tej pory refaktoryzacje moga, by´c stosowane z powodzeniem w jezykach proceduralnych. , Gl´ ownym mankamentem rozwiazania, nad kt´orym pracujemy, jest to, z˙ e metoda , searchWord caly czas pozostaje do´s´c zlo˙zona, trudna w zrozumieniu i nieprzygotowana na rozbudowywanie . Jednak kolejne zmiany zostawimy do nastepnego rozdzialu. ,

Zlote reguly refaktoryzacji Powt´ orzmy na koniec podstawowe elementy, kt´ore w prosty spos´ob moga, spowodowa´c, i˙z kod bedzie bardziej samodokumentujacy sie, i z˙ e bedzie sie, go czytalo jak ksia˙ , , , ,zke. , 1. przeanalizuj odpowiedzialno´s´c swoich klas, p´ol w klasie, metod i zmiennych; analiza ta jest baza, do wprowadzanych zmian; 2. je´sli odpowiedzialno´s´c jest zbyt du˙za podziel te elementy na skladowe (poprzez Wydzielenie metody lub Wydzielenie zmiennej); 3. je´sli odpowiedzialno´s´c jest zbyt mala (co dotyczy gl´ownie klas i czasami metod), polacz , je;

51 R Mistrz Programowania BNS IT, http://www.bnsit.pl

´ ˙ E - TECHNIKI, KTORE ´ ˙ ROZDZIAL 2. KOD, KTORY CZYTA SIE, JAK KSIA,ZK CALKOWICIE ODMIENIA, TWOJE ZYCIE PROGRAMISTY ,

4. upewnij sie, s´c klasy, metody, , z˙ e nazwy definiuja, jednoznacznie odpowiedzialno´ zmiennej lub pola; je´sli nie - zmie´ n je najszybciej jak to mo˙zliwe; nazwy to gl´ owne no´sniki informacji w twoim kodzie; 5. warunki wydzielaj do osobnych zmiennych lub metod, aby bezpo´srednio i jednoznacznie wyrazi´c intencje, ora za nimi stoi; , kt´ 6. ciesz sie, kodem, kt´ ory jest czytelny.

Kod trudny w testowaniu prawdopodobnie nadaje sie, do refaktoryzacji Jak ju˙z wspominalem, testowanie jest bardzo wa˙znym uzupelnieniem procesu refaktoryzacji - jest ono niezbedne, aby mie´c pewno´s´c, i˙z wprowadzane zmiany rzeczywi´scie , nie zmieniaja, obserwowalnego zachowania. Jest jeszcze jeden pow´ od, kt´ ory sprawia, z˙ e testowanie jest takie wa˙zne. Wa˙zne Je´sli chcesz przetestowa´c fragment swojego kodu i wydaje ci sie, to trudne a nawet niemo˙zliwe, prawdopodobnie kod wymaga refaktoryzacji.

Czesto mialem okazje, bra´c udzial w sytuacji, kt´ora przebiegala nastepuj aco. Ra, , , zem z innym programista, analizuje, jego kod oraz testy do kodu. Zauwa˙zam, z˙ e pewien fragment w og´ ole nie jest przetestowany. - Dlaczego nie ma testu do tej metody? Konsternacja na twarzy mojego rozm´owcy. - Bo wiesz . . . tego sie, nie da przetestowa´c . . . Zazwyczaj patrze, wtedy z niedowierzaniem i zaczynamy analizowa´c rozwiazanie. Po , pewnym czasie wsp´ olnie ju˙z stwierdzamy, z˙ e tego kodu sie, nie da przetestowa´c. Jest po prostu nienajlepiej napisany i wymaga refaktoryzacji. Na przyklad trudno przetestowa´c dluga, metode, scie skomplikowanych scenariuszy, do , gdy˙z zazwyczaj zawiera kilkana´ kt´orych nale˙zy przygotowa´c czesto zlo˙zone dane wej´sciowe i spodziewane wyj´sciowe. , Podzielenie metody na mniejsze cze´ c mniejsze frag, sci powoduje, z˙ e mo˙zemy testowa´ menty, co jest zazwyczaj du˙zo prostsze. Dlatego uwa˙zam, z˙ e ka˙zdy programista powinien zna´c techniki testowania, nawet

52 R Mistrz Programowania BNS IT, http://www.bnsit.pl

KOD TRUDNY W TESTOWANIU PRAWDOPODOBNIE NADAJE SIE, DO REFAKTORYZACJI

je´sli sam testowaniem sie, nie zajmuje. Spojrzenie na kod z punktu widzenia testera pozwala odkry´c jego slabe punkty. Uwaga! W tym miejscu ko´ nczy sie, udostepniana bezplatnie cze´ c ksia˙ sli te, , s´ ,zki. Je´ mat cie, zaciekawil, je´sli chcialby´s pozna´c go glebiej zapraszamy na na, sza, strone, http://www.bnsit.pl, aby dowiedzie´c sie, wiecej. Mo˙zesz naby´c , pelna,, licencjonowana, wersje, tej ksia˙ ,zki w formie elektronicznej, jak i papierowej oraz warsztaty, kt´ore stanowia, multimedialna, forme, przekazania do´swiadczenia zwiazanego z refaktoryzacja., , Uwaga! Je´sli chcialby´s wsp´ oltworzy´c te, ksia˙ ,zke, np. przygotowujac , wersje, w innym jezyku programowania, albo masz pomysl na nowa, ksia˙ , ,zke, , napisz na adres [email protected]

53 R Mistrz Programowania BNS IT, http://www.bnsit.pl