Jak udokumentować swój kod w celu sprawdzenia jego minimalnego czasu? [Zamknięte]

22

Chcę udokumentować mój kod w taki sposób, aby minimalne zapotrzebowanie na czytanie i przeglądanie kodu było możliwe kilka miesięcy później.

Wiem, że istnieją różne rodzaje dokumentacji (w kodzie źródłowym i na zewnątrz, diagramy sekwencji itp.).

Chcę tylko wiedzieć, jaki jest skuteczny sposób na udokumentowanie mojego kodu, aby gdy kilka miesięcy później chcę zobaczyć mój kod, spędzam mniej czasu na czytaniu kodu i zrozumieniu przepływu kodu.

Hamed_gibago
źródło
42
Najlepszym sposobem na poświęcenie mniej czasu na późniejsze czytanie kodu jest pisanie jaśniejszego i bardziej zrozumiałego kodu.
Mael
Dokumentacja zależy od celu. Jeśli zwracasz się do programistów, komentarze w kodzie mogą być bardzo przydatne. Jeśli zwracasz się do analityków, przydatne są również diagramy przeglądu. Jeśli zwracasz się do odbiorców technicznych, zrób instrukcję obsługi.
Laiv
@Laiv Cóż, biorąc pod uwagę autora własnego kodu i być może innego kodu deweloperów.
Hamed_gibago
Największą rzeczą jest utrzymanie małego kodu. Jeśli kod potrzebny do implementacji elementu w systemie śledzenia problemów jest duży, zespół może potrzebować nauczyć się jego dalszego podziału, aby ilość sprawdzanego kodu nie była przytłaczająca.
Berin Loritsch

Odpowiedzi:

16

Muszę przyznać, że nie zgadzam się z niektórymi rzeczami zalecanymi przez inne odpowiedzi, więc zamierzam rzucić dwa centy;

Komentarze

Dokumentacja jest wyjątkowo pomocna dla nieznajomych czytających Twój kod. Zwykle wiele rzeczy nie jest wystarczająco gadatliwych, aby można je było przeczytać i zrozumieć od razu, a następnie powinieneś wyjaśnić, co robisz.

Edycja : dyskusja w sekcji komentarzy wskazała coś słusznego - nadmierne komentowanie zwykle odbywa się podczas pisania złego kodu.

Komentowanie twojej pracy powinno być precyzyjne i minimalne, ale moim zdaniem zdecydowanie powinno być obecne. Przynajmniej komentarz na każde 15 linii kodu. Na przykład nad blokami kodu dodaj wiersz o tym, co robisz:

def login(username: str, password: str, create_session: bool = True):

    # Filter the user we need from the database
    hash = md5(password)
    users = db.table("users", db_entities.USER)
    results = [x for x in users.query(lambda c: c.get("username") == username and c.get("password_hash") == hash)]


    if len(results) == 0:
        return None, None
    else:
        # Create a login session record in the database.
        if create_session:
            sessions = db.table("sessions", db_entities.SESSION)
            ses = sessions.new()
            ses.set("username", username) \
                .set("expiery", 31536000 + time.time())
            sessions.update(ses)
            return results[0], ses
        else:
            return results[0], None

Minimalne komentarze wyjaśniające, dlaczego i co robisz, są bardzo pomocne w całym kodzie. Nie zgadzam się z odpowiedzią, która stwierdza

Jeśli napotkam kod zawierający komentarze, przygotowuję się na najgorsze: kod prawdopodobnie będzie zły, a szczerze mówiąc, komentarze również mogą być złe.

Wiele razy, z wdziękiem, udokumentowano dobry kod. Prawdą jest, że źli programiści widzą swoją dokumentację w stylu: „W porządku, mój kod jest zły, dodajmy kilka zdań, aby było jaśniej”.

Tak, i chociaż zdarza się to dość często, prawdą jest również, że dobrzy programiści, którzy piszą czysty kod, również chcą mieć pewność, że powrócą do swojego kodu i zrozumieją, dlaczego chcą, aby jego funkcja zachowywała się w ten sposób lub dlaczego potrzebowali tego linia, która wydaje się nieco zbędna itp.

Tak, komentarze wyjaśniające oczywiste rzeczy, niejasne komentarze, komentarze, które zostały właśnie zebrane, aby upewnić się, że „ten kod jest udokumentowany, tak, cokolwiek”, mają zapach kodu. Sprawiają, że czytanie kodu jest trudniejsze i irytujące. (Dodanie przykładu poniżej)

# Logging into Gmail when the module is imported
_client = login()
def get_client():
    global _client
    return _client

