Wprowadzenie dodatkowych zmiennych lokalnych jako zamienników komentarzy

12

Czy to dobry styl, aby używać dodatkowych, zbędnych technicznie zmiennych lokalnych, aby opisać, co się dzieje?

Na przykład:

bool easyUnderstandableIsTrue = (/* rather cryptic boolean expessions */);

if(easyUnderstandableIsTrue)
{
    // ...
}

Jeśli chodzi o narzut techniczny, oczekuję, że kompilator zoptymalizuje tę dodatkową linię. Ale czy jest to uważane za niepotrzebny wzdęcie kodu? Moim zdaniem zmniejsza to ryzyko nieaktualnych komentarzy.

BooleanAssange
źródło
10
„Czy to dobry styl, aby używać dodatkowych, zbędnych technicznie zmiennych lokalnych, aby opisać, co się dzieje?”. Tak. Naprawdę niewiele można tu powiedzieć.
David Arno,
3
Uważam, że taki styl (tj. Używanie wielu zmiennych pośrednich o nazwach opisowych) jest bardzo pomocny podczas czytania mojego kodu później. Oczywiście możesz pisać złożone wyrażenia i zapisywać kilka nazw, nie wprowadzając zmiennych pośrednich, ale dlaczego miałbyś chcieć? Czytanie kodu może być sporym wyzwaniem, nawet jeśli jest ono stosunkowo dobrze napisane, więc nie sądzę, że niepotrzebne komplikowanie go jest rozsądną drogą.
Mael
Uważam, że w katalogu refaktoryzacji Martina Fowlera nazywa się to Consolidate Expression Expression .
Brandin

Odpowiedzi:

16

Jaki jest koszt posiadania dodatkowej zmiennej? W większości języków żaden, zarówno w językach skompilowanych, jak i interpretowanych.

Jaka jest z tego korzyść?

  • Podobnie jak wyodrębnianie tajemniczego wyrażenia logicznego do oddzielnej metody, zmniejszasz ryzyko powielonego kodu , ale nieco mniej niż w przypadku osobnej metody. Jeśli wyrażenie warunkowe zostanie ponownie użyte w samej metodzie, będziesz mógł ponownie użyć zmiennej; jeśli wyrażenie pojawi się w innej metodzie, nie zrobisz tego.

    Zauważ, że jeśli twój język programowania nie pozwala na niezmienne zmienne lokalne lub masz sposób na wymuszenie, ze względu na styl, że żadna ze zmiennych nie zostanie ponownie przypisana, taka refaktoryzacja może być ryzykowna w dłuższej perspektywie. Jeśli wartość zmiennej zostanie zmieniona, bardzo trudno będzie zrozumieć kod.

  • Jesteś zmniejszając ryzyko dokumentacja coraz zsynchronizowany z kodem . Programiści zwykle aktualizują nazwy zmiennych i metod łatwiej niż komentarze .¹ Dlatego nie jest niczym niezwykłym, aby zobaczyć kod taki jak:

    // Find if the user is an actual author in order to allow her to edit the message.
    if (currentUser.isAdministrator || (message.author == currentUser && !message.locked))

Wyrażenie prawdopodobnie zaczęło się od if (message.author == currentUser), a następnie ewoluowało, aby obsługiwać przypadki zablokowanych wiadomości i administratorów, którzy nie muszą być autorami i nie dbają o zablokowane rzeczy; jednak komentarz nie odzwierciedla żadnej z tych zmian.

Obie korzyści nie są szczególnie ważne, ale biorąc pod uwagę niski koszt dodatkowych zmiennych, naprawdę możesz rozważyć ich użycie.

Zauważ, że jeśli twoje wyrażenie logiczne stanie się zbyt złożone: ²

  • Wyodrębnij go do osobnej metody i:
  • Przebuduj go na wiele prostych wyrażeń boolowskich.

Powyższy przykład wygląda następująco:

class Message
{
    ...
    public boolean canBeEditedBy(User user)
    {
        ...
        if (user.isAdministrator) {
            return true;
        }

        return this.author == user && !this.locked;
    }
}

...
if (message.canBeEditedBy(currentUser)) // See? Much more readable now!
{
    ...
}

¹ Źródło: moja własna obserwacja moich rówieśników tworzących głównie oprogramowanie biznesowe; YMMV. Prawdziwe badania mogą pokazać różne wyniki. Osobiście przypuszczam, że gdy programiści czytają kod, skupiają się na kodzie , a komentarze są dokumentacją, a nie kodem; dlatego zwykle nie czytają komentarzy, więc trudno byłoby oczekiwać, że je zaktualizują.

² Zbyt skomplikowany próg jest definiowany za pomocą prostej formuły: jeśli połowa programistów, którzy sprawdzają Twój kod, wyrażą zamiar zamordowania cię, próg zostanie osiągnięty. Powyższe wyrażenie boolowskie jest na tyle proste, że wymaga refaktoryzacji; jednak cztery części z rzędu if ((a && b) || (c && d))czynią go potencjalnie refaktoryzacyjnym. Zauważ, że jeśli wyrażenie jest płaskie, liczba części jest w większości nieistotna: if (a || b || c || d || ... || z)jest wystarczająco czytelna.

Arseni Mourzenko
źródło