Ewolucja oprogramowania i refaktoryzacja

Plan wykładów





Wykład dotyczący ewolucji oprogramowania i refaktoryzacji jest ostatnim z cyklu wykładów poświęconych inżynierii oprogramowania. Przedstawia przyczynę ciągłe ewolucji oprogramowania, czynników wpływających na jej postęp, sposoby pielęgnacji oprogramowania i omawia związane z nią koszty.


Agenda


 

W trakcie wykładu zostaną omówione następujące zagadnienia




Geneza ewolucji oprogramowania


Zmiana jest naturalnym elementem świata – każdy jego element ulega ewolucji. Podobnie jest z oprogramowaniem: w trakcie swojego życia program ewoluuje w odpowiedzi na różne bodźce i siły, które na niego wpływają:




Waga pielęgnacji oprogramowania



Aby uzmysłowić sobie istotę procesu pielęgnacji oprogramowania, warto przeanalizować powyższy wykres, przedstawiający dotychczasowy i prognozowany udział przedsięwzięć pielęgnacyjnych w stosunku do wszystkich przedsięwzięć związanych z oprogramowaniem. Wynika z niego, że udział liczby przedsięwzięć informatycznych, które dotyczą jedynie pielęgnacji istniejącego oprogramowania, stale rośnie, z ok. 10% w latach 50-tych, do ok. 60% obecnie. Trend ten, choć w mniejszym nasileniu, zostanie utrzymany w najbliższych latach i w roku 2020 osiągnie ok 67%


Wykres można interpretować w ten sposób, że obecnie rozwój nowego oprogramowania wymaga znacznie mniejszych nakładów, niż pielęgnacja już istniejącego. Wskazuje to na rosnącą wagę pielęgnacji jako fazy w cyklu życia programu.




Kolejny przykład dowodzący wzrostu wagi pielęgnacji programów dotyczy znanego prawa Moore'a, które mówi, że wydajność procesorów dostępnych na rynku podwaja się średnio co osiemnaście miesięcy. Ta wykładnicza zależność w zasadzie sprawdza się od dłuższego czasu, choć mówi się także o kresie możliwości technologii opartych na krzemie, który zmieni tę zasadę.


Jednak tworzenie oprogramowania o złożoności wzrastającej w podobnym tempie jest niemożliwe; co więcej, nawet znacznie mniej ambitny cel, jakim jest liniowy wzrost rozmiaru programów, także nie został osiągnięty. To oznacza, że oprogramowanie w swoim rozwoju napotyka na istotną przeszkodę, która nie istnieje w przypadku sprzętu. Tą przeszkodą jest problem z zarządzaniem złożonością i procesami starzenia się oprogramowania.



Ewolucja a pielęgnacja


Ponieważ dotąd zamiennie pojawiały się pojęcia ewolucji oprogramowania i jego pielęgnacji, dlatego warto bliżej im się przyjrzeć i określić je precyzyjniej.


Ewolucja oprogramowania jest procesem jego rozwoju sterowanym zmianami wymagań, poprawą błędów czy też rozwojem sprzętu. Ewolucja jest nieunikniona: oprogramowanie ewoluuje, ponieważ to leży w jego naturze.


Natomiast pielęgnacja to zaplanowany proces, który służy do kontrolowania ewolucji i czynników, które na nią wpływają. Pielęgnacja ma na celu wykrywanie i usuwanie błędów, poprawę atrybutów jakościowych działania programu oraz adaptację do zmian w nim zachodzących.


Ponieważ jednak, w kontekście oprogramowania, ewolucja zawsze wymaga jakiejś formy pielęgnacji, dlatego pojęcia te czasem stosuje się zamiennie.



Pielęgnacja w modelu kaskadowym


Model kaskadowy rozwoju oprogramowania zakłada, że kolejne fazy są realizowane przez dostawcę (producenta) do momentu wdrożenia, natomiast pielęgnacja programu zaczyna się wraz z przekazaniem go użytkownikowi. Takie założenie bardzo utrudnia przepływ informacji zwrotnej między użytkownikiem a dostawcą. W efekcie program przestaje odpowiadać potrzebom i oczekiwaniom użytkownika, natomiast dostawca nie jest o nich powiadamiany, ponieważ użytkownik jest zainteresowany utrzymaniem systemu w ruchu, nawet za cenę jego pielęgnacji.


