Nie wymyślaj sobie wymagań – krótka historia naszego “babola”

Nawet jeśli zaczynacie współpracę z dużym, korporacyjnym klientem od drobnych funkcjonalności czy MVP to prędzej czy później przyjdzie Wam zmierzyć się z czymś większym. W końcu dostaniecie na swój talerz cały moduł ogromnego systemu czy kluczowy, najczęściej używany widok w ich produkcie. Będąc w takiej sytuacji warto uniknąć pewnych prostych błędów, które zazwyczaj sami sobie wprowadzamy i właśnie o jednym z takich błędów z naszej własnej historii chcemy Wam dzisiaj opowiedzieć.

Dawid Perdek

Dawid Perdek. Principal Developer w Synergy Codes. Większość czasu pracował z Angularem, ale realizował też projekty z wykorzystaniem Reacta i Electrona. Poza pisaniem kodu prowadzi Gildię Software Delivery, w ramach której badane i udoskonalane są firmowe procesy dotyczące rozwijania oprogramowania. Inicjator, lubi pracę z ludźmi, chętnie dzieli się wiedzą, czy to w firmie, czy poza nią. Ostatnio mocno rozwija się w kierunku modelowania i architektury oprogramowania.

 

Piotrek Błaszczyk

Piotr Błaszczyk. Principal Developer w Synergy Codes. Zaczynał jako backend developer, lecz od 5 lat głównie związany z frontendem. Zaangażowany w wiele inicjatyw firmowych, wspierających ulepszanie procesów. Prowadzi Gildię „Software Stack Diversity” której celem jest rozpoznawanie nowych technologii, umożliwiających rozwój firmy w nowych obszarach. Specjalizuje się w architekturze frontendowej oraz szeroko pojętym procesie wytwarzania oprogramowania. Prywatnie pasjonat fotografii, nauki oraz mąż i tata 2 urwisów.


Cel projektu, czyli co było do zrobienia  

Jeden z naszych klientów zlecił nam implementację funkcjonalności odpowiadającej za prezentację danych na kafelkach – na usta ciśnie się aż: „klasyczny dashboard”. Ale, ale! Ponadto użytkownik miał mieć możliwość wybierania z kilkunastu rodzajów kafelków: dodawania, usuwania oraz zmiany ich kolejności. Funkcjonalność miała również wspierać zarządzanie wieloma takimi dashboardami – layout manager. W wymaganiach pojawiły się takie rzeczy, jak kilka predefiniowanych rozmiarów kafelków, udostępnianie dashboardów, dodawanie ich do ulubionych czy zarządzanie ich widocznością w zależności od roli/kontekstu. Dashboardy miały być Data Driven i oferować programistom klienta możliwość dodania nowych typów kafelków w kilku prostych krokach. 

Aha, do tego dostaliśmy na start dwie sugerowane biblioteki do implementacji layoutowania. Nie były to propozycje z typu tych „nie do odrzucenia”, ale zostało mocno podkreślone, że na pewno nie chcemy pisać od zera własnego rozwiązania. 

Jak podeszliśmy do tematu 

Do zadania podeszliśmy kompleksowo. Mieliśmy do dyspozycji dwa niewielkie, współpracujące ze sobą zespoły programistów z analitykiem, designerem i testerem na pokładzie. Po zebraniu wymagań, stworzeniu mockupów i wstępnym rozpisaniu zadań w backlogu, przeszliśmy do pierwszego etapu działań – przygotowania do implementacji. 

Rozpoczęliśmy od ujednolicenia wiedzy, czyli tego, co jest do zrobienia. Do osiągnięcia tego celu wykorzystaliśmy Event Storming. Klient nie był obecny na warsztatach, wystarczający był dla nas reprezentant eksperta domenowego w osobie naszego analityka. Znaleźliśmy również “hotspoty” czyli punkty, które jeszcze musimy sprawdzić lub wyjaśnić z klientem. 