Przykładowe wyjaśnienie: „Cholera, Sherlock. Czy _client = login()loguje się do usługi pocztowej? OMG!”

Więcej wyjaśnień: login()metoda nie ma związku z login()metodą z powyższego przykładu.

Ale komentarze, które są zgodne ze standardami, wyjaśniają dlaczego, a nie jak, i odpowiadają na właściwe pytania , są bardzo ( bardzo ) pomocne.

Komentarze wbudowane

Jednej rzeczy NIE powinieneś (a gdybym mógł napisać to większe, zrobiłbym), jest pisanie komentarzy w tym samym wierszu kodu. To sprawia, że ​​komentarze są bardzo specyficzne dla linii, co całkowicie pomija cel komentowania twojego kodu.

Na przykład złe komentarze w tekście:

outer = MIMEText(details["message"]) # Constructing a new MIMEText object
outer["To"] = details["to"] # Setting message recipient
outer["From"] = "xAI No-Reply" # Setting message sender
outer["Subject"] = details["subject"] # Setting message subject
outer.preamble = "You will not see this in a MIME-aware mail reader.\n" # I don't know what I'm doing here, I copied this from SO.
msg = outer.as_string() # Getting the string of the message
_client = details["client"] # Assigning the client
_client.sendmail(SENDER, details["to"], msg) # Sending the mail

Znacznie łatwiej byłoby odczytać i zrozumieć ten kod bez komentarzy, co czyni bałagan i nieczytelnym.

Zamiast tego komentarze w kodzie powinny znajdować się nad blokami kodu i powinny odpowiadać na ważne pytania, które mogą pojawić się podczas czytania bloku kodu.

# Constructing the email object with the values 
# we received from the parameter of send_mail(details)
outer = MIMEText(details["message"])
outer["To"] = details["to"]
outer["From"] = "xAI No-Reply"
outer["Subject"] = details["subject"]
outer.preamble = "You will not see this in a MIME-aware mail reader.\n"
msg = outer.as_string()

# Sending the mail using the global client (obtained using login())
_client = details["client"]
_client.sendmail(SENDER, details["to"], msg)

O wiele jaśniej, prawda? Teraz już wiesz, że musisz użyć login()funkcji i podać parametry send_mail()we wszystkim, czego użyłeś. Pomaga trochę, ale wciąż brakuje jednej rzeczy.

Dokumentacja funkcji

Był szeroko dyskutowany. Powinieneś zawsze poinformować czytelników, o czym jest twoja funkcja, dlaczego i co robi. Jak to robi, nie należy to do dokumentacji, ale może do przypisów funkcji.

Powinieneś jasno opisać, czego oczekujesz od swoich parametrów, a jeśli chcesz, aby zostały uzyskane / utworzone w określonej metodzie. Powinieneś zadeklarować, jaką funkcję ma zwrócić funkcja, jakie jest jej użycie itp.

Znowu taka jest moja opinia i metodologia podczas pisania mojego kodu. Nie tylko te, ale to tylko niektóre rzeczy, których nie mogłem zgodzić się z innymi odpowiedziami. No i oczywiście nie tylko komentarze odczytują twój kod, ale sam kod. Napisz czysty kod, zrozumiały i łatwy w utrzymaniu . Pomyśl o swoim własnym ja podczas kodowania ;-)

Łosoś Yotam
źródło
5
Nie zgadzaj się z danym przykładem - zamiast pisać wiele komentarzy w jednej ogromnej funkcji, powinieneś skomponować ją z wielu mniejszych funkcji o opisowych nazwach, które będą działać jako komentarze. Bez ryzyka braku synchronizacji z tym, co naprawdę robi kod .
user11153,
6
Wreszcie trochę zdrowia psychicznego. Wyodrębnianie każdego fragmentu kodu, który mógłby użyć komentarza do jego własnej funkcji, to sposób, w jaki uzyskujemy tysiące funkcji rozmieszczonych w setkach plików.
user369450
2
Ten drugi przykład jest piękny.
Lekkość ściga się z Moniką
7
Komentarze w drugim przykładzie są zbyt szczegółowe. Niektóre z nich (np. „Znaleźliśmy coś?”) Po prostu powtórz to, co mówi kod i lepiej je usunąć. W innym przypadku można uzyskać większą czytelność poprzez refaktoryzację, na przykład utworzenie warunku pętli (stream.is_empty ()) lub przeniesienie sprawdzania akceptacji liter na zewnątrz.
Frax
3
@cpburnz, „Musiałem przekopać się przez zbyt wiele starszych projektów i bibliotek stron trzecich bez komentarzy do kodu, aby docenić komentarze wyjaśniające, co się dzieje i dlaczego”. dokładnie o to mi chodzi: komentarze mają na celu wyjaśnienie bzdurnego kodu. Ponieważ pytanie brzmi: „jak napisać kod tak łatwy do odczytania”, to wyraźnie ta odpowiedź jest błędna, ponieważ skupia się na pisaniu komentarzy w celu wyjaśnienia złego kodu, a nie na pisaniu dobrego kodu.
David Arno,
55

