Konserwacja oprogramowania
Mianem konserwacji (maintenance) określa się wszelkie działania związane z
modyfikacją oprogramowania, wykonywane po przekazaniu go użytkownikom do
eksploatacji. Konieczność takich działań może wynikać z przyczyn tkwiących w
samych programach lub w ich otoczeniu. Choć oprogramowanie nie zużywa się
podczas pracy, to może zawierać defekty, które nie wykryte w czasie testów ujawnią
się po pewnym czasie i doprowadzą do wystąpienia błędów. W takim przypadku
konieczne jest podjęcie naprawy polegającej na usunięciu przyczyn błędnego
działania. Innym powodem wprowadzania zmian może stać się starzenie
oprogramowania. W miarę upływu czasu na rynku pojawiają się nowe rozwiązania
technologiczne, z którymi stare oprogramowanie nie może współpracować.
Konieczność wymiany sprzętu albo chęć wykorzystania zalet nowej technologii może
wymusić zmiany dostosowujące oprogramowanie do nowych wersji sprzętu lub
oprogramowania
systemowego.
Najważniejszą
przyczyną
modyfikacji
oprogramowania są jednak zmiany zachodzące w wymaganiach użytkowników w ślad
za nieustannie zmieniającymi się potrzebami biznesowymi.
Wszystkie trzy rodzaje konserwacji oprogramowania:
korekcyjna (corrective) - związana z usuwaniem defektów,
adaptacyjna (adaptive) - dostosowująca do nowych warunków pracy, i
ulepszająca (perfective) - dostosowująca do nowych wymagań
użytkownika,
są na ogół wykonywane w sposób planowy. Prócz tego może niekiedy pojawić się
potrzeba przeprowadzenia doraźnych napraw wymuszonych ujawnieniem się
defektów uniemożliwiających funkcjonowanie programu. Standard IEEE 1219
klasyfikuje ten typ zmian jako konserwację awaryjną (emergency). W miarę
wprowadzania kolejnych zmian struktura oprogramowania oraz jego dokumentacji
pogarsza się. Z tego powodu podejmuje się czasem dodatkowe działania
porządkujące, których celem jest poprawa struktury oprogramowania lub
dostosowanie dokumentacji do rzeczywistego stanu programów. Tego typu działania
są nazywane konserwacją prewencyjną (preventive).
Odzyskanie nakładów poniesionych na wielkie systemy informatyczne
administracyjne, biznesowe, wojskowe itp., których koszt liczy się w setkach milionów
lub nawet w miliardach złotych, jest możliwe dopiero po wielu latach eksploatacji.
Dlatego systemy te żyją długo i w ciągu całego tego czasu są poddawane działaniom
konserwacyjnym. Liczne badania rynkowe wskazują, że łączny koszt konserwacji,
poniesiony w ciągu lat życia oprogramowania, może dwu-, a nawet trzykrotnie
przekroczyć początkowe nakłady poniesione na jego opracowanie. Te same badania
dowodzą, że tylko niespełna jedna czwarta tych kosztów jest związana z usuwaniem
defektów, podczas gdy ponad trzy czwarte kosztów wynika z potrzeb adaptacji lub
ulepszenia oprogramowania. Ostatni wynik ma ogromne znaczenie praktyczne, gdyż
pokazuje, że konserwacja jest czymś nieuniknionym. Nawet najlepiej skonstruowane i
przetestowane programy będą musiały ulegać modyfikacji, gdyż zarówno rozwój
technologii, jak i rozwój potrzeb biznesowych są nieprzewidywalne i nieuniknione.
1. Struktura konserwacji
Działania związane z konserwacją oprogramowania polegają na usunięciu
fragmentów programu, zmianie ich treści lub napisaniu całkiem nowych fragmentów.
Mimo podobnego charakteru pracy działania wykonywane podczas konserwacji
przebiegają w warunkach odmiennych od warunków towarzyszących oryginalnemu
projektowi. Podstawowym źródłem problemów związanych z konserwacją jest
znacznie niższa znajomość modyfikowanego oprogramowania przez wykonawców
pracy, wynikająca z następujących powodówŁ
Konserwacja następuje często wiele lat po wyprodukowaniu programu
i jest wykonywana przez zespół, który albo nie brał udziału w
oryginalnym projekcie, albo na skutek upływu lat nie pamięta już ani
przyjętych wówczas rozwiązań, ani motywacji towarzyszących
podejmowaniu głównych decyzji projektowych.
Dostępna dokumentacja nie odzwierciedla rzeczywistej struktury
oprogramowania. Może to być wynikiem nieprawidłowości
oryginalnego projektu albo wynikiem konserwacji wykonanej w
poprzedzającym okresie, w czasie której z braku czasu nie
aktualizowano całej dokumentacji w ślad za dokonywanymi w
programach zmianami.
Technologia, w jakiej jest wykonane oprogramowanie, zestarzała się i
nie jest dobrze znana członkom zespołu, który ma wprowadzić zmiany.
Ten poważny problem, występujący z wielką siłą podczas konserwacji
długo żyjącego oprogramowania, jest znany pod nazwą problemu
systemów odziedziczonych (legacy systems).
Konieczność rozwiązania wymienionych trudności wymusza wykonanie w
każdym projekcie, którego celem jest konserwacja oprogramowania, trzech rodzajów
działańŁ
Zrozumienie oprogramowania;
Analiza wpływu;
Testowanie regresyjne.
Zrozumienie oprogramowania
Warunkiem sukcesu projektu jest dokładne poznanie struktury
modyfikowanego programu, funkcji wykonywanych przez poszczególne komponenty,
zachowania systemu wynikającego z reguł współpracy komponentów oraz struktury i
przeznaczenia wykorzystanych w programie zbiorów danych. Stare szacunki
wskazują, że prace związane z poznaniem modyfikowanego programu mogą
pochłonąć grubo ponad 50% całkowitego kosztu konserwacji.
Jedną z technik stosowanych z powodzeniem na tym etapie pracy jest
inżynieria odwrotna, nazywana niekiedy inżynierią wstecz (reverse engineering),
polegająca na badaniu oprogramowania i odtwarzaniu - na podstawie kodu - modelu
jego budowy na odpowiednio wysokim poziomie abstrakcji. Jest to zadanie trudne,
jednak możliwe do wykonania nawet w takiej sytuacji, w której jedynym dostępnym
rodzajem dokumentacji oprogramowania jest kod źródłowy. Standard IEEE 1219
sugeruje sposób wykonania tego działania w postaci sześciu kroków.
1. Wyodrębnienie z kodu syntaktycznych jednostek programowych.
2. Opisanie semantyki tych jednostek i wyodrębnienie jednostek
funkcjonalnych.
3. Opisanie interfejsu jednostek funkcjonalnych (wejście-wyjście).
4. Stworzenie modelu przepływu sterowania między jednostkami.
5. Zdefiniowanie i opisanie funkcji systemu.
6. Stworzenie kompletnego modelu struktury i zachowania systemu.
Trzy pierwsze kroki, prowadzące do poznania programu drogą lokalnej
analizy kodu, są silnie wspierane przez istniejące środowiska programistyczne. Trzy
ostatnie, prowadzące do stworzenia modelu systemu drogą abstrakcji pojęciowej,
muszą być wykonane ręcznie.
Analiza wpływu
Zrozumienie sposobu działania oprogramowania i stworzenie modelu jego
budowy umożliwia dość szybkie zlokalizowanie tych komponentów, które
odpowiadają za realizację modyfikowanej funkcjonalności, i ustalenie dzięki temu
zakresu działania. Trudniejszym zadaniem jest określenie wpływu projektowanych
zmian na działanie innych komponentów systemu, których działanie nie powinno ulec
zmianie. Źródłem problemu mogą stać się niejawne powiązania między
komponentami wykorzystującymi wspólne zbiory lub inne struktury danych albo
między komponentami korzystającymi z usług niższych warstw oprogramowania o
strukturze warstwowej.
Zakres analizy wpływu (impact analysis) może w niektórych przypadkach
znacznie wykroczyć poza badanie funkcjonalnych i strukturalnych aspektów
oprogramowania.
Jeżeli modyfikacje niezbędne do realizacji zmienionych wymagań
funkcjonalnych użytkownika powodują zmniejszenie wydajności oprogramowania, to
może zaistnieć konieczność zastosowania nowego, wydajniejszego sprzętu. Jeżeli
przedmiotem modyfikacji jest stary system odziedziczony, to może się okazać, że
stare modele komputerów nie są już dostępne na rynku i zmiana sprzętu jest
równoznaczna z przeniesieniem systemu na nowy sprzęt wyposażony w zupełnie
inny system operacyjny. W większości przypadków taka zmiana wymusi głębokie
zmiany w architekturze systemu. Podobnej natury problemy mogą wystąpić w razie
konieczności wymiany systemu zarządzania bazy danych, wokół której jest
zbudowana aplikacja.
Rozszerzenie
możliwości
oprogramowania
lub
przeniesienie
oprogramowania do nowej, szybszej i wydajniejszej, infrastruktury informatycznej
oznacza przy tym zwykle stworzenie nowych okazji do dalszej modyfikacji systemu.
Celem tej modyfikacji może być ulepszenie, np. przyspieszenie działania,
wprowadzenie nowych funkcji lub uproszczenie obsługi, innych części programu.
Następstwem tych zmian może być niekiedy potrzeba zmodyfikowania przebiegu
procesów biznesowych tak, aby zmaksymalizować korzyści przedsiębiorstwa płynące
z posiadania ulepszonego systemu wspomagającego.
Testowanie regresyjne
Wszelkie zmiany wprowadzone do oprogramowania podczas konserwacji
wymagają przetestowania i zatwierdzenia. Przedmiotem testów powinno być nie tylko
sprawdzenie działania dodanej lub zmienionej funkcjonalności, ale także
sprawdzenie, czy wprowadzone zmiany nie naruszyły sposobu działania pozostałej,
teoretycznie niezmienionej, części oprogramowania. Niezbędnym elementem
konserwacji jest więc szeroko zakrojone testowanie regresyjne.
W większości przypadków można wykorzystać podczas konserwacji gotowy
zestaw testów opracowany w czasie procesu wytwarzania oprogramowania. Jeśli taki
zestaw istnieje, to można go powtórzyć w całości albo - jeżeli pełne testowanie
wymaga zbyt dużo czasu - można posłużyć się podzbiorem testów wybranym zgodnie
z ustaloną strategią.
2. Proces konserwacji
Badania pokazują, że działania związane z konserwacją oprogramowania
wykonuje się często pospiesznie, w odpowiedzi na doraźne problemy użytkownika,
który żąda natychmiastowego dostosowania systemu do jego potrzeb. W takich
warunkach modyfikacji podlega przede wszystkim kod programu, który po testowaniu
jest wprowadzany do eksploatacji. Aktualizacja dokumentacji projektowej i
analitycznej ma miejsce tylko wtedy, gdy wystarczy na nią czasu (rys. 1). Tego typu
postępowanie zapewnia szybką modyfikację systemu niewielkim kosztem, rodzi
jednak ryzyko wprowadzenia błędów oraz prowadzi do szybkiej degradacji
architektury oprogramowania i dezaktualizacji dokumentów projektowych.
Rysunek 1. Model szybkiej zmiany
W zastosowaniach odpowiedzialnych, w których błędne działanie systemu
może powodować znaczne straty, konserwacja oprogramowania staje się działaniem
planowym, rozpoczynającym się od etapu gromadzenia zgłoszeń zmian i
decydowania o ich implementacji. Kolejne etapy układają się w dobrze określony
proces konserwacji, zbliżony pod względem zakresu i układu działań do oryginalnego
procesu wytwórczego. Szczególnym przypadkiem są zwinne procesy wytwórcze, w
których z góry zakłada się opracowanie szeregu wydań oprogramowania. Prowadzi to
do zatarcia granicy między oryginalnym projektem a konserwacją, gdyż opracowanie
kolejnego wydania programu nie różni się istotnie od jego konserwacji.
2.1. Procedura kontroli zmian
Konserwacja oprogramowania jest działaniem angażującym zarówno
wykonawców tego działania, jak i organizację, która to oprogramowanie eksploatuje.
Koszt wprowadzenia zmian oraz ryzyko związane z wdrażaniem każdej zmienionej
wersji systemu narzucają konieczność wprowadzenia mechanizmu kontroli zmian,
którego zadaniem jest ograniczenie zakresu i częstości modyfikacji oprogramowania.
Elementami tego mechanizmu są: określenie osób, które mają prawo zgłaszać
żądania zmian, określenie sposobu rozpatrywania i zatwierdzania zgłoszeń oraz
wskazanie sposobu przekazywania zgłoszeń do realizacji.
Przykładowa procedura oceny i akceptacji zmian, stosowana podczas
konserwacji oprogramowania jednego z największych systemów informatycznych, z
jakimi autor miał okazję się zetknąć, jest pokazana na rys. 2. Prawo zgłaszania żądań
zmiany mają kierownicy jednostek organizacyjnych przedsiębiorstwa. Opatrzone ich
podpisem wnioski są najpierw oceniane pod względem zasadności merytorycznej,
obejmującej sprawdzenie, czy celów zmiany nie można osiągnąć przy użyciu już
istniejących środków. Jeśli żądanie zmiany zostanie uznane za zasadne, oceniany
jest zakres zmiany na poziomie funkcji systemu (poziom opisów analitycznych) i tak
ocenione wnioski są przekazywane dalej w postaci wstępnej rekomendacji zmiany.
Następnym etapem jest ocena czasu i kosztu zmiany, dokonywana z udziałem
przedstawicieli producenta systemu. Jeżeli korzyści przeważają nad kosztami, to
zmiany zyskują status zmian uzgodnionych i są gromadzone do czasu podjęcia
decyzji realizacyjnej
Rysunek 2. Procedura oceny i akceptacji zmian
Ostatnim etapem są negocjacje biznesowe dotyczące wykonania zmian przez
producenta, obejmujące ocenę kosztu realizacji pakietu zmian i ustalenie terminu
oddania nowej wersji systemu. Istotnym elementem negocjacji jest ustalenie ceny
zamówienia, która na ogół nie jest równa sumie kosztu zmian wchodzących w skład
pakietu. Znaczącym składnikiem kosztu jest testowanie, które obejmie cały zmieniony
system. Ponadto, zarówno zrozumienie, jak i analiza wpływu zmian wprowadzanych
w tych samych modułach programu w niewielkim tylko stopniu zależą od
szczegółowego charakteru każdej zmiany.
2.2. Norma IEEE 1219
Standard IEEE 1219 definiuje proces wykonania i zarządzania działaniami
związanymi z konserwacją oprogramowania. Proces ten składa się z siedmiu faz,
ułożonych sekwencyjnie podobnie do kaskadowego modelu wytwarzania
oprogramowania (rys. 3). Kolejne fazy procesu obejmują poznanie i modyfikację
dokumentacji analitycznej, analizę wpływu, zaprojektowanie rozwiązania i
aktualizację dokumentacji projektowej, implementację zmian, testowanie regresji oraz
zatwierdzenie i przekazanie zmodyfikowanej wersji oprogramowania.
Rysunek 9.3. Proces konserwacji oprogramowania
Standard powstał pod wyraźnym wpływem wymagań stawianych procesom
opracowania oprogramowania dla systemów wojskowych. Proponowane w nim
procedury i schemat działania są niezwykle sformalizowane - znacznie bardziej, niż
stosuje się to w projektach komercyjnych. Z tego względu standard ten można
traktować jako pewien wzorzec procesu konserwacji oprogramowania, adaptowany w
miarę potrzeb do wymagań dziedziny zastosowania.
Identyfikacja problemu. Pierwszą fazą procesu konserwacji jest identyfikacja
zgłoszeń zmian. Wszystkie zgłoszenia są klasyfikowane pod względem ważności,
otrzymują numery identyfikacyjne i są wprowadzane do repozytorium projektu. Po
wstępnej ocenie zakresu i kosztu realizacji zgłoszenia są grupowane w bloki zmian i
przekazywane do realizacji jako zatwierdzone zgłoszenia zmiany.
Analiza. Dane wejściowe do następnej fazy obejmują zatwierdzone
zgłoszenia zmiany oraz dostępną dokumentację analityczną oprogramowania. Celem
tej fazy jest przeprowadzenie studium wykonalności zmiany i opracowanie
szczegółowej analizy rozwiązania. Elementem analizy jest identyfikacja potencjalnych
zagrożeń dla bezpieczeństwa systemu. Wynikiem pracy jest raport wykonalności,
raport analizy, zaktualizowana specyfikacja wymagań, wstępna lista zmian do
wykonania oraz strategia testowania.
Projektowanie. Dane wejściowe fazy projektowania obejmują wszystkie
dokumenty opracowane w fazie analizy, dostępną dokumentację projektową, listingi
kodu oraz dokumentację bazy danych. Celem działań jest przeprowadzenie analizy
wpływu na poziomie modułów programu, opracowanie projektu zmian i przygotowanie
planu testów. Elementem weryfikacji projektu jest wskazanie powiązania wymagań z
zaprojektowanymi zmianami (
traceability). Wyniki prac obejmują zaktualizowaną listę
zmian do wykonania w kodzie programu, zaktualizowaną dokumentację analityczną i
projektową, zaktualizowany plan testów oraz udokumentowane ograniczenia i
zagrożenia realizacyjne.
Implementacja. Dane wejściowe fazy implementacji obejmują wszystkie
dokumenty opracowane w fazie projektowania, listingi kodu i dokumentację bazy
danych. Celem działań jest opracowanie zmienionych wersji komponentów,
przeprowadzenie testów jednostkowych i integracyjnych oraz wykonanie przeglądu
gotowości do testowania. Wyniki prac obejmują zaktualizowany kod programu i
dokumentację oraz raport gotowości do testowania.
Testowanie systemowe. Dane wejściowe fazy testowania systemowego
obejmują kod programu i dokumentację, przygotowane w fazie implementacji. Celem
działań jest przeprowadzenie testów funkcjonalnych oraz testów interfejsu na
poziomie całego systemu, wykonanie testów regresji oraz dokonanie przeglądu
wyników testów systemowych i przeglądu gotowości do testowania akceptacyjnego.
Wyniki prac obejmują działający system, raport testowania oraz raport gotowości do
testowania akceptacyjnego.
Testowanie akceptacyjne. Dane wejściowe fazy testowania akceptacyjnego
obejmują przede wszystkim zmodyfikowany system, raport gotowości do testowania
akceptacyjnego, plan testów akceptacyjnych oraz dokumentację procedur i
przypadków testowych. Celem działań jest przeprowadzenie testów akceptacyjnych i
zatwierdzenie zmodyfikowanej wersji oprogramowania. Wyniki prac obejmują gotową
do eksploatacji wersję systemu oraz raport testowania akceptacyjnego.
Przekazanie. Ostatnią fazą procesu konserwacji jest przekazanie
zmienionego oprogramowania użytkownikom. Lista zadań do wykonania obejmuje
zabezpieczenie rezerwowej kopii systemu przed modyfikacją, przygotowanie
nośników dystrybucyjnych i opracowanie dokumentacji nowej wersji. Proces zmian
kończy instalacja oprogramowania w docelowym środowisku pracy - jeśli jest to
unikalny system zamawiany, albo udostępnienie nowej wersji użytkownikom - jeśli jest
to produkt masowy, instalowany przez użytkowników lub dystrybutorów.
3. Inżynieria odwrotna
Podstawowe prace koncepcyjne związane z konstrukcją oprogramowania nie
przebiegają na poziomie instrukcji programu, które opisują program ze wszystkimi
szczegółami, tylko na wyższym poziomie abstrakcji określonym przez architekturę
oprogramowania. Architektura, czyli struktura utworzona przez komponenty
oprogramowania współpracujące ze sobą w dobrze określony sposób, wyznacza
poziom abstrakcji odpowiedni dla twórczego podejmowania najważniejszych decyzji
projektowych. Podczas tworzenia oprogramowania architektura jest najważniejszym
elementem kształtowanym przez projektanta. Podczas konserwacji architektura jest
czymś zastanym, do czego projektant musi się dostosować.
Jeżeli dokumentacja architektury istnieje, to można od razu przystąpić do
dostosowywania struktury programu do nowych potrzeb. Jeżeli dokumentacji nie ma
albo istniejąca dokumentacja jest nieaktualna, to jedynym źródłem informacji o
strukturze oprogramowania staje się kod programu. Niestety, architektura
oprogramowania nie jest jawnie reprezentowana na poziomie kodu. Żaden język
programowania nie zawiera konstrukcji warstwy, klienta i serwera, ani innych
elementów architektonicznych, które można by łatwo zobaczyć w treści programu. W
takim przypadku jedynym sposobem ustalenia architektury oprogramowania jest
odgadnięcie jej przez architekta - czyli postawienie pewnej hipotezy i zweryfikowanie
tej hipotezy w konfrontacji ze strukturą posiadanego kodu programu.
Głównym problemem analizy kodu jest jego wielkość i złożoność. Liczba klas
wchodzących w skład oprogramowania dużego systemu, np. takiego jak każdy z
systemów opisanych w punkcie 1.5.2, może sięgać kilkunastu tysięcy. Odnalezienie
zależności i powiązań między tymi klasami i ich metodami, podobnie jak odszukanie
zależności i powiązań między podprogramami dużego programu napisanego w
języku strukturalnym, jest trudne i wymaga planu, wysiłku oraz wsparcia
odpowiednich narzędzi.
Działania prowadzące do rozpoznania i udokumentowania architektury
oprogramowania, dostępnego tylko w postaci kodu, można przedstawić w postaci
sekwencji kroków, które zazwyczaj trzeba powtarzać wielokrotnie, w iteracyjnym
procesie odkrywczym.
1. Wyodrębnienie elementarnych danych strukturalnych z plików źródłowych i
innych źródeł informacji (komentarzy, istniejących dokumentów
projektowych, dostępnych notatek z procesu konserwacji).
2. Standaryzacja postaci danych i zapisanie ich w repozytorium (bazie
danych) umożliwiającym wyszukiwanie i zestawianie danych w różnych
przekrojach.
3. Weryfikacja spójności danych oraz ustalenie statycznych i dynamicznych
powiązań występujących między jednostkami programu - podprogramami,
klasami, plikami itp.
4. Budowanie abstrakcji, tworzenie i weryfikacja hipotez architektonicznych i
rekonstruowanie architektury oprogramowania.
Sukces tych działań i zbudowanie modelu architektury otwiera drogę do
efektywnej konserwacji oprogramowania. Umożliwia opartą na twardych podstawach
analizę wpływu zmian, ustalanie zakresu modyfikacji i implementację w ramach
istniejącej architektury lub implementację połączoną z refaktoryzacją modelu.
Wyodrębnienie danych
Jeżeli jedynym źródłem informacji są pliki źródłowe programu, to praca musi
rozpocząć się od statycznej analizy kodu. Analiza atrefaktów źródłowych, takich jak
pliki nagłówkowe, pliki programu, pliki struktury projektu (np. makefile), umożliwia
ustalenie podstawowych elementów struktury programu oraz podstawowych relacji,
jakie między nimi występują. Zakres wyszukiwanych danych, który może objąć np.
ustalenie listy klas, metod, funkcji i struktur danych oraz łączących je relacji, takich jak
zawieranie, dziedziczenie, definiowanie, wywoływanie, określa analityk zależnie od
typu języka i celów analizy.
Masowy i rutynowy charakter tych działań skłania do wykorzystania
automatycznych narzędzi maszynowej analizy kodu, takich jak:
analizatory leksykalne, podobne do darmowego programu flex (ściśle
biorąc, flex jest generatorem lekserów);
analizatory składniowe, takie jak Rigiparse, SNiFF+ lub YACC (ściśle
biorąc, YACC jest generatorem parserów);
analizatory drzewa składni, takie jak Rigiedit lub Gen++;
standardowe narzędzia analizy tekstu, takie jak popularny w systemach
uniksowych program grep;
narzędzia pokrycia kodu ułatwiające poznanie dynamicznych zachowań
programu.
Tworzenie bazy danych
Dane uzyskane podczas analizy programu zapisuje się w repozytorium
projektu w sposób umożliwiający maszynowe wyszukiwanie i analizowanie ich treści.
Jednym z możliwych sposobów takiego zapisu jest format RSF (Rigi Standard
Format), spopularyzowany przez darmowy edytor Rigi. Elementarny wpis do bazy
danych ma w tym formacie postać trójki opisującej relację zachodzącą między dwoma
elementami programu (tab. 1).
Tabela 1. Struktura danych w formacie RSF
Relacja
Element
Element
call
main
printf
data
main
FILE
file
main
"list.c"
is_subclass
Pozycja
Ograniczona
containsmethod
Pozycja
oczekuj
contains_method
Pozycja
rezerwuj
Nietrudno się domyślić, że pierwszy wiersz tab. 1 opisuje fakt, że funkcja main
wywołuje funkcję printf, drugi wiersz stwierdza, że funkcja main zawiera definicję
struktury FILE, a trzeci wiersz mówi, że definicja funkcji main jest zawarta w pliku o
nazwie list.c.
Weryfikacja danych
Dane uzyskane podczas analizy kodu i zapisane w bazie danych powinny być
poddane wstępnej weryfikacji, której celem jest wykrycie niejasności i niespójności
opisu. Przyczyną takich anomalii może być np. pojawienie się takich samych nazw
metod lub zmiennych w różnych klasach albo wystąpienie takich samych nazw klas w
różnych pakietach. Inną przyczyną może być niedoskonałość narzędzi, prowadząca
do niewykrycia podczas statycznej analizy kodu definicji funkcji, które są wywoływane
przez inne funkcje. Bardziej subtelnym przykładem niejasności może być brak
wywołań pewnych metod, których definicje występują w kodzie programu. Taka
sytuacja może prowadzić do odkrycia klas i metod abstrakcyjnych.
Analiza zgromadzonych danych, weryfikacja ich spójności oraz uzupełnienie
brakujących informacji wymagają świadomych działań analityków, wspomaganych
przez narzędzia przeglądania repozytorium projektu.
Rekonstrukcja architektury
Kolejnym krokiem działań może być próba wyodrębnienia struktury
podstawowych powiązań elementów programu i przedstawienia jej np. w postaci
grafu wywołań funkcji lub odtworzonej hierarchii klas. Na przykład, trzy ostatnie
wiersze w tab. 1 odtwarzają fragment struktury klas pokazanej na rys. 4.44. W dużym
programie nie jest to jednak zadanie łatwe, a pożytek z automatycznie
wygenerowanego grafu zależności, który wygląda podobnie jak na rys. 4, nie jest
duży, cokolwiek by ten graf przedstawiał.
Rysunek 9.4. Wstępny graf zależności
4. Systemy odziedziczone
Mianem systemów odziedziczonych lub spadkowych (legacy systems)
określa się stare systemy informatyczne, eksploatowane w organizacji i ewoluujące
wraz z nią przez długi czas, np. kilkanaście lat, i wciąż odgrywające istotną rolę w jej
normalnym funkcjonowaniu. Mijający czas sprawił, że technologia, w której
zbudowano oprogramowanie po raz pierwszy, jest coraz odleglejsza od technologii
istniejących obecnie na rynku i coraz trudniej jest znaleźć specjalistów zdolnych do
dalszego utrzymywania systemu. Pierwotni twórcy oprogramowania odeszli do innej
pracy i nie można polegać na ich pamięci i doświadczeniu. Wielokrotne zmiany,
wymuszone przez zmiany w eksploatującej ten system organizacji, naruszyły
strukturę oprogramowania i nałożyły na nią całą masę prowizorycznych rozwiązań,
których przeznaczenia nikt nigdy porządnie nie udokumentował. Posiadana przez
firmę dokumentacja jest, w najlepszym przypadku, niekompletna, a w gorszym -
zaginęła.
Wszystkie te utrudnienia powodują systematyczny wzrost kosztu dalszej
konserwacji oprogramowania, aż do nadejścia chwili, w której koszt wprowadzenia
kolejnej zmiany zaczyna przekraczać koszt zbudowania nowego systemu. Decyzja o
wycofaniu starego systemu i zastąpieniu go nowym jest jednak trudna i wiąże się z
dużym ryzykiem dla firmy.
Przeważnie nie ma aktualnej specyfikacji funkcjonalnej starego systemu, a
zawarte w oprogramowaniu reguły biznesowe nie są nigdzie
udokumentowane. Opracowanie już tylko samej specyfikacji wymagań dla
nowego systemu wymaga czasu i wysiłku, a co najważniejsze - wiąże się
z dużym ryzykiem popełnienia błędu, który mógłby zakłócić przebieg
procesów biznesowych.
W starym systemie są zgromadzone dane, bieżące i historyczne,
niezbędne do normalnego funkcjonowania firmy. Format przechowywania
danych jest często daleki od systematyczności i nie zawsze jest w pełni
udokumentowany. Przeniesienie danych do nowego systemu wymaga
czasu i wysiłku oraz stwarza niebezpieczeństwo zagubienia lub
zniekształcenia części przenoszonych informacji.
Wdrożenie nowego systemu pociąga za sobą konieczność poniesienia
kosztów związanych z przeszkoleniem personelu i - być może - zmianą
części procesów biznesowych. Co więcej, brak zaufania do nowego
systemu w początkowym okresie może prowadzić do konieczności
równoległej eksploatacji obu systemów (starego i nowego) w pewnym
okresie, co stwarza istotne utrudnienia organizacyjne.
Z tych powodów firma stara się na ogół utrzymywać stary system tak długo,
jak długo jest to technicznie i ekonomicznie możliwe.
Niekiedy kres eksploatacji oprogramowania kładzie awaria i niemożliwość
odtworzenia środowiska sprzętowego, do którego ten system jest przywiązany.
Przeniesienie aplikacji na nowy sprzęt i nową platformę programową staje się okazją
do opracowania systemu od nowa. Jeżeli konieczne jest odtworzenie projektu lub
reguł biznesowych zawartych w starym systemie, to niezbędnym elementem nowego
projektu jest etap inżynierii odwrotnej starego systemu.
4.1. Opakowanie
Rozwiązaniem części wymienionych problemów mogłaby być wymiana
programów aplikacyjnych przy jednoczesnym zachowaniu całej struktury danych.
Niestety, takie rozwiązanie jest możliwe tylko w niektórych przypadkach. Najstarsze
systemy często nie mają systematycznie zbudowanej struktury bazy danych i zamiast
tego przechowują dane w wielu słabo udokumentowanych plikach systemu
operacyjnego. Nawet jeśli dane są przechowywane w tabelach bazy danych, to na
skutek długotrwałej konserwacji oraz potrzeby uzyskania odpowiedniej wydajności
struktura tych danych może być zdenormalizowana i wyposażona w liczne
redundancje, trudne do opanowania bez dokładnej dokumentacji. Tym bardziej, że
tabele będą pochodziły z bardzo starych wersji RDBMS, niewspieranych już przez
producenta i wykazujących liczne specyficzne właściwości.
Znacznie częściej stosowanym sposobem poradzenia sobie z problemem jest
zakonserwowanie systemu odziedziczonego w takiej postaci, w jakiej jest, i
rozszerzanie lub zmienianie jego funkcji przez dodawanie nowych modułów kodu. Ta
technika konserwacji, nazywana opakowaniem starego systemu (wrapping), polega
na potraktowaniu całego starego systemu odziedziczonego jako dostawcy pewnego
rodzaju usług odpowiadających realizowanym przez ten system funkcjom. Wszystkie
udostępniane usługi można skatalogować, a następnie opracować dla każdej z nich
zewnętrzny interfejs (adapter), poprzez który można tę usługę wywoływać w sposób
przyjęty w wybranej technologii implementacyjnej, np. EJB 3.0. Przykładowa struktura
takiego opakowania jest pokazana na rys. 5. Dzięki temu możliwe staje się
dobudowywanie nowych funkcji systemu przy jednoczesnym wykorzystaniu starego
systemu w niezmienionej postaci.
Rysunek 5. Opakowanie systemu odziedziczonego
4.2. Korporacyjna szyna usług
Dużym ułatwieniem przy integrowaniu starych systemów odziedziczonych z
nowymi aplikacjami, wykorzystywanymi w przedsiębiorstwie, jest oparcie dalszego
rozwoju systemu na koncepcji korporacyjnej szyny usług (Enterprise Service Bus -
ESB). Centralnym elementem tej architektury jest oprogramowanie warstwy
pośredniej sterujące przepływem komunikatów (wywołań usług) między wieloma
różnymi aplikacjami biznesowymi dołączonymi do systemu. Jednym z elementów
oprogramowania szyny jest repozytorium danych, które zawiera opisy wszystkich
usług udostępnianych przez poszczególne aplikacje, lokalizację punktów dostępu do
tych usług oraz opisy sposobów formatowania i przekazywania wiadomości przez
usługi. Wykorzystując to repozytorium, oprogramowanie szyny jest w stanie
zrealizować standardowe wywołania usług na rzecz dowolnych aplikacji, które tych
usług potrzebują. Dodatkowo, oprogramowanie szyny rozwiązuje problemy
transakcyjności, bezpieczeństwa i niezawodności realizacji usług. Oprogramowanie
szyny może też zawierać mechanizmy sterujące przepływem zadań wchodzących w
skład procesów biznesowych realizowanych w postaci sekwencji wywołań usług.
Komponentami dołączanymi do szyny mogą być nowe moduły aplikacyjne, bazy
danych lub odpowiednio opakowane systemy odziedziczone.
Aby dokładniej przedstawić architekturę korporacyjnej szyny usług, warto
porównać ją z innymi rozwiązaniami problemu integracji wielu niejednorodnych
aplikacji. Najstarszym sposobem integracji jest architektura połączeń typu każdy z
każdym (point-to-point), w której aplikacje porozumiewające się ze sobą - np. nowe
moduły aplikacyjne i stary system odziedziczony - wymieniają dane poprzez
indywidualnie zaprojektowane interfejsy (rys. 6a). Zarówno liczba różnych interfejsów,
jak i stopień skomplikowania systemu szybko wzrastają wraz ze zwiększaniem się
liczby połączonych w ten sposób aplikacji.
Odmienne podejście przyjmuje architektura zcentralizowana (hub and spoke),
w której istnieje centralny komponent akceptujący wywołania i przekazujący je do
odpowiednich aplikacji współpracujących (rys. 6b). Architektura zcentralizowana
upraszcza problem integracji systemu, jest jednak mało podatna na dalsze
rozszerzanie systemu. Ponieważ drogi komunikacji między aplikacjami są
zakodowane w oprogramowaniu komponentu centralnego, więc dodanie każdej
nowej aplikacji wymaga odpowiedniego przeprojektowania tego komponentu.
Korporacyjna szyna usług opiera się na zasadzie zdecentralizowanego
kojarzenia partnerów komunikacyjnych. Zwornikiem systemu jest mechanizm
publikowania opisów usług przez aplikacje, które te usługi udostępniają, w
repozytorium systemu (rys. 6c). Mechanizm publikowania jest standardowym
elementem systemu, dzięki czemu dołączenie nowej aplikacji do systemu nie wymaga
wprowadzania żadnych zmian w oprogramowaniu szyny. Po dołączeniu i
opublikowaniu usług nowej aplikacji dowolna inna aplikacja może rozpoznać istnienie
potrzebnej usługi i wywołać ją w standardowy sposób, bez konieczności
wprowadzania jakichkolwiek zmian do oprogramowania szyny. Ponieważ nie ma
potrzeby centralnego sterowania współpracą aplikacji, system sterowania
komunikacją może działać w sposób równoległy, zapewniając bardzo wysoką
wydajność przetwarzania.
Rysunek 9.6. Architektury integracyjne: (a) połączenia każdy z każdym; (b) zcentralizowana; (c)
korporacyjna szyna usług
Architektura korporacyjnej szyny usług jest bardzo bliska koncepcji
architektury usługowej (Service-Oriented Architecture - SOA), w której procesy
biznesowe są komponowane z usług świadczonych przez odrębne komponenty,
powiązane jedynie przez istniejący system komunikacyjny. W terminologii SOA
oprogramowanie szyny pełni rolę brokera usług.
Istnieje wiele gotowych rozwiązań oprogramowania korporacyjnej szyny
usług, zarówno oferowanych przez czołowych producentów oprogramowania, np.
Microsoft BizTalk Server, IBM WebSphere Enterprise Service Bus lub BEA AquaLogic
Service Bus, jak i darmowych, np. WS02 Enterprise Service Bus, Apache ServiceMix,
JBoss Enterprise Service Bus.