Nasza strona używa cookies. Dowiedz się więcej o celu ich używania i zmianie ustawień w przeglądarce. Korzystając ze strony, wyrażasz zgodę na używanie cookies, zgodnie z aktualnymi ustawieniami przeglądarki. Rozumiem

Narzędzia i rozwiązania Continuous Development

Poznaj korzyści, jakie dają procesy Continuous Development i dowiedz się, jak wpływają na rozwój produktu.

Nowoczesne oprogramowanie powstaje bardzo szybko i wymaga elastyczności od m.in. programistów bardziej niż kiedykolwiek wcześniej. Aby nadążyć za rozwojem technologicznym, trzeba na bieżąco śledzić nowości w branży. Narzędzia i rozwiązania wiążące się z Continuous Development pomagają programistom dostarczać napisany kod szybciej i w sposób ustandaryzowany, zrozumiały dla osób z zewnątrz.

"Continuous” (ang. ciągły) według słownika Cambridge to proces lub czynność trwająca bez przerwy / bez przerwania.

Praca z wykorzystywaniem składowych Continuous Development (Continuous Integration oraz Continuous Delivery) to ciągłość i automatyzacja wszystkich etapów powstawania kodu, czyli ciągła integracja, dostarczanie lub ciągłe wdrażanie oprogramowania.

Spróbujmy w takim razie zrozumieć, jakie korzyści płyną z wykorzystywania CD (Continuous Development) i w jaki sposób bezpośrednio wpływa to na rozwój produktu.

W tym tekście spróbujemy dowiedzieć się, dlaczego temat CD i jego składowe są tak ważnym elementem w nowoczesnym programowaniu. Powiem również o tym, jakie korzyści płyną z ich wykorzystywania w codziennym planowaniu i wdrażaniu oraz w jaki sposób bezpośrednio wpływa to na rozwój produktu i doświadczenie osób uczestniczących w tych procesach.


Continuous Integration, Deployment, Delivery a Development

Zacznijmy od wyjaśnienia sformułowania "Continuous Integration".

Myśląc “ciągły”, większość programistów i testerów, skojarzy to od razu z integracją. Dlatego możemy przyjąć, że CI jest prawdopodobnie najbardziej znanym i najczęściej wykorzystywanym elementem całego procesu. Próbując opisać to w jednym zdaniu, CI to ciągłość w kompilacji i testowaniu tworzonego kodu za pomocą testów jednostkowych i integracyjnych, które od razu mogą nam powiedzieć, czy nasz nowy kod naprawiający daną funkcjonalność, nie uszkadza czegoś innego (np. wyciek pamięci poprzez nieumiejętną rezerwację i niezwolnienie zasobów).

źródło: Ericsson

Innymi słowy, po każdym review kodu i "wypchnięciu" (utworzeniem commita, baseline’a, rewizji - w zależności od wykorzystywanego repozytorium) swojego fragmentu do całości projektu, zostaje automatycznie (przy pomocy Jenkinsa/Bamboo) uruchomiony proces kompilacji, po którym w zależności od rezultatów, uruchamiane są kolejne narzędzia/testy lub wysyłany jest raport z błędami, które spowodowały niepowodzenie.

Jak można zauważyć, ważną zaletą ciągłej integracji jest to, że zapewnia programistom natychmiastową informację zwrotną i aktualizacje statusu oprogramowania, nad którym pracują.

W przypadku Continuous Delivery i Deployment sprawa wygląda trochę inaczej. Powyższe procesy są do siebie podobne i mogą być stosowane niezależnie od siebie.

Różnice powinien wyjaśnić rysunek poniżej.


źródło: Ericsson

Jak można zauważyć na powyższym obrazku, większa część procesu jest taka sama w obu przypadkach. Jedyna różnica, jaką można zaobserwować, widoczna jest na etapie dostarczania na produkcję.