IMO najlepszą dokumentacją jest dokumentacja, której tak naprawdę nie potrzebujesz. Nienawidzę także pisania dokumentacji i komentarzy.

Powiedziawszy to:

  • Wybierz czytelne i mówiące nazwy. Nie używaj n, ale zamiast tego numberOfItemsFoundna przykład.
  • Nie zawracaj sobie głowy zapisywaniem części obliczeń w zmiennej stałej zamiast pchania wszystkiego w jedną linię.
  • Przenieś częściowe zadania z gałęzi do ich własnych (wbudowanych) funkcji, jeśli ponownie je wykorzystasz lub funkcja nadrzędna staje się długa i żmudna do naśladowania.
  • Bądź bardziej rozbudowany i optymalizuj kod tylko pod kątem czytelności tam, gdzie jest to naprawdę wymagane.
Mario
źródło
19
Oto dobra miara dokumentacji (link obowiązkowy).
Neil
4
Powinno to również znajdować się na liście: wyjaśnij w kodzie, dlaczego robisz to, co robisz.
t3chb0t
2
+1 za ostatni przedmiot pocisku, ponieważ przedwczesna optymalizacja jest (w 97% przypadków) źródłem wszelkiego zła
gmauch
4
numberOfItemsFoundjest jednak dość gadatliwy; zbyt gadatliwy jest również problem.
Matthieu M.
6
@ MatthieuM., Rzadko jest „zbyt gadatliwy” problem z nazwami w kodzie. Zbyt zwięzły lub tajemniczy jest jednak bardzo częstym problemem.
David Arno,
25

Traktuj swój kod jako dokumentację

Twój kod jest twoją podstawową dokumentacją. Dokładnie opisuje, co faktycznie robi wynikowa aplikacja, biblioteka lub cokolwiek innego. W związku z tym wszelkie próby przyspieszenia zrozumienia tego kodu muszą zaczynać się od samego kodu.

Wiele napisano na temat pisania czytelnego kodu, ale niektóre kluczowe punkty to:

  • nie polegaj na komentarzach w celu wyjaśnienia złego kodu, ulepsz kod i pozbądź się komentarzy,
  • pisać krótko ukierunkowane funkcje, metody, klasy itp.,
  • używaj nazw odpowiednich do kontekstu (np. njest dobry dla pętli, dłuższe nazwy opisowe są potrzebne dla elementów o większym zakresie),
  • traktuj nazwy funkcji tak, jakby były komentarzami, np. nie używaj UpdtTblz komentarzem wyjaśniającym, że aktualizuje tabelę o dostarczone reguły, kiedy UpdateTableContentsWithSuppliedRulesmoże być używana jako nazwa,
  • unikać zmienności. Za każdym razem, gdy zmieniasz zawartość zmiennej, zwiększasz złożoność kodu. W miarę możliwości przypisz tę nową wartość do nowej zmiennej (o dobrej nazwie).
  • i co najważniejsze, unikaj „sprytnego” kodu. Jedynym sprytnym kodem jest kod, który jest łatwy do odczytania. Jeśli napiszesz trochę skomplikowanego kodu i pomyślisz „wow, czyż nie jestem sprytny?”, Prawie na pewno odpowiedź brzmi „nie, nie jesteś”.

Lepiej czytać kod

Czytanie kodu, niezależnie od tego, jak proste jest, jest wyuczoną umiejętnością. Nikt z natury nie jest dobry w czytaniu kodu. To wymaga praktyki; dużo praktyki. Na przykład przejdź do Github lub cokolwiek innego i przeczytaj kod używanych bibliotek, a nie tylko tych bibliotek. Znajdź kod do przeczytania i odczytu.

Komentarze to zapach kodu

Dopiero wtedy dochodzimy do innych rodzajów dokumentacji. Po pierwsze, jak już wspomniano, unikaj komentarzy. Jeśli napotkam kod zawierający komentarze, przygotowuję się na najgorsze: kod prawdopodobnie będzie zły, a szczerze mówiąc, komentarze również mogą być złe. Ktoś, kto nie potrafi dobrze komunikować się za pomocą kodu, raczej nie będzie w stanie lepiej komunikować się za pomocą języka naturalnego.