Powoduje to małą efektywność pielęgnacji realizowanej w modelu kaskadowym.



Klasyfikacja programów a ewolucja


W kontekście pielęgnacji oprogramowania, Lehman wprowadził prosty podział programów na trzy kategorie:





Programy typu S


Programy typu S reprezentują teoretyczną gałąź rozwoju inżynierii oprogramowania. Wobec nich zakłada się, że powstały na podstawie pełnej i kompletnej specyfikacji, w której zawarto wszystkie niezbędne informacje w sposób jednoznaczny i niesprzeczny. Przyjmuje się założenie, że specyfikacja odpowiada niezmiennym potrzebom użytkownika, a zatem jego udział w pracach nad systemem nie jest konieczny. Jedyną podstawą do tworzenia programu, a następnie jego weryfikacji jest właśnie specyfikacja. Wszelkie cechy, które oprogramowanie posiada, a które nie zostały uwzględnione w specyfikacji, są ignorowane, ponieważ z punktu widzenia specyfikacji nie istnieją.


W takim modelu proces ewolucyjny w zasadzie nie występuje, ponieważ wszelkie żądania zmian w oprogramowaniu, niezależnie od ich natury i źródła, powodują stworzenie nowej specyfikacji, której implementacją jest zupełnie nowy program.


Oczywiście, model ten jest rzadko spotykany w praktyce: już założenie o kompletności i niespójności specyfikacji ogranicza jego stosowalność jedynie do bardzo małych problemów, zwykle o znaczeniu teoretycznym.



Programy typu P




Kategorią programów, która w większym stopniu nawiązuje do rzeczywistości rozwoju i ewolucji oprogramowania, są programy typu P. Model budowany na podstawie obrazu środowiska (świata rzeczywistego) naśladuje pewne cechy tego środowiska, ale z natury jest niekompletny. Niepełność modelu jednak jest pożądaną cechą, ponieważ pozwala pomijać nieistotne elementy środowiska, a co za tym idzie – stosować to podejście do większych i bardziej złożonych zadań niż w przypadku programów typu S. Na podstawie modelu powstaje specyfikacja (również niepełna, z możliwymi sprzecznościami), a następnie program. Jeżeli w środowisku zachodzi zmiana, która wymaga odzwierciedlenia w programie, wówczas program podlega modyfikacji.


W przypadku programów należących do tej kategorii środowisko posiada wpływ na ewolucję programu, a sam program jest z natury ułomnym narzędziem pozwalającym w przybliżeniu rozwiązywać postawiony problem. Program jest uważany za poprawny, jeżeli produkuje akceptowalne (z subiektywnego punktu widzenia użytkownika) rozwiązania. Zachowanie programu powodujące stworzenie nieakceptowalnego (z powodu błędu lub zbyt ubogiej funkcjonalności) rozwiązania stanowi podstawę ewolucji takiego programu.



Programy typu E


Programy typu E odpowiadają dużej grupie rzeczywistych programów, osadzonych i pracujących przez długi czas w środowisku, dla którego powstały. Są to zwykle duże systemy, tworzone na zamówienie przez duże organizacje wytwarzające oprogramowanie. Specyfikacja i model są – podobnie jak w przypadku programów typu P – z natury niepełne i mogą posiadać błędy lub luki. Jednak największa różnica polega na integracji programu ze środowiskiem, co oznacza, że oba elementy na siebie nieustannie oddziałują. W ten sposób zmiana w środowisku natychmiast oddziałuje na program, wywierając potrzebę zmiany także w nim. Powoduje to niemal nieustanny napływ informacji zwrotnej od użytkowników systemu, co pozwala na wprowadzanie zmian najistotniejszych z ich punktu widzenia.


"Prawa" Lehmana