W przypadku Continuous Deployment zautomatyzowaniu poddane zostały wszystkie kroki od momentu powstania kodu, aż do integracji z produkcją. Po przejściu wszystkich automatycznych testów każda zmiana kodu jest wdrażana na produkcje, gdy tylko będzie to możliwe. Ponieważ zmiany są dostarczane szybko, bez przerwy i bez interwencji człowieka, ciągłe wdrażanie może być postrzegane jako ryzykowne. Dlatego też wymaga wysokiego stopnia zaufania, zarówno w istniejącej infrastrukturze aplikacji, jak i w zespole pracującym z takim rodzajem środowiska. Taka ciągłość jest często wykorzystywana w aplikacjach mobilnych, które stosunkowo często przesyłają aktualizacje swoim klientom w ramach istniejącej już aplikacji (sprawdź, jak często aktualizują się niektóre aplikacje na Twoim smartfonie).

W Continuous Delivery ten ostatni etap w cyklu ciągłego dostarczania jest wykonywany manualnie. Opiera się to na ciągłej integracji i tak jak w jej przypadku, każde zatwierdzenie review jest automatycznie testowane w momencie jego dodania. Oprócz zautomatyzowanych testów jednostkowych i integracyjnych, system ciągłego dostarczania będzie obejmował testy funkcjonalne, ewentualnie inne testy, takie jak wstępnie wygenerowane testy akceptacyjne. Po kompilacji i pozytywnym zakończeniu testów nasze zmiany są gotowe do wdrożenia na produkcje
w dowolnym momencie.


Korzyści z Continuous Development

Teraz wiesz już, czym jest proces Continuous Development i na jakie elementy się dzieli. Możemy więc spróbować przeanalizować, w jakim celu wdraża się rozwiązania oparte o ciągłość czynności, a następnie przyjrzymy się przyszłości programowania i wpływu Continuous Development na jej kształtowanie.

Ciągły rozwój pozwala firmom programistycznym szybko wprowadzać nowy kod, uzyskiwać przydatne opinie i minimalizować czas pomiędzy kodowaniem i wdrażaniem. Dobrze wdrożony proces daje nam wiele zalet, dzięki którym dana firma może szybciej opracowywać nowe funkcje i przejąć lub utrzymać pozycję lidera wśród konkurencji.

Łatwo zauważyć, że oznacza to przede wszystkim sprawniejsze i szybsze przekazywanie funkcji do testowania i integracji. Ciągły rozwój pozwala szybciej opracowywać i wdrażać nowe funkcje przy użyciu zautomatyzowanych procesów. W odniesieniu do lat dziewięćdziesiątych ubiegłego wieku widać wyraźną poprawę szybkości, z jaką firmy mogą testować zmiany oraz wdrażać nowe pomysły. Pod koniec XX wieku testy potrafiły trwać miesiącami, a kolejne wersje programu klientom udostępniane były raz do roku, co dziś jest nie do pomyślenia.
Wprowadzenie do całego procesu automatyzacji umożliwia szybką identyfikację niezgodności, więc niemal natychmiast udaje się zidentyfikować problem i go rozwiązać, a w przypadkach szczególnych zadecydować o wycofaniu.

Jakość produktu to kolejny pozytywny aspekt. Jak już pisałem – ciągły rozwój oparty na zautomatyzowanych testach oraz wysyłaniu raportów do końcowych użytkowników pozwala na ulepszanie oprogramowania w sposób ciągły. Pozwala to na szybszą reakcję osób zaangażowanych w projekt. W rezultacie skraca się czas reakcji na pojawiające się problemy, dając możliwość natychmiastowego cofnięcia zmian lub przygotowania i dostarczenia niezbędnych poprawek. Metody takie, jak podejście kaskadowe (ang. Waterfall model), wymagają od programistów założenia, które funkcje są istotniejsze z punktu widzenia użytkownika. Ciągłość, wykorzystując informacje zwrotne i dane wejściowe, pomaga na zaplanowanie cyklu życia w taki sposób, aby w najlepszy sposób określone zostały priorytety zadań oraz projektów.

Dbałość o jakość ma jeszcze jedną istotną zaletę. Mianowicie rozwijanie produktu w sposób ciągły zmniejsza ryzyko związane z kompilacją dużych i dziurawych fragmentów kodu, które niejednokrotnie w nich występują. Dla programistów i testerów to istotne ułatwienie, pozwalające wprowadzać nowe koncepcje stopniowo w łatwiejszych do wprowadzenia i poprawy mniejszych paczkach. Małe iteracje mogą być wdrożone szybciej, przetestowane i poprawione lub wycofane, jeśli pojawi się taka konieczność.

