Każdego dnia, w każdej chwili naszej kariery inżynierskiej napotykamy wiele różnych problemów o różnym stopniu złożoności i sytuacji, w których musimy podjąć decyzję lub odłożyć ją z powodu braku danych. Za każdym razem, gdy budujemy nowe usługi, konstruujemy infrastrukturę, a nawet tworzymy procesy rozwojowe, dotykamy ogromnego świata różnych wyzwań.
Trudno, a może nawet niemożliwe jest wymienienie wszystkich problemów. Na niektóre z nich natkniesz się tylko wtedy, gdy pracujesz w określonej niszy. Z drugiej strony jest wiele, które wszyscy musimy zrozumieć, jak rozwiązać, ponieważ są kluczowe dla budowania systemów informatycznych. Z dużym prawdopodobieństwem natkniesz się na nie we wszystkich projektach.
W tym artykule podzielę się swoimi doświadczeniami dotyczącymi niektórych problemów, na jakie natknąłem się podczas tworzenia programów komputerowych.
Jeśli zajrzymy do Wikipedii, znajdziemy następującą definicję
W zorientowanym aspektowo rozwoju oprogramowania, kwestie przekrojowe to aspekty programu, które wpływają na kilka modułów, bez możliwości ich uwzględnienia w żadnym z nich. Kwestie te często nie mogą być czysto rozłożone od reszty systemu zarówno w projekcie, jak i implementacji, i mogą skutkować rozproszeniem (duplikacją kodu), splątaniem (znacznymi zależnościami między systemami) lub jednym i drugim.
Opis ten doskonale opisuje istotę sprawy, ale chciałbym go nieco rozszerzyć i uprościć:
Zagadnienie przekrojowe to koncepcja lub komponent systemu/organizacji, który wpływa na wiele innych części (lub „przecina się”).
Najlepszymi przykładami takich obaw są architektura systemu, rejestrowanie, bezpieczeństwo, zarządzanie transakcjami, telemetria, projektowanie baz danych i wiele innych. Wiele z nich omówimy szczegółowo w dalszej części artykułu.
Na poziomie kodu, kwestie przekrojowe są często implementowane przy użyciu technik takich jak Aspect-Oriented Programming (AOP) , gdzie kwestie te są modularne do oddzielnych komponentów, które można stosować w całej aplikacji. Dzięki temu logika biznesowa pozostaje odizolowana od tych kwestii, co sprawia, że kod jest bardziej czytelny i łatwiejszy w utrzymaniu.
Istnieje wiele możliwych sposobów klasyfikowania aspektów poprzez segmentowanie ich według różnych właściwości, takich jak zakres, rozmiar, funkcjonalność, ważność, cel i inne, ale w tym artykule zamierzam użyć prostej klasyfikacji zakresu. Mam na myśli, gdzie skierowany jest ten konkretny aspekt, czy jest to cała organizacja, konkretny system, czy konkretny element tego systemu.
Zatem podzielę aspekty na makro i mikro .
Przez aspekt makro rozumiem głównie względy, które bierzemy pod uwagę w odniesieniu do całego systemu, takie jak wybrana architektura systemu i jej projekt (monolityczna, mikrousługi, architektura zorientowana na usługi), stos technologiczny, struktura organizacyjna itd. Aspekty makro odnoszą się głównie do decyzji strategicznych i decyzji podejmowanych na wysokim szczeblu.
Tymczasem aspekt Micro jest znacznie bliższy poziomowi kodu i rozwojowi. Na przykład, który framework jest używany do interakcji z bazą danych, struktura folderów i klas projektu, a nawet konkretne wzorce projektowania obiektów.
Mimo że klasyfikacja ta nie jest idealna, pomaga ona zrozumieć potencjalne problemy oraz znaczenie i wpływ rozwiązań, które stosujemy w ich rozwiązywaniu.
W tym artykule skupię się przede wszystkim na aspektach makro.
Kiedy dopiero zaczynałem uczyć się o architekturze oprogramowania, przeczytałem wiele interesujących artykułów o prawie Conwaya i jego wpływie na strukturę organizacyjną. Zwłaszcza ten . Tak więc to prawo stwierdza, że
Każda organizacja projektująca system (rozumiany szeroko) stworzy projekt, którego struktura będzie kopią struktury komunikacyjnej danej organizacji.
Zawsze wierzyłem, że ta koncepcja jest rzeczywiście bardzo uniwersalna i odzwierciedla Złotą Zasadę.
Następnie zacząłem uczyć się podejścia Erica Evansa do projektowania zorientowanego na domenę (DDD) w zakresie modelowania systemów. Eric Evans podkreśla znaczenie identyfikacji ograniczonego kontekstu. Koncepcja ta polega na podzieleniu złożonego modelu domeny na mniejsze, bardziej zarządzalne sekcje, z których każda ma swój własny, ograniczony zestaw wiedzy. Podejście to wspomaga skuteczną komunikację w zespole, ponieważ zmniejsza potrzebę rozległej wiedzy na temat całej domeny i minimalizuje przełączanie kontekstu, dzięki czemu rozmowy stają się bardziej wydajne. Przełączanie kontekstu jest najgorszą i najbardziej zasobożerną rzeczą na świecie. Nawet komputery mają z tym problem. Chociaż mało prawdopodobne jest osiągnięcie całkowitego braku przełączania kontekstu, uważam, że właśnie do tego powinniśmy dążyć.
Wracając do prawa Conwaya, znalazłem w nim kilka problemów.
Pierwszy problem, na jaki natrafiłem w przypadku prawa Conwaya, które sugeruje, że projekt systemu odzwierciedla strukturę organizacyjną, to potencjał tworzenia złożonych i kompleksowych kontekstów ograniczonych. Ta złożoność pojawia się, gdy struktura organizacyjna nie jest zgodna z granicami domeny, co prowadzi do kontekstów ograniczonych, które są silnie współzależne i obciążone informacjami. Prowadzi to do częstego przełączania kontekstów przez zespół programistów.
Innym problemem jest to, że terminologia organizacyjna przecieka na poziom kodu. Gdy struktury organizacyjne ulegają zmianie, konieczne są modyfikacje bazy kodu, co pochłania cenne zasoby.
Tak więc, podążanie za Inverse Conway Maneuver pomaga budować system i organizację, które zachęcają do pożądanej architektury oprogramowania. Warto jednak zauważyć, że to podejście nie sprawdzi się zbyt dobrze w już uformowanej architekturze i strukturach, ponieważ zmiany na tym etapie są przedłużane, ale jest wyjątkowo skuteczne w startupach, ponieważ szybko wprowadzają wszelkie zmiany.
Ten wzorzec lub „antywzorzec” napędza budowanie systemu bez żadnej architektury. Nie ma żadnych reguł, żadnych granic ani żadnej strategii, jak kontrolować nieuchronnie rosnącą złożoność. Złożoność jest najgroźniejszym wrogiem w podróży budowania systemów oprogramowania.
Aby uniknąć stworzenia takiego systemu, musimy przestrzegać określonych zasad i ograniczeń.
Istnieje niezliczona ilość definicji architektury oprogramowania. Wiele z nich mi się podoba, ponieważ obejmują różne jej aspekty. Jednak, aby móc rozumować o architekturze, musimy naturalnie uformować niektóre z nich w naszych umysłach. I warto zauważyć, że ta definicja może ewoluować. Więc przynajmniej na razie mam następujący opis dla siebie.
Architektura oprogramowania dotyczy decyzji i wyborów, które podejmujesz każdego dnia i które mają wpływ na tworzony system.
Aby podejmować decyzje, musisz mieć w „torbie” zasady i wzorce rozwiązywania pojawiających się problemów, ważne jest również stwierdzenie, że zrozumienie wymagań jest kluczem do zbudowania tego, czego potrzebuje firma. Jednak czasami wymagania nie są przejrzyste lub nawet nie są zdefiniowane, w takim przypadku lepiej poczekać, aby uzyskać więcej wyjaśnień lub polegać na swoim doświadczeniu i zaufać swojej intuicji. Tak czy inaczej, nie możesz podejmować właściwych decyzji, jeśli nie masz zasad i wzorców, na których możesz polegać. Właśnie tutaj przechodzę do definicji stylu architektury oprogramowania.
Styl architektury oprogramowania to zbiór zasad i wzorców, które określają sposób tworzenia oprogramowania.
Istnieje wiele różnych stylów architektonicznych, skupionych na różnych aspektach planowanej architektury, a stosowanie wielu z nich na raz jest sytuacją normalną.
Na przykład takie jak:
Architektura monolityczna
Projektowanie zorientowane na domenę
Oparty na komponentach
Mikrousługi
Rury i filtry
Zdarzeniowe
Mikrojądro
Zorientowany na usługi
i tak dalej…
Oczywiście, mają swoje zalety i wady, ale najważniejszą rzeczą, której się nauczyłem, jest to, że architektura ewoluuje stopniowo, w zależności od rzeczywistych problemów. Rozpoczęcie od architektury monolitycznej to świetny wybór, aby zmniejszyć złożoność operacyjną, bardzo prawdopodobne, że ta architektura będzie odpowiadać Twoim potrzebom nawet po osiągnięciu etapu dopasowania produktu do rynku (PMI) podczas tworzenia produktu. W skali możesz rozważyć przejście na podejście oparte na zdarzeniach i mikrousługi w celu osiągnięcia niezależnego wdrożenia, heterogenicznego środowiska stosu technologicznego i mniej sprzężonej architektury (i mniej przejrzystej w międzyczasie ze względu na naturę podejść opartych na zdarzeniach i pub-sub, jeśli zostaną przyjęte). Prostota i wydajność są blisko siebie i mają na siebie duży wpływ. Zazwyczaj skomplikowane architektury wpływają na szybkość rozwoju nowych funkcji, wspierają i utrzymują istniejące oraz stanowią wyzwanie dla naturalnej ewolucji systemu.
Jednakże złożone systemy często wymagają złożonej i kompleksowej architektury, co jest nieuniknione.
Słusznie, to bardzo, bardzo szeroki temat i jest wiele świetnych pomysłów na to, jak ustrukturyzować i zbudować systemy dla naturalnej ewolucji. Na podstawie mojego doświadczenia opracowałem następujące podejście:
Ważne jest również zrozumienie liczb i wskaźników, takich jak DAU (liczba aktywnych użytkowników dziennie), MAU (liczba aktywnych użytkowników miesięcznie), RPC (liczba żądań na sekundę) i TPC (liczba transakcji na sekundę), ponieważ może to pomóc w podejmowaniu decyzji, gdyż architektura dla 100 aktywnych użytkowników i 100 milionów aktywnych użytkowników jest inna.
Na koniec chciałbym powiedzieć, że architektura ma znaczący wpływ na sukces produktu. Źle zaprojektowana architektura produktów jest wymagana w skalowaniu, co bardzo prawdopodobnie prowadzi do porażki, ponieważ klienci nie będą czekać, aż skalujesz system, wybiorą konkurenta, więc musimy wyprzedzać potencjalne skalowanie. Chociaż przyznaję, że czasami nie może to być podejście szczupłe, chodzi o to, aby mieć skalowalny, ale nie już skalowany system. Z drugiej strony, posiadanie bardzo skomplikowanego i już skalowanego systemu bez klientów lub planów zdobycia wielu z nich będzie Cię kosztować pieniądze w Twojej firmie za nic.
Wybór zestawu technologii jest również decyzją na poziomie makro, ponieważ wpływa na zatrudnianie, perspektywy naturalnej ewolucji systemu, skalowalność i wydajność systemu.
Poniżej znajduje się lista podstawowych kwestii, które należy wziąć pod uwagę przy wyborze zestawu technologii:
Jak korzystanie z wielu zestawów technologii może wpłynąć na rozwój firmy?
Z jednej strony wprowadzenie jednego stosu więcej może zwiększyć skalę zatrudnienia, ale z drugiej strony wiąże się z dodatkowymi kosztami utrzymania, ponieważ musisz obsługiwać oba stosy. Tak więc, jak powiedziałem wcześniej, moim zdaniem, tylko dodatkowa potrzeba powinna być argumentem za włączeniem większej liczby stosów technologicznych.
Na czym jednak polega zasada wyboru najlepszego narzędzia do rozwiązania konkretnego problemu?
Czasami nie ma innego wyjścia, jak tylko sięgnąć po nowe narzędzia w celu rozwiązania konkretnego problemu, opierając się na powyższych założeniach. W takich przypadkach warto wybrać najlepsze rozwiązanie.
Tworzenie systemów bez wysokiego sprzężenia z konkretną technologią może być wyzwaniem. Mimo to pomocne jest dążenie do stanu, w którym system nie jest ściśle sprzężony z technologią i nie umrze, jeśli jutro konkretny framework lub narzędzie stanie się podatne na ataki lub nawet przestarzałe.
Innym ważnym czynnikiem jest zależność od oprogramowania open source i własnościowego. Oprogramowanie własnościowe daje mniejszą elastyczność i możliwość dostosowania. Nadal najbardziej niebezpiecznym czynnikiem jest uzależnienie od dostawcy, w którym stajesz się zależny od produktów, cen, warunków i planu działania dostawcy. Może to być ryzykowne, jeśli dostawca zmieni kierunek, podniesie ceny lub zaprzestanie produkcji produktu. Oprogramowanie open source zmniejsza to ryzyko, ponieważ nie kontroluje go pojedyncza jednostka. Wyeliminowanie pojedynczego punktu awarii na wszystkich poziomach jest kluczem do budowania niezawodnych systemów wzrostu.
Pojedynczy punkt awarii (SPOF) odnosi się do dowolnej części systemu, która w przypadku awarii spowoduje, że cały system przestanie działać. Eliminacja SPOF-ów na wszystkich poziomach jest kluczowa dla każdego systemu wymagającego wysokiej dostępności. Wszystko, w tym wiedza, personel, komponenty systemu, dostawcy chmury i kable internetowe, może zawieść.
Istnieje kilka podstawowych technik, które możemy zastosować w celu wyeliminowania pojedynczych punktów awarii:
W tym artykule omówiliśmy kilka kluczowych aspektów makroekonomicznych i sposoby radzenia sobie z ich złożonością.
Dziękuję za przeczytanie! Do zobaczenia następnym razem!