Czym jest jakość oprogramowania?

Wielu programistów i firm z branży IT często mówi, że potrafi wytwarzać oprogramowanie wysokiej jakości i że bardzo ważnym jest, aby o tą jakość zabiegać. Nie ma w tym nic dziwnego – wszyscy jesteśmy gotowi zgodzić się, że jakość powinna być możliwie wysoka. Problem pojawia się jednak w momencie, gdy trzeba doprecyzować pojęcia i stwierdzić, czym tak naprawdę charakteryzuje się oprogramowanie wysokiej jakości i jak można tą jakość osiągnąć.
 REKLAMA 
 Baner srodtekstowy350x350 strona KSeF 
Jakość nie jedno ma imię

Po pierwsze, należy zauważyć, że na pojęcie jakości możemy patrzeć przynajmniej na dwa sposoby. Oprogramowanie może być rozpatrywane jedynie w kontekście technologicznym, jako długi i złożony kod zapisany w jednym lub kilku językach programowania. Myślenie o jakości oprogramowania w tym obszarze sprowadza nas do zastanawiania się właśnie nad tym kodem źródłowym (code quality) oraz na całej otoczce technicznej. Drugim podejściem jest spojrzenie szersze – biorące pod uwagę klienta i finalnego odbiorcę. W tym podejściu oprogramowanie jest produktem (lub usługą), który rozwiązuje jakiś zestaw problemów. Myśląc o jego jakości, możemy zastanawiać się nad bardzo wieloma czynnikami, takimi jak wygoda użycia, zgodność ze specyfikacją biznesową czy efektywność w rozwiązywaniu zadanego problemu. Warto już na samym początku zauważyć, że te dwa spojrzenia dotyczą obszarów związanych ze sobą, ale jednak rozłącznych. Może być bowiem tak, że oprogramowanie jest napisane w najnowocześniejszych technologiach, korzysta z najlepszych praktyk i wzorców inżynierskich, ma wspaniałą dokumentację techniczną, ciągłą integrację i zestaw testów jednostkowych… ale kompletnie mija się z tym, czego tak naprawdę potrzebuje użytkownik – nie daje żadnej wartości dodanej do biznesu (lub ogólnie życia). Może być też odwrotnie, że aplikacja jest super użyteczna i pomaga ludziom, ale napisana jest w bardzo “brudny” sposób jako zlepek obejść, haków i dziwnych sztuczek. Widać więc, że jakość pojmowana dość niskopoziomowo, czyli blisko technologii, oraz jakość widziana z zewnątrz to dwa inne (choć zapewne powiązane) pojęcia. W dalszej części tekstu postaramy się omówić kilka aspektów, które wyznaczają i niejako definiują oprogramowanie wysokiej jakości, zarówno na poziomie kodu źródłowego, jak i systemowego ujęcia całości. Tam gdzie to możliwe podamy również sposoby radzenia sobie z problemami i metody zapewnienia odpowiednio wysokiego poziomu jakości w danym obszarze.

Jakość specyfikacji

Chciałoby się powiedzieć, żeby zrobić coś dobrze trzeba wiedzieć dokładnie co się robi. Być może taka prawda sprawdza się w pewnych dziedzinach życia? Niestety jednak w świecie oprogramowania najczęściej nie mamy tego luksusu, aby widzieć cały obrazek na początku. Większość projektów IT, niezależnie od przyjętej metodologii, zaczyna się od rozmów z “klientem” (który w szczególnych przypadkach może być osobą, która tworzy software sama dla siebie). Wszystko po to, aby dowiedzieć się, o co chodzi w tym projekcie, jaki jest cel, jakie mają być funkcje i kto ma tego używać. Z reguły na początku wydaje się, że wiele jesteśmy w stanie przewidzieć i wyobrazić sobie co będzie dalej. I tu się zaczyna dbanie o jakość. Im bardziej zdamy sobie sprawę, że na początku projektu widzimy tylko jakąś fatamorganę, widmo nie wiadomo czego, tym lepiej – mamy większą szansę na rozwój i dojrzewanie do dobrych decyzji. Innymi słowy, oczywiście musimy zrobić wszystko co się da, aby zrozumieć rzeczywistość i konkretną sytuację. Zebrać wymagania, zrobić opisy, sesje z burzą mózgów, rysunki itd. I to się składa wszystko na dobry opis wymagań dla systemu, ale największy wpływ ma nasze zdrowe podejście. Jeśli zrobimy super analizę na początku (upfront) i się w niej zamkniemy, to niszczymy projekt zanim się jeszcze na serio rozpocznie. Potem jest już tylko gorzej.