Ale nie tylko jakość produktu możemy podnosić. Istotne jest również zwiększanie produktywności zespołów i można to robić w łatwy sposób. Zespoły, których projekty dostarczane są w formie Continuous Development, dzięki raportowaniu pracy na poszczególnych etapach, mogą dokonywać poprawki bez konieczności oczekiwania na finalne testy. Dzięki temu, osoby odpowiedzialne za dany element produktu, pracują w sposób ciągły, co jest bardziej wydajne i skraca czas niezbędny do przygotowania w pełni funkcjonalnego produktu. W niedalekiej przyszłości takie działania pozwolą zoptymalizować oprogramowanie i skrócić czas do prawidłowego wdrożenia oprogramowania, wzbogaconego o nowe funkcje.

Znając już podstawowe funkcje i zalety wykorzystania metodyk Continuous, możemy zająć się narzędziami, które znacznie ułatwią wdrożenie lub zarządzenie projektem.


Narzędzia metodyk Continuous

Do procesu zarówno Continuous Integration, jak i Continuous Delivery w Ericsson, wykorzystujemy Jenkinsa wraz z pluginami. Oprogramowanie to pozwala na automatyzację kroków procesu, znacząco obniżając czas i koszt tworzenia kolejnych wersji aplikacji.

Etapami, które udało się zmodyfikować z pomocą Jenkinsa, są:

  • pobranie kodu źródłowego;
  • kompilacja;
  • poddanie kodu testom jednostkowym i funkcjonalnym;
  • analiza statyczna kodu źródłowego;
  • integracja gotowego do wdrożenia fragmentu kodu


Korzystanie z metodyk Continuous, szczególnie Integration i Development, niejeden raz poprawiło lub też uratowało efekty pracy kilku osób. Bardzo często, mając zautomatyzowane całe środowisko - od kompilacji, przez statyczną analizę, aż do testów funkcjonalności, najdłuższe test case’y puszczane są na noc, aby w razie problemów można od rana rozpocząć analizę problemu lub od razu dostarczyć zmiany na produkcję. Warto wspomnieć, że cały proces w tym konkretnym projekcie, praktycznie od zera, został zautomatyzowany przez jeden zespół po przejęciu projektu.

Automatyzacja całego procesu zajęła niecałe dwa lata, ale udało nam się osiągnąć całkowitą automatyzację - wliczając w to wysyłanie raportów, zliczanie statystyk i notyfikacje w przypadku zmian wartości, generowanie raportów dołączanych do review przy minimalnej interakcji z użytkownikiem, kolejkowanie dostarczania na produkcję i podejmowanie decyzji o statusie wyniku testów na podstawie known issues, które nie powinny za każdym razem wpływać na werdykt (znając dany problem i mając świadomość, że zespół pracuje nad jego rozwiązaniem, możemy go pominąć przy kolejnych wynikach).

Dzięki wykorzystaniu Continuous Integration udało się uniknąć opóźnień, które mogły mieć wpływ na termin udostępnienia najnowszej wersji klientowi. Przykładem może być znalezienie poważnego błędu niecałą dobę przed prezentacją dema u klienta. Mając dodatkowe nocne godziny i kolejkowanie dostarczenia po zakończonych testach, udało się wszystko naprawić, przetestować i zintegrować na produkcji dla klienta, przed godziną dziewiątą. Tak, aby demo można było zaprezentować na najnowszej wersji.

Jenkins jest platformą ciągłej integracji o otwartym źródle i jest w wielu firmach podstawowym narzędziem w cyklu życia oprogramowania. Jednak jego interfejs od wielu lat jest niezmienny i w porównaniu z aktualnymi trendami, nie jest przyjazny dla użytkownika. Co więcej, konfiguracja Jenkinsa może wymagać od nas dużo pracy i cierpliwości, w zależności od tego, do czego chcemy go wykorzystywać.

