Strona Główna / Blog

Jak dobre praktyki programowania przekładają się na rozwój aplikacji w chmurze?

Damian Mazurek

Damian Mazurek

CTO w Chmurowisko. Jestem architektem pracującym z .NET, Node.JS i Microsoft Azure. Specjalizuję się w budowaniu globalnie rozproszonych aplikacji oraz rozwiazań IoT. W Chmurowisku odpowiadam za projekty związane z tworzeniem rozwiązań dla naszych klientów z wykorzystaniem rozwiązań PaaS oraz FaaS. Skontaktuj się z nim pisząc na ten adres.

SOLID i inne dobre praktyki tworzenia oprogramowania są (mam nadzieję!) powszechnie znane i stosowane przez programistów na całym świecie. Pytamy o nie na rozmowach kwalifikacyjnych, wytykamy ich braki w przeglądzie kodu i mamy wyrzuty sumienia, gdy musimy przymknąć na nie oko, aby dostarczyć projekt na czas.

W ostatnich latach świat rozwoju oprogramowania gruntownie się zmienił i obecnie, aby być dobrym i pożądanym na rynku programistą, trzeba dołożyć do swojego pudełka z narzędziami chmurę publiczną. Jak to zrobić, aby utrzymać wysoką jakość kodu także w chmurze? Jakie są dobre praktyki rozwoju aplikacji chmurowych i czy bardzo odbiegają od tych, które już znamy? 

Dziś podpowiadamy, jak przenieść obecną wiedzę i doświadczenie na chmurę, żeby wzmocnić swoją pozycję wszechstronnego programisty!

Błędne założenia przy tworzeniu systemów rozproszonych

Jako programiści często czynimy założenia. Czasem pomagają nam one dojść do celu i pokonać napotkany problem, lecz bywa, że stwarzają zagrożenie na środowisku produkcyjnym. Polecam ten artykuł o tzw. błędnych założeniach przy tworzeniu systemów rozproszonych (ang. fallacies of distributed systems).

Na przykład przy tworzeniu usługi do komunikacji z Service Busem, czy wrappera dla punktu końcowego w Azure Functions powinniśmy zakładać nie tylko działające ścieżki czy ewentualne błędy logiczne, ale również obsługę przypadków pogorszenia się stanu usługi, z którą się komunikujemy. Takie scenariusze najlepiej wyłapywać już na poziomie testów automatycznych (zarówno integracyjnych, jak i jednostkowych). 

Programowanie defensywne

Spora część zestawu praktyk zwanych Defensive Programming dotyczy zarówno zabezpieczania się przed niedostępnością usług trzecich czy problemami z asynchronicznością, jak i uwzględniania różnic w zachowaniu tych usług w zależności od środowiska. Aby skutecznie radzić sobie z podobnymi kwestiami, stworzono wiele wzorców, które możemy zaimplementować w kodzie:

Zastosowanie chociażby jednej z tych praktyk znacząco zredukuje ryzyko konieczności spędzenia wielu długich godzin na gaszeniu pożaru na produkcji.

SOLID w chmurze

Już od dwóch dekad SOLID pomaga programistom tworzyć wysokiej jakości, łatwy w utrzymaniu kod. Ten prosty zestaw zasad powstał jednak w czasach, kiedy nikomu nie śniło się, że będziemy wdrażać aplikacji w jakiejś tam chmurze.

Jakiś czas temu Microsoft wydał ciekawy white paper na temat pierwszej zasady SOLID, Single Responsibility Principle (zasada pojedynczej odpowiedzialności). A co z kolejnymi? Spróbujmy przełożyć je na chmurę publiczną.

Open/Closed (otwarte-zamknięte)

Klasa, metoda, itd., powinny być otwarte na rozszerzenie swojej funkcjonalności, ale bez jednoczesnego bezpośredniego edytowania kodu źródłowego. Z doświadczenia wiem, że chociaż w teorii ta zasada brzmi prosto, to w codziennej pracy często o niej zapominamy. Jak przenieść to założenie do świata chmury?