Rezultaty wypracowane w ramach warsztatu posłużyły nam jako wsad do kolejnego etapu. Faza Discovery została podzielona na dwie niezależne części. Jeden z zespołów zajął się inwestygacją istniejącego kodu backendowego (dotychczasowa strona w .NET) i zapoznawał się ze strukturą bazy danych. W tym samym czasie do drugiego zespołu oddelegowana została analiza dostępnych na rynku bibliotek wraz z przygotowaniem Proof-of-Concept (PoC) i końcową rekomendacją. W wyniku fazy discovery, która trwała +/- tydzień, zrealizowaliśmy kilka takich PoC oraz wybraliśmy bibliotekę (Muuri), która miała być odpowiedzialna za layoutowanie kafelków.  

Od początku mieliśmy na względzie dość dużą złożoność funkcjonalności oraz potrzebę zaadresowania wymagania klienta co do elastyczności. Dlatego zdecydowaliśmy się jak najwcześniej stworzyć szkielet docelowego rozwiązania. Architektura angularowa została oparta o dynamicznie tworzone komponenty, bazujące na metadanych zwracanych z bazy. 

Rezultaty inwestygacji, stworzone PoC, rozplanowana architektura oraz wybrana biblioteka pozwoliły na dostarczenie stosunkowo precyzyjnych wycen. Bazując na tym klient ostatecznie potwierdził z nami zakres pracy i mogliśmy siadać do implementacji… 

Jeśli chcesz poznać więcej szczegółów na temat przebiegu każdego z etapów przygotowań do implementacji, zapraszamy na nasz webinar pod koniec września! 

Startujemy z implementacją 

Dzięki wypracowanej wcześniej architekturze, początek implementacji szedł bardzo sprawnie. Szkielety komponentów pojawiały się w docelowej aplikacji w szybkim tempie, efekty na widokach były więcej niż zadowalające. Pomagała nam też przy tym technologia – Angular dostarcza chociażby dependency injection (z którego sporo korzystaliśmy) oraz przetarte wzorce implementacji wielu rzeczy. Po kilku sprintach przyszła pora na pierwsze demo z klientem. 

Odbiór efektów naszej pracy był pozytywny. Znalazło się jednak kilka uwag i to w miarę istotnych. Dotyczących tak naprawdę bazowej funkcjonalności – layoutowania. Najważniejsza dotyczyła możliwości pozostawiania pustych przestrzeni w układzie kafelków. Było to możliwe, a okazało się, że nie powinno! 

Brzmi to jak całkiem poważny problem, przecież znaliśmy ograniczenia wybranej przez nas biblioteki. Musieliśmy coś szybko wymyślić. Zorganizowaliśmy wewnętrzny warsztat dotyczący samej funkcjonalności layoutowania, którego celem była odpowiedź na pytanie: co robimy dalej? Już na początku spotkania dotarło do nas, że mogliśmy sobie wymyślić wymagania co do zachowania biblioteki, takie jak drag&drop kafelków z palety na canvas czy swobodne ich rozmieszczanie, pozwalające na pozostawianie pustych przestrzeni. Musieliśmy też przyznać się przed sobą do tego, że trochę pod te możliwości dokonaliśmy ostatecznego wyboru biblioteki. 

Zmiana biblioteki 

Doszliśmy do jedynej słusznej odpowiedzi na pytanie postawione jako cel warsztatu – trzeba zmienić bibliotekę. Wybrane przez nas Muuri dostarczało możliwość tworzenia dowolnego layoutu. Charakteryzowało się również świetną wydajnością oraz oferowało drag&dropa – co według nas było kluczowe! Natomiast gdy zrezygnujemy z możliwości wrzucania kafelków na canvas i zablokujemy swobodę layoutowania, wybrana przez nas biblioteka przegrywa z drugą opcją, czyli Packery. Musieliśmy dokonać zmiany, szkoda, że doszliśmy do tego dopiero w drugiej połowie czasu do deadline’u. Wiedzieliśmy, że zmiana nie będzie trywialna, niektóre mechanizmy wypracowane w fazie przygotowania do implementacji były w jakimś stopniu spięte z wybraną biblioteką. Podjęliśmy wyzwanie i udało się wszystko dowieźć. Klient zadowolony z końcowego efektu, minimalna obsuwa względem pierwotnego terminu przebaczona, great success.  

