Po pierwsze, w tym pytaniu chciałbym trzymać się z dala od polemiki dotyczącej tego, czy komentowanie kodu źródłowego jest dobre czy złe. Po prostu staram się lepiej zrozumieć, co ludzie mają na myśli, gdy mówią o komentarzach, które mówią DLACZEGO, CO I JAK.
Często widzimy wytyczne takie jak „Komentarze powinny WIEDZIEĆ DLACZEGO; sam kod powinien WIEDZIEĆ JAK”. Łatwo jest zgodzić się z tym stwierdzeniem na poziomie abstrakcyjnym. Jednak ludzie zwykle upuszczają to jak dogmat i wychodzą z pokoju bez dalszych wyjaśnień. Widziałem to używane w tak wielu różnych miejscach i kontekstach, że wygląda na to, że ludzie mogą zgodzić się na hasło, ale wydaje się, że mówią całkowicie o różnych sprawach.
Wróćmy zatem do pytania: jeśli komentarze powinny WAM powiedzieć, DLACZEGO, o co DLACZEGO mówimy? Czy to jest powód, dla którego ten fragment kodu istnieje? Czy to właśnie powinien robić ten fragment kodu? Byłbym naprawdę wdzięczny, gdyby ktoś mógł podać jasne wyjaśnienie, a następnie dodać kilka dobrych przykładów (złe przykłady nie są tak naprawdę potrzebne, ale można je dodać dla kontrastu).
Istnieje wiele pytań na temat tego, czy komentarze są dobre, czy złe, ale nikt nie odpowiada na konkretne pytanie, jakie są dobre przykłady komentarzy, które mówią DLACZEGO.
źródło
There are many questions on whether comments are good or bad, but no one that addresses the specific question of what are good examples of comments that tell you WHY.
Jeśli wszyscy podają prawidłowy przykład, wszystkie są poprawnymi odpowiedziami. Format tej witryny ma ułatwić proces pytań i odpowiedzi, w którym nie wszystkie odpowiedzi są sobie równe.Odpowiedzi:
Najczęstszym i najbardziej charakterystycznym przykładem są komentarze dotyczące różnych obejść. Na przykład ten:
Na pewno znajdziesz więcej przykładów w źródłach Git i Linux; oba projekty starają się przestrzegać tej zasady.
Polecam również przestrzeganie tej zasady jeszcze bardziej surowo z dziennikami zatwierdzeń . W przypadku komentarzy do kodu może się zdarzyć, że naprawisz kod, ale zapomnij zaktualizować komentarz. Ilość kodu w zwykłym projekcie gwarantuje, że nastąpi to wcześniej czy później. Z drugiej strony dziennik zatwierdzeń jest powiązany z konkretną zmianą i można go przywołać za pomocą funkcji „adnotacji” / „obwiniania” systemu kontroli wersji. Znowu Git i Linux mają kilka dobrych przykładów.
Spójrz np. Na to zatwierdzenie . (nie kopiowanie tutaj, jest za długie). Ma cztery akapity zajmujące prawie całą stronę (i nieco przesadzone) opisujące, co dokładnie było nie tak i dlaczego było złe, a następnie ciągnie się i modyfikuje wszystkie duże SZEŚĆ linii. Używają takich komentarzy do dwóch celów:
(uwaga: wymyślenie tych dwóch przykładów zajęło mi co najwyżej 10 minut losowego przeglądania repozytorium git, więc z pewnością łatwiej byłoby znaleźć tam więcej)
źródło
Komentarz, który wyjaśnia, dlaczego wyjaśnia przyczyny kodu - na przykład:
Komentarz, który wyjaśnia, jak wyjaśnia działanie kodu.
Różnica polega na tym, że opiekun może spojrzeć na pierwszy i powiedzieć: „Och, więc to może być nieaktualne!” W drugim przypadku wspomniany opiekun ma komentarz, który nie mówi niczego, czego sam kod nie ujawnia (przy założeniu dobrych nazw zmiennych).
Oto prawdziwy przykład, dlaczego komentarz, z jakiegoś kodu iOS, nad którym pracowałem, gdzie potrzebowaliśmy uzyskać adres bramy (lub rozsądne przypuszczenie). Mogłem po prostu zostawić komentarze, które mówiły takie rzeczy jak „Zainicjuj gniazdo odbiorcze”, ale to tylko powiedziałoby opiekunowi (lub mnie w przyszłości), co się dzieje, a nie dlaczego musiałem robić tę dziwną kludge, aby uzyskać adres bramy w pierwsze miejsce.
źródło
Chciałbym rozpocząć swoją odpowiedź cytatem napisanym przez Jeffa Atwooda w jego blogu Kod mówi wam jak, komentarze mówią wam dlaczego :
Stwierdza również, że:
Całkowicie się zgadzam i w tym miejscu muszę dodać, że zanim zacznę upraszczać kod, sprawię, że kod będzie działał, a następnie zacznę refaktoryzację. Więc podczas pierwszego uruchomienia przed refaktoryzacją dodajmy, dlaczego komentarze bardzo pomagają.
Na przykład, jeśli używasz 3 zagnieżdżonych pętli z dwuwymiarowymi hashtabami, aby wypełnić tabelę dni tygodnia podczas analizowania danych, bardzo łatwo jest stracić kontrolę nad tym, co zostało zrobione przez kogoś lub nawet przez ciebie, jeśli nie spojrzysz na to przez kilka tygodni i nagle dokonujesz refaktoryzacji.
Górna część jest przykładem działania 3 zagnieżdżonych pętli przed refaktoryzacją.
Wyjaśnienie niektórych warunków rozgałęzienia może pomóc w lepszym zrozumieniu kodu dzięki temu, co myślałeś w tym procesie:
Nawet prosty i oczywisty kod działa dobrze z komentarzami. Żeby było trochę bardziej oczywiste, bardziej zrozumiałe lub łatwiejsze do zrozumienia dla kolegów, a nawet dla ciebie w utrzymaniu oprogramowania.
Pewnie xp twierdzi, że ma kod, który sam się wyjaśnia, ale czy komentarz w jednym wierszu boli?
Uważam również, że następujące zasady z tego bloga są bardzo pomocne:
Każdy, kto musi wrócić do własnego kodu, kogoś innego, a nawet kodu starszego, wie, że może to być ból głowy. Więc zamiast być leniwym lub próbować być uber-koderem, nie komentując niczego lub bardzo mało, dlaczego nie uczynić swojego własnego lub jakiegoś biednego robala, który musi zachować twój kod, przyszłe życie o wiele łatwiej, przestrzegając podanych zasad.
Również wiele dokonanych decyzji programistycznych jest wątpliwych podczas przeglądów i nie zawsze jest jasne, dlaczego niektóre części zostały napisane tak, jak były, nawet jeśli niektóre sekcje kodu są niezbędne dla działania programu z powodu poważnego błędu wykrytego, ponieważ kod był używany przez lata . Aby nie zanudzić was wszystkich tl; dr zamknij ostatnią cytatem z acmqueue :
źródło
int directionCode = (x > oldX) ? DIRECTIONCODE_RIGHT : (x > oldX) ? DIRECTIONCODE_LEFT : DIRECTIONCODE_NONE;
jest błąd. Z pewnością powinno być... (x < oldX) ? DIRECTIONCODE_LEFT : DIRECTIONCODE_NONE;
. Dobre pomysły na komentarze - zły kod.Staram się redukować komentarze do odwołań, w których określona funkcjonalność / kod jest wyjaśniona dokładniej, lub wyjaśnić, dlaczego wybrano określony sposób programowania.
Biorąc pod uwagę, że inni programiści o podobnych umiejętnościach używają lub czytają Twój kod, ważne jest, aby skomentować, jeśli używasz innego niż oczekiwano sposobu osiągnięcia czegoś. Możesz więc w komentarzu wyjaśnić, dlaczego wybierasz ten sposób.
Na przykład, jeśli możesz użyć dwóch różnych czujników na urządzeniu z Androidem, a jeden z nich nie odpowiada Twoim potrzebom, możesz w komentarzu wyjaśnić, dlaczego wybrałeś drugi.
Zatem „dlaczego” powinno uzasadniać dokonane wybory.
źródło
Komentarze powinny informować o tym, czego nie zawiera kod, niekoniecznie określany przez DLACZEGO , JAK i CO . Jeśli masz dobre nazwiska i dobrze określone funkcje, to całkiem możliwe, że kod dokładnie powie ci, co się dzieje. Na przykład:
Ten kod naprawdę nie wymaga komentarzy. Nazwy funkcji i typów ułatwiają ich zrozumienie.
Czasami jednak stworzenie płynnego kodu takiego jak powyższy może być trudne lub niemożliwe. Na przykład następny fragment kodu służy do znalezienia statystycznie losowego punktu na kuli. Matematyka jest dość nieprzejrzysta, więc komentarz z linkiem do objaśnienia ma pomóc WIEDZIEĆ, jak działa. Można to zawrzeć w funkcji, która mówi CO robi bez potrzeby komentowania, jeśli jest potrzebna więcej niż jeden raz, w przeciwnym razie tytuł linku również pomaga w tym dziale.
Innym przykładem, gdy komentarze mówią, czego nie robi kod, jest wyjaśnienie decyzji. W następnym przykładzie kod nie blokuje zmiennej nie-lokalnej w wątku kodu. Jest ku temu powód, a komentarz wyjaśnia DLACZEGO . Bez komentarza może to zostać uznane za błąd lub nawet nie zostać zauważone.
Być może można by usprawnić stwierdzenie, dlaczego losowy obiekt nie jest tworzony w pierwszej kolejności w pętli równoległej. Jeśli nie ma żadnego powodu, może również sprawić, że ktoś przyjdzie i zda sobie sprawę, że cały pomysł jest głupi i jest dobrym miejscem do refaktoryzacji.
źródło
WriteText
zamiast//
?Pomocne może być rozpoznanie różnych rodzajów „dlaczego” - w szczególności:
Powody, dla których kod, który wydaje się zbyt skomplikowany, nie działałby, gdyby został uproszczony (np. Pozornie zbędny typecast może być konieczny, aby zapewnić działanie kodu w niektórych przypadkach narożnych).
Powody, dla których pewna szczególna prosta operacja, która wydaje się niebezpieczna, jest w rzeczywistości bezpieczna (np. „Nasza procedura pobierania danych zgłasza, że element fikcyjny za ostatnim jest mniejszy niż cokolwiek innego, a element później jest większy; każdy element, który powinien zostać posortowany przed drugim, w spójnej kolejności rosnącej lub malejącej, będzie miał co najmniej jeszcze jeden (prawdopodobnie obojętny) element następujący po nim ”).
W wielu przypadkach komentarz drugiego typu w jednej części kodu może „pasować” do komentarza pierwszego typu w innym (np. „Chociaż wydaje się, że ta sekwencja operacji może być uproszczona, procedura Fitza opiera się na Wongle nie jest Woozled, dopóki Bandersnatch nie zostanie zlikwidowany. ")
źródło
Nie zapominaj, że pisząc program, nie piszesz tylko losowo, robisz to, ponieważ masz model tego, czego chcesz , czy to w oficjalnym dokumencie, czy tylko w twojej głowie. Rzeczy w twojej głowie są tak samo prawdziwe jak oprogramowanie / dane w komputerze (i równie dobrze mogą zawierać błędy).
Ktoś czytający Twój kod może nie mieć tego modelu w głowie, więc komentarze mogą mu powiedzieć, co to był model i jak kod się z nim odnosi. Myślę, że to właśnie oznacza „dlaczego”. Z pewnością dobrze jest, aby sam kod był jak najbardziej zrozumiały, ale to nie zawsze jest wystarczająco dobre. Przykład:
Ponadto model zmienia się w czasie i zmiany te należy przenieść do kodu. Komentarze muszą więc nie tylko powiedzieć „dlaczego” coś jest w kodzie, ale równie ważne, jak to zmienić w odpowiedzi na przewidywane zmiany modelu. Przykład:
Myślę, że cel komentarzy jest czasem zaniedbywany.
źródło
Nie wszystkie moje komentarze są typu „dlaczego”, ale wiele z nich jest.
Oto przykłady z jednego pliku źródłowego (Delphi):
Zauważ, że (my) dlaczego komentarze zwykle poprzedzają kod, który to zrobi (stąd kończą się dwukropkiem).
Mam kilka komentarzy wyjaśniających tylko to, co się dzieje, np. Gdy proces ma wiele kroków, które mają logiczne grupowanie (a kod nie jest refaktoryzowany, aby pokazać to automatycznie), skomentuję:
źródło
Rozumiem DLACZEGO powód, dla którego robisz coś w możliwie dziwny lub może nielogiczny sposób, z uwagi na okoliczności, które tego wymagają. JAK można zobaczyć w samym kodzie, bez względu na to, jak dziwne to jest, nawet jeśli kod nie ma „sens”. CO jest prawdopodobnie najlepiej powiedziano na początku dokumentacji klasy / funkcji. To pozostawia Cię z dodaniem DLACZEGO , gdzie wyjaśnisz wszystko, co nie jest zawarte w JAK i CO, a także szczególne sposoby, które musisz podjąć z powodów niezależnych od ciebie.
Oczywiście nie zawsze tak jest poza krajem jednorożców i tęcz ...
W JAKI SPOSÓB:
CO:
DLACZEGO:
źródło
critters.dance()
, to komentarz po prostu powtarza to, co oczywiste, a „Nie mogliśmy zmusić go do działania w inny sposób, który próbowaliśmy” jest całkowicie nieprzydatny. Ponadto powiedzenie „wywołamy metodę dla każdego obiektu” bardzo wyraźnie powtarza ten kod.Nauczyłem się ZAWSZE pisać komentarze w plikach nagłówkowych C ++ (ponieważ nie zawsze jest jasne, CO robi funkcja, chociaż nazwa daje dobrą wskazówkę), zwłaszcza jeśli przekazujesz API innym programistom lub używasz narzędzia do autodoc, takiego jak doxygen.
Więc dla mnie typowy komentarz wygląda jak
Jedynym razem, kiedy użyłem DLACZEGO komentarzy, są rzeczy trudne do uchwycenia, a czasem nawet dla programisty, takie jak „NIE DOTKNIJ TEGO! Ponieważ ...” lub „PROGRAM ZOSTANIE ZAWIESZONY, JEŚLI LINIA JEST USUNIĘTA ...”
Obejścia, hacki i dziwne zachowania kwalifikują się do DLACZEGO kryteriów w moich oczach ...
Bardzo dobrym, a nawet przezabawnym przykładem jest to „obejście” jakiegoś pomieszanego kodu napisanego przez osobę o imieniu Richard, ktoś inny go zawinął i wyjaśnił dlaczego w komentarzach ... https://stackoverflow.com/a/184673/979785
Niestety zdarza się, że jesteś zmuszony owinąć byka ****, ponieważ nie możesz dotknąć oryginału albo dlatego, że „zawsze tak było”, albo nie masz dostępu, albo… no cóż, nie mam czasu, aby naprawić oryginał, ponieważ tak naprawdę nie kwalifikuje się do narzutu.
źródło
documentation
tag jest godny pożałowania, ale nadal nie dotyczy pytania).Kod ma określać plan wykonania. W ten sposób obserwujący program (lub kompilator) może dowiedzieć się, co robić i jak to zrobić. To, co jest podzielone na etapy, które może śledzić programista. Prymitywne kroki to jak.
Cel kodera to inna sprawa. W prostym, jasnym i prostym kodzie zamiar jest oczywisty. Każdy rozsądnie biegły czytelnik ludzki dojdzie do celu bloku kodu, po prostu czytając kod. Większość kodów powinna czytać w ten sposób.
Czasami związek między intencją a planem jest niejasny. Kod ujawnia co i jak, ale nie dlaczego. Wtedy warto opowiedzić się o intencjach. Dlaczego programista zamierza.
źródło
Mając teraz ten problem, przebijamy się przez procedury składowane i widoki w oparciu o złożony i nieco skomplikowany model danych.
Mamy (liczne) wymyślone selekcje, takie jak „Przypadek, gdy x.account nie ma wartości zerowej i x.adres w (wybierz adres z fedex), a następnie x.account inaczej y.account koniec” przez cały czas i oczekuje się produktywności, chociaż nie ma czasu na wszystko, aby przeczytać cały kod źródłowy. A ten przykład w pewnym sensie ma sens, ale wciąż jest nieprzenikniony.
Komentarze wyjaśniające, dlaczego jeśli w fedex to x, a jeśli nie to y - rzuca światło na cały system, a kiedy czytamy wystarczająco dużo z nich, zaczynamy to rozumieć. I to jest zbyt uproszczone i istnieją setki lub tysiące podobnych oświadczeń. Moje serce ciepło świeci w kierunku każdego, kto był twórcą z 2007 roku, który włożył te, dlaczego.
Tak, tak, złożone skomplikowane modele danych i owłosione żywioły oraz procedura przechowywana z wieloma ważnymi nazwanymi ścieżkami, proszę, z miłości do B-ga, powiedz nam dlaczego.
źródło
Właśnie napisałem ten komentarz; jest to konkretny przykład wyjaśnienia, dlaczego wiersz kodu jest tym, czym jest, a w szczególności dlaczego go zmieniłem.
Metoda sprawdza przechowywane dane i ocenia, czy są one kompletne do dnia dzisiejszego z jednej strony i do daty rozpoczęcia z drugiej strony.
Jak zapewne można się domyślać, operator większy niż był równy lub większy. Komentarz wyjaśnia, dlaczego stara wartość ma sens i dlaczego nowa wartość jest lepsza. Jeśli ktoś spojrzy na to w przyszłości, zobaczy, że użycie „>” nie jest przeoczeniem, ale optymalizacją. Następnie mogą to zmienić lub zostawić, w zależności od potrzeb w danym momencie.
źródło