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 luźne sprzężenie. Usługa jest spójna , jeśli zapewnia funkcjonalność, która logicznie należy do siebie. Usługi są luźno powiązane , jeśli możesz zmienić jedną usługę bez zmiany drugiej. 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.

Hermetyzowanie wiedzy o domenie. 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 wszyscy klienci będą musieli wymuszać reguły biznesowe, a wiedza domenowa rozprzestrzeni się po różnych częściach 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 wiedzy o domenie w bramę. 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 powinien wdrażać znajomości specyfiki domeny, aby nie stać się poważnym obciążeniem.

Uwidacznia 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 zaplecza mogą używać protokołu komunikacyjnego w stylu RPC ze względu na wydajność.

Projektowanie i testowanie 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, nadal przeprowadzałbyś integrację i testy obciążeniowe w stosunku do rzeczywistych usług).

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.

Abstrakcja infrastruktury 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.

Przekazywanie przekrojowych zagadnień 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żanie usług 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.