Skuteczne rozwiązania przy płynnych warunkach pracy

W tym artykule inżynier oprogramowania Zbigniew Manasterski szczegółowo opisuje swój najnowszy projekt dla międzynarodowej instytucji finansowej i przedstawia często płynne i wymagające warunki pracy, w których poruszają się najlepsi deweloperzy.

Wstęp

Jestem inżynierem oprogramowania i obecnie pracuję jako freelancer w międzynarodowej instytucji finansowej. Wraz z dwoma kolegami, również konsultantami, półtora roku temu mieliśmy za zadanie zaprojektowanie i wdrożenie dla jednej z jednostek biznesowych nowej aplikacji, która miałaby zastąpić dotychczasową aplikację. System miał być wykorzystywany do automatyzacji części procesu biznesowego, za który odpowiadała ta jednostka. Proces ten polega na interakcji z klientami i przekłada się na wyższe przychody dla firmy. Stara aplikacja nie była zgodna z globalną polityką międzynarodowej centrali firmy i powodowała zbyt wiele problematycznych zdarzeń w tak ważnym procesie biznesowym. Te dwa czynniki wystarczyły do zatwierdzenia budżetu dla nowego projektu.

Konfiguracja projektu

Każdy zespół projektowy w organizacji pracuje w Scrumie — zarówno pracownicy, jak i konsultanci. W tym Scrumie nie ma żadnych „ról pośrednich” — jest Zespół deweloperski, Właściciel produktu (Product Owner, PO), Scrum Master i interesariusze. Właściciel produktu dyktuje zawartość backlogu produktu, a zespół deweloperski dokonuje szacunku i akceptuje zawartość backlogu sprintu. W tej konfiguracji nie ma architektów ani analityków, więc moi koledzy i ja pełniliśmy również te role. Zanim zajmiemy się funkcjami biznesowymi w zakresie testów odbiorczych, omawiamy wymagania i projekt doświadczeń użytkownika ze stroną biznesową, planujemy architekturę, tworzymy i testujemy kod.

Trudne początki projektu

Na początku projektu interesariusze jednostki biznesowej nieco wątpili w informatyczną część zespołu, tj. w nas i naszego PO. Ale trzy miesiące po rozpoczęciu projektu straciliśmy PO — opuścił on organizację, aby stworzyć własny startup — i okazało się to lepsze dla projektu, ponieważ ten PO miał już złe doświadczenia z jednostką biznesową i nie wierzył, że jest w stanie dostarczyć przydatne w działaniu i użyteczne wymagania. Kwestie zaufania stanowiły zresztą problem po obu stronach, a strona biznesowa wahała się, czy będziemy w stanie zrozumieć ich potrzeby, częściowo ze względu na złożoność domeny. Jednak do zespołu przypisano nowego PO, który szybko stworzył kilka warsztatów i nalegał na dodatkowe udoskonalenia i spotkania z obecnymi interesariuszami jednostki biznesowej. Wtedy wszystko zaczęło się układać.

Jednocześnie ogłoszono, że organizacja zmieni swoją strukturę, w ramach której połączone zostaną jednostki biznesowe z kilku krajów. Ponadto aplikacje stosowane w niektórych krajach musiały zostać zintegrowane lub zastąpione nowymi, wspólnymi dla wszystkich. Kierownik najwyższego szczebla, który był odpowiedzialny za jednostkę biznesową, dla której pracowaliśmy, jak również za inne podobne jednostki z innych integrujących krajów, wysłał swojego analityka, który miał działać jako uzupełnienie PO i przedstawić pewne wymagania wspólne dla poszczególnych krajów.

Od chwiejnych początków do solidnej współpracy ze stroną biznesową

Dzięki nowemu PO i wsparciu ze strony naszego kierownictwa zaczęliśmy spędzać dużo czasu na rozmowach ze stroną biznesową. Poznaliśmy się lepiej, a firma zaczęła bardziej angażować się w projekt. Ale doszło do starć między interesariuszami – niektórzy wywierali presję na dostarczanie lokalnych funkcji, a część z nich pracowała nad dopasowaniem aplikacji do innych globalnych wymagań. Czasami musieliśmy wkraczać między nich jako negocjatorzy. Jednocześnie musieliśmy pamiętać, że żadnego z aktualnych lokalnych procesów w żadnej z jednostek biznesowych nie można było w pełni odwzorować do aplikacji tak, aby dostosować ją do wszystkich. Lokalne procesy musiały ulec zmianie. Mimo to niektóre z lokalnych wymogów były związane z różnymi przepisami prawnymi w każdym kraju, o czym również musieliśmy pamiętać. Biorąc pod uwagę ograniczoną ilość czasu, wskazaliśmy, że niemożliwe jest dostarczenie wszystkich lokalnie wymaganych funkcji dla każdego kraju. Udało nam się skłonić interesariuszy do skoncentrowania się na dostarczaniu wszystkich funkcji wymaganych do zastąpienia starej aplikacji. Ponadto po dostosowaniu priorytetów między interesariuszami możliwe było bardziej płynne kontynuowanie projektu i dalsza poprawa stosunków.