Na podstawie tej klasyfikacji M. Lehman, począwszy od roku 1968, zaproponował osiem praw dotyczących natury ewolucji oprogramowania. Kolejne prawa pojawiały się w dłuższych odstępach czasu, aż do lat 90-tych XX wieku. Prawa te zostały opracowane nie na podstawie analizy statystycznej czy metod formalnego dowodzenia, lecz na podstawie obserwacji ewolucji kilku dużych systemów informatycznych (klasycznym przykładem był IBM OS/360). To spowodowało krytykę użytego przez Lehmana pojęcia 'prawo', skoro jego obserwacje dotyczyły kilku arbitralnie wybranych systemów. Wyniki te zostały ponownie zbadane w serii projektów FEAST, i nazwa 'prawa Lehmana' utrzymała się.


Warto pamiętać, że prawa Lehmana dotyczą programów typu E – dużych, wielokrotnie modyfikowanych systemów, które ewoluują przez dłuższy okres czasu. Jak dotąd brak jest potwierdzenia stosowalności tych praw dla innych typów programów.



Prawo nieustannej zmiany


Prawo to przypomina zasady rządzące światem natury: organizm umieszczony w określonym środowisku dostosowuje się do niego lub ginie. W przypadku oprogramowania sytuacja jest nieco bardziej złożona: potrzeba zmian wynika nie z samego programu, ale z informacji zwrotnej pochodzącej z samego środowiska. To żądania zmian funkcjonalnych powodują konieczność modyfikacji (poprawy błędu, rozszerzenia funkcjonalnego etc.) oprogramowania.


Istnieje też dodatkowy czynnik: program posługuje się pewnym modelem rzeczywistości, z którą współpracuje. Im bardziej model ten nie odpowiada faktycznemu stanowi, tym bardziej konieczne staje się dostosowanie modelu do zmieniającej się rzeczywistości.


Jeżeli dążenie do zmian zostanie w pewien sposób zahamowane, wówczas w miarę upływu czasu oprogramowanie będzie w coraz mniejszym stopniu odpowiadało potrzebom środowiska, a co za tym idzie - postrzegane jako coraz mniej użyteczne.



Prawo wzrastającej złożoności



Drugie prawo Lehmana opisuje zjawisko znane w wielu dziedzinach fizyki: zwiększanie nieuporządkowania (entropii) w miarę upływu czasu. Wprowadzanie zmian do oprogramowania (nazywanych często progresywnymi) zwykle narusza pierwotną strukturę programu, a kumulacja zmian tylko ten proces nasila. Liczba powiązań i interakcji pomiędzy różnymi modułami w systemie zwiększa się, co utrudnia zrozumienie go, a także jego dalsze modyfikacje.


Alternatywą jest poniesienie dodatkowych nakładów w trakcie pielęgnacji, poświęconych na czynności antyregresywne: upraszczanie struktury i lepsze wkomponowanie wprowadzanych zmian w istniejące oprogramowanie.


Równowaga pomiędzy czynnościami progresywnymi a regresywnymi zależy od ilości i rodzaju informacji zwrotnej płynącej ze środowiska: inaczej są obsługiwane żądania związane z naprawą błędów, a inaczej z rozszerzeniami funkcjonalnymi.



Prawo samoregulacji


Proces ewolucji jest wypadkową sił obecnych w środowisku oraz reakcji na nie. Z uwagi na liczność tych sił, na różnym poziomie i o różnym natężeniu, wiele obserwacji dokonanych na istniejącym oprogramowaniu wskazuje, że ich suma posiada rozkład normalny. Oznacza to, że taki system sterowany informacją zwrotną płynącą ze środowiska ma właściwości samoregulujące.


Prawo organizacyjnej stabilności




Prawo to jest szczególne, ponieważ opisuje obserwację sprzeczną z intuicją. Powszechnie przyjmuje się, że wydajność pracy zależy od jej organizacji i decyzji zarządczych na różnych szczeblach.


Tymczasem w przypadku oprogramowania (typu E) tempo jego rozwoju w fazie pielęgnacji jest w przybliżeniu stałe i nie jest związane z ilością dostępnych zasobów. Brooks w swojej książce "Mityczny osobomięsiąc" wskazuje nawet przykłady przedsięwzięć programistycznych, w których zwiększanie zasobów prowadzi do zmniejszenia wydajności i wydłużenia harmonogramu prac z uwagi na bardziej złożoną komunikację.