Strzeż się dokumentacji API generowanej automatycznie

Uważaj też na dokumentację API generowaną automatycznie. Jeśli będę musiał czytać takie dokumenty, to dlatego, że twój kod jest tak trudny do odczytania. Ponownie, zrób kod prosty i będę mógł go odczytać bezpośrednio.

Testy też są dokumentami

Testy są również dokumentacją. Więc nie traktuj swoich testów jednostkowych jako uciążliwości. Potraktuj je jako sposób komunikowania się z innymi (twoje sześciomiesięczne później bycie tutaj), jak działa kod i jest przeznaczony do użycia.

Narysuj zdjęcia, jeśli to pomoże

Jeśli podoba Ci się UML, to na pewno znajdź dobre narzędzie i generuj diagramy UML ze swojego kodu. Po prostu nigdy nie próbuj używać go do generowania kodu. Nie jest dobry jako narzędzie do projektowania, w wyniku czego powstanie okropny kod.

Mieć dokument „1000 stóp”

Na koniec napisz sobie dokument poglądowy. Czym zajmuje się aplikacja? Jak to robi? Z jakimi innymi systemami się łączy? Rzeczy jak te. Nie próbuj jednak opisywać tutaj struktury kodu. Niech kod to zrobi. Niech ten dokument przypomni Ci, dlaczego napisałeś kod w pierwszej kolejności.

David Arno
źródło
14
Zgadzam się z całą twoją tezą, tyle że komentarze mają swoje miejsce. Chociaż zgadzam się, że komentarze nie mają sensu add 1 to i, komentarze powinny wyjaśniać, dlaczego kod robi to, co robi. Na przykład, kod if (!something.Exists()) {...}może użyć komentarza w stylu: // something exists only when (explanation of the broader scenario).
Jonathan
16
Wszyscy widzieliśmy nasz uczciwy udział // increment x x++; komentarzy, które są bezużyteczne, ale źle jest wylewać dziecko z kąpielą i twierdzić, że komentarze są zawsze złe. Na przykład komentarze do formularza // this case should never happen because xyz throw exception "unreachable".
angrydust
7
Bardzo ładna lista. Ale jak @ Jonathan. Nie zgadzam się z komentarzami. Czasami jednak trzeba brać pod uwagę błędy we frameworku stron trzecich. Chociaż można to przełożyć na własne funkcje, nadal miło jest zostawić trochę opisu, dlaczego konieczne jest obejście (numer błędu lub nazwa błędu / opis błędu).
magu_
16
@DavidArno Ale nie możesz tego zrobić dla komentarza wyjaśniającego, dlaczego coś nie zostało zrobione. Jak //XXX: Not using straight-forward method Foo here because .... Takie komentarze mogą być niezwykle cenne, ale z oczywistych powodów nie można ich przekazać kodem.
cmaster
7
Podoba mi się to jeszcze bardziej dramatycznie: każdy komentarz jest brakiem dobrego wyrażenia się w kodzie . Na przykład mam komentarz 4-liniowy w jednej metodzie, wyjaśniający obejście błędu innej firmy. Nie udało mi się wyrazić tego dobrze w kodzie, więc jest to w komentarzu . Powiedziałbym, że poprawia to czytelność, ponieważ wątpię, aby ktokolwiek lubił przewijać się w poziomie, aby przeczytać bardzo długą i bardzo opisową nazwę metody. „Komentarze to zapachowy kod” - tak, ale musimy pamiętać, że nie wszystko, co pachnie, jest do cholery.
R. Schmitz
5

Podaj list motywacyjny

O ile nie jesteś w bardzo technicznej dziedzinie, większość pytań dotyczących kodu nie dotyczy „jak”, ale „dlaczego” lub „co”.

W związku z tym sposobem na ograniczenie liczby osób zaglądających do kodu jest napisanie jego krótkiego opisu. Zaletą tego jest to, że można dość łatwo skompilować przegląd opisów i że jest to znacznie łatwiej dostępne. (Nawet osobom, które nie chcą / nie mogą zobaczyć kodu).

Nawet jeśli ludzie są techniczni, list motywacyjny powinien zawierać wskazówki, gdzie powinni czegoś szukać.

Proste bardzo minimalistyczne punkty:

  1. Wprowadzenie, dlaczego ten kod (podstawowy) istnieje
  2. Jaką funkcję spełnia podzbiór kodu
  3. Gdzie jest kod (na przykład nazwa skryptu)

