Aby zebrać w jednym miejscu praktyczną i aktualną wiedzę dotyczącą praktyk inżynierskich, postanowiłem swoje doświadczenia zebrać w serii artykułów pod wspólną nazwą Praktyk Inżynierskich. Mam nadzieję że to kompendium będzie miejscem, do którego możesz wracać po wskazówki i rozwiązania.
W cyklu Praktyk Inżynierskich:
Drivery architektoniczne [TEN ARTYKUŁ]
W ostatnim artykule opisywałem jak inżynierowie mogą współpracować z biznesem w zakresie ulepszania roadmapy.
Dziś kontynuujemy temat najlepszych praktyk inżynierskich, ucząc się na praktycznych przykładach najlepszych firm produktowych. Na tapet bierzemy więc Drivery Architektoniczne. Dowiesz się, jakie problemy rozwiązują i w jaki sposób je definiować, a także wykorzystywać w pracy.
Co się dzieje, kiedy projektujemy “na czuja”?
Często rozmawiam z liderami technicznymi, których projektowanie opiera się na intuicji i subiektywnych przekonaniach. Osoby decyzyjne kierują się aktualnymi trendami i osobistymi preferencjami.
Spotkałeś/aś kiedyś z taką sytuacją? Jeśli nie, zadaj sobie następujące pytanie:
Jak wiele produktów, z którymi pracowałeś/aś było oparte na mikroserwisach? Jak wiele z nich tego potrzebowało?
Podejmując decyzje pod wpływem chwili, narażamy się na wpadnięcie w pułapkę overengineeringu. Systemy, które dotknęła ta bolączka są skomplikowane, przepełnione funkcjami i możliwościami. Zespół kończy z produktem coraz droższym i trudniejszym w utrzymaniu.
Co więcej, brak spójnej wizji w projektowaniu sprawia, że zespół nie dostosowuje się do potrzeb odbiorców. Optymalizujemy nasz produkt pod kryteria, które nikogo nie interesują. Bez jasności, co jest ważne dla biznesu, rodzą się nieporozumienia i konflikty, a ocena postępów zaczyna graniczyć z niemożliwością.
W dłuższej perspektywie, brak jasnych kryteriów i ram dla produktu prowadzi do zwiększenia kosztów i opóźnień. Nieoptymalne rozwiązania wymagają częstych zmian. Niejasne miary sprawiają, że trudno jest ocenić, czy produkt jest na właściwie rozwijany.
Efekt? Jakość leci na łeb na szyję.
Organizacje z silną kulturą inżynierską pracują inaczej.
Pracując jak inżynierowie
Wysoko rozwinięte organizacje inżynierskie podchodzą do projektowania systemów w sposób bardziej przemyślany i celowy.
Kluczem do sukcesu jest skupienie na driverach architektonicznych – czynnikach, które kierują, wpływają i kształtują ostateczną architekturę oprogramowania.
Aby skutecznie wykorzystywać drivery w pracy, musimy posiadać miary, które pozwolą ocenić, czy dany system spełnia oczekiwania. Dzięki temu możemy przeprowadzać dokładną ocenę różnych propozycji rozwiązań, bazując na jasno określonych kryteriach.
W sytuacjach, gdy żadne z proponowanych rozwiązań nie spełnia wszystkich oczekiwań, niezbędne mogą być negocjacje z interesariuszami. Dzięki jasno zdefiniowanym driverom, widzimy na jakie kompromisy się zgadzamy. Możemy więc skuteczniej komunikować i argumentować nasze decyzje.
Co więcej, odpowiednie dokumentowanie zarówno procesu projektowania, jak i podjętych decyzji, pozwala na zachowanie ciągłości wiedzy, ułatwiając przyszłe prace nad produktem.
Przykład z branży
W tej edycji newslettera przykładem podzielił się Karol Kreft – Technical Leader w Volt.io, gdzie współtworzy infrastukturę do obsługi płatności w czasie rzeczywistym.
Q: W jaki sposób wykorzystujecie drivery architektoniczne w swojej codziennej pracy?
A: W Volcie podejmujemy decyzje technologiczne w oparciu o dane. Dlatego sięgamy po drivery architektoniczne np. gdy szukamy odpowiedzi na pytanie pod które atrybuty jakościowe powinniśmy optymalizować nasze systemy. Operując na płatnościach, szczególnie istotna jest integralność danych, ale nie możemy też zapominać o dostępności i bezpieczeństwie. To najczęściej te kwestie są poruszane przez zespoły na refinementach oraz we wcześniejszych fazach planowania.
Q: Jakie zalety widzisz z pracy z driverami na poziomie zespołu i organizacji?
A: Dostrzegam podobieństwo między stosowaniem driverów architektonicznych a innymi, popularnymi praktykami z zakresu wytwarzania oprogramowania takimi jak Definition Of Ready, 3Amigos, Impact Mapping czy codzienny stand-up. To dzięki nim potwierdzamy, że rozumiemy problem, przed którym stoi nasz użytkownik, a także oceniamy rozwiązanie, biorąc pod uwagę wszystko to, co odkryjemy na każdym etapie jego wdrażania.
Zidentyfikowanie ograniczeń nie jest większym problemem. Te wynikające z technologii nadal można pokonać. Za trudniejsze uważam te bezpośrednio związaną z legislacją, których w świecie fintechu nie brakuje. Jednocześnie, z perspektywy zespołu deweloperskiego, to atrybuty jakościowe są na pierwszym miejscu. To dzięki nim programiści odkrywają pozafunkcjonalne wymagania, kształtujące oddolnie naszą architekturę.
Ok, a więc jak tego wszystkiego dokonać?
Drivery architektoniczne w teorii i praktyce
Rozpocznijmy od podstaw – bez nich trudno iść dalej.😉
Czym są drivery architektoniczne? Simon Brown w książce “Software Architecture for Developers” opisuje je tak:
Regardless of the process that you follow (traditional and plan-driven vs lightweight and adaptive), there’s a set of common things that really drive, influence and shape the resulting software architecture.
Czyli mówimy tutaj o głównych czynnikach, które mają wpływ na naszą architekturę. Nierozpoznane odpowiednio wcześnie powodują, że nasze rozwiązanie będzie rozwijane w nieodpowiednim kierunku.
Wyodrębniamy cztery kategorie driverów architektonicznych w projektowaniu systemów:
Główne funkcje.
Atrybuty jakościowe.
Ograniczenia.
Praktyki techniczne i architektoniczne.
Pierwszy z nich jest w miarę oczywisty. Projektujemy pod określone wymagania. Skupiamy się, aby zrealizować główne funkcje, zarówno w krótkim, jak i długim terminie. Musimy je zdefiniować jasno dla wszystkich członków zespołu.
Ostatni zależy wyłącznie od nas – sami narzucamy sobie wybrane praktyki. Mówimy tutaj zarówno o praktykach programistycznych (jak testy jednostkowe), jak i architektonicznych (jak nacisk na modularność).
Kwestie atrybutów jakościowych i ograniczeń rodzą natomiast najwięcej pytań i wątpliwości, dlatego dziś to je chciałbym Ci szerzej przybliżyć.
Atrybuty jakościowe
Atrybuty te, nazywane również wymaganiami niefunkcjonalnymi, to wewnętrzne miary systemu, przez które rozwiązanie może być oceniane. Nie widać ich na pierwszy rzut oka, jednak to od nich zależy czy produkt będzie dobrze przyjęty przed klientów.
Część atrybutów jakościowych możesz zauważyć na grafice poniżej:
Kolejne atrybuty jakościowe możesz znaleźć w artykule Love Sharma lub w książkach „Software Architecture for Developers" Simona Brown, czy „Fundamentals of Software Architecture" Marka Richardsa i Neala Forda.
W ramach pracy z atrybutami jakościowymi warto wybrać z interesariuszami kilka z nich i to pod nie optymalizować pracę systemu.
Ograniczenia
Rzadko kiedy pracujemy bez żadnych ograniczeń ze świata zewnętrznego. Zwykle mamy jednak ustalone deadline’y, współpracujemy z zewnętrznymi organizacjami czy kontynuujemy istniejące procesy. Nasza praca musi się do tego dostosować.
Wyróżniamy trzy główne rodzaje ograniczeń , do których pownniśmy sobie zadawać następujące pytania:
Technologiczne – Jakie wymogi techniczne musimy spełnić? Jakie technologie są dozwolone? Jaki kształt ma zespół?
Organizacyjne – Jakie wymogi stawia organizacja? Co jest standardem organizacyjnym? Jakie procesy musimy wziąć pod uwagę?
Środowiskowe – Jakie restrykcje nakłada na nas świat zewnętrzny? Jakie ograniczenia nakładają firmy, z którymi współpracujemy?
Zadając takie pytania jesteśmy w stanie określić kluczowe ograniczenia.
Poprawne miary dla driverów
Co to znaczy, że system jest wydajny? Zapytaj 2 interesariuszy, a dostaniesz 3 odpowiedzi. 😅
Ale to właśnie dlatego warto pytać.
Kluczowym jest, aby dla atrybutów jakościowych i ograniczeń zdefiniować dobre miary. Dzięki temu będziemy w stanie wiedzieć, czy podążamy we właściwym kierunku.
Pierwsze, co mogę polecić to skupienie się, aby najpierw otworzyć dyskusję i ustalić czy dany driver jest istotny. Dopiero później przyjdzie czas na szczegóły.. Dlaczego? Trudno jest podać rozmówcy właściwe informacje, kiedy bez kontekstu zadajemy bardzo szczegółowe pytanie.
Pracę można podzielić więc na 2 fazy:
Zbieranie informacji - Czy zależy nam na wydajnym XYZ? Dlaczego? A co jeśli XYZ nie będzie dostępne? Co się stanie? Czy myślimy o rozszerzalności systemu?
Uszczegóławianie - Jak określimy czy coś jest wydajne/skalowalne/ABC? Jak zmierzymy, że tak jest? Jakie sytuacje możemy tolerować?
Jeśli dalej nie macie właściwych miar, to polecam zajrzeć do książki How to Measure Anything. Jest tam świetna instrukcja jak mierzyć rzeczy „niemierzalne". Całość opiera się o decyzje, jakie chcemy podjąć za pomocą miar. W skrócie:
Define a Decision Problem and the Relevant Uncertainties.
Determine what you know now.
Compute the value of additional information.
Apply the relevant measurement instrument(s) to high-value measurements.
Projektowanie i ocena na podstawie driverów
Drivery nie powinny zostać raz spisane, a następnie odłożone na półkę. Poszczególne drivery będą nas kierować podczas projektowania i wyboru rozwiązania.
W ramach samego projektowania, warto podzielić pracę na 3 etapy:
Definiowanie propozycji – wymyślamy możliwości, czyli w jaki sposób możemy zrealizować dane wymaganie.
Ocenianie – za pomocą driverów architektonicznych oceniamy rozwiązania pod względem wyznaczonych kryteriów.
Podejmowanie decyzji – wybieramy jedno z rozwiązań. Zwykle nie ma tutaj najlepszego rozwiązania, więc od razu definiujemy kompromis, na jaki idziemy podejmując tę decyzję.
Co zyskujemy, trzymając się tej kolejności? Dzięki temu unikniemy błędów poznawczych, takich jak efekt skupienia czy heurystyka zakotwiczenia. To zaś da nam większą szansę na wybranie dopasowanego rozwiązania.
Jak to wygląda w praktyce? W przykładzie poniżej mamy 2 propozycje (funkcje serverless i aplikacje webową) oraz 2 drivery architektoniczne (ograniczenie czasowe i wydajność):
Dla każdej z ocen zostało określone ryzyko (w skali 1-10) oraz zwięźle wyjaśniony powód. Dzięki temu możemy:
Wybierać rozwiązania obiektywniej.
W bardziej konstruktywny sposób wyrażać sprzeciw.
Współdzielić w zespole nasze modele mentalne dotyczące rozwiązań.
Uczyć inne osoby dokonywania oceny.
Tak wykonana ocena jest również świetnym argumentem w negocjacji z interesariuszami, może też służyć do dokumentowania wybranych rozwiązań.
Negocjacje
Najciekawszą sytuacją, jaka może wyjść w ramach oceny projektu rozwiązania jest ta, gdy uświadamiamy sobie, że żadne rozwiązanie nie jest w stanie nas zadowolić. 😬
Wtedy musimy rozpocząć trudny proces negocjacji z interesariuszami, które drivery możemy zmodyfikować i w jaki sposób. Na szczęście, jeśli:
właściwie zidentyfikowaliśmy kluczowe drivery architektoniczne,
dobrze przeprowadziliśmy ocenę rozwiązań na bazie driverów,
to mamy wszystkie informacje potrzebne do tego, by takie negocjacje przeprowadzić.
Jak więc się do tego zabrać? Na samym początku musimy wyjaśnić drugiej stronie skąd w ogóle negocjacja. Wykorzystanie tabeli oceny pozwala się lepiej porozumieć się nie tylko wewnątrz zespołu produktowego, ale również pomiędzy interesariuszami.
Następnie musimy podjąć decyzję, które drivery zmieniamy. Mamy do wyboru na przykład:
Okrojenie zakresu funkcjonalnego.
Usunięcie atrybutu jakościowego np. wyjście tylko na jeden kraj.
Zmiana atrybutu jakościowego np. obsługa 1 000 klientów dziennie zamiast 10 000 dziennie.
Opóźnienie zakończenia prac dla całości / części rozwiązania.
Przesunięcie certyfikacji na kolejny etap.
Mając szerszą perspektywę, łatwiej jest odpuścić pojedynczy element. Wiemy nie tylko co tracimy, ale też co zostaje dalej zostaje.
Dokumentowanie projektowania i decyzji
Cała powyższa praca może być przeprowadzona w formie dyskusji na spotkaniach. Ma to jednak swoje wady:
Po przeprowadzonej dyskusji nie zostają nam żadne artefakty.
Chcąc wrócić do kiedyś podjętej decyzji, nie mamy do czego się odnieść.
Trudno jest skalować wiedzę – wymieniać się informacjami z innymi zespołami.
Aby sobie z tym poradzić, organizacje z silną kulturą inżynierską zaczęły wykorzystywać formę pisaną do utrwalania informacji. Wyklarowały się 2 rodzaje dokumentów:
Request for Comments – wykorzystywane do przeprowadzenia dyskusji i dogłębnego odkrywania pomysłów.
Architectural Decision Records – zbierają decyzję architektoniczną i powody, które skłoniły nas do podjęcia tych decyzji.
Oba te dokumenty mogą być wykorzystywane, aby przeprowadzać prace inżynierskie, jednak na nieco innym etapie działania i w innym celu.
Wstępny pomysł** – RFC** – chcemy szybko zebrać feedback od organizacji czy dana propozycja jest realna.
Projekt i kilka rozwiązań** – **RFC lub ADR – wykonujemy ocenę rozwiązań, porównujemy spełnianie driverów architektonicznych.
Docelowe rozwiązanie – ADR – dokumentujemy podjętą decyzję, aby rozumieć jej powody w przyszłości.
Cały proces jest przystępnie opisany na stronie inżynierów Spotify (chociaż sam obrazek jest trochę za długi 😅):
Czy dokumentowanie nie będzie trwało zbyt długo?
Dokumentowanie ma swoje zalety, z którymi identyfikuje się np. Amazon kultywując kulturę pisania:
Jasność myśli : Pisemne formułowanie myśli wymaga od autora dokładnego przemyślenia i zrozumienia tematu.
Dokładność i szczegółowość : Dokumenty pozwalają na dokładne przedstawienie problemu, analizę różnych rozwiązań oraz uzasadnienie wyboru konkretnego rozwiązania
Zachowanie ciągłości : Pisane dokumenty stanowią trwałą bazę wiedzy, do której można wracać w przyszłości.
Ułatwienie dyskusji i krytyki : Kiedy pomysły są przedstawione na piśmie, łatwiej jest je analizować, krytykować i udoskonalać.
Prowadzenie solidnej dokumentacji ma swoje koszta, ale długofalowo one się zwracają.
Materiały
Powyższy tekst jest tylko pigułką najważniejszych informacji o temacie.
Jeśli chcesz dowiedzieć się więcej, przygotowałem garść materiałów, które przybliżą Ci omawiane obszary:
Książka „Software Architecture for Developers" – Simon Brown _
https://softwarearchitecturefordevelopers.com/
Książka “Fundamentals of Software Architecture” - Mark Richards, Neal Ford _https://www.oreilly.com/library/view/fundamentals-of-software/9781492043447/
Artykuł “Modular Monolith – Architectural Drivers” – Kamil Grzybek _https://www.kamilgrzybek.com/blog/posts/modular-monolith-architectural-drivers
Podsumowanie
Aby projektować właściwe rozwiązanie, należy wiedzieć pod co je optymalizujemy. W tym właśnie pomagają nam drivery architektoniczne. Dzięki nim sterujemy rozwiązaniem we właściwym kierunku.
A jak wygląda projektowanie u Ciebie? Wybierasz z zespołem na podstawie widzimisię, czy macie zdefiniowane czynniki architektoniczne? 🤔
Automatyzacja wdrożeń i zapewniania jakości
W kolejnym wydaniu wydaniu opowiadam o praktykach inżynieryjnych które stosowane są w nowoczesnych firmach produktowych i automatyzacji dookoła.