Weźmy na przykład usługę Azure Function, która otrzymuje obraz, zmniejsza jego rozdzielczość, a następnie przesyła przetworzony plik do określonego folderu. Dodatkowo chcemy mieć również możliwość nakładania na pomniejszony obraz znaku wodnego. Zamiast rozszerzać tę konkretną funkcję o nowe linie kodu (i narażać się na wprowadzenie nowych błędów oraz złamanie pierwszej zasady SOLID), możemy stworzyć nową funkcję nasłuchującą na zmiany w folderze, do którego trafia pomniejszony obraz, i nakładającą znak wodny osobno na plik.

Liskov (zasada podstawienia Liskov)

Ta zasada mówi, że możliwość podstawienia obiektu o podtypie obiektu, który spodziewamy się otrzymać, nie powinna wymagać zmiany zachowania systemu. Zasadę podstawienia można zastosować nie tylko do interfejsu najmniejszych elementów w kodzie, takich jak klasy, ale również do interfejsów komunikacyjnych pomiędzy różnymi modułami systemu.

Komunikacja pomiędzy usługami w chmurze powinna być zaimplementowana w taki sposób, aby wymiana jednego z komponentów nie wiązała się z przepisywaniem wszystkich zależnych od niego modułów. Efekt taki można uzyskać, wykorzystując różne opcje komunikacji za pomocą eventów, wiadomości, czy poleceń, jak i stosując tradycyjną zasadę Liskov w kodzie – oddzielając się warstwą abstrakcji od konkretnej implementacji danej metody komunikacji.

Interface Segregation (segregacja interfejsów)

Żaden z bytów nie powinien zależeć od elementów interfejsu, których nie używa. Złamanie tej zasady ilustruje na przykład sytuacja, w której klasa ConsoleLogger implementuje interfejs IConsole z dwoma metodami ReadFromConsole i WriteToConsole. A to dlatego, że ConsoleLogger nie będzie używać metody czytającej dane wprowadzone przez użytkownika. Implementując ją, zanieczyszczamy logikę klasy, co może wpłynąć na jej późniejsze utrzymywanie.

Jak to przełożyć na chmurę? Np. kontener dockerowy z obrazem bazy danych nie potrzebuje wszystkich narzędzi zamkniętych w osobnym kontenerze, na którego obrazie budujemy komponenty systemu. Posegregowanie kontenerów i użycie ich do budowy nowych w zależności od faktycznych potrzeb pomoże uniknąć problemów z utrzymaniem takiego systemu.

Dependency Inversion (odwrócenie zależności)

Odwrócenie zależności to kwintesencja współczesnej chmury publicznej, w której większość tworzonej przez nas logiki może być zarządzana przez eventy dostarczane przez wiele usług typu EventGrid, IoT Hub, czy nawet przez zmiany w bazie danych. Zamiast tworzyć usługi, które bezpośrednio sterują logiką systemu od wewnątrz, można oprzeć kontrolę na reakcji na konkretne eventy i interakcje użytkowników z aplikacją (patrz Liskov).

Kluczowe wnioski

  • Pisząc kod aplikacji korzystającej z chmury publicznej, zakładaj, że wszystko, co może pójść nie tak, pójdzie nie tak. Zabezpiecz swój kod na taką ewentualność, korzystając z istniejących już wzorców.
  • SOLID ma zastosowanie nie tylko bezpośrednio w kodzie. Przełożenie praktyk na pracę z usługami w chmurze wpłynie pozytywnie na wydajność, łatwość utrzymywania i bezpieczeństwo Twojej aplikacji. Spróbuj znaleźć sposób na przełożenie jednej z zasad SOLID na Twój projekt i zaproponuj go swojemu zespołowi!

Już wkrótce otwieramy nowe kursy

Zostań specjalistą chmury publicznej

Dołącz do listy mailingowej!

Dołącz do naszego newslettera

Staramy się wysyłać tylko wartościowe informacje, np. co miesiąc dostaniesz spis najważniejszych nowości z chmur Azure, AWS i GCP, z krótkimi opisami i linkami.