
/ 18.11.2024
Pracując w stylu outside-in development chcemy jak najszybciej przedstawić funkcjonalność, która jest najbliższa interesariuszom, najczęściej chodzi jakąś makietę UI, pokazującą jak dana funkcjonalność będzie wyglądać z punktu widzenia użytkownika końcowego. Mimo że nie ma tam jeszcze zaimplementowanej domeny, czy bazy danych możemy przedstawić tzw. Walking Skeleton, zawierający podstawowe komponenty systemu. Aby można było to zaprezentować w środowisku stagingowym, a nie produkcyjnym, wykorzystujemy tak zwane feature toggles/flags, czyli przełączniki funkcji.
Jak wprowadzić możliwość udostępniania funkcji różnym grupom użytkowników bez wdrażania? Czy istnieje sposób na skuteczne testowanie funkcji w środowisku produkcyjnym i natychmiastowe wycofywanie ich w razie potrzeby? Odpowiemy na te pytania, omawiając flagi funkcji lub czasami określane jako przełączniki funkcji.
Spis treści
Przełączniki funkcji, znane również jako flagi, to technika, która pozwala programistom włączać lub wyłączać określone funkcje w aplikacjach bez konieczności wdrażania nowego kodu. Można to zilustrować przykładem, kiedy włączasz światło w domu, nie musisz za każdym razem zmieniać okablowania domu, wystarczy użyć przełącznika i gotowe, a jeśli chcesz je wyłączyć, naciskasz przełącznik ponownie, a światło zgaśnie. Dokładnie to samo dotyczy flag funkcji, pozwalają na wydanie nowej funkcji w oprogramowaniu lub platformie bez przestojów, a zatem można to zrobić w dowolnym momencie, w tym w godzinach pracy.
Oznacza, że taki przełącznik pozwala wybrać ścieżkę w kodzie w sposób dynamiczny, czy to w momencie budowania, czy uruchamiania produktu, albo w środowisku wykonawczym. Jest to użycie “if” w kodzie, które umożliwia zmianę zachowania kodu, bez jego przepisywania i przetwarzania wszystkiego w potoku wdrażania.
Jednocześnie ta technika pozwala dużo częściej integrować kod, ponieważ nie wymaga tego, by tkwić na swojej gałęzi funkcji przez kilka tygodni i czekać aż funkcja zostanie w pełni skończona, zanim się zintegruje z resztą kodu. Można niedokończone funkcjonalności łączyć z całą resztą kodu, wrzucać na “MAIN” – główną gałąź kontroli wersji i ten niedokończony kod wrzucić na produkcję (oczywiście tak, żeby tej produkcji nie zepsuć ?).
Flagi funkcji umożliwiają zespołom kontrolę nad wydawaniem funkcji, przeprowadzaniem testów A/B, zarządzaniu długiem technicznym i zapewnieniu płynniejszego wdrożenia. Poniżej główne zalety flag funkcji w kodzie:
1. Mniejsze ryzyko wdrożenia
Flagi funkcji dają poczucie bezpieczeństwa psychologicznego, ponieważ wiemy, że w każdej chwili mogę ten przełącznik wyłączyć i tej funkcjonalności nie będzie widział. Zyskujemy odwagę, żeby ten kod dużo częściej integrować i stopniowo wdrażać oraz eksperymentować z różnymi wersjami funkcji.
2. Szybsze dostarczanie oprogramowania
Przełączniki umożliwiają testowanie nowych funkcji w środowisku produkcyjnym bez udostępniania ich wszystkim użytkownikom, niezależnie od głównej bazy kodu.
3. Szybsze uzyskanie informacji zwrotnych
Dzięki flagom funkcji można zbierać wewnętrzny feedback od moich użytkowników z firmy, nanieść zmiany na niedokończonej funkcjonalności.
4. Ulepszony proces rozwoju
Przełączniki funkcji pomagają segmentować użytkowników na podstawie różnych atrybutów, tworzyć i porównywać różne warianty funkcji oraz mierzyć ich wyniki, pomagając zoptymalizować wrażenia użytkownika i cele biznesowe.
5. Kontrolowanie i monitorowanie
Flagi określają, kto może uzyskiwać dostęp do funkcji oraz zbierania opinii i danych przed udostępnieniem ich wszystkim. można również używać do stopniowego udostępniania funkcji podzbiorowi użytkowników oraz monitorowania ich wydajności i wpływu.
6. Szybsze zmiany zachowań, bez konieczności zmian w kodzie źródłowym.
Przełączniki funkcji pozwalają w dowolnym momencie na zmianę zachowania systemu. Mogą wymagać jedynie ponownego deploymentu, a nawet i ten krok można pominąć w przypadku np. wykorzystania Spring Cloud Config, który pozwoli na zmianę konfiguracji aplikacji, bez negatywnego wpływu na jej dostępność.
Przełączniki funkcji według Martina Fowlera można sklasyfikować w następujący sposób:
W Javie istnieją różne podejścia do wdrażania przełączania funkcji, w tym przełączniki istniejące w pliku konfiguracyjnym, oparte na bazie danych lub korzystanie z zewnętrznych usług zarządzania nimi. W niektórych przypadkach istnieje dodatkowa aplikacja interfejsu użytkownika z listą funkcji i „przełącznikiem” obok nich. Jeśli flaga znajduje się w pozycji „on”, funkcja będzie dostępna w docelowej aplikacji. Teraz omówimy zalety i wady tych podejść oraz kiedy ich używać.
W tym podejściu przełączniki funkcji są zdefiniowane w plikach konfiguracyjnych, takich jak właściwości, YAML lub JSON. Aplikacja odczytuje te pliki konfiguracyjne w czasie wykonywania i włącza lub wyłącza funkcje na podstawie wartości przełączników.
Zalety:
Wady:
Kiedy używać: Przełączniki oparte na konfiguracji są odpowiednie, gdy potrzebujesz prostego i statycznego sposobu kontrolowania dostępności funkcji, który nie wymaga zmian w czasie wykonywania ani brania pod uwagę kontekstu.
W tym podejściu przełączniki funkcji są przechowywane i zarządzane w bazie danych lub scentralizowanym systemie zarządzania konfiguracją. Aplikacja wysyła zapytanie do bazy danych lub odczytuje konfigurację w czasie wykonywania, aby określić, które funkcje powinny być włączone lub wyłączone.
Zalety:
Wady:
Kiedy używać: Przełączniki oparte na bazie danych są przydatne, gdy potrzebna jest dynamiczna kontrola nad dostępnością funkcji, wymagają czynników kontekstowych i chcą uniknąć ponownego uruchamiania aplikacji lub wdrażania kodu w celu modyfikacji przełączników. Są one szczególnie korzystne w aplikacjach na dużą skalę lub systemach rozproszonych.
Dostępnych jest kilka rozwiązań do zarządzania flagami funkcji. Istnieje kilka bibliotek SDK dostępnych w Javie, które można wykorzystać do implementacji przełączników funkcji. Biblioteki te oferują różne funkcje, opcje integracji i możliwości zarządzania. Wybierając bibliotekę SDK dla swojego projektu Java, należy wziąć pod uwagę takie czynniki, jak kompatybilność frameworka, wymagania dotyczące zarządzania funkcjami, łatwość użytkowania, czy wsparcie społeczności, aby wybrać tę, która najlepiej odpowiada Twoim potrzebom. Niektóre z popularnych narzędzi to:
Plusy:
Minusy:
FF4J (Feature Flipping for Java)
Plusy:
Wady:
Plusy:
Minusy:
Plusy:
Minusy:
Plusy
Minusy
W zależności od potrzeb aplikacji można łączyć powyższe podejścia do wdrożenia przełączników funkcji. Ostatecznie wybór sposobu implementacji flagi w kodzie zależy od takich czynników, jak złożoność aplikacji, wymagany poziom kontroli, potrzeba modyfikacji w czasie wykonywania oraz kompromisy, które chcemy wprowadzić w odniesieniu do zmian kodu, wdrożeń i wydajności.
Opcja warunkowa “if” pozwala rozdzielić deployment od releasu ponieważ za tym “if” będzie się kryła informacja, kto tak naprawdę będzie widział daną funkcjonalność, a komu to ukryjemy.
Dlaczego jest to ważne zrozumieć różnicę między wdrożeniem a wydaniem projektu?
Powyższe dwie koncepcje różnią się od siebie.
Deployment, czyli wdrożenie to – wydarzenie techniczne, gdy wprowadzamy zmiany w oprogramowaniu i przerzucamy kod docelowo na środowisko produkcyjne, możemy to wypuścić w dowolnym momencie.
Release , czyli wydanie to ekscytujacy moment, w którym te nowe funkcje stają się dostępne dla użytkowników końcowych. Tutaj flagi funkcji pozwalają kontrolować wydanie tej nowej funkcji na platformie wdrożeniowej, czyli wybieramy, kto będzie mógł zobaczyć nowe wersje oprogramowania.
Podsumowując, przełączniki funkcji rozdzielają te dwie funkcje, codziennie możemy wdrażać nowe oprogramowanie, ale teraz możemy podejmować decyzje komu i kiedy pokazujemy nowe wersje.
Flagowanie funkcji umożliwia sprawne wykonywanie CI/CD, pozwalając programistom na częste scalanie ich pracy do współdzielonego repozytorium, bez obawy o zepsucie czegokolwiek lub spowodowanie, że użytkownik końcowy uzyska dostęp do niedokończonych funkcji.
Przełączniki dają kontrolę nad zachowaniem aplikacji lub platformy, co oznacza, że cały kod jest zawsze wdrażany, ale niektóre gałęzie kodu można testować dla nowych funkcji zmodyfikowanego zachowania, lub go wyłączyć, dopóki nie zostanie włączona flaga. Z kolei za każdym razem, gdy włączasz przełącznik, wtedy ten kod jest dostępny dla użytkowników.
To zależy od strategii testowania, czy to testy jednostkowe, czy manualne itp. Ważne jest, żeby nie testować każdej możliwej kombinacji flagi funkcji, a przeprowadzać testy tam, gdzie jest prawdopodobieństwo, że coś się wydarzy.
Test zakończy się też niepowodzeniem, jeśli funkcja jest obecnie wyłączona. Dlatego najlepiej jest usunąć testy, z głównego przebiegu procesu, dopóki funkcja nie zostanie formalnie wydana. Do tego czasu najlepiej uruchamiać testy tylko wtedy, gdy jest to wymagane i jeśli funkcja została włączona. Po ostatecznym wydaniu funkcji testy można dodać do głównego przebiegu testu.
Sposób zarządzania przełącznikami funkcji pokazuje jakość organizacji. Nieusuwanie flag funkcji po ich zamierzonym użyciu może prowadzić do kilku problemów:
Aby uniknąć tych problemów, konieczne jest rygor inżynierski i trzymanie się ustalonego zestawu praktyk w celu usuwania flag funkcji, gdy spełnią one swoje zadanie. Proces ten powinien obejmować regularne przeglądy kodu, inicjatywy czyszczenia flag i dokumentację, aby zapewnić, że flagi są odpowiednio zarządzane przez cały cykl rozwoju.
Co się może stać, gdy błędnie wykorzystamy feature flagi? Firma może stracić milliony dolarów dochodu. Tak jak firma Knights Capital, która straciła 460 milionów dolarów w ciągu 28 minut ?. Więcej o tym przypadku możesz przeczytać tutaj.
Aby zmaksymalizować korzyści płynące z przełączania funkcji, jednocześnie minimalizując wyzwania i ryzyko, należy zdefiniować cykl życia przełączania funkcji i odpowiednio zarządzać udokumentowanym systemem przełączania funkcji.
Z pewnością flagi funkcji mogą przynieść wiele korzyści, taki jak rozwój oparty na użytkownikach czy zmniejszanie ryzyka związanego z większymi wydaniami.
Najważniejsze jest jednak to, by pamiętać, że dobrze przygotowane flagi funkcji muszą być proste w utrzymaniu jako prosty kod i wartości konfiguracyjne. Dlatego zawsze warto się zastanowić nad tym, jaką złożoność wprowadzamy w kod i czy można osiągnąć ten sam wynik w prostszy sposób.
/ Co u nas słychać