Powrót30 marca 2025

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

Clean codeJavaScript

matryoshka
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 early
3 */
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 request
10 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żenia if , 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?
  1. Słowo kluczowe else
    Zwykle, gdy słowo kluczowe else 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.
  2. 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.
v-shaped function
Przykład V-kształtnej funkcji
Czas na naprawę!
  1. 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.
  2. Gdy kod jest rozgałęziany przez jakieś warunki (np. para if-else), zredukuj jego rozgałęzienia do pojedynczego bloku if, 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ębie if.
./fixed.js
Kopiuj
1/**
2 * Pseudo fuction that demonstrates fixing the problem of not returning early
3 */
4function handleRequest(request) {
5 // ================== Guard Clauses ==================
6 if (request === null || request === undefined) {
7 console.log("Request is missing.");
8 return;
9 }
10
11 if (!request.isValid) {
12 console.log("Invalid request.");
13 return;
14 }
15 // ================== Guard Clauses ==================
16
17 // Branching conditions flatened and splited in managable chunks
18 if (!request.user.isAuthenticated) {
19 console.log("User not authenticated.");
20 return;
21 }
22
23 // Branching conditions flatened and splited in managable chunks
24 if (!request.user.hasPermission("admin")) {
25 console.log("User doesn't have permission.");
26 return;
27 }
28
29 // Process the request if all checks pass
30 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.
plen