Przykład

  1. Ten zestaw skryptów zdrapuje StackOverflow i upvotes odpowiedzi Dennisa Jaheruddina
  2. za. Ten skrypt jest odpowiedzialny za analizowanie kodu HTML i analizowanie, czy jest on właściwym użytkownikiem
  3. za. Skrypt znajduje się na stronie: ScrapeAndVote / RecognizeDennis.scr
Dennis Jaheruddin
źródło
1

Największy przyrost prędkości zwykle uzyskuję z budowania osobnych zatwierdzeń, z których każdy reprezentuje pośredni krok, który się kompiluje i działa.

Więc jeśli muszę wprowadzić nowy parametr do funkcji w celu zaimplementowania określonej funkcji, to jest jeden zatwierdzenie, które nie robi nic poza dodaniem parametru w deklaracji, w definicji i we wszystkich witrynach wywołań. Następnie kolejne zatwierdzenie wprowadza funkcjonalność, a trzecie aktualizuje strony wywołujące, które korzystają z nowej funkcji.

Łatwo to przejrzeć, ponieważ zmiany czysto mechaniczne można szybko przejrzeć, a następnie zejść im z drogi.

Podobnie, jeśli sformatujesz kod, zawsze powinno to być osobne zatwierdzenie.

Simon Richter
źródło
1

Chociaż istnieją istniejące pozorne różnice zdań między istniejącymi odpowiedziami, choćby dla podkreślenia, postaram się streścić zwykłą poradę w sposób, który wyjaśni, skąd wszyscy pochodzą:

  1. Po pierwsze, napisz czysty kod; każda inna „dokumentacja” sama się załatwi. Czysty kod to cały zestaw zasad, których należy się uczyć przede wszystkim: klasy z pojedynczą odpowiedzialnością, krótkie metody, które wykonują jedną rzecz, dobre nazwy zmiennych i metod, lepsze nazwy klas / typów niż te poprzez skupienie się na metaforach (np. Wywołanie MultiButtSupporter a soda), testy jednostkowe wskazujące wymagania, SUCHE, SOLIDNE, spójny paradygmat i tak dalej.
  2. Kod ujawnia, jak działa kod; komentarze pokazują, dlaczego kod działa. Na przykład wyjaśnij +1 słowem „zapobiega błędowi wyłączania o 1” lub jakąś skomplikowaną formułę słowem „wyprowadzony z tego podręcznika lub strony internetowej”.
  3. Cokolwiek zrobiłeś z komentarzami, punkt 1 powyżej może to osiągnąć w czystym kodzie. Zobacz komentarze jako niepowodzenia / niezbędne zło, a nawet kłamstwa, jeśli z czasem nie zsynchronizują się z kodem, gdy oba są edytowane. Komentarze nie powinny rekompensować źle napisanego kodu, ponieważ dlaczego komentarze byłyby pisane z większym talentem lub troską niż kod?

Z drugiej strony, jeśli coś, prawdopodobnie popełniam błąd zbyt daleko, prawie nigdy nie używam komentarzy. Twoi recenzenci kodu poinformują cię, czy masz równowagę w niewłaściwym dla nich miejscu, ale jeśli podejmiesz świadomy wysiłek, aby zastosować się do powyższego 3-punktowego planu, prawdopodobnie i tak będziesz blisko ich optymalnego poziomu.

JG
źródło
2
W jaki sposób komentarz „zapobiega błędowi wyłączonemu o 1” różni się od komentarza, który mówi, że „+1 nie jest literówką” lub „Nie wiem, czy wystąpiły błędy w jednym programie”? (Przydatne komentarze ogólnie odnoszą się do czegoś większego niż +1 w kodzie źródłowym lub do czegoś poza kodem źródłowym.) Tak więc nadal pozostawia „wyprowadzony z tego podręcznika lub strony internetowej” jako prawidłowy i rzeczywiście świetny przykład w twoim punkcie # 2. Wówczas punkt 3 wydaje się sugerować, że możesz wyrazić „wyprowadzony z tego podręcznika lub strony internetowej” używając wystarczająco czystego kodu bez żadnych komentarzy; wow, chciałbym zobaczyć to w akcji.
Jirka Hanika
@JirkaHanika Może off-by-one był złym przykładem. Jeśli chodzi o 3, miałem na myśli raczej „każdy może” niż „może każdy”; więc nie, nie sądzę, że sam kod może wyjaśnić takie rzeczy. (Cóż, możesz wypróbować gaussianFromThisTextbookNamesApproximation jako nazwę zmiennej, ale to zły pomysł!)
JG