| Termin | Definicja |
|---|---|
| brak podziału logiki aplikacji i wysyłki | Brak podziału logiki aplikacji i wysyłki to usterka architektury utrudniająca niezależny rozwój tych dwóch warstw systemu. Na czym polega brak podziału logiki aplikacji i wysyłkiBrak podziału logiki aplikacji i wysyłki oznacza sytuację, w której kod odpowiedzialny za podejmowanie decyzji biznesowych jest bezpośrednio połączony z kodem przekazującym dane do odbiorcy. Logika aplikacji może określać na przykład, jakie dane należy obliczyć, które rekordy wybrać, jak zweryfikować formularz albo jaki rezultat zwrócić użytkownikowi. Logika wysyłki zajmuje się natomiast dostarczeniem tego rezultatu, na przykład przez odpowiedź HTTP, wiadomość e-mail, żądanie do zewnętrznego interfejsu API, zapis do kolejki albo komunikat wyświetlany w interfejsie. W prawidłowo uporządkowanym systemie te odpowiedzialności są rozdzielone przez jasno określone interfejsy. Moduł aplikacyjny przekazuje dane lub polecenie do warstwy wysyłki, ale nie musi znać szczegółów protokołu, biblioteki sieciowej, formatu transportowego ani sposobu obsługi połączenia. Usterka architektoniczna pojawia się wtedy, gdy jedna funkcja lub jeden moduł jednocześnie wykonuje obliczenia, modyfikuje stan, buduje komunikat, otwiera połączenie, wysyła dane i interpretuje błąd transportowy. Objawy połączenia decyzji aplikacyjnych z transportemPierwszym objawem jest trudność w ponownym wykorzystaniu tej samej logiki. Jeżeli reguła wyboru danych znajduje się wewnątrz funkcji wysyłającej żądanie HTTP, użycie jej w zadaniu cyklicznym, eksporcie pliku lub lokalnym teście wymaga odtworzenia całego mechanizmu komunikacji. Kod staje się zależny od konkretnego odbiorcy, adresu usługi, nagłówków, kodów odpowiedzi i struktury pakietu. Zmiana sposobu dostarczenia danych może wtedy wymagać modyfikacji także tej części programu, która powinna pozostać niezmieniona. Typowym sygnałem jest obecność w jednej metodzie warunków biznesowych oraz instrukcji charakterystycznych dla transportu. Przykładowo kod może najpierw sprawdzać status zamówienia, następnie tworzyć nagłówki żądania, serializować obiekt do JSON, wysyłać go, analizować kod HTTP i ponownie zmieniać status zamówienia. Taka metoda ma kilka niezależnych powodów do zmiany. Zmiana reguły biznesowej, formatu danych, biblioteki komunikacyjnej lub sposobu ponawiania transmisji może naruszyć pozostałe działania. Brak separacji utrudnia także rozróżnienie błędu merytorycznego od błędu dostarczenia. Odrzucenie danych przez regułę aplikacji nie jest tym samym co przerwane połączenie, przekroczenie limitu czasu lub odpowiedź serwera z kodem 503. Jeżeli wszystkie przypadki są obsługiwane w jednym bloku wyjątków, system może raportować nieprecyzyjne komunikaty, niepotrzebnie ponawiać operacje albo uznawać wysyłkę za zakończoną mimo braku potwierdzenia. Skutki dla testowania, zmian i spójności danychSilne sprzężenie obu warstw podnosi koszt testów. Test jednostkowy logiki aplikacji powinien sprawdzać wynik decyzji dla określonych danych wejściowych, bez konieczności uruchamiania sieci, zewnętrznego serwera czy skrzynki pocztowej. Gdy kod obliczeniowy sam wykonuje wysyłkę, test wymaga atrap transportu albo rzeczywistego środowiska integracyjnego. W efekcie testy stają się wolniejsze, bardziej kruche i zależne od stanu usług poza aplikacją. Osobnym problemem jest kolejność operacji. Jeżeli program zmienia lokalny stan przed wysłaniem komunikatu, a transmisja kończy się błędem, system może przechowywać informację sugerującą sukces, którego odbiorca nie odnotował. Jeżeli wysyłka następuje przed zapisem zmiany, awaria procesu pomiędzy tymi czynnościami może doprowadzić do ponownego wysłania tego samego komunikatu. Dlatego rozdzielenie warstwy aplikacyjnej i wysyłki powinno obejmować także jawne określenie statusów, identyfikatorów operacji, zasad ponawiania oraz informacji o tym, czy dana czynność jest idempotentna, czyli czy wielokrotne wykonanie daje ten sam efekt. Praktycznym sposobem ograniczenia problemu jest wydzielenie serwisu aplikacyjnego, który przyjmuje dane wejściowe i zwraca wynik decyzji, oraz osobnego adaptera transportowego, który realizuje wysyłkę. Adapter może implementować interfejs w rodzaju „wyślij komunikat”, podczas gdy kod aplikacyjny korzysta wyłącznie z tej abstrakcji. W testach adapter można zastąpić obiektem zapisującym przekazane dane bez wykonywania transmisji. W środowisku produkcyjnym ten sam interfejs może korzystać z właściwego klienta HTTP, mechanizmu pocztowego lub kolejki. Rozpoznanie usterki i kierunek uporządkowania koduDiagnostykę warto rozpocząć od prześledzenia pełnego przepływu: danych wejściowych, walidacji, decyzji aplikacyjnej, przygotowania komunikatu, wysyłki, potwierdzenia oraz zapisu rezultatu. Należy sprawdzić, czy każda operacja ma jeden jasno określony właściciel oraz czy błąd jednej warstwy jest przekazywany dalej w sposób rozróżniający jego przyczynę. Przydatne jest również wyszukanie metod, które równocześnie odwołują się do modeli domenowych, klienta sieciowego, serializatora i mechanizmu logowania. Taka kombinacja często wskazuje na zbyt szeroki zakres odpowiedzialności. Porządkowanie kodu powinno przebiegać etapami. Najpierw można nazwać dane przekazywane między warstwami i ustalić, które pola oznaczają decyzję aplikacji, a które szczegóły transportu. Następnie należy przenieść komunikację do osobnego modułu, zdefiniować obsługę sukcesu i błędów oraz dodać testy logiki bez uruchamiania zewnętrznych usług. Dopiero później warto zmieniać mechanizm ponawiania, kolejki lub format komunikatu, ponieważ wcześniejsze rozdzielenie odpowiedzialności ułatwia ocenę skutków takich zmian. Warszawskie Pogotowie Komputerowe wykonuje profesjonalną naprawę laptopów, komputerów PC i ich podzespołów, dlatego przy problemach z aplikacją na komputerze można zlecić sprawdzenie środowiska systemowego, instalacji programu oraz podstawowych przyczyn jego nieprawidłowego działania. |