Identyfikacja problemów 

Po zamknięciu tematu od razu usiedliśmy do wyciągania z tego lekcji. Szukaliśmy punktów na osi czasu projektu, w których podejmowaliśmy błędne decyzje lub używaliśmy nieodpowiednich procesów czy narzędzi. Idąc od początku – brak klienta na Event Stormingu. Nawet najlepszy analityk nie umie czytać w myślach klientowi, więc dobrze by było, żeby na początkowym etapie analizy mieć pod ręką kogoś, kto podejmuje finalne decyzje. 

Dalej mamy rzecz bardziej procesową, czyli oddelegowanie wyboru biblioteki do jednego z dwóch zespołów bez poprawnego procesu. Zespół 2 przygotował PoC dla każdej z bibliotek, przeanalizował wymagania dostarczone przez Zespół 1, przekazał im decyzję i praca ruszyła. Fakt użycia gotowego rozwiązania nieco uśpił naszą czujność. Podświadomie założyliśmy, że wymagania dostosują się do możliwości biblioteki, a nie szukaliśmy biblioteki spełniającej wcześniej postawione wymagania. Zabrakło tutaj zarówno bieżącej walidacji wymagań i stanu PoC między zespołami, jak i przede wszystkim odbijania tego od klienta. Zamiast podejścia „fail fast”, brnęliśmy w zaparte bez upewnienia się, że idziemy w dobrym kierunku. Nie pokazaliśmy klientowi demo wytworzonych PoC, a tylko przekazaliśmy, jaki wybór padł. 

No i rzecz, której na pewno dało się najłatwiej uniknąć. Wymyślanie swoich wymagań. Drag&Drop był dla nas oczywistą koniecznością, która nigdy nie padła z ust klienta. Podobnie z pustymi przestrzeniami między kafelkami. Wystarczyło o to w dowolnym momencie zapytać i wszystko byłoby jasne.  

ZOBACZ TEŻ:  Miał napisać 17 tys. linii kodu w dwa tygodnie. Historia Angulara

Morał  

Na pierwszy rzut oka, przy mniej szczegółowym opowiedzeniu tej historii może się wydawać, że to klient zawiódł. Nie podał pełnych wymagań, potem jeszcze coś kluczowego zmienił po demo, zły klient! Prawda jest jednak taka, że to po naszej stronie jako usługodawców, a najlepiej nawet partnerów, jest zadbanie o to, by wiedzieć wszystko, co potrzebne do dostarczenia dokładnie tego, czego klient potrzebuje. 

To po naszej stronie leży proaktywne wydobywanie wiedzy od klienta, bieżące walidowanie z nim wymagań oraz efektów naszej pracy. To my musimy przygotować architekturę w sposób jak najbardziej elastyczny, odraczając wszystkie decyzje do „ostatniego odpowiedzialnego momentu”. Nie możemy budować bazowych mechanizmów pod konkretną bibliotekę ani stosować przy ich implementacji workaroundów. 

Takie podejście doskonale się sprawdzi przy szybkim tworzeniu MVP, ale gdy w grę wchodzi długofalowa współpraca, to warto unikać wyżej wymienionych błędów.  

Jeśli chcesz dowiedzieć się więcej o naszych błędach i wnioskach, zapraszamy na webinar pod koniec września! 

ZOBACZ TEŻ:  Angular vs React. Która z technologii jest wydajniejsza?

baner

Zapraszamy do dyskusji

Patronujemy

 
 
More Stories
Co zrobić, gdy baza danych puchnie? O skalowaniu w chmurze