Czy to normalne, że programista czasami nie ma 100% przejrzystości w stosunku do własnego kodu? [Zamknięte]

19

Nie jestem specjalistą od programowania, więc może dlatego, ale zauważyłem, że za każdym razem, gdy tworzę skomplikowany kod (jak ostatnio stworzona gra w szachy), jestem w stanie napisać poprawny kod, aby program działał, chociaż stwierdzam, że później - a nawet kilka sekund później - często muszę się zatrzymywać i zastanawiać, jak to działa?

Nie tylko to, ale również nie myślę o kodzie, a zamiast tego piszę. Na przykład w mojej grze w szachy postanowiłem użyć pięciowymiarowej tablicy do przetwarzania ruchów i odkryłem, że mogę to zrobić bez zbytniego świadomego myślenia. Jednak gdy przestałem czytać i przeczytałem, trudno mi było objąć całą pięciowymiarową koncepcję i zajęło mi kilka minut, aby w pełni zrozumieć, co zrobiłem i jak działa sam kod.

Czy to normalne, że programiści piszący złożony kod nie rozumieją, co robią przez połowę czasu?

83457
źródło
13
To znak, że zbyt mocno starasz się być mądrym. Jeśli masz problemy z samodzielnym odczytaniem, musisz napisać prostszy, bardziej modułowy kod.
SHODAN
3
Aby dodać do innych (wnikliwych) odpowiedzi w tym sensie, że pachnie zbyt skomplikowanym lub źle zaprojektowanym kodem (nie martw się, większość z nas musiała przejść ten etap): Dokument . Zarówno poprzez nadanie odpowiednich nazw zmiennym / metodom / klasom / modułom, poprzez dodanie odpowiedniego opisu do każdej funkcji, jak i (gdy nie ma innego wyjścia) napisanie prostego komentarza wyjaśniającego, dlaczego i jak używasz złożonego fragmentu kod.
SJuan76,
4
ja nie mam 100% przejrzystości w stosunku do własnego kodu.
CodesInChaos
2
Ta tablica 5D naprawdę brzmi, jakby mogła użyć jakiejś abstrakcji.
3
Czy którykolwiek programista ma przez cały czas 100% przejrzystości swojego kodu?
Johan

Odpowiedzi:

30

Nie, to nie jest normalne 1 . Przynajmniej nie jest to normalne dla dobrych programistów. Prawdopodobnie jest to normalne, że ktoś uczy się programować.

Oprogramowanie do pisania nie polega tylko na łączeniu linii kodu, dopóki nie zadziała. Musisz świadomie pracować nad tym, aby kod był łatwy do zrozumienia. Pewien programista, którego bardzo szanuję, powiedział mi kiedyś: „kod jest czytany wiele razy więcej niż jest napisany” . Chociaż powinno to być całkowicie oczywiste, nie byłem tego świadomy, dopóki mi nie powiedział. Znaczna część twojego kodu jest pisana tylko raz, być może przepisana raz lub dwa razy więcej, ale w końcu będziesz czytać kod często przez cały okres użytkowania oprogramowania.

Jeśli trudno ci zrozumieć kod w kilka minut po jego napisaniu, oznacza to, że kod jest zbyt skomplikowany. Przestań dodawać kod i wymyśl lepszy sposób. Na przykład pięciowymiarowa tablica prawie nigdy nie jest dobrym pomysłem. Nawet naprawdę inteligentni programiści mają trudności ze zrozumieniem tak złożonej struktury danych.

Ten sam programista, który powiedział mi o czytelności kodu, powiedział również: „pokaż mi swoje struktury danych, a ja powiem ci, jak działa twój kod” . Oznacza to, że dobry kod zaczyna się od przejrzystych, zrozumiałych struktur danych. Jeśli właściwie zaprojektujesz swoje dane, kod jest prawie drugorzędny. Trzeba przyznać, że to stwierdzenie jest trochę hiperbolą, ponieważ oprogramowanie to oczywiście coś więcej niż dane, ale zaczyna się od danych. Pracuj więc nad stworzeniem przejrzystych, łatwych do zrozumienia struktur danych, a kod będzie znacznie łatwiejszy do zrozumienia.


1 Z pewnością istnieje kod, który jest bardzo złożony i trudny do zrozumienia nawet dla najmądrzejszych programistów. Niektóre problemy są z natury złożone. Zaryzykowałbym jednak stwierdzenie, że ogromna większość kodu napisanego przez zdecydowaną większość programistów nie jest tego typu kodem.