Specyfikacja wymagań i ogólnie wstępna wizja systemu wysokiej jakość powinna więc być lekka. Możliwie spójna i kompletna, poparta faktami i badaniami – ale przede wszystkim lekka. Zarówno metaforycznie (czyli nie stawia ciężkich, twardych ograniczeń) jak i dosłownie (jest lekka, czyli krótka). Oczywiście można polemizować – jeśli jednak jesteś bardzo mocno przywiązany do budowania zaawansowanych formalizacji wstępnych wymagań do systemu, to znajdź taki dokument z toczącego się projektu i porównaj go z tym co stało się w projekcie po 6, 9 albo 12 miesiącach. Ciekawy jestem czy cokolwiek zgadza się z pierwotnym obrazkiem. Wątpię. Oczywiście można sobie radzić z tymi problemami na wiele sposobów. Popularnym podejściem jest wprowadzenie różnych nisko lub wysoko-poziomych mechanizmów zarządzania zmianą (change managment), które zakładają jakąś formalizację opisu tego co i jak się zmienia. Często rozwiązuje się nimi część problemów – niestety strasznie trudno utrzymać sytuacje, w której zarówno wyraźnie widać zmiany usadowione w rozłączonych fragmentach czasu i jednocześnie widać jeden spójny obraz systemu w jego aktualnej formie.

Jakkolwiek zadanie to nie byłoby skomplikowane, to musimy w jakiś sposób je rozwiązać – dostosować się zmian. Więcej o tym w dalszych częściach tekstu.

Jakość architektury

Podobnie jak przy okazji formalizacji wymagań i specyfikacji systemu – musimy odpowiednio podejść do sformułowania podstaw architektury. Nauczeni doświadczeniem z pracy z klientem, który jest w stanie zmienić zdanie 3 razy w czasie jednej rozmowy – musimy tą obiektywną rzeczywistość odzwierciedlić w architekturze. Oczywiście budując dom, architekt najpierw wszystko dokładnie rysuje, wylicza, szacuje i daje dokładne wytyczne robotnikom. A oni robią i jest. W budownictwie jest to oczywiste – ale informatyka to nie budownictwo i słowo architekt występuje w obu dziedzinach w zupełnie innym znaczeniu. Oprogramowanie nie jest zmienne – jest płynne. W odróżnieniu od betonu, który zasycha i zasadniczo niewiele się zmienia, oprogramowanie płynie. Architektura wysokiej jakości powinna więc od początku zakładać tę płynność. Mamy do dyspozycji mnóstwo wspaniałych narzędzi – takich jak wzorce projektowe, integracyjne, dobre praktyki czy modelowe rozwiązania. Co więcej, w parze z architekturą idzie z reguły usadowienie jej w jakiejś konkretnej technologii, która dodatkowo narzuca pewne podejścia i koncepty. To wszystko jest dobre i im lepiej zrozumiemy narzędzia, które mamy do dyspozycji, tym lepiej. Ale, podobnie jak w przypadku specyfikacji – im bardziej się utwardzimy i zamkniemy w jednej, niezmiennej architekturze, tym gorzej.

