Jak unikać "piekła zagnieżdżeń": Wzorzec wczesnego zwracania

Obraz autorstwa @juliakadel na Unsplash
Problem
Na początek, zobaczmy pseudo-funkcję, która wpadła w problem "piekła zagnieżdzeń"
./problematic.js
Kopiuj
1/**2 * Pseudo fuction that demonstrates problem of not returning early3 */4function handleRequest(request) {5 if (request !== null && request !== undefined) {6 if (request.isValid) {7 if (request.user.isAuthenticated) {8 if (request.user.hasPermission("admin")) {9 // Process the request10 console.log("Doing some magic with yout request...");11 } else {12 console.log("User doesn't have permission.");13 }14 } else {15 console.log("User not authenticated.");16 }17 } else {18 console.log("Invalid request.");19 }20 } else {21 console.log("Request is missing.");22 }23}24
Jakie problemy spostrzegamy?
- Kod jest nieliniowy, przez liczne rozgałęzienia jest on trudny do analizy.
- Wyrażenia
else
są w dużej odległości od wyrażeniaif
, utrudnia to to znalezienie powiązania między nimi. Sytuacji nie poprawia nawet kolorowanie nawiasów przez nasze IDE. - Refaktoryzacja jest bardzo trudna. Jeśli chcemy wyciąć fragment logiki i przenieść go w inne miejsce, możemy skończyć z wiszącymi nawiasami, które zepsują nasz kod. Albo, co gorsza, z nieoczekiwanymi błędami logicznymi wynikającymi z trudnego do śledzenia kodu.
Rozwiązanie
Wzorzec wczesnego zwracania.
Czym jest Wzorzec wczesnego zwracania?
Wzorzec wczesnego zwrotu, jak sama nazwa wskazuje, to sposób pisania funkcji/metod, które zwracają wynik tak szybko jak pozwalają na to warunki.
Jak określić, czy kod nie stosuje się do tego wzorca?
- Słowo kluczowe
else
Zwykle, gdy słowo kluczoweelse
pojawia się w naszym kodzie, oznacza to, że coś jest nie tak. Powinniśmy zastanowić się, czy jego użycie jest właściwym wyborem. - Funkcje w kształcie litery V
Kiedy lewa strona twojego kodu zaczyna tworzyć kształt litery V, oznacza to, że twój kod ma poważny problem z nadmiernym zagnieżdżaniem. Jeśli w końcu długość twojego kodu wzrośnie do setek, a nawet tysięcy linii, szybko zorientujesz się, że niemożliwe jest zarządzanie tym kodem w sposób efektywny.

Przykład V-kształtnej funkcji
Czas na naprawę!
- Zidentyfikuj "Guard Clauses"
Znajdź wszystkie warunki, które walidują parametry funkcji, sprawdź je jak najszybciej i zwróć wynik lub rzuć błąd, jeśli to konieczne na samym początku. - Gdy kod jest rozgałęziany przez jakieś warunki (np. para
if-else
), zredukuj jego rozgałęzienia do pojedynczego blokuif
, aby zapobiec nadmiernemu zagnieżdżaniu. Zachowaj "Happy Path" (ścieżkę, która najprawdopodobniej będzie wykonywana) na poziomie funkcji, bez zagnieżdżania w obrębieif
.
./fixed.js
Kopiuj
1/**2 * Pseudo fuction that demonstrates fixing the problem of not returning early3 */4function handleRequest(request) {5 // ================== Guard Clauses ==================6 if (request === null || request === undefined) {7 console.log("Request is missing.");8 return;9 }1011 if (!request.isValid) {12 console.log("Invalid request.");13 return;14 }15 // ================== Guard Clauses ==================1617 // Branching conditions flatened and splited in managable chunks18 if (!request.user.isAuthenticated) {19 console.log("User not authenticated.");20 return;21 }2223 // Branching conditions flatened and splited in managable chunks24 if (!request.user.hasPermission("admin")) {25 console.log("User doesn't have permission.");26 return;27 }2829 // Process the request if all checks pass30 console.log("Request processed.");31}32
Gotowe!
Podsumowanie
Korzyści z Wzorca wczesnego zwracania:
- Kod łatwiejszy do analizy: Kod jest liniowy, nie ma trudnych do śledzenia zagnieżdżeń.
- Kod łatwiejszy do debugowania: Każdy z warunków brzegowych może być łatwo debatowany z osobna, z powodu braku głębokich zagnieżdżeń.
- Kod łatwiejszy do refaktoryzacji: Wystarczy wyciąć kod, który chcesz, i nie martwić się o łączenie nawiasów.