Będąc w temacie Jenkinsa, warto wspomnieć o konkurencji, dzięki której temat Continuous można integrować na wiele sposobów i znaleźć aplikacje, które spełniają wszystkie wymagania i założenia konfiguracyjne konkretnego projektu. Lista zawiera zarówno rozwiązania komercyjne, jak i open source. Wybrałem w sumie 3 aplikacje, z których każda jest lepsza od reszty w czymś innym, ale to tylko kilka z wielu propozycji dostępnych na rynku.

  • TravisCI – open source, bardzo duże i pomocne community, duża ilość obsługiwanych technologii
  • Bamboo – bardzo dobry support, ze względu na odpłatność produkt stabilny i dopracowany
  • GitLab CI – Łatwość użytkowania, niski próg wejścia w zarządzanie projektami


Modern Software Development

Omawiając tematykę CI, należy również wspomnieć o Modern Software Development oraz zmianach, które dzięki zastosowaniu skalowalnych i elastycznych elementów, mogą być wprowadzane bez długotrwałych przerw w produkcji.

Zanim omówimy zasady obowiązujące przy „modnym” programowaniu, powinniśmy podzielić programistów na dwie grupy. Pierwsza to klasyczni deweloperzy, którzy zajmują się programowaniem za pomocą algorytmów, nie korzystają z gotowych rozwiązań, a każdą funkcję starają się napisać samodzielnie. Zupełnie inaczej wygląda sytuacja w drugiej grupie. Nowoczesny programista, aby dotrzymać kroku nowinkom technicznym w branży IT, powinien być elastyczny w tworzeniu kodu i otwarty na nowe rozwiązania. Dlatego nie liczy się tylko znajomość języka programowania, ale również umiejętność wyszukiwania i łączenia ze sobą odpowiednich bibliotek, aby zminimalizować napisany kod do niezbędnego minimum.

Modern Development, zwany również programowaniem pasywnym, którego główną zaletą jest możliwość szybszego tworzenia i modyfikowania aplikacji, niż w przypadku programowania klasycznego, znanego jako aktywne. Patrząc, w jaką stronę zmierza rozwój i utrzymywanie aplikacji, klasyczny deweloper powinien całkowicie zmienić swój sposób myślenia.

Dokładnie taka sytuacja ma miejsce w przypadku Continuous Integration. Sprawna rozbudowa i migracja między różnymi systemami wymaga nauczenia się rozbudowy środowiska integracyjnego i podzielenie go na mobilne elementy, które dzięki odpowiednim narzędziom, będą się ze sobą komunikować, nie będąc jednocześnie od niego zależne.

Powyższy akapit nie ma na celu zakwestionować klasycznego programowania i jego użyteczności. Nadal jest ono bardzo potrzebne i wręcz niezbędne do zrozumienia i oceny kodu, który został już napisany (w innych aplikacjach, czy też bibliotekach). Aby korzystać z dobrodziejstw gotowych rozwiązań, w dalszym ciągu wymagana jest umiejętność programowania i raczej nigdy to się nie zmieni.


Przygotowanie projektu do Continuous Development

Teraz spróbujmy się zastanowić, jak przygotować już istniejący lub nowy projekt do wdrożenia Continuous Development.

Skomplikowane i czasochłonne. Te dwa wyrazy mogą określać proces tworzenia środowiska programistycznego. Jednakże właściwa integracja umożliwia zmniejszenie czasu potrzebnego do zbudowania, przetestowania i wdrożenia nowych wersji kodu, ograniczając jednocześnie ilość pracy potrzebnej do osiągnięcia oczekiwanych rezultatów. Odpowiednie oprogramowanie, wdrożone na potrzeby wykonywanych zadań, pozwala szybko podejmować decyzje w przypadku napotkania problemów, praktycznie na każdym z etapów ciągłości. Uproszczenie procesu wdrażania jest możliwe dzięki wykonaniu pięciu następujących po sobie kroków.

Usprawnienie procesu planowania

