Mądrzy przed szkodą

Prasa informatyczna publikuje interesujące artykuły na temat testowania oprogramowania. Przedstawiane metody pozwalają w systematyczny sposób wykrywać i usuwać błędy popełnione w trakcie tworzenia systemu. Jednak w większości są dość kosztowne w stosowaniu i w istotny sposób opóźniają prace nad systemem. Znacznie taniej jest nie dopuszczać do powstawania błędów niż je pracowicie usuwać.

Prasa informatyczna publikuje interesujące artykuły na temat testowania oprogramowania. Przedstawiane metody pozwalają w systematyczny sposób wykrywać i usuwać błędy popełnione w trakcie tworzenia systemu. Jednak w większości są dość kosztowne w stosowaniu i w istotny sposób opóźniają prace nad systemem. Znacznie taniej jest nie dopuszczać do powstawania błędów niż je pracowicie usuwać.

Im dalej, tym drożej

Typowy cykl "życia" projektu informatycznego składa się z kilku faz, które, mówiąc w niewielkim uproszczeniu, następują po sobie. Najpierw robi się studium wykonalności, potem opracowanie wymagań, analizę, projekt, program i wreszcie wdrożenie. Najgroźniejsze błędy popełnia się w początkowych etapach trwania projektu - błędy w architekturze, źle określone wymagania, niewłaściwe odwzorowanie rzeczywistości w systemie informatycznym. Ale najbardziej intensywne testy trwają po etapie programowania. I to wtedy wykrywa się większość błędów.

To stanowczo za późno. Po to, aby poprawić usterki, trzeba się cofnąć o wiele etapów, a to zawsze wymusza ogromne koszty. Przypuśćmy, że pisząc program do rejestracji dokumentów, założyliśmy, iż numer dokumentu składa się wyłącznie z cyfr i przechowujemy go na liczbie całkowitej. Kiedy zaczęto wprowadzać do programu pierwsze dokumenty, okazało się, że niektóre numery mają w środku litery. Trzeba więc uaktualnić strukturę bazy danych, logikę biznesową aplikacji oraz formatki i procedury związane z komunikacją z użytkownikiem, zmieniając stosowny typ z liczby całkowitej na tekst. Każda z tych zmian wymusza poprawki w dokumentacji, procedurach testujących, nawet na diagramach, które programiści zdążyli rozwiesić na ścianach pokoju. Musimy tę kontrolę potraktować bardzo rygorystycznie, aby w żadnym elemencie systemu, dokumentacji i narzędziach towarzyszących numer dokumentu nie został liczbą. Tylko w ten sposób możemy całkowicie naprawić problem.

Gdyby ten test wykonać na etapie początkowych prac nad systemem, koszty odnalezienia błędu byłyby znacznie mniejsze. Mniejsze byłoby także ryzyko, że przeoczono inny problem, który ujawni się po wprowadzeniu nie kilku, a kilku tysięcy dokumentów do naszej przykładowej aplikacji.

Co robić, aby błędów unikać, a te, które się wkradły, eliminować możliwie wcześ-nie? Wyobraźmy sobie scenę na skrzyżowaniu dwóch ulic - głównej i podporządkowanej. Główną ulicą jedzie z dużą prędkością samochód. Jego kierowca, dojeżdżając do skrzyżowania, widzi, że ulicą podporządkowaną jedzie inny samochód i nie zwalnia. Nie zaczyna jednak hamować, wiedząc, że ma pierwszeństwo. Rozlega się huk, brzęk, chwila ciszy, a potem najczęściej przekleństwa - doszło do kolizji. Kto jest winien? Zgodnie z kodeksem drogowym obaj. Ten, który wyjeżdżał z drogi podporządkowanej, jest winny wymuszenia pierwszeństwa. Ale ten, który jechał drogą główną, także otrzyma mandat. Widząc, że drugi samochód nie zwalnia, powinien był sam ograniczyć prędkość w celu uniknięcia zderzenia.