Dane zebrane przez Lehmana wskazują, że tempo rozwoju każdego systemu na pewnym etapie stabilizuje się na stałym poziomie. Wykres przedstawia najbardziej znany przykład, na podstawie którego Lehman sformułował swoje prawa: tempo rozwoju systemu IBM OS/360. Do wydania 19 tempo wzrostu jest w przybliżeniu stałe, natomiast chaotyczne zachowanie w ostatnich wydaniach jest interpretowane jako efekt zbyt dużej ilości informacji zwrotnej wprowadzonej do wydania 20.



Prawo zachowania przyzwyczajeń



Znajomość celów realizowanych przez oprogramowanie jest jednym z czynników wpływających na jego rozwój. Zbyt duża liczba zmian zawartych w wydaniu powoduje, że użytkownicy nie są w stanie tych zmian przyswoić i opanować, czyli w praktyce nie korzystają z dodanej funkcjonalności. Powoduje to poczucie chaosu i nadmiaru informacji. Im większa funkcjonalność jest związana z kolejnymi wydaniami programu, tym trudniej jego odbiorcom zapoznać się ze zmianami i wykorzystać je. W ten sposób tempo rozwoju zależy od stopnia przyswojenia wiedzy o wprowadzonych zmianach przez każdego z użytkowników.


Ponadto, duża liczba zmian to duża liczba potencjalnych błędów, które następnie będą wymagały kolejnego, czysto naprawczego wydania programu.


Dane zgromadzone przez Lehmana wskazują, że zależność między liczbą nowych funkcji a czasem potrzebnym do ich przyswojenia nie jest liniowa. Prawdopodobnie istnieją pewne progi funkcjonalności dostarczanej w każdym wydaniu, powyżej których konieczne staje się zmodyfikowanie zachowania programu.


Prawo to nazywa się prawem zachowania przyzwyczajeń, ponieważ nawyki związane z obsługą oprogramowania stanowią bardzo wyrazisty i intuicyjny przykład czynnika ograniczającego tempo rozwoju oprogramowania.



Prawo ciągłego wzrostu




Prawo szóste jest zbliżone do prawa pierwszego, choć dotyczą one nieco innego zjawiska. Opisuje ono nowe, niezależne źródło zmian w oprogramowaniu.


Zakłada się zwykle, że w momencie powstawania programu jego specyfikacja zawiera definicje wszystkich wymagań. W trakcie rozwoju, z powodu ograniczeń budżetowych i organizacyjnych, są ograniczane one do pewnego ich podzbioru. Wymagania, które nie zostały zawarte w tym podzbiorze, są wykluczane z dalszych prac lub odraczane na przyszłość.


Jednak w pewnym momencie funkcje, które nie zostały zaimplementowane, staną się utrudnieniem w pracy z systemem, zmniejszając jego użyteczność. W ten sposób powstaje potrzeba zmian funkcjonalnych obejmujących wymagania pominięte we wcześniejszych fazach. Implementacja tych wymagań ma za zadanie utrzymać poziom satysfakcji użytkowników z systemu na dotychczasowym poziomie.


Pielęgnacja oprogramowania zakłada więc nieustanny rozwój funkcjonalny. Co ciekawe, w innych dziedzinach inżynierii, np. budownictwie lądowym, sytuacja taka nie występuje lub jej waga jest znacznie mniejsza: od mostu nikt nie wymaga, aby w miarę upływu czasu był on wyposażony w dodatkowe możliwości, np. podnoszenie i opuszczanie przęsła w celu przepuszczenia ruchu wodnego lub zwiększenie nośności



Prawo spadku jakości


Jakość oprogramowania jest postrzegana z dwóch punktów widzenia: z zewnątrz, przez użytkownika, i z wewnątrz, przez programistę. Oba punkty widzenia dotyczą innych problemów: użytkownika interesują błędy i funkcjonalność, natomiast programistę także wewnętrzna struktura programu. Jakość w obu tych aspektach ulega degradacji w miarę upływu czasu.