Zanim przejdziemy do automatyzacji, powinniśmy usprawnić proces planowania i śledzenia zadań, wraz z zespołem programistów/testerów. Takie rozwiązania umożliwią nam metody wytwarzania oprogramowania Agile oraz framework Scrum, w zależności od upodobań. Sprawny system zapewni, że każdy członek zespołu będzie wiedział, jakie zadania są do wykonania na każdy interwał czasowy, zwany Sprintem w Scrumie i jak te zadania odnoszą się do całego projektu. Dzięki temu, w łatwy sposób, w każdym momencie, można określić, w jakim stadium prac jesteśmy i czy początkowe estymaty były poprawne.

Kontrola wersji

Kolejnym krokiem jest wykorzystywanie aplikacji do kontroli wersji kodu źródłowego. Innymi słowy, musimy zadbać o repozytorium dla naszego projektu. Na dzień dzisiejszy, najpopularniejszy jest GIT, ale nic nie stoi na przeszkodzie, żebyśmy korzystali na przykład z Clear-Case lub SVN. Git idealnie nadaje się do prawidłowego i uporządkowanego zarządzania kodem źródłowym projektu, zwłaszcza gdy wielu programistów buduje i wykonuje zmiany w kodzie w obrębie jednej gałęzi.

Testowanie

Mając już przeszkolony zespół i kod w repozytorium, powinniśmy się zająć testami. Według niektórych osób to powinien być punkt pierwszy. Po ustaleniu wymagań dotyczących nowej funkcjonalności programiści powinni rozpocząć pisanie testów, które pozwolą automatycznie przetestować tę funkcję przed jej wdrożeniem. Jeśli funkcjonalność nie przejdzie testów, można wygenerować i wysłać raport, aby deweloper mógł jak najszybciej wprowadzić niezbędne zmiany w kodzie.

Połączenie wszystkiego w całość

Kolejnym etapem jest połączenie poszczególnych części w jeden element, dzięki którym jeszcze bardziej zbliżymy się do Continuous Development. Na początek powinniśmy spróbować połączyć repozytorium z narzędziem do integracji (opisany wyżej Jenkins). Sprawdzić, czy komunikacja działa poprawnie, na przykład poprzez dodanie zmian i sprawdzenie, czy dany commit wyświetla się prawidłowo w Jenkinsie.

Przepisanie instrukcji

Ostatnim, ale wcale nie mniej ważnym krokiem, jest przepisanie instrukcji kompilacji do narzędzi integracjnych. Dzięki temu następny krok zostanie zautomatyzowany. W skrócie wygląda to tak, że komendy, które wpisywaliśmy z klawiatury, teraz muszą zostać wywołane samoistnie, z użyciem skryptu lub instrukcji bezpośrednio napisanych w konfiguracji.


Warto postawić na Continuous Development

Prosty, czy nawet jedynie częściowo wdrożony ciągły proces rozwoju oprogramowania, przysparza wielu korzyści, pod warunkiem, że jego zastosowanie jest porządnie przemyślane i wykonane z należytą starannością. Odpowiednio dobrane narzędzia i ich połączenie pozwalają usprawnić proces tworzenia i testowania kodu. Ma to kluczowe znaczenie dla wydajności ciągłego rozwoju projektu.

Continuous Development to możliwość obserwowania przez użytkowników postępów we wdrażaniu zmian w czasie rzeczywistym i jednocześnie możliwość wyeliminowania procesu ręcznego śledzenia zmian. Rozwiązuje również problemy związane z codziennymi działaniami zespołu, który pracuje nad projektem, pozwalając na wprowadzenie niezbędnych poprawek po napotkaniu na błąd.

Szukasz więcej informacji na temat procesów składających się na Continuous Development? Napisz na cezary.irzykowski@ericsson.com, postaram się pomóc!


O autorze

Cezary Irzykowski to Senior Software Developer, który od 5 lat pracuje w Ericsson (z dziewięciomiesięczną przerwą). Zaczynał od Development Supportu (głównie integracja i automatyzacja). Aktualnie pracuje nad rozwijaniem zewnętrznych narzędzi, które wykorzystywane są do testowania funkcjonalności w 4G. Prywatnie zajmuje się zbieraniem retro konsol od Nintendo i oglądaniem dobrych filmów.