Wydawać by się mogło, że takie postawienie sprawy właściwie przekreśla tradycyjną architekturę oprogramowania. Bo skoro wiem tylko, że wszystko się zmienia, to znaczy, że nie wiem nic. To nieprawda. Zasadniczym zakresem tematycznym, który powinien nas interesować to systemy rozproszone. Wysoka modularność, współpraca wielu niezależnych, lub luźno powiązanych elementów, możliwość wymiany małych części, lub tworzenie różnych wariantów tego samego modułu, to podejścia, które przyniosą nam wartość dodaną. Ludzie mający do czynienia z monolitami (układ: jedna wielka baza danych i do tego wielki serwer aplikacyjny) z reguły postrzegają podejście rozproszone (dziesiątki lub setki małych kawałków fruwających gdzieś w koło) jako trudniejsze, bardziej skomplikowane i przez to gorsze i bardziej ryzykowne. Takie spojrzenie to postawienie sprawy do góry nogami. Systemy monolityczne to pewien szczególny przypadek – uproszczenie. Nadaje się do pewnej klasy problemów. Szczególnie takich, które są dość małe lub niewymagające wielkich regularnych zmian czy wysokiej wydajności i niezawodności. Nie raz opłaca się zacząć od małego, prostego monolitu. Ale w pewnym momencie – gdy projekt się rozwija, trzeba cały czas myśleć o tym, czy aby nie nadszedł czas pokrojenia wszystkiego na mniejsze, niezależne kawałki. Oczywiście można mi nie wierzyć. Nie jestem ani Bogiem ani nawet kimś super oświeconym. Warto jednak przyjrzeć się jak to robią inni. Praktycznie wszystkie duże biznesy internetowe jak Facebook, Google, Linkedin, Twitter (…) bazują na modularnym podejściu – co więcej mają bardzo różnorodny techniczne “stos”, bo zdają sobie sprawę, że nie ma jednego narzędzia, technologii i podejścia dobrego do wszystkiego.

W ostatnich czasach podejścia SOA, cloud, SaaS itd. stały się bardzo popularne. Nie przez przypadek – okazuje się, że w końcu myślenie rozproszone i wielowarstwowe zaczyna znajdować swoje miejsce i powoli (czasem bardzo powoli) zaczyna być zrozumiane. Wciąż jednak wiele jest do zrobienia w tej dziedzinie.

Jakość implementacji

Mając ustalone wymagania (luźno) i architekturę (rozproszoną) możemy próbować programować. Jak określić “jakość programowania”? Możemy tu znów poruszać się na kilku płaszczyznach. Po pierwsze spójność. Spójność nazw i wszelkich konwencji stylistycznych. Projekt wysokiej jakości powinien mieć swój jasno zdefiniowany styl, w którym jednoznacznie określono jak formatować kod źródłowy, jak nazywać elementy, gdzie je umieszczać itd. Jeśli jednak myślisz w tym momencie, że w dobrym projekcie te reguły powinny być gdzieś spisane w formie dokumentu – to niestety błądzisz. Spisanie dokumentu z notatkami może być dobrym pierwszym krokiem. Jednak dokument z regułami ma taką wadę, że potrzebuje “policjanta”, który będzie sprawdzać, czy reguły są spełnione. Zamiast więc opisywać prawo i rekrutować służby sprawiedliwości, lepiej pomyśleć jak informatyk i zbudować automat. Tak naprawdę są tylko dwa dobre sposoby opisania takich standardów. Pierwszy – przez zdefiniowanie serii reguł w jakimś automacie do kontroli stylu (StyleCop, Checkstyle, Sonar, cokolwiek). Wszystko co się da, musi się samo sprawdzać! To jest wysoka jakość. Druga (trochę gorsza) droga, to dostarczenie dobrych przykładów wewnątrz kodu i przekazanie wszystkim jasnego komunikatu. Jeśli chcecie kopiować, to kopiujcie stąd. Wiadomo bowiem, że nieśmiertelna metoda Kopiego-Pasta, będzie stosowana również w Twoim projekcie. Także,warto zadbać, aby istniało przynajmniej jedno dobre źródło do kopiowania.