Jakość zewnętrzna dotyczy liczby i rodzaju znajdowanych błędów oraz funkcji oferowanych przez system. System pracujący w satysfakcjonujący sposób przez dłuższy czas także jest narażony na wykrycie w nim błędu. Wśród innych powodów można wymienić zwiększające się z upływem czasu potrzeby i oczekiwania użytkowników, ich przyzwyczajenia, a także ewoluujące standardy jakościowe oprogramowania, szczególnie przy pojawiającej się na rynku konkurencji. W oczach użytkownika program, który nie nadąża za postępem, staje się przestarzały i mniej użyteczny, nawet jeżeli jego funkcjonalność nie ulega zmianie.


Jakość wewnętrzna jest bardziej obiektywną miarą złożoności struktury programu. Pokazuje ona pośrednio, jaka jest zdolność programu do pielęgnacji. Zmiany, wprowadzane wraz z ewolucją, zwykle nie są prawidłowo integrowane z istniejącą strukturą i ją pogarszają.


Lehman wskazuje, że jedynie rygorystyczna pielęgnacja jest w stanie zapobiec spadkowi jakości oprogramowania w miarę upływu czasu.



Prawo przyrostowego rozwoju



Prawo to jest uogólnieniem i podsumowaniem pozostałych praw, i nie jest oparte na nowych obserwacjach, a raczej dostarcza nowych wniosków wynikających ze znanych już faktów. Stwierdza, że ewolucja oprogramowania jest złożonym, wielopoziomowym i uwzględniającym wiele punktów widzenia systemem z informacją zwrotną. Przykładem tego wniosku jest analiza przedstawionego wcześniej wykresu prezentującego rozwój systemu IBM OS/360. Stabilny rozwój w początkowym okresie wynika ze stabilnej pracy systemu sterowanego informacją zwrotną. Załamanie i niestabilność wzrostu po 19 wydaniu wynikała z próby nadmiernego rozwoju systemu w wydaniu 20, co spowodowało konieczność wprowadzenia poprawek w kolejnych wydaniach. Zaburzyło to trend wzrostu systemu.


Rola informacji zwrotnej znana była już wcześniej, jednak dopiero teraz została ona wyrażona tak dobitnie. Lehman podkreśla, że zaskakujący dla niego jest fakt, iż została ona zinterpretowana w ten sposób dopiero po kilkunastu latach badań.



Wnioski z praw Lehmana



Prawa Lehmana pokazują, że oprogramowanie, które ma być użyteczne przez dłuższy czas, musi ewoluować. W przeciwnym razie jego jakość wewnętrzna (struktura kodu) oraz zewnętrzna (postrzegana przez użytkowników) pogarsza się, aż oprogramowanie ulega wyparciu z rynku.


Istotnym problemem jest wzrost złożoności oprogramowania w miarę rozwoju programu. Istnieje punkt nasycenia, poza którym dalszy rozwój jest bardzo trudny lub nawet niemożliwy, o ile nie wcześniej stosowano technik zarządzania złożonością i nie restrukturyzowano programu na bieżąco.


Jednym z silniejszych twierdzeń Lehmana jest ograniczenie tempa rozwoju i wskazanie, że nie zależy ono od podejmowanych decyzji zarządczych.



Rozwój jądra Linuxa




Prawa Lehmana nie dotyczą jednak wszystkich rodzajów oprogramowania.


Na wykresie przedstawiono rozwój jądra systemu Linux. Pierwsza wersja, udostępniona w marcu 1994 roku, składała się z 487 plików o łącznej długości 165 KLOC. Wersja 2.3.39, opublikowana w styczniu 2000 roku, obejmowała już 4854 pliki o łącznej długości 2.2 MLOC. Warto jednak zauważyć, że rozwój systemu, szczególnie w tzw. wersji rozwojowej następował w tempie szybszym od liniowego, co stanowi zaprzeczenie czwartego prawa Lehmana. Zatem istnieje możliwość rozwoju systemu szybszego niż przewidział to Lehman.



Czynniki sukcesu rozwoju jądra Linuxa



Jakie czynniki wpływają na tę właściwość Linuxa?


