Czy zastanawiałeś się kiedyś, czy Twój kod nie jest przepełniony booleanami? W tym wpisie wyjaśniamy, czym jest „boolean obsession”, jak jej unikać i poprawić czytelność oraz elastyczność kodu.
Czym jest Boolean Obsession?
„Boolean obsession” to termin określający nadmierne korzystanie z typów boolean (prawda/fałsz) w kodzie. Chociaż booleany są wygodnym i często prostym sposobem reprezentowania stanu, ich nadmiar może prowadzić do problemów z czytelnością i zrozumieniem kodu. Kiedy kod zaczyna być zbyt zależny od wartości logicznych, staje się mniej intuicyjny, trudniejszy do utrzymania, a także mniej elastyczny na przyszłe zmiany.
Gdzie zazwyczaj pojawia się problem?
Najczęściej spotykane miejsca, w których boolean obsession może się pojawić to:
- Parametry metod: Gdy funkcje przyjmują wiele parametrów boolean, kod staje się nieczytelny, ponieważ nie zawsze jest jasne, co dany parametr oznacza. To znaczy wiadomo, ale często zachodzi potrzeba by sprawdzić różne warianty parametrów. Dodatkowo taka metoda tych parametrów może dostawać coraz więcej.
- Wewnętrzne flagi w klasach i obiektach: Wzrost liczby flag w klasach i obiektach może spowodować rozrost logiki warunkowej, co utrudnia rozumienie tego, co się dzieje w programie.
- Rozbudowane instrukcje warunkowe: Gdy kod zaczyna zawierać wielopoziomowe warunki oparte na wielu booleanach, debugowanie i śledzenie logiki staje się bardziej skomplikowane. Jedyny ratunek to bardzo dobrze pokrycie tej pokrętnej logiki w testach.
Przykłady
Zbyt wiele parametrów w funkcji
Myślę, że pierwszy przykład świetnie obrazuje problem. Mamy tutaj dwie flagi isAdmin
oraz isGuest
. W swojej karierze wiele razy widziałem podobny kod. Problem jaki tutaj się pojawia trudne do ogarnięcia instrukcje warunkowe (ifologia), którą mają sprawdzić dokłada rodzaj użytkownika. Nawet nie chcę wiedzieć jak ta funkcja by wygląda gdyby trzeba było dodać więcej typów użytkowników.
function createUser(name: string, isAdmin: boolean, isGuest: boolean) { if (isAdmin && !isGuest) { console.log(`${name} jest adminem.`); } else if (!isAdmin && isGuest) { console.log(`${name} jest gościem.`); } else { console.log(`${name} jest zwykłym użytkownikiem.`); } }
Różne stany w API (i nie tylko)
Innym, ciekawych przykładem z jakim ostatnio miałem styczność, to odpowiedź z API. W jednym z endpointów było pole isOnline
, które przyjmowało dwie wartości true
lub false
. Wszystko wyglądało całkiem dobrze, do momentu w którym nastąpiła integracja z innym systemem, który nie potrafił określić czy użytkownik jest on-line. Co zrobili programiści by nie psuć kontraktu? Dodali null
jako trzeci stan.
isOnline = boolean | null;
To teraz cytując klasyka, „biorę od państwa po 200 zł i pytam jak to będzie wyglądało jeśli trzeba będzie dodać dwa stany”?
Dobra wiadomość jest taka, że da się prosto naprawić.
Jak unikać Boolean Obsession?
- Enumy i typy wyliczeniowe: Zamiast booleanów, używaj bardziej opisowych typów, które lepiej wyrażają możliwe stany.
- Obiekty konfiguracyjne: Zamiast przekazywać wiele booleanów, lepiej jest używać obiektu konfiguracji, który opisuje więcej szczegółów w bardziej zrozumiały sposób. To ogólnie dobra praktyka aby funkcje miały jak najmniej parametrów. Jeżeli jest ich dużo (powyżej 3), to oznacza, że coś poszło mocno nie tak.
- Klarowne nazewnictwo: Zadbaj o to, aby zmienne boolean miały nazwy dokładnie opisujące ich rolę, np. zamiast
isActive
, użyjuserHasActiveSubscription
, co od razu daje pełniejszy kontekst. W tym przypadkuisActive
może sugerować czy dany użytkownik jest zalogowany w systemie. - Unikaj zagnieżdżania logiki warunkowej: Gdy warunki stają się zbyt złożone, rozważ refaktoryzację kodu, np. dzieląc logikę na mniejsze funkcje.
Jak można poprawić przytoczone wcześniej przykłady?
Pierwszy przykład można zrefaktoryzować w następujący sposób – booleana zamienić zmienną role
.
function createUser(name: string, role: 'admin' | 'guest') {}
W przypadku odpowiedzi API można zrobić podobnie.
status = 'online' | 'offline' | 'unknown';
Podsumowanie
Boolean obsession to jeden z tych ukrytych problemów, które mogą sprawić, że kod staje się trudniejszy do zrozumienia, rozbudowy i utrzymania. Co więcej, bezmyślne brnięcie w to może skutkować tworzeniem coraz większego długu technologicznego.
Używając enumów, obiektów konfiguracyjnych i dobrego nazewnictwa, możemy zwiększyć czytelność kodu oraz ułatwić jego przyszłe rozwijanie.
Dlatego zawsze przed użyciem booleana warto zadać sobie pytanie czy istnieje szansa, że może pojawić się trzecia (i kolejne) opcje.