Kodeks drogowy nakłada na uczestników ruchu obowiązek zachowania ograniczonego zaufania. Niezastosowanie się do niego jest karalne. Podobnie powinni postępować informatycy. Informatyczna "zasada ograniczonego zaufania" jest jednak znacznie silniejsza niż drogowa. Można ją streścić w trzech punktach:

  • trzeba zakładać, że program nie działa

  • można ufać sobie tylko w ograniczonym stopniu

  • nie można ufać innym uczestnikom projektu i komponentom programu.

    Właściwi ludzie, właściwe narzędzia

    Brzmi to banalnie, bo właściwi ludzie są potrzebni w każdej dziedzinie, nie tylko w tworzeniu systemów informatycznych. Ale chyba tylko w informatyce tak ogromne znaczenie ma ich wiedza i zaangażowanie. Jednocześnie informatyka jest grą zespołową, w czym bardziej przypomina dziedziny sportu niż inżynierii. Zespół przeciętniaków, ale dobrze współpracujących z sobą, będzie prawdopodobnie osiągał lepsze wyniki niż grupa gwiazd - bardzo dobrych z merytorycznego punktu widzenia, ale rywalizujących ze sobą i starających się zaspokajać przede wszystkim własne ambicje.

    Dobrzy pracownicy muszą mieć dobre narzędzia. Współczesne metodyki inżynierii systemów informatycznych mają wbudowane procedury, które pozwalają ograniczyć ryzyko pojawienia się błędów. Na przykład UML (Unified Modelling Language), notacja przeznaczona dla systemów obiektowych, ma wiele różnych typów diagramów. Każdą istotną cechę systemu informatycznego można opisać na każdym z tych diagramów w nieco inny sposób. Jeżeli spróbujemy modelować system, biorąc pod uwagę kilka różnych punktów widzenia, i uzyskamy spójny model, to jest duża szansa, że modelowanie wykonano prawidłowo.

    Sprawdzenie spójności dla systemu zawierającego kilkadziesiąt klas czy tablic jest oczywiście niewykonalne dla człowieka z czysto "obliczeniowych" przyczyn. Nikt bowiem - poza genialnymi matematykami - nie ma "takiej głowy", w której "pomieściłoby się" aż tyle elementów, cech i zależności. I tutaj z pomocą przychodzą narzędzia CASE, które pozwalają automatycznie sprawdzić poprawność i spójność różnych diagramów. Inwestycja we współczesne narzędzia tego typu będzie więc dobrym wydatkiem, jeśli tylko potraktuje się ją jako wspomaganie, a nie substytut pracy koncepcyjnej ludzi.

    Kontrola jakości

    Ale nawet dobry, zgrany zespół, stosując dobre narzędzia, będzie popełniał błędy, a sam może znaleźć tylko część z nich. Umysł ludzki ma taką ciekawą cechę, że jest bardziej skłonny do powtarzania wcześniej wykonanych czynności niż do wynajdywania nowych. Autor danego fragmentu systemu nigdy nie będzie zdolny do przewidzenia wszystkich możliwoś-ci wystąpienia błędów. Po prostu nie pomyśli o niektórych ewentualnościach, a przy innych uzna: "Nie, to na pewno działa", choćby nawet podświadomie.

    Dlatego konieczne jest, aby kontrolę jakości przeprowadzały inne osoby. W małych zespołach takie sprawdzenie może być wykonywane wzajemnie ("ja testuję twoje, a ty moje"). W większych warto wyznaczyć osoby odpowiedzialne tylko za zapewnienie jakości. Osoby te powinny, korzystając z opisów analitycznych, spróbować "wykonać" pewne rzeczywiste czynności na zaprojektowanym systemie. W różnych fazach rozwoju systemu to "wykonanie" będzie wyglądało różnie. Jeżeli kontrola jakości odbywa się na etapie projektu, to będzie ona polegać na przejściu - z ołówkiem w ręku - scenariuszy, sprawdzeniu, czy wszystkie "samodzielne byty świata rzeczywistego" mają odzwierciedlenie w postaci klas, komponentów, tablic itp.

    Warto także wtedy sprawdzić, jak projekt jest przystosowany do zaakceptowania zmian. Zmiana jest bowiem najbardziej naturalną rzeczą w systemie informatycznym. Każdy dobry system informatyczny musi być zdekomponowany w takim stopniu, aby zmiana w jednym miejscu miała możliwie małe konsekwencje dla innych, niezależnych elementów. Takie sprawdzenie najlepiej wykonać już w fazie projektu. Na przykład, jeżeli wcześ-niej założono, iż kontrahent może mieć jedną siedzibę, można sprawdzić, jakie modyfikacje w systemie wymusi założenie, że każdy kontrahent może mieć więcej niż jedną siedzibę. Jeżeli konsekwencją takiej zmiany była modyfikacja elementów systemu np. odpowiedzialnych za korespondencję seryjną, to znaczy, że został źle zdekomponowany i dlatego jest mało elastyczny.

    Stała współpraca z odbiorcą

    Istotnym elementem kontroli jakości jest stała weryfikacja postępu prac z użytkownikiem końcowym. Warto w tym celu zapoznać desygnowanego przez odbiorcę pracownika ze szczegółami konstrukcyjnymi systemu. Jeżeli jest to informatyk, będzie to dla niego prawdziwa przyjemność. Taka osoba nie dopuści do sytuacji, w której przygotowywane jest bardzo ciekawe i zaawansowane rozwiązanie, ale różne od tego, czego potrzebuje klient. Firmy informatyczne czasem "bronią się" przed włączaniem osób z zewnątrz w proces wytwórczy. Niepotrzebnie! Taka współpraca może dać obu stronom wiele korzyści i nie ma potrzeby się jej bać.

    Elementem takiej współpracy może być przygotowanie prototypu. Pozwala on przyszłym użytkownikom "poczuć" aplikację na długo, zanim zostanie ona ukończona. Z jednej strony sprawia, że przyzwyczajają się oni do pewnych elementów (np. formy komunikacji), z drugiej zaś pozwala zebrać komentarze: co jest niezbyt udane, czego nie ma wcale, a co można by zrobić inaczej. Prototyp może być przygotowany stosunkowo wcześnie w procesie tworzenia systemu. Wiedza, uzyskana dzięki niemu od odbiorcy, ma ogromne znaczenie dla bezpieczeństwa i komfortu pracy informatyków.

    Programowanie defensywne

    Na najniższym poziomie najlepszym sposobem na zapewnienie jakości jest programowanie defensywne. Najlepiej je zilustrować na przykładzie. Przypuśćmy, że piszemy funkcję, która ma odnaleźć w podanym tekście fragment występujący między dwoma znacznikami - otwierającym i zamykającym. Najprostszy sposób rozwiązania takiego problemu to sprawdzenie tekstu od pierwszego znaku do ostatniego. Po napotkaniu znacznika otwierającego zaczynamy kopiowanie znaków do podręcznego bufora, a kiedy napotkamy znacznik zamykający, zwracamy bufor jako wartość funkcji.

    Informatyk, który ufa sobie, swoim kolegom i komponentom dostarczanym przez inne firmy, zaprogramuje algorytm w tak oczywisty sposób, jak opisany. Doświadczony informatyk zaprogramuje ten algorytm tak, aby w żadnej sytuacji nie dochodziło do niebezpiecznych sytuacji.

    Po pierwsze, program pisany defensywnie sprawdzi najpierw, czy tekst, który otrzymał, jest rzeczywiście tekstem, a nie na przykład wartością zerową (nul). Po drugie, upewni się, czy podany tekst ma skończoną długość. Podczas sprawdzania tekstu znak po znaku zabezpieczy się na wypadek niepoprawnego użycia funkcji: kiedy w tekście znajduje się tylko znacznik otwierający, tylko zamykający albo więcej niż po jednym ze znaczników, lub nie znalazł się żaden. I rzecz bardzo ważna - działanie tej funkcji w każdym z tych przypadków brzegowych jednoznacznie opisze w dokumentacji. Ponieważ programista defensywny nie ufa także sobie, na koniec sprawdzi, czy długość tekstu wybranego spomiędzy znaczników nie jest większa od długości tekstu dostarczonego.

    Kolejny problem, który autor funkcji rozwiąże na etapie jej projektowania i programowania, wiąże się z zarządzaniem zasobami. Upewni się więc, czy nowo przydzielony bufor, gdzie znalazł się odnaleziony tekst, zostanie zwolniony po użyciu. Gdyby nie był zwalniany, odpowiednio częste wywoływanie naszej funkcji wyczerpałoby pamięć operacyjną, powodując awarię aplikacji.

    Te wszystkie małe, wręcz mikroskopijne, decyzje mają ogromny wpływ na jakość programu. Przy całym szacunku dla menedżerów, nawet najlepsze zarządzanie nie zastąpi dobrej pracy inżynierów kodu. Praca kierowników - organizowanie kontroli jakości, wbudowywanie w proces mechanizmów konsultacji z końcowymi odbiorcami - może co najwyżej uniemożliwić wprowadzenie na rynek złego programu, ale nie umożliwi stworzenia dobrego. O tym decyduje się na najniższym poziomie - każdy informatyk czyni to w każdej sekundzie swojej pracy.

    Bolesna zmiana

    Programowanie defensywne, a także wczesna weryfikacja dokonań zespołu informatycznego, niestety, nie są całkiem pozbawione problemów. Największy problem stwarza konstrukcja psychiczna człowieka. Każdej osobie sprawia trudność przyznanie się do błędu. A jeżeli trzeba przyjąć zasadnicze założenie "moje programy są pełne błędów" i pamiętać o tym na wszystkich etapach prac nad systemem, to trudność ta staje się tym większa i trwała.

    Nie ma dobrej rady na to, jak menedżerowie mogliby sprawić, by informatycy zaczęli krytycznie podchodzić do własnej pracy. Pocieszeniem może być obserwacja, że taki obyczaj łatwo "rozchodzi się" w zespole. Jeżeli jeden członek zespołu zaczyna stosować defensywne podejście, to dość szybko widać jego efekty. W ten sposób inni mogą się przekonać do zmiany swojego stosunku do własnych "dzieł".

    W wielu firmach informatycy są karani za błędy (np. zmniejszeniem premii) albo nagradzani za ich brak. Mechanizm "kija i marchewki" jest dobry przy rutynowych procesach, gdzie z góry są określone: efekt oraz czas dojścia do niego, a technologia nie sprawia trudności. Niewiele projektów informatycznych spełnia te założenia, przynajmniej w początkowych fazach. Skoro więc mowa o przebudowie mentalności informatyków, to kierownicy powinni przede wszystkim zacząć od przebudowy własnej mentalności. Zamiast więc narzekać: "O nie, znowu wyskoczył błąd!" menedżer powinien się cieszyć: "Wspaniale, znowu znaleźliśmy błąd u nas, a więc nie pojawi się on już u klienta". Oczywiście trzeba zachować umiar w takim podejściu, aby nie popaść w przesadę i nie premiować za usterki.

    Błędy pod kontrolą

    Informatycy popełniają błędy, tak jak popełniają je wszyscy. Zaproponowane w tym artykule techniki i metody nie wyeliminują ich całkowicie - informatycy nigdy nie staną się bogami. Ale metody te pomogą zmniejszyć liczbę błędów, a te, które i tak się pojawią, będzie można odnaleźć i usunąć jeszcze w procesie wytwórczym. Można dbać o jakość programu na długo przed poddaniem go pierwszym testom w tradycyjnym tego słowa znaczeniu. Warto spróbować, to naprawdę się opłaca.

  • W celu komercyjnej reprodukcji treści Computerworld należy zakupić licencję. Skontaktuj się z naszym partnerem, YGS Group, pod adresem [email protected]

    TOP 200