Jest to produkt open source, tworzony jednocześnie w sposób równoległy przez wielu programistów. Wymagania są definiowane na bieżąco i szeregowane wg priorytetów do implementacji w kolejnych wersjach. Występuje zatem pętla sprzężenia zwrotnego: program jest rozwijany na bieżąco, zgodnie ze zmianami środowiska (jest to potwierdzenie pierwszego prawa Lehmana). Ponadto znaczne nakłady są inwestowane w bieżącą restrukturyzację kodu, co pozwala zaoszczędzić znaczne środki w późniejszych fazach.


Linux jest też zorganizowany w sposób modularny, dzięki czemu możliwe jest tak szerokie zrównoleglenie prac. Znaczna część funkcjonalności jest zaimplementowana w sterownikach, które są niezależne od samego jądra.


Linux posiada dwie zasadnicze gałęzie konfiguracji: stabilną, na której znajdują się elementy przetestowane, o wysokiej wiarygodności, oraz rozwojową, zawierającą wszystkie elementy, także te nie do końca przetestowane. Sukcesywnie elementy z tej ostatniej są testowane i przenoszone na gałąź główną. To rozwój gałęzi rozwojowej – wielokierunkowy, żywiołowy – charakteryzuje się ponadliniowym wzrostem.



Pielęgnacja w modelu spiralnym




W modelu spiralnym, odzwierciedlającym ewolucyjną naturę tworzenia oprogramowania, pielęgnacja nie jest fazą kończącą cykl życia programu – jest elementem każdego przyrostu funkcjonalnego. Pozwala ona na lepsze zaimplementowanie nowych wymagań bez degradacji istniejącej struktury oprogramowania.


Modele pielęgnacji oprogramowania





Zatem można wyróżnić także inną klasyfikację modeli pieęgnacji oprogramowania, opartą na obserwacjach E. Raymonda dotyczących metod open source:

Szczególnie interesujący jest ten drugi model, reprezentowany m.in. przez Linuxa, w którym system nieustannie znajduje się w fazie pielęgnacji. Ważne jest to, że charakteryzuje się on większym tempem wzrostu niż przewidziane prawami Lehmana, charakterystycznymi dla stylu budowy katedry. Zatem model ciągłego, wielokierunkowego rozwoju okazuje się skuteczniejszy niż model planowanego rozwoju.



Pracochłonność pielęgnacji




Na pielęgnację oprogramowania składają się cztery różne rodzaje aktywności




Koszt pielęgnacji oprogramowania




Jak już wskazano na wstępie, pielęgnacja jest procesem wymagającym coraz więcej wysiłku i poświęcenia większych zasobów niż w tworzenie oprogramowania. Przyjmuje się, że koszt pielęgnacji w każdym systemie może być porównywalny lub wyższy od kosztu jego stworzenia, w zależności od czasu jego pielęgnacji i innych, wymienionych wcześniej, czynników. Skrajnym przykładem jest dysproporcja kosztu stworzenia i pielęgnacji jednej linii kodu w systemie tworzonym przez Boeinga dla Sił Powietrznych USA: napisanie kosztowało $30, natomiast pielęgnacja ponad stukrotnie więcej! Wynika to z obserwacji, że roczny koszt pielęgnacji rośnie wraz z okresem jej trwania.


Na wykresie przedstawiono przykład dwóch produktów, różniących się kosztem wytworzenia i pielęgnacji. W przypadku produktu A koszt produkcji był wyższy niż produktu B, jednak pozwoliło to ograniczyć koszt pielęgnacji i w sumie całkowity koszt związany z programem (ang. total cost of ownership , TCO).



Model kosztowy Boehma




Zaproponowany przez Boehma prosty model kosztowy przewiduje, że pielęgnacja oprogramowania jest związana z wysiłkiem proporcjonalnym do rozmiaru modyfikowanego kodu. Oznacza to, że pielęgnacja systemu, którego koszt budowy wyniósł np. 125 osobomiesięcy, wyniesie rocznie taką część tego kosztu, jaka uległa zmianie w tym okresie (np. dla 10% będzie to 12.5 osobomiesiąca).


Model ten, wzorowany na COCOMO, może zostać rozszerzony także o inne czynniki wpływające na wysokość oszacowania. W takim przypadku czynniki te są mnożone przez otrzymany wynik.