To oczywiście nie wszystko. Drugą rzeczą, której nie sposób pominąć, to testy. Bo nie ma kodu bez błędów i nie ma zmian, które nie mają na nic wpływu i nie ma poprawek, które nie niosą ryzyka regresji itd. Ogólnie temat testów jest zbyt szeroki, żeby zmieścić go w tym tekście w całości. W dzisiejszych czasach wiadomo już dobrze, że warto robić testy jednostkowe i że jest to ogólnie “dobra rzecz”. Niestety samo posiadania “jakichś testów jednostkowych” nie wiele daje. Ba, w pewnych przypadkach może nawet szkodzić. Myślę tu szczególnie o przypadkach, kiedy wprowadziliśmy jakieś kosztowne zmiany do architektury systemu po to, aby był łatwiej “testowalny”. Zmiany mogą być kosztowne w momencie ich wprowadzania, a jeśli są nieprzemyślane, to mogą generować dodatkowy koszt podczas całego dalszego życia projektu. Wszystko ma raczej mały sens, jeśli testy, które powstaną będą niskiej jakości lub jeśli będą zaniedbane. Więcej o jakości testów można znaleźć w artykule Michała na Trzeciej Kawie: Testowanie Testów, natomiast o zaniedbanych (nieaktualnych, nieuruchamiających się, zagubionych, nic nie testujących…) testach chyba nie warto pisać – bo każdy pewnie je widział.

Jakość środowiska rozwojowego

To jest bardzo obszerny i niestety bardzo często pomijany element. Wydajność i jakość pracy zależy bardzo mocno od narzędzi. Oczywiście w pewnym sensie każdy program da się napisać w Notatniku. Da się też kompletnie ręcznie aktualizować wszystkie biblioteki, budować paczki instalacyjne i kopiować je ręcznie na serię serwerów / stacji testowych. Wszystko się da. Co więcej, jak ludzie się do tego przyzwyczają, to nawet mniej więcej robią to sprawnie. Nieważne jednak jak sprawnie by tego nie robili. Jeśli procedura tworzenia, budowania, instalowania, uruchomiania paczek testowych i produkcyjnych nie jest powtarzalna (zautomatyzowana, albo dokładnie opisana), to zawsze jest miejsce na pomyłki, opóźnienia i marnotrawstwo czasu. To samo tyczy się wszystkich problemów związanych z bezpośrednim środowiskiem pracy programisty – czyli IDE i narzędzi dookoła. Jeśli nie działa nam podpowiadanie składni, jeśli automatycznie podkreślanie błędów jest popsute i podkreśla cały dokument na czerwono albo ignoruje wszystkie błędy, lub jeśli automatycznie odnajdywanie zależnych bibliotek notorycznie próbuje ściągnąć nam przestarzałą wersje biblioteki xyz, której używamy… to tracimy i jakość, i czas!

Jedyną szansą na obronę w tym obszarze jest wprowadzenie nawyków ciągłej optymalizacji środowiska pracy. Niektórzy robią to instynktownie i nie mogą znieść jakichkolwiek popsutych elementów. Będą narzekać na popsuty edytor, designer, skrypt… tak długo, aż znajdą lekarstwo. Niestety inni po prostu szybko przywykną. Jeśli masz w projekcie rolę kierowniczą, Twoim zadaniem jest znaleźć tych pierwszych, zebrać ich doświadczenia i wiedzę i doprowadzić do przekazanie jej całemu zespołowi.

Co do praktycznych rozwiązań to z pewnością nie można dzisiaj pominąć kwestii ciągłej integracji i budowania zautomatyzowanych procesów wokół niej. Pisałem o tym więcej we wcześniejszym artykule: Pan Jenkins przybywa na ratunek. Tutaj powtórzę tylko, że nie można utożsamiać ciągłej integracji tylko z automatem do kompilowania kodu. Współczesne rozwiązania w tym segmencie, przez swoją elastyczność i możliwości integracji, pozwalają nam zautomatyzować prawie każdą nudną / powtarzalną czynność. Głównie po to, aby programiści mogli się skupić na kreatywnej pracy!