Potrzeba nowoczesnego podejścia do projektowania oprogramowania

Dobre relacje ze stroną biznesową pozwoliły nam na wykorzystanie metodologii projektowania projektu opartej na domenie (DDD), ale mimo to sytuacja nie była idealna. Udało nam się stworzyć język wszechobecny i doskonały model domeny, tak jak opisano w książce „Projektowanie oparte na domenie” Erica Evansa.

Ale organizacja przechodziła wiele zmian. Jednostka biznesowa, dla której projekt był przeznaczony, została połączona w jednostkę międzykrajową z nowym i bardziej zaangażowanym kierownictwem. To nowe kierownictwo oddelegowało do projektu nowych interesariuszy, aby narzucić nową wizję i nowe priorytety. Jedną z takich różnic był zestaw funkcji raportowania. Jednostka lokalna wymagała wdrożenia wielu funkcji raportowania, aby pracownicy mogli w ramach aplikacji wykonywać zadania w zakresie zapewnienia jakości. Stało się tak po części dlatego, że znaczna niestabilność starej aplikacji wymusiła od firmy ciągłe sprawdzanie czy aplikacja i proces działają poprawnie.

Jednak ta część nie była tak istotna dla nowego kierownictwa i po dostarczeniu kilku nowych funkcji raportowania zostaliśmy skierowani do realizacji innych zadań. Według nowych interesariuszy analitycy danych powinni mieć możliwość korzystania z naszej bazy danych do przeprowadzania niezbędnego raportowania.

Na późniejszym etapie projektu okazało się to dużym problemem. Ponieważ przestaliśmy omawiać, co będzie potrzebne do raportowania, nie odkryliśmy części wiedzy wymaganej do stworzenia właściwego modelu domeny – nasz model był dobry, ale nie do końca właściwy.

Nie ma miejsca na błędy

Dowiedzieliśmy się o tym, gdy analitycy danych zapytali, jak pracować z naszym modelem danych do pobierania danych dla potrzebnych raportów. W naszym modelu okazało się, że umowy między klientem a firmami zewnętrznymi, które świadczyły niektóre usługi wykorzystywane w tym procesie, nie zostały zachowane w naszej aplikacji. Zasoby, które powinny być przypisane do określonego dostawcy przez określony okres, były przesuwane między innymi dostawcami przed zakończeniem tego okresu. Zdawaliśmy sobie sprawę z istnienia tego okresu i uwzględniliśmy tę koncepcję w naszym modelu. Nie byliśmy jednak świadomi, że cały czas powinniśmy przechowywać zasoby przydzielone dostawcom dla tego okresu.

Ta kwestia mogła powodować problemy — dostawcy rozliczali organizację, dla której pracowaliśmy, częściowo na podstawie przydzielonych zasobów. Przydziały te były również wykorzystywane do oceny wyników dostawców. Firmy o gorszych wynikach mogłyby uzyskać mniej zasobów przydzielonych w kolejnych okresach i mieć z tego powodu mniej pracy, co mogło potencjalnie prowadzić do rozwiązania stosunku pracy z pracownikami. Zasadniczo nasz błąd mógł kosztować kogoś pracę! Najgorsze, że kiedy to odkryliśmy, nasza aplikacja już funkcjonowała.

Refaktoryzacja nowo opracowanego modelu dla dopasowania do działań biznesowych

Na szczęście organizacja, dla której pracujemy, daje deweloperom dużą swobodę wyboru zakresu prac, który dopuszczają w każdym sprincie. Jest on skonfigurowany w taki sposób, aby zapewnić inżynierom oprogramowania wystarczająco dużo czasu na dostarczenie kodu dobrej jakości, który jest zgodny z zasadami SOLID*. W naszej aplikacji zapisaliśmy wiele testów jednostkowych i integracyjnych — niektóre z nich zostały oparte na historyjkach użytkownika, ponieważ uważamy, że kod, który jest objęty zautomatyzowanymi testami, ma większą jakość niż podobny kod, który nie przeszedł żadnych testów. Dzięki 80% pokrycia kodu byliśmy w stanie przeprowadzić kilka burzy mózgów, aby dowiedzieć się jak poddać nasz model refaktoryzacji pod kątem lepszego dopasowania do procesu biznesowego. Musieliśmy zmienić cykl życia jednego z naszych agregatów i wprowadzić zupełnie nowy obiekt, aby ułatwić zarządzanie zdarzeniami związanymi z nowym cyklem życia.