Czynniki wpływające na koszt pielęgnacji




Na koszt pielęgnacji ma wpływ wiele czynników technicznych i pozatechnicznych.




Inżynieria Ponowna


Inżynieria ponowna (czyli re-inżynieria) jest pojęciem stosowanym w odniesieniu do pielęgnacji istniejących systemów o słabej pielęgnowalności. Celem jest zwiększenie tej zdolności przez zmianę jego wewnętrznej struktury, aktualizację dokumentacji etc. Stosowanie jej pozwala ograniczyć koszty związane z pielęgnacją, a także ryzyko związane ze stworzeniem całkowicie nowego oprogramowania. Oczywiście, wiąże się z tym dodatkowy koszt, jaki należy ponieść w fazie tworzenia programu, jednak jest on rodzajem inwestycji zwracającej się podczas pielęgnacji. Z uwagi na koszty, warto stosować inżynierię ponowną, szczególnie w tych fragmentach systemu, które często ewoluują.



Refaktoryzacja



Szczególnym przypadkiem inżynierii ponownej jest refaktoryzacja. Dotyczy ona tylko zmian zachodzących w kodzie programu, a więc na najniższym poziomie restrukturyzacji.


Pojęcie wywodzi się od faktoryzacji, czyli przydziału odpowiedzialności do obiektów. Refaktoryzacja jest zatem ponownym podziałem systemu na obiekty. Wynika z tego, że dotyczy głównie paradygmatu obiektowego, choć pojęcia tego używa się także w stosunku do języków strukturalnych (np. C).


Spośród własności refaktoryzacji warto wspomnieć o dwóch najważniejszych: jej celem jest poprawa jakości wewnętrznej struktury kodu, a jednocześnie nie może ona zmieniać zachowania programu (tzn. program po przekształceniu zachowuje się identycznie jak przed zmianą). Zapewnienie tej ostatniej własności jest najtrudniejszym krokiem refaktoryzacji.



Koszt refaktoryzacji


drak slajdu

http://wazniak.mimuw.edu.pl/index.php?title=Io-13-wyk-Slajd33&action=edit



Przykład




Przykładem refaktoryzacji jest najprostsze przekształcenie: wyłączenie metody z kodu. Metoda scalarProduct() wykonuje dwie funkcje: obliczenie pewnych wartości, a następnie ich wyświetlenie. Celem refaktoryzacji jest zatem zmniejszenie jej złożoności poprzez podział. W efekcie, z metody zostaje wyłączona nowa metodaprintScalarProduct (), która zawiera kod odpowiedzialny za wyświetlanie wyników. Jest ona wywoływana z oryginalnej funkcji, przez co wywołanie tej ostatniej powoduje dokładnie te same efekty co poprzednio.


Analizując to przekształcenie warto zastanowić się nad warunkami jego poprawności. Aby istniała możliwość utworzenia nowej metody, inna o takiej nazwie nie może już istnieć (taki błąd wykryłby kompilator) ani nie może być odziedziczona, co spowodowałoby zmianę zachowania programu (taki błąd jest znacznie trudniejszy do wykrycia). Oba te warunki można zweryfikować bez konieczności uruchamiania programu, jedynie na podstawie analizy jego kodu źródłowego.



Podsumowanie




Podczas wykładu zaprezentowano podstawowe zagadnienia związane z ewolucją i pielęgnacją oprogramowania. Ewolucja jest procesem naturalnym i w praktycznych zastosowaniach nie da się jej uniknąć. Prawa Lehmana, opisujące naturę ewolucji jednej z kategorii oprogramowania, pokazują, że programy, które nie ewoluują, stają się coraz mniej użyteczne. Czynnikiem wspomagającym pielęgnację jest sterowanie ewolucją poprzez informację zwrotną płynącą ze środowiska. Dlatego cyklem życia szczególnie dobrze wspomagającym tę fazę rozwoju oprogramowania jest model spiralny.


Koszt związany z pielęgnacją zwykle przekracza koszt stworzenia oprogramowania. Dlatego stosowanie cyklicznej restrukturyzacji pozwala ograniczyć ten koszt, za cenę dodatkowych nakładów w fazie rozwoju.