To wszystko prowadzi nas jeszcze do tematu wyboru technologii. Często wybór rozwiązania serwerowego, platformy wytwarzania oprogramowania itd. podyktowany jest różnymi dziwnymi argumentami. Może być tak, że tworzenie rozwiązania w technologii XYZ wynika z tego, że cała nasza organizacja ma podpisaną umowę ramową z dostawcą tej technologii (i nie szkodzi, że istnieją lepsze i darmowe rozwiązania…), albo z tego, że Wielki Guru Architekt jest zafascynowany tą technologią, albo też dlatego, że po prostu umiemy w niej tworzyć i nie mamy czasu na wypróbowanie innych rozwiązań. Niestety takie ważne rzeczy jak np. fakt, czy platforma pozwala podmieniać kod w locie czy robić deployment w tle bez czekania 20 minut na opublikowanie nowej wersji często giną gdzieś w gąszczu innych cech. To wielki błąd. Jeśli serwerowi aplikacji brakuje jakiejś funkcji / cechy, to prawdopodobnie możemy ją sami doprogramować lub dokupić jakiś moduł. Mamy dodatkowy koszt, ale w miarę stały i osadzony w jednym momencie. Jeśli jednak dana technologia przez swoją filozofię jest nieproduktywna od podstaw, chociażby przez bardzo długi cykl instalacji nowych wersji aplikacji (często mają tak duże serwery aplikacji Java EE), to nie bardzo możemy zrobić cokolwiek aby to poprawić i tracimy pieniądze przez cały czas trwania projektu! Warto zapoznać się chociażby z Play! framework, żeby przekonać się, że można tworzyć software i praktycznie nigdy nie czekać bezczynnie na jakiś tajemniczy proces wewnętrzny. Technologia ma znaczenie!

Bardzo fajnym wyznacznikiem jakości naszego warsztatu jest sprawdzenie, ile czasu i wysiłku kosztuje nas wprowadzenie (rozumiane jako całość drogi od edytora kodu źródłowego, poprzez kontrolę wersji, po wdrożenie na produkcji) zmiany składającej się z dokładnie jednej linii lub nawet jednego znaczka! Czy to da się zrobić w całości w 10 minut? Godzinę? Dzień? Znam przypadki, w których nawet dzień to za mało! To powinno powodować przynajmniej zastanowienie…

Jakość procesu wytwórczego


Kolejny szeroki i chyba najbardziej kontrowersyjny temat, gdyż dotyka bardzo “miękkiej” – subiektywnej tematyki. Wiele osób chciałoby pewnie napisać, że jedyną szansą na projekty wysokiej jakości jest podejście zwinne (agile). Takie czasy i moda… I po części takie wnioski niesie wiele eksperymentów i badań. Jak zwykle jednak uogólnienia nie działają. Ponieważ temat jest szeroki, skupię się tylko na kilku wybranych aspektach sprawy. Jak zorganizowana jest cała nasza praca i jakie ma to podstawy?

Po pierwsze – czy w naszym procesie nie negujemy rzeczywistości albo czy nasze założenia nie są próżnymi, miłymi życzeniami do czarodziejskiej wróżki? Ironizuję nieco, ale chodzi mi o sytuacje (których wcale nie jest mało), w których ludzie wierzą, że zaprojektują coś i opiszą, klient to podpisze i potem będzie wszystko dobrze. Wciąż są miejsca, w których prowadzi się wielki “up-front design” z głęboką wiarą w jego sukces. A problem w tym, że nie można mówić o sukcesie czy porażce rzeczy, która w całości jest fikcją. Słyszałem nie raz skargi programistów i kierowników, że największą bolączką projektu są zmienne wymagania. Nie raz chciało mi się powiedzieć – “jakże wielkie szczęście macie, że klient zmienił wymagania, bo przecież były bez sensu!”. W najgorszym razie zmienne wymagania to rzeczywistość, której nie możemy odrzucić i zmienić. W optymistycznym przypadku zmienne wymagania to pozytywna sprawa, bo ratuje nas przed wypuszczeniem głupiego i bezużytecznego systemu. Jakkolwiek by nie było w naszej sytuacji, musimy przygotować się na zmiany. Bo one będą następować cały czas.