Ponadto dodaliśmy testy dla nowych scenariuszy, a także przeprowadziliśmy szeroko zakrojone testy ręczne, które pomogły nam wychwycić kilka niezauważonych wcześniej przypadków brzegowych. Logika stała się bardziej skomplikowana, ale dzięki jednemu dodatkowemu etapowi refaktoryzacji i testowania udało nam się uwzględnić wszystkie przypadki i wdrożyliśmy zmiany w produkcji. Następnie udało nam się wyjaśnić analitykom danych jak korzystać z naszego modelu danych. Po ukończeniu kilku iteracji „raportów z testów” wraz z analitykami byliśmy pewni, że firma będzie opierać swoją decyzję na poprawnych danych.

Rezultatem są wydajne procesy biznesowe

Ogólnie rzecz biorąc, projekt odniósł sukces. Zespół biznesowy jest bardzo zadowolony z tego narzędzia. Byli oni pod wrażeniem wyglądu, sposobu nawigowania i układu – wszystkie elementy, które stale omawialiśmy w trakcie całego projektu, a co najważniejsze – narzędzie spełniają ich potrzeby. Kierownictwo miało nadzieję, że projekt zakończy się szybciej, niemniej jednak nadal są zadowoleni z wyników. Aktualnie proces wymaga mniejszych ręcznych nakładów i ułatwia zapewnienie jakości i odnajdowanie problemów z procesem. Narzędzie zastąpi swojego starszego odpowiednika w innych krajach w organizacji, tak aby w każdym miejscu używano tej samej wersji.

Dobre relacje pomogły utorować drogę do projektu

W trakcie całego projektu miałem okazję obserwować ewolucję owocnych relacji z interesariuszami i dowiedziałem się, jak ważne są takie relacje. Bez dobrej woli nie bylibyśmy w stanie dostarczyć wszystkich funkcji w wymaganym zakresie (ponieważ testy i jakość były koniecznością, każdy brak czasu oznaczał zmniejszenie zakresu). Doprowadziłoby to do tego, że pracownicy jednostki biznesowej podejmowaliby więcej pracy ręcznej niż jest to konieczne.

Wreszcie nie bylibyśmy w stanie stworzyć języka wszechobecnego potrzebnego do stworzenia modelu domeny, który umożliwił nam skuteczną komunikację z firmą na temat funkcji i wymagań.

 Zasady SOLID dla ulepszenia wyników

Po raz kolejny udowodniono jak ważne jest dobre pokrycie kodu oraz przestrzeganie zasad SOLID podczas pisania kodu. Stosowanie tych zasad znacznie ułatwia testowanie kodu przy użyciu testów jednostkowych i integracyjnych. Posiadanie kodu zgodnego z SOLID i pokrytego testami pozwoliło nam płynnie poradzić sobie z kilkoma problematycznymi domenami i sesjami refaktoryzacji. W każdej chwili byliśmy pewni, że w razie potrzeby będziemy mogli zmienić i refaktoryzować nasz model i kod, aby dopasować nowe odkrycia i nowe wymagania biznesowe.

Dziękuję za uwagę!

Linki zewnętrzne

Jeżeli chcesz dowiedzieć się więcej o projektowaniu opartym na domenie — DDD, polecam zapoznanie się z pozycjami „Domain-Driven Design” Erica Evansa lub „Implementing Domain-Driven Design” (tytuł polski „DDD dla architektów oprogramowania”) Vaughna Vernona.

*SOLID oznacza następujące zasady: zasada jednej odpowiedzialności, zasada otwarte-zamknięte, zasada podstawienia Liskov, zasada segregacji interfejsu i zasada odwrócenia zależności. Wyjaśnienie tych zasad można znaleźć w wielu miejscach, ale polecam lekturę z jednego z największych promotorów zasad SOLID: Roberta C. Martina. Jeden z jego artykułów zatytułowany „Principles Of Ood” (Zasady projektowania obiektowego) zawiera krótkie, ale pouczające wyjaśnienie.

Skuteczne-rozwiazania-blog-ProData-Consult

Zbigniew Manasterski jest programistą z dziesięcioletnim doświadczeniem komercyjnym, pracującym głównie nad opracowywaniem rozwiązań z wykorzystaniem technologii takich jak .NET Core czy ReactJS. Jest specjalistą w zakresie programowania obiektowego (OOP); posiada silne kompetencje w zakresie tworzenia stron internetowych, szczególnie w warstwie frontendu; ma również doświadczenie w obszarze backendu. Pracował w kilku branżach, w tym w przemyśle elektronicznym i telekomunikacyjnym, a także w Centrum Rozwoju firmy Microsoft w Norwegii.