Not MVP
Od niedawna mam pewne zboczenie. Po kilku niespodziankach, kiedy myje ręce w pociągu, nie zaczynam od mydła, sprawdzam, czy jest woda. Jak pewnie można się domyślić, po solidnym nałożeniu go na ręce (jego obecność w pociągu wydaje się luksusem) musiałem szukać ręcznika, aby je z rąk zetrzeć (obecność ręcznika w pociągowej toalecie jest mniejszym luksusem niż mydło, ale zdarza się go zakosztować). Jaki sens ma mydło, jak nie ma wody? Ważniejsza jest woda, mydło czy ręczniki? Z perspektywy użytkownika dla mnie najważniejsza jest woda, mydło to dodatek, bez ręcznika też mogę umyć ręce. Z kolei jak już to mydło jest i jest pierwszym naturalnym elementem w procesie, to kto spodziewa się, że nie będzie wody? Wyobraźcie sobie Waszą frustrację kiedy macie obsmarowane ręce mydłem i nic innego nie da się zrobić. Masz zapaćkane ręce, ciężko wyjść nie obsmarowawszy klamki oraz kolejno mijanych drzwi, wracasz na miejsce, nawet jeżeli masz chusteczki, to prawdopodobnie ufajdasz sobie plecak/torebkę/ciuchy sięgając po nią. Sytuacja staje się dramatyczniejsza, gdy nie masz w co się wytrzeć, a przed Tobą jeszcze kilkugodzinna podróż. Niby pierdoła, a ile może spowodować potencjalnych szkód, ile zajmuje czasu i zachodu, aby wrócić do poziomu “czyste ręce”.
Widzę tu mocną analogię do MVP i zjawisk które obserwuję ostatnimi czasy w projektach. W przypadku mycia rąk w pociągu można by się zastanowić, czy w takiej sytuacji nie byłoby lepsze, że jak nie ma wody, to nie ma mydła, albo mamy jakiś komunikat, że załatwiasz się w toalecie na własną odpowiedzialność, gdyż pełen proces nie jest obsługiwany 😉 Ta sytuacja kojarzy mi się z wyścigiem fronendu i backendu i integracją.
User story z definicji powinno być małe (a przynajmniej mieścić się w sprincie) i dostarczać wartość biznesową. Z doświadczenia i obserwacji, to jest najtrudniejsza część dla zespołów programistycznych, dekompozycja.
Realne problemy w projektach
Jeżeli w zespole mamy role backendowców i frontendowców, w dodatku architektura jest rozproszona i pocięta na niezależne częsci to często spotykam się z problemem, czy kontekście zmiany biznesowej, backend do frontu ma wchodzić pierwszy, czy frontend, może wejść przed backendem (np. na mockach). Pogarszać sytuację może błędne podzielenie i programowanie “niezależnych” serwisów (często błędnie zdefiniowane MVP), które nie są od razu integrowane tworząc wartość biznesową. Na przykład, ktoś uznał, że przyjmiemy bardzo dużo ludzi do projektu, bo chcemy zrobić go szybko, będziemy dzielić zadania na tyle niezależne, aby nie przeszkadzać sobie w developmencie. W systemie ABC mocno rozwijamy AB (core MVP) a C zakładamy, że powstaje sobie na boku, bo będzie potrzebny za kilka miesięcy w procesie. Piszemy więc osobne story na komponent C. Za kilka miesięcy okazuje się, że wymagania biznesowe patrząc z góry, zmieniły się i:
- AB przejęły pewne odpowiedzialności C (mamy duplikacje i brak źródła prawdy)
- C spuchł, a po kilku miesiącach okazuje się, że wykorzystanie biznesowe to będzie 10% (overengineering)
- aby zintegrować AB z C potrzebujemy sporego refaktoru
Podobnie sytuacja ma się z backendem i frontem. Jeżeli mamy te role silnie rozdzielone, frontowiec ma czas, wiemy, że backend pod ten front nie powstanie w tym samym sprincie, to przygotowujemy sam front i pokazujemy go na wszelkiego rodzaju “zaślepkach” biznesowi. Sam fakt szybkiego feedbacku od biznesu czy front spełnia wymagania, jest ok. Jednak wyobraźmy sobie sytuacje, że taki front pokazujemy na demo po sprincie, pokazując jak działa proces. Biznes nie ma pojęcia, ile rzeczy jest jeszcze do zrobienia po stronie logiki w backendzie i że w zasadzie to, co pokazujemy nie działa i nie ma sensu wypuszczać na produkcję. To jest pułapka. Ciężko przekonać ludzi nietechnicznych, że to jest tylko front, samo jego zachowania, interakcja GUI. Możemy mówić, że to nie gotowe itp. ale Product Owner będzie cisnął z kolejnymi zadaniami, zostawiając “wiszący front”, aż w końcu inny zespół napisze backend i to zintegruje (w zasadzie nie wiadomo kiedy). A co jeżeli logika backendowa nie będzie pasowała do frontu? Ktoś może powiedzieć, że to są podstawowe błędy w prowadzeniu developmentu. Niech rzuci kamieniem ten, kto nie spotkał się z sytuacją upfront design, zrobiliśmy coś na wyrost, integrację zostawiliśmy na koniec i okazało się, że to działać nie będzie.
Myślę wtedy o linii produkcyjnej. Mamy fabrykę odkurzaczy, chcemy wypuścić szybko produkt. Backendowcy to ci od silników, frontowcy produkują obudowy. Mamy więcej frontowców, powstał design obudowy, wcześniej niż silniki (pomimo że wymiary były dogadane oraz interfejsy połączenia) i trzaskamy kolejne elementy obudowy. Wypuścić ich, nie wypuścimy, bo jaka wartość z samej obudowy odkurzacza. Jak już silnikowcy skończą i będą próbować się integrować – wsadzić silnik w obudowę – może okazać się, że interfejsy się zmieniły, po drodze w silniku sporo rzeczy uległy zmianie i np. musi być on teraz większy, albo potrzebuje więcej przestrzeni na chłodzenie itp. Przykład może i przejaskrawiony, ale mam nadzieję, że oddaje sens. Przykład z życia – w pewnym projekcie funkcjonalność biznesowa została ukończona w 6 miesięcy, biznes założył, że zaraz można to wypuszczać na produkcje, brakuje tylko integracji z jednym systemem, który będzie udostępniał ten serwis. Ukończenie tego zajęło kolejne kilka miesięcy, z dużą frustracją biznesu i zespołu.
Wasty – “mudas”
W lean te rzeczy o których piszę są nazwane jako “mudy”. Te które wprowadzamy przez budowanie osobno frontu i backendu i wypuszczanie ich osobno podchodzą pod:
- ryzyko nadprodukcji – “waste of overproduction” – robimy coś czego nie materializujemy od razu, nie weryfikujemy w pełni działającej funkcjonalności z biznesem, może się okazać, że praca pójdzie do kosza, albo do przerobienia, w dodatku wykorzystujemy “zasoby” na rzeczy które nie wiadomo czy przyniosą wartość, lepiej byłoby się skupić nad tym co jest teraz ważne, niż co może być ważne
- praca w toku – z perspektywy biznesowej user story, backend bez frontu, front bez backendu to tak naprawdę nieukończona praca, niezintegrowana praca
- ryzyko “transportation” – zmiany przygotowywane na kiedyś będzie trzeba zmergować
- waiting – późna integracja = późny feedback, późne testy, czekanie frontu na backend itd.
Jeżeli kogoś interesuje mocniej temat “mud” to może rozjaśni więcej moja prezentacja
Jak to może wyglądać?
W idealnym świecie, najlepiej jest jak backend z frontem są podczepione pod jedno user story, oczywiście muszą być to odpowiednie małe zadania, idealnie jak (nawet w przypadku różnych repozytoriów frontu i backendu) te zmiany wejdą na jednym “merge requeście”, od razu możemy przetestować integracje, mamy pełną zmianę biznesową – czyli wodę i mydło.
Jeżeli jest tak, że faktycznie, ciężko jest robić front i backend jednocześnie, to powinniśmy zapewnić jak najszybszą integrację, np. w sprincie N wchodzi zakontraktowany (interfejsy) backend, w sprincie N+1 front. Dla pewnych usługobiorców nasze API może być wystarczające do “robienia biznesu”.
Filozoficzne posłowie
Żarty pomiędzy “frontowcami” i “backendowcami” są na porządku dziennym. Wyrosły mocne specjalizacje. Technologie mocno się rozwinęły dając większe możliwości. Czy one dzisiaj ułatwiają? Cała ewolucja JS i frameworków frontowych, zrozumienie koncepcji i sposobów programowania wymaga już pełnego etatu i wydzielonej roli. Z moich obserwacji wielu ludzi z obszaru frontu przyszło z nurtu grafiki, można się nauczyć Reacta czy Angulara, ale niekoniecznie niesie to ze sobą dobre umiejętności programistyczne. W moim odczuciu wiele frontów nie wymaga stosowania tak zaawansowanych technologii, dałoby się to zrobić w zwykłym htmlu i ładnie ostylować i też by działało. Kiedyś każdy programista był dziś określanym “fullstackiem”, ale coś się stało przez te lata (technologie), że teraz mamy role jakie mamy, podziały i wojenki na poziomie backendy, frontendy. Moim zdaniem służy to powstawaniu strat.
Ciekaw jestem jak wygląda u Was rozdzielanie prac w zespołach w kontekści opisanego tutaj problemu, dobre praktyki?