A więc jednak agile? Niekoniecznie! To, że akceptujemy rzeczywistość i nie negujemy tego co pewne nie sprawia, że jesteśmy agile’owcami. To znaczy tylko, że nie jesteśmy szaleńcami!

Jeśli zdamy sobie sprawę z faktów, to musimy zdecydować się jak stawimy im czoła. Musimy coś wybrać, bo najgorszym wyborem jest brak jakiegokolwiek wyboru.. Możemy skorzystać z jednej z wielu sformalizowanych metodyk – typu SCRUM, RUP lub jakieś odmiany Lean (i jeszcze masa innych…). Czego byśmy nie wybrali, to warto wystrzegać się ideologizacji i fanatyzmu. Wdrażanie Scrum dla Scrum’a za wszelką cenę jest gorsze od nieposiadania żadnej nazwanej metodyki. To, o czym musimy pamiętać, to że utarte i sprawdzone metody, działające w innych projektach / zespołach / krajach / firmach, być może kompletnie nie pasują do naszego konkretnego zadania i klienta! Nie ma jednej odpowiedzi dla wszystkich.

No i ostatnia sprawa. Dość modne jest w niektórych kręgach podejście, że metodyka pracy – metody zarządzania, prowadzenie projektu, podziału zadań, odbioru pracy itd… że to wszystko nie zależy od technologii i narzędzi. Nieprawda! Zależy i to bardzo. Jeśli zdecydujemy się na przykład na podejście z częstymi, regularnymi releasami, a nasze środowisko techniczne jest bardzo ciężkie, to okaże się, że tak naprawdę 80% czasu szykujemy releasy i nie robimy tak na serio nic więcej. No i w drugą stronę – czasem zakładamy dość duży czas na pewne typowe, powtarzalne czynności – które można by zminimalizować lub w ogóle wyeliminować przez zmiany technologiczne. Znam przypadki, gdzie ogólne problemy z jakością systemu próbuje się rozwiązywać tylko (albo głównie) przez wprowadzanie kolejnych zmian organizacyjnych. Nowe procesy, nowe metody, nowe podejścia, lekkie, ciężkie, opisane lub nie – spotkania, dokumenty, kierownicy, eksperci, konsultanci. Dlaczego tak jest? Pewnie trochę dlatego, że wiele zmian jest inicjowanych przez kierownictwo organizacji, które nie ma przed oczami technologii, tylko zarządzanie.

A tymczasem prawdziwa przyczyna problemu (zaskakująco?) może leżeć w bardzo niskiej warstwie technologii, którą po prostu można wymienić lub zrefaktoryzować (co oczywiście kosztuje)! Podstawa przy myśleniu o jakości oprogramowania to myśleć dużo o oprogramowaniu, a nie o filozofii zarządzania. Jeśli pracujemy w firmie tworzącej oprogramowanie (nie ważne czy nią kierujemy, czy po prostu uczestniczymy jakoś w procesach) to pierwsze rozwiązanie jakie powinno nam przychodzić na dowolny problem to… oprogramowanie – czyli technologia. A nie procesy, schematy, spotkania, organizacja, biurokracja, kontrola…

Podsumowanie

W tym długim (lecz mam nadzieję, nie aż tak nudnym) wpisie chciałem pokazać przede wszystkim to, że jakość oprogramowania to bardzo szeroki temat. Dużo szerszy niż tylko standardy kodowania, przeglądy kodu i testy jednostkowe. Jeśli naprawdę chcemy z pasją tworzyć rozwiązania wysokiej jakości, musimy pomyśleć globalnie i kreatywnie. Być może największe problemy z naszą jakością kryją się zupełnie nie tam, gdzie wcześniej ich szukaliśmy! Być może wcale nie trzeba zmieniać dużo po to, aby było dużo lepiej…

Źródło: http://www.trzeciakawa.pl
Autor: Witold Bolt

PRZECZYTAJ RÓWNIEŻ:


Back to top