Udostępnij za pośrednictwem


Projektuj pod kątem rozwoju

Ewolucyjny projekt jest kluczem do ciągłych innowacji

Wszystkie udane aplikacje zmieniają się na przestrzeni czasu: czy to w celu naprawienia błędów, dodania nowych funkcji, wprowadzenia nowych technologii, czy też poprawienia skalowalności i odporności istniejących systemów. Jeśli wszystkie elementy aplikacji są ze sobą ściśle powiązane, wprowadzenie zmian do systemu staje się bardzo trudnym zadaniem. Wprowadzenie zmian w jednej części aplikacji może spowodować usterkę w innej części lub sprawić, że zmiany rozprzestrzenią się w całej bazie kodu.

Ten problem nie dotyczy tylko monolitycznych aplikacji. Aplikacja może być rozłożona na usługi, ale nadal wykazuje ścisłe powiązania, które powodują, że system pozostaje sztywny i kruchy. Jeśli jednak usługi są projektowane z myślą o ich ewolucji, zespoły mogą wprowadzać innowacje i stale dostarczać nowe funkcje.

Mikrousługi stają się popularnym sposobem osiągnięcia ewolucyjnego projektu, ponieważ dotyczą one wielu zagadnień wymienionych tutaj.

Zalecenia

Wymuś wysoką spójność i poluzuj powiązania. Usługa jest spójna, jeśli dostarcza funkcję, która logicznie składa się w całość. Usługi są luźno powiązane, jeśli jest możliwe wprowadzenie zmian w jednej usłudze bez wpływu na drugą. Wysoka spójność zazwyczaj oznacza, że zmiany w jednej funkcji będą wymagały zmian w innych powiązanych funkcjach, w których wszystkie powiązane funkcje znajdują się w jednej usłudze. Jeśli okazuje się, że aktualizacja usługi wymaga przeprowadzenia skoordynowanych aktualizacji innych usług, może to być sygnał, że usługi nie są spójne. Jednym z celów projektowania opartego na domenie (DDD) jest zidentyfikowanie tych granic.

Hermetyzuj znajomość domeny. Gdy klient korzysta z usługi, odpowiedzialność za wymuszanie reguł biznesowych domeny nie powinna spadać na klienta. Zamiast tego usługa powinna hermetyzować całą znajomość domeny, za którą jest ona odpowiedzialna. W przeciwnym razie każdy klient będzie musiał wymuszać reguły biznesowe, a znajomość domeny zostanie rozprzestrzeniona na różne części aplikacji.

Użyj asynchronicznej obsługi komunikatów. Asynchroniczna obsługa komunikatów jest sposobem na rozdzielenie producenta komunikatu od konsumenta. Producent nie zależy od konsumenta reagującego na komunikat lub wykonującego dowolną określoną akcję. Dzięki architekturze publikowania/subskrybowania producent może nawet nie wiedzieć, kto jest konsumentem komunikatu. Nowe usługi z łatwością mogą konsumować komunikaty bez żadnych modyfikacji względem producenta.

Nie wbudowuj znajomości domeny do bramy. Bramy mogą być przydatne w architekturze mikrousług dla takich elementów jak routing żądań, tłumaczenie protokołów, równoważenie obciążenia lub uwierzytelnianie. Jednak bramy powinny być ograniczone do tego rodzaju funkcji infrastruktury. Nie powinny implementować znajomości domeny, aby nie stać się dużą zależnością.

Prezentuj otwarte interfejsy. Unikaj tworzenia niestandardowych warstw tłumaczenia, które znajdują się między usługami. Zamiast tego usługa powinna prezentować interfejs API za pomocą prawidłowo zdefiniowanego kontraktu interfejsu API. Interfejs API powinien być poddany kontroli wersji, dzięki czemu można rozwijać interfejs API, zachowując zgodność z poprzednimi wersjami. W ten sposób można zaktualizować usługę bez konieczności koordynowania aktualizacji wszystkich usług, które są od niej zależne. Usługi użytku publicznego powinny prezentować interfejs API RESTful przy użyciu protokołu HTTP. Usługi wewnętrznej bazy danych mogą używać protokołu obsługi komunikatów w stylu RPC ze względu na wydajność.

Projektuj i testuj pod względem kontraktów usług. Gdy usługi prezentują dobrze zdefiniowane interfejsy API, można programować i testować względem tych interfejsów API. W ten sposób można programować i przetestować pojedynczą usługę bez konieczności uruchamiania wszystkich zależnych od niej usług. (Oczywiście integracja i test obciążeniowy będą wykonywane na rzeczywistych usługach).

Korzystanie z funkcji fitness. Funkcje fitness mierzą wynik, aby sprawdzić, czy jest bliżej, czy dalej od optymalnego rozwiązania. Funkcje fitness pomagają chronić cechy architektoniczne w miarę upływu czasu. Funkcja fitness to dowolny mechanizm, który zapewnia obiektywną ocenę integralności cech architektury. Ocena może obejmować różne mechanizmy, takie jak metryki, testy jednostkowe, inżynieria chaosu itd. Na przykład architekt może zidentyfikować czas ładowania strony jako ważną cechę. Następnie obciążenie powinno mieć funkcję fitness, aby przetestować czas ładowania strony i uruchomić test w ramach ciągłej integracji.

Oddziel infrastrukturę od logiki domeny. Nie pozwól, aby logika domeny pomieszała się z funkcjami związanymi z infrastrukturą, takimi jak obsługa komunikatów lub trwałość. W przeciwnym razie zmiany w logice domeny będą wymagać przeprowadzenia aktualizacji warstw infrastruktury i na odwrót.

Odciąż przekrojowe zagadnienia do oddzielnej usługi. Jeśli na przykład kilka usług musi uwierzytelnić żądania, można przenieść tę funkcję do własnej usługi. Następnie można rozwinąć usługę uwierzytelniania — na przykład dodając nowy przepływ uwierzytelniania — bez dotykania żadnych usług, które z niej korzystają.

Wdrażaj usługi niezależnie. Gdy zespół DevOps może wdrożyć pojedynczą usługę niezależnie od innych usług w aplikacji, aktualizacje mogą być przeprowadzane szybciej i bezpieczniej. Poprawki i nowe funkcje mogą być wprowadzane w bardziej regularnych cyklach. Projektowanie zarówno aplikacji, jak i procesu publikacji powinno przebiegać tak, aby wspierać niezależne aktualizacje.