Bryan Oakley
źródło
8
[1] Z bardziej pesymistycznego punktu widzenia jest to normalne, ale nie jest dobre.
Dan
1
Jeśli „pięciowymiarowa tablica” jest jedynie mapą od 4-krotnej lub 5-krotnej do strategii, autor mógłby użyć tabeli skrótów lub funkcji wyszukiwania pomocnika. Jeśli jednak autor spędza większość czasu na kodowaniu mechaniki inicjalizacji tablicy (zagnieżdżone pętle for), wówczas rzeczywisty „wgląd w algorytm” zostanie utopiony w stosie „kodu mechanicznego”. Programiści starają się oddzielić ten drugi rodzaj hałasu od siebie. Zatem dobrzy programiści muszą umieć pisać biblioteki przede wszystkim w celu przechowywania kodu mechanicznego.
rwong
Tablica 1-D to linia, 2-d to siatka, 3-d to sześcian, 4-d to linia kostek, 5-d to siatka kostek itp., Ale nie widzę zastosowania za tak złożoną strukturę danych, jeśli chodzi o szachy.
user2785724,
15

Istnieją dwa rodzaje tego: 1.) zamieszanie 2.) błoga ignorancja

Pierwszy jest zły i może zniknąć z czasem i doświadczeniem.

Drugi jest dobry, gdy projekty stają się większe: jeśli musisz pamiętać każdy szczegół implementacji tylko po to, aby móc pracować z twoim kodem, coś jest z nim nie tak (patrz „ukrywanie informacji”).

Każdy programista zapomni o tym, jak działał kod, więc pisze go w taki sposób, aby inny nowy program zrozumiał i był w stanie go utrzymywać bez niszczenia innych części programu, które również są mu nieznane.

Tak więc „niewiedza” jest w rzeczywistości ciągłym procesem rozwoju oprogramowania - to po prostu jak lub czy nim zarządzasz.

telep
źródło
1
Dotykasz tutaj czegoś ważnego, a mianowicie tego, jak ważne jest programowanie przy użyciu zdrowych rozsądków i konwencji, ponieważ szczegóły implementacji naprawdę zostają zapomniane. Ale jeśli wzorce i konwencje w kodzie są sensowne, łatwo jest w razie potrzeby wybrać szczegóły z kontekstu. Z drugiej strony, jeśli kod jest monolityczny, nieprzenikniony i zbyt sprytny, nie tylko w końcu zapomnisz o szczegółach, ale inni programiści próbujący utrzymać kod będą mieli znacznie trudniejszy czas.
Craig
12

Powiedziałbym, że jest to bardziej powszechne niż ludzie się przyznają. Nawet Brian Kernighan wspomniał o tym:

Debugowanie jest dwa razy trudniejsze niż pisanie kodu. Dlatego, jeśli piszesz kod tak sprytnie, jak to możliwe, z definicji nie jesteś wystarczająco inteligentny, aby go debugować.

Kiedy jedziemy do sklepu, dokonujemy sekwencji szczegółowych regulacji pozycji pedałów i kierownicy. W tej chwili jest to bardzo łatwe. Teraz wyobraź sobie, czy zapisałeś te korekty na papierze i dałeś je znajomemu, który potrzebował wskazówek do sklepu.

Podobnie lubimy pisać kod na jednym poziomie abstrakcji, ale lubimy go czytać w wielu wyższych warstwach abstrakcji. Dlatego nasz ulubiony sposób pisania i czytania kodu jest w konflikcie. Oznacza to, że uczynienie kodu łatwym do odczytania jest zwykle osobnym, świadomym krokiem z innym zestawem umiejętności.

To, co czyni dobrego programistę, to trudności w czytaniu tego, co właśnie napisali, w tym momencie tworzą abstrakcję. Lepszy programista robi to wiele razy, za każdym razem robi się bardziej wybitny. W końcu doświadczeni programiści zaczynają od tego procesu, ale często po przeczytaniu tego, co właśnie napisali, wciąż widzą pole do poprawy.

Karl Bielefeldt
źródło
Muszę się z tym nie zgodzić z Brianem, uwielbiam debugować, jestem jedną z niewielu osób, które znam w branży, które to robią, ale nie oceniam kodu, który piszę tak wysoko.
James Snell
@JamesSnell Nie powiedział, że debugowanie jest złe lub nieprzyjemne, tylko że jest trudne, a debugowanie skomplikowanego kodu jest jeszcze trudniejsze.
cbojar
5

Myślę, że to odejdzie wraz z doświadczeniem.

Jeśli piszesz złożone systemy, musisz mieć możliwość pisania czystego, łatwego w utrzymaniu kodu, który zrozumie zarówno Ty, jak i ktoś inny w przyszłości. Zasadniczo rzecz, którą teraz robisz, nie jest skalowalna.

Będziesz miał wiele chwil, w których będziesz patrzył na kod napisany 6 miesięcy temu i zastanawiałeś się „co tu się do cholery dzieje?”, Ale jeśli zdarzy się to dzień po napisaniu kodu, musisz pomyśleć „czysty” kod ”więcej.

Źródło: nigdy nie korzystałem z 5-wymiarowej tablicy :)

Erez Eshkol
źródło
3
@ 83457 - ponieważ tablica 5d jest złym modelem problemu 2d. Jeśli naprawdę uważasz, że to dobry kod, upuść go na codereview.stackexchange.com i sprawdź, jakie odpowiedzi otrzymasz.
James Snell
2
@ 83457 - Jeśli to „mylące jak diabli”, odpowiedziałeś sobie. Możliwe, że tablica 5-D nie jest myląca, ale prawdopodobnie nie dla większości z nas, bez względu na nasz poziom umiejętności.
dbasnett,
2
@ 83457 jest mylące, ponieważ piekło powinno być już bardzo dobrą motywacją do nieużywania tego.
Fabio Marcolini,
3
Dopóki masz dobry powód dla każdego wymiaru, nie widzę powodu, aby unikać tablicy 5D. Być może istnieje lepsze rozwiązanie, takie jak słownik ze złożonym kluczem lub kilkoma tablicami o niższych wymiarach, ale mogę sobie wyobrazić, że tablica 5D jest odpowiednia do trudnego problemu, takiego jak szachowa sztuczna inteligencja.
CodesInChaos
2
@CodesInChaos Oprócz tego, że nie są to tylko tablice, reprezentują one znaczące sekwencje (na przykład zagnieżdżone drzewa decison). Nadając im odpowiednie nazwy i nadając im typy, aby nie mogły być nadużywane (nawet jeśli typy te są opakowujące tablice), kod staje się bardziej przejrzysty i mniej prawdopodobne, że zawiera błędy, za niewielką opłatą.
deworde
5

„Normalny” jest bardzo subiektywny, więc mówię: jest bardzo powszechny, ale należy go unikać.

Jedną z cech „dobrego kodu” (słyszałem, że coś takiego istnieje) jest jasność: powinna być tak jasna, na jaką pozwalają leżące u jej podstaw problemy. Jeśli problem jest złożony, kod również byłby złożony, ale jest to złożona właściwość , w przeciwieństwie do przypadkowej złożoności (po raz pierwszy usłyszałem o tym rozróżnieniu w przemówieniu Richa Hickeya ) wprowadzonej przez niewłaściwe użycie niewłaściwych narzędzi, wzorów, technik i praktyki.

Zdarzają się przypadki, gdy brak jasności jest akceptowalny, nawet gdy problem nie jest bardzo skomplikowany, np. Gdy piszesz stronę promocyjną, o której wiesz, że będzie trwać tak długo, jak trwa kampania marketingowa. Jest to kod jednorazowy, którego nie można utrzymywać. W innych (i większości) przypadkach jest to niedopuszczalne, ponieważ utrzymanie takiego kodu będzie kosztowało dużo. Jednak jest to powszechne.

Związane z:

  • Kiedy zrozumienie oznacza przepisywanie - artykuł na temat problemu ze zrozumieniem kodu.
  • Efektywna ML - długa rozmowa na temat, między ML / OCaml, jak pisać kod dla „czytelników” (tj. Opiekunów): „Preferuj czytelników nad pisarzami”. Polecam oglądać bez względu na to, jakiego języka używasz.
scriptin
źródło
2

Nie sądzę, że to normalne, ale w przypadku bardzo złożonych programów, takich jak wspomniany program szachowy, myślę, że z pewnością jest to możliwe.

Wiele lat temu, kiedy właśnie skończyłem szkołę podstawową (więc wciąż byłem stosunkowo niedoświadczony, pisząc duże programy), napisałem swój pierwszy prawdziwy kompilator. Analiza była prosta, ale potem musiałem celować w cztery różne zestawy instrukcji mikroprocesorowych. Zamierzałem napisać kompilator we własnym języku, więc najpierw wykorzystałem tylko funkcje języka, którego absolutnie potrzebowałem, napisałem pierwszy generator kodu w asemblerze i przetestowałem, czy wygenerował poprawny kod dla podzbioru języka. Byłem wtedy w stanie użyć kompilatora do samodzielnej kompilacji i dodać pozostałe funkcje, a także użyć ich w samym kompilatorze

Następnie napisałem generatory kodu zaplecza dla każdego mikroprocesora i przetestowałem, czy wszystkie wygenerowały poprawny kod, ale poprawny nie był zbyt optymalny. Następnie przystąpiłem do pisania optymalizatorów dla każdego generatora kodu.

Kiedy testowałem dane wyjściowe generatorów kodu po dodaniu całej optymalizacji, często byłem zaskoczony kodem wygenerowanym przez kompilator. Często nie tak pisałem kod ręcznie, ale był poprawny i dość zwięzły.

Kiedy nie było dla mnie oczywiste, w jaki sposób generator kodu wytworzył część kodu, który on wykonał, próbowałem zastosować logikę ręcznie, ale czasami po prostu się poddałem. Gdybym dodał dużo danych wyjściowych śledzenia, byłbym w stanie je śledzić, ale nie zawracałem sobie głowy, ponieważ wygenerowany kod był zadowalający i musiałem przejść do innych projektów.

tcrosley
źródło
Wydaje mi się, że masz bardzo dobre wykształcenie i solidne podstawy, i że przyswoiłeś wiedzę na bardzo wysokim poziomie. Myślę, że jest to dość rzadkie wśród typowych programistów. Najbardziej typowi programiści (w tym ja) muszą walczyć, aby nadążyć za wiedzą potrzebną do dzisiejszego zadania, ponieważ technologia zmienia się tak szybko.
rwong
@rwong Dziękuję. Większość to doświadczenie - piszę programy od 46 lat i nie mam zamiaru wkrótce rezygnować.
tcrosley,
2

Tutaj jest wiele przyzwoitych odpowiedzi.

Mam na to kilka uwag.

Jednym z nich jest to, że jeśli nie rozumiesz, dlaczego twój kod wydaje się działać, a) prawdopodobnie nie działa (prawdopodobnie tylko wydaje się, że działa), i b) albo nie zrozumiałeś wystarczająco dobrze problematycznej domeny, kiedy zaczął kodować lub nie rozbił problematycznej domeny na mniejsze, uproszczone jednostki, zanim zacząłeś.

Moje drugie podejście polega na tym, że prawdziwym kluczem jest stosowanie zdrowego rozsądku i konwencji w kodzie. To o wiele większy temat, niż może rozwiązać jeden mały post. Ale szukaj dobrej literatury na ten temat, w tym niektórych starych standbys, takich jak książki „Code Complete” i „Writing Solid Code”.

Zmiana szczegółów implementacji. Jedyną rzeczywistą stałą jest funkcjonalny cel kodu. Jeśli kiedykolwiek napiszesz więcej niż jedną funkcję, z czasem zapomnisz szczegółowe, szczegółowe szczegóły implementacji. Ale z pewnością powinieneś zrozumieć, jak działają elementy, kiedy je konstruujesz, i powinieneś być w stanie narysować schemat całości i zrozumieć, jak elementy działają razem.

Jeśli użyjesz wzorców i będziesz postępować zgodnie ze zdroworozsądkowymi konwencjami, o wiele łatwiej będzie wybrać szczegółowe dane dotyczące implementacji, gdy ponownie spojrzysz na kod. Lub gdy ktoś, kto nigdy wcześniej nie widział kodu, patrzy na niego po raz pierwszy. Ponadto przestrzeganie tych konwencji i wzorców z biegiem czasu będzie oznaczać, że szczegóły implementacji będą się wyróżniać od samych konwencji i wzorców, co jest kolejnym czynnikiem, który ułatwi zrozumienie kodu.

Większość problemów, które rozwiązujemy za pomocą oprogramowania, są z natury złożone. Projektowanie oprogramowania to ćwiczenie w zarządzaniu złożonością.

Craig
źródło
1

Nie nazwałbym tego normalnym , ale na pewno może się zdarzyć. Jeśli przytrafi ci się to wkrótce po napisaniu fragmentu kodu, myślę, że albo twój kod jest niepotrzebnie skomplikowany i powinien zostać uproszczony, albo łatwo się rozpraszasz. :)

Ale jeśli odłożysz swój kod, skoncentrujesz się na innych projektach i powrócisz do niego po tygodniach, miesiącach, a nawet latach, nic dziwnego, że będziesz musiał to wszystko rozgryźć ponownie.

Ale możesz coś z tym zrobić. Z tego, co mówisz, wydaje się, że nie myślisz wystarczająco dużo o swoim kodzie, gdy go piszesz, a zatem utrudniasz przyszłej jaźni zrozumienie, co się dzieje. Wykorzystaj tę wiedzę na swoją korzyść: jest to najlepsza motywacja do stworzenia dobrze skonstruowanego, dobrze udokumentowanego i zrozumiałego kodu. Z doświadczenia z pierwszej ręki wiesz, co się dzieje, gdy nie dbasz o jakość swojego kodu. Wiedza o tym powinna uczynić cię lepszym programistą na dłuższą metę. Kiedy współpracujesz przy projektach oprogramowania, twoi koledzy będą ci wdzięczni za stworzenie zrozumiałego kodu. Poprawi się również współczynnik defektów kodu.

Mindriot
źródło