Ist es normal, dass ein Programmierer zeitweise keine 100% ige Klarheit über seinen eigenen Code hat? [geschlossen]

19

Ich bin kein erfahrener Programmierer, das mag der Grund sein, aber mir ist aufgefallen, dass ich immer dann, wenn ich komplexen Code erstelle (wie ein Schachspiel, das ich kürzlich gemacht habe), den richtigen Code schreiben kann, um das Programm zum Laufen zu bringen. obwohl ich das später finde - oder sogar ein paar Sekunden später! - muss ich oft innehalten und nachdenken, wie funktioniert das?

Nicht nur das, sondern ich neige auch dazu, nicht an den Code zu denken und tippe stattdessen einfach weg. Zum Beispiel habe ich in meinem Schachspiel beschlossen, ein fünfdimensionales Array für die Verarbeitung von Zügen zu verwenden, und ich stellte fest, dass ich dies ohne zu viel bewusstes Denken tun konnte. Als ich jedoch anhielt und darüber las, fand ich es schwierig, mich mit dem gesamten fünfdimensionalen Konzept vertraut zu machen, und ich brauchte ein paar Minuten, um zu verstehen, was ich tat und wie der Code selbst funktioniert.

Ist es normal, dass Programmierer beim Schreiben von komplexem Code die Hälfte der Zeit nicht verstehen, was sie tun?

83457
quelle
13
Es ist ein Zeichen dafür, dass Sie zu sehr versuchen, klug zu sein. Sie müssen einfacheren, modulareren Code schreiben, wenn Sie Probleme haben, ihn selbst zu lesen.
SHODAN
3
Hinzufügen zu anderen (aufschlussreichen) Antworten in dem Sinne, dass es nach überkompliziertem oder schlecht gestaltetem Code riecht (keine Sorge, die meisten von uns mussten diese Phase bestehen): Dokument . Beides, indem Sie Variablen / Methoden / Klassen / Module mit korrekten Namen versehen, jeder Funktion eine korrekte Beschreibung hinzufügen und (wenn Sie keinen anderen Weg sehen) einen einfachen Inline-Kommentar schreiben, der erklärt, warum und wie Sie ein komplexes Snippet von verwenden Code.
SJuan76
4
Ich habe nie 100% Klarheit über meinen eigenen Code.
CodesInChaos
2
Das 5D-Array klingt wirklich so, als könnte es eine Abstraktion gebrauchen.
3
Hat jeder Entwickler jederzeit 100% ige Klarheit über seinen Code?
Johan

Antworten:

30

Nein, es ist nicht normal 1 . Zumindest ist das für gute Programmierer nicht normal. Wahrscheinlich ist normal für jemanden Programm zu lernen.

Das Schreiben von Software setzt nicht nur Codezeilen aufeinander, bis es funktioniert. Sie müssen bewusst daran arbeiten, den Code leicht verständlich zu machen. Ein Programmierer ich sagte mir sehr einmal respektieren „Code mehr Lese Weise mal als es geschrieben steht“ . Während das völlig offensichtlich sein sollte, war es eine Tatsache, die ich nicht gewusst hatte, bis er es mir sagte. Ein Großteil Ihres Codes wird nur einmal geschrieben, möglicherweise ein- oder zweimal neu geschrieben, aber Sie werden den Code im Laufe der Lebensdauer der Software häufig lesen.

Wenn Sie den Code wenige Minuten nach dem Schreiben schwer verstehen, ist dies ein Signal dafür, dass Ihr Code zu komplex ist. Hören Sie auf, Code hinzuzufügen, und finden Sie einen besseren Weg. Zum Beispiel ist ein fünfdimensionales Array fast nie eine gute Idee. Selbst sehr, sehr kluge Programmierer haben Schwierigkeiten, eine derart komplexe Datenstruktur zu verstehen.

Das gleiche Programmierer, der mich über die Lesbarkeit des Codes sagte auch gesagt , „zeigen Sie mir Ihre Datenstrukturen und ich kann Ihnen sagen , wie Ihr Code funktioniert“ . Das heißt, guter Code beginnt mit sauberen, verständlichen Datenstrukturen. Wenn Sie Ihre Daten richtig gestalten, spielt der Code fast eine untergeordnete Rolle. Zugegeben, diese Aussage ist etwas übertrieben, weil Software offensichtlich mehr als nur Daten ist, sondern mit Daten beginnt . Wenn Sie also saubere, leicht verständliche Datenstrukturen erstellen, wird der Code erheblich verständlicher.


1 Natürlich gibt es Code, der selbst für die klügsten Programmierer sehr komplex und schwer zu verstehen ist. Einige Probleme sind von Natur aus komplex. Ich würde jedoch sagen, dass die überwiegende Mehrheit des Codes, der von der überwiegenden Mehrheit der Programmierer geschrieben wurde, nicht diese Art von Code ist.

Bryan Oakley
quelle
8
[1] Aus pessimistischer Sicht ist es normal, aber nicht gut.
Dan
1
Wenn das "fünfdimensionale Array" lediglich eine Karte von einem 4-Tupel oder einem 5-Tupel zu einer Strategie ist, könnte der Autor eine Hash-Tabelle oder eine Hilfssuchfunktion verwendet haben. Wenn der Autor jedoch die meiste Zeit damit verbringt, die Mechanismen für die Initialisierung des Arrays zu programmieren (verschachtelte For-Loops), wird der eigentliche "Algorithmus-Einblick" in dem Stapel "mechanischer Codes" untergehen. Programmierer versuchen, die letztere Art von Rauschen getrennt zu halten. Daher müssen gute Programmierer wissen, wie man Bibliotheken schreibt, um diesen mechanischen Code aufzunehmen.
rwong
1-D-Array ist eine Linie, 2-D ist ein Gitter, 3-D ist ein Würfel, 4-D ist eine Linie von Würfeln, 5-D ist ein Gitter von Würfeln usw., aber ich sehe keine Verwendung für solch eine komplexe Datenstruktur, wenn es um Schach geht.
user2785724
15

Es gibt zwei Arten davon: 1.) Verwirrung 2.) glückselige Unwissenheit

Der erste ist schlecht und kann mit der Zeit und Erfahrung verschwinden.

Das zweite ist gut, wenn Projekte größer werden: Wenn Sie sich jedes Implementierungsdetail merken müssen, um mit Ihrem Code arbeiten zu können, stimmt etwas nicht (siehe "Verstecken von Informationen").

Jeder Entwickler wird vergessen, wie Code funktioniert hat, und schreibt ihn so, dass ein anderer neuer Entwickler ihn verstehen und pflegen kann, ohne andere Teile des Programms zu beschädigen, die ihm ebenfalls unbekannt sind.

"Nicht wissen" ist also eigentlich eine Konstante in der Softwareentwicklung - es ist nur, wie oder ob Sie es verwalten.

telep
quelle
1
Sie berühren hier etwas Wichtiges, wie wichtig es ist, mit vernünftigen Mustern und Konventionen zu programmieren , da Implementierungsdetails in der Tat in Vergessenheit geraten. Wenn die Muster und Konventionen im Code jedoch sinnvoll sind, ist es einfach genug, die Details bei Bedarf aus dem Kontext zu übernehmen. Auf der anderen Seite, wenn der Code monolithisch, unergründlich und übermäßig clever ist, werden Sie nicht nur die Details irgendwann vergessen, sondern andere Programmierer, die versuchen, den Code zu pflegen, werden es viel schwerer haben.
Craig
12

Ich würde sagen, es kommt häufiger vor, als die Leute zugeben. Sogar Brian Kernighan spielte darauf an:

Das Debuggen ist doppelt so schwierig wie das Schreiben des Codes. Wenn Sie den Code so geschickt wie möglich schreiben, sind Sie per Definition nicht schlau genug, um ihn zu debuggen.

Wenn wir zum Geschäft fahren, nehmen wir eine Abfolge detaillierter Anpassungen der Positionen der Pedale und des Lenkrads vor. Das ist im Moment sehr einfach. Stellen Sie sich vor, Sie hätten diese Änderungen auf Papier aufgezeichnet und sie einem Freund gegeben, der eine Wegbeschreibung zum Geschäft benötigte.

Ebenso schreiben wir gerne Code auf einer Abstraktionsebene, aber wir lesen ihn gerne in mehreren höheren Abstraktionsebenen. Unsere bevorzugte Art, Code zu schreiben und zu lesen, steht daher in Konflikt. Das bedeutet, dass das Lesen von Code in der Regel ein separater, bewusster Schritt mit unterschiedlichen Fähigkeiten ist.

Was einen guten Programmierer auszeichnet, ist, dass er an diesem Punkt eine Abstraktion erzeugt, wenn er Schwierigkeiten hat, das zu lesen, was er gerade geschrieben hat. Ein besserer Programmierer macht das mehrmals und wird jedes Mal wählerischer. Erfahrene Programmierer beginnen später mit dem Prozess, sehen aber oft noch Verbesserungspotenzial, nachdem sie das gerade Geschriebene gelesen haben.

Karl Bielefeldt
quelle
Da muss ich Brian widersprechen, ich liebe das Debuggen, ich bin einer der wenigen Leute, die ich in der Branche kenne, aber ich bewerte keinen Code, den ich so hoch schreibe.
James Snell
@JamesSnell Er hat nicht gesagt, dass das Debuggen schlecht oder unangenehm ist, nur, dass es schwierig ist, und das Debuggen von kompliziertem Code ist noch schwieriger.
Cbojar
5

Ich denke, das ist etwas, das mit der Erfahrung verschwindet.

Wenn Sie komplexe Systeme schreiben, müssen Sie in der Lage sein, sauberen, wartbaren Code zu schreiben, den sowohl Sie als auch eine andere Person in der Zukunft verstehen können. Das, was Sie jetzt tun, ist im Wesentlichen nicht skalierbar.

Sie werden viele Momente haben, in denen Sie sich einen Code ansehen, den Sie vor 6 Monaten geschrieben haben, und sich überlegen, was zum Teufel hier vor sich geht, aber wenn es einen Tag nach dem Schreiben des Codes passiert, müssen Sie überlegen, ob Sie sauber sind Code 'mehr.

Quelle: nie ein 5 dimensionales Array verwendet :)

Erez Eshkol
quelle
3
@ 83457 - weil ein 5d-Array ein schlechtes Modell für ein 2d-Problem ist. Wenn Sie wirklich der Meinung sind, dass es ein guter Code ist, legen Sie ihn auf codereview.stackexchange.com ab und sehen Sie, welche Antworten Sie erhalten.
James Snell
2
@ 83457 - Wenn es verdammt verwirrend ist, haben Sie sich selbst geantwortet. Es ist möglich, dass ein 5-D-Array nicht verwirrend ist, aber wahrscheinlich nicht für die meisten von uns, unabhängig von ihrem Können.
Dbasnett
2
@ 83457 verdammt verwirrend zu sein, sollte schon eine sehr gute Motivation sein, das nicht zu nutzen.
Fabio Marcolini
3
Solange Sie für jede Dimension einen guten Grund haben, sehe ich keinen Grund, ein 5D-Array zu vermeiden. Vielleicht gibt es eine bessere Lösung, wie ein Wörterbuch mit einem komplexen Schlüssel oder mehrere Arrays mit niedrigeren Dimensionen, aber ich kann mir sehr gut vorstellen, dass ein 5D-Array für ein heikles Problem wie eine Schach-KI geeignet ist.
CodesInChaos
2
@CodesInChaos Abgesehen davon, dass dies nicht nur Arrays sind, stehen sie für sinnvolle Sequenzen (z. B. verschachtelte Entscheidungsbäume). Indem Sie sie entsprechend benennen und ihnen Typen zuweisen, damit sie nicht missbraucht werden können (selbst wenn diese Typen als Wrapper für Arrays verwendet werden), machen Sie den Code klarer und enthalten mit geringerer Wahrscheinlichkeit Fehler, ohne dass dies Kosten verursacht.
Deworde
5

"Normal" ist sehr subjektiv, also sage ich: Es ist sehr verbreitet, sollte aber vermieden werden.

Eines der Merkmale des "guten Codes" (ich habe gehört, dass es so etwas gibt) ist die Klarheit: Es sollte so klar sein, wie es die zugrunde liegenden Probleme zulassen. Wenn das Problem komplex ist, wäre der Code auch komplex, aber das ist inhärente Komplexität, im Gegensatz zu zufälliger Komplexität (ich habe zuerst von dieser Unterscheidung in Rich Hickeys Vortrag gehört ), die durch die falsche oder nicht korrekte Verwendung der richtigen Werkzeuge, Muster, Techniken und Methoden eingeführt wurde Praktiken.

Es gibt Fälle, in denen Unklarheiten akzeptabel sind, auch wenn das Problem nicht sehr komplex ist, z. B. wenn Sie eine Werbeseite schreiben, von der Sie wissen, dass sie für die Dauer der Marketingkampagne gültig ist. Das ist ein Wegwerfcode, der nicht gewartet werden darf. Für andere (und die meisten) Fälle ist dies nicht akzeptabel, da die Pflege eines solchen Codes viel kostet. Es ist jedoch üblich.

Verbunden:

  • Wenn Verstehen Umschreiben bedeutet - Artikel über das Problem des Verstehens des Codes.
  • Effektive ML - ein langes Gespräch unter ML / OCaml über das Schreiben des Codes für "Leser" (dh Betreuer): "Bevorzugen Sie Leser gegenüber Schriftstellern." Ich empfehle, das zu beobachten, egal welche Sprache Sie verwenden.
scriptin
quelle
2

Ich denke nicht, dass es normal ist, aber für sehr komplexe Programme, wie das von Ihnen erwähnte Schachprogramm, halte ich das mit Sicherheit für möglich.

Vor vielen Jahren, als ich gerade mein Abitur gemacht hatte (also noch relativ unerfahren war, große Programme zu schreiben), schrieb ich meinen ersten richtigen Compiler. Das Parsen war unkompliziert, aber dann musste ich es auf vier verschiedene Mikroprozessor-Befehlssätze ausrichten. Ich wollte den Compiler in seiner eigenen Sprache schreiben, also habe ich zuerst nur die Funktionen der Sprache verwendet, die ich unbedingt brauchte, den ersten Codegenerator in Assembler geschrieben und getestet, dass er den richtigen Code für die Teilmenge der Sprache generiert. Von da an konnte ich den Compiler verwenden, um sich selbst zu kompilieren, die verbleibenden Funktionen hinzuzufügen und sie auch im Compiler selbst zu verwenden

Ich habe dann die Backend-Codegeneratoren für jeden Mikroprozessor geschrieben und getestet, dass sie alle den richtigen Code generiert haben, aber obwohl der Code korrekt war, war er nicht sehr optimal. Also habe ich Optimierer für jeden Codegenerator geschrieben.

Als ich die Ausgabe der Codegeneratoren nach dem Hinzufügen der gesamten Optimierung testete, war ich häufig überrascht, welchen Code der Compiler generierte. Es war oft nicht so, wie ich den Code von Hand geschrieben hätte, aber es war richtig und ziemlich präzise.

Als mir nicht klar war, wie der Codegenerator einen Teil des Codes produzierte, versuchte ich, die Logik von Hand durchzugehen, aber es gab Zeiten, in denen ich einfach aufgab. Wenn ich viel Trace-Ausgabe hinzugefügt hätte, hätte ich es verfolgen können, aber ich habe mich nicht darum gekümmert, da der generierte Code zufriedenstellend war und ich mit anderen Projekten weitermachen musste.

Tcrosley
quelle
Mir scheint, Sie haben eine sehr gute Ausbildung mit einem soliden Fundament und Sie haben das Wissen auf sehr hohem Niveau verinnerlicht. Ich denke, das ist etwas selten unter den typischen Programmierern. Die meisten typischen Programmierer (einschließlich mir) müssen sich abmühen, mit dem für die heutige Aufgabe erforderlichen Wissen Schritt zu halten, da sich die Technologie so schnell ändert.
rwong
@rwong Danke. Das meiste davon ist Erfahrung - ich schreibe seit 46 Jahren Programme und habe nicht die Absicht, bald aufzuhören.
Tcrosley
2

Hier gibt es viele anständige Antworten.

Ich habe ein paar Einstellungen dazu.

Eine ist, dass wenn Sie nicht verstehen, warum Ihr Code zu funktionieren scheint, a) es wahrscheinlich nicht funktioniert (es scheint wahrscheinlich nur zu funktionieren) und b) Sie entweder die Problemdomäne nicht gut genug verstanden haben, als Sie hat mit dem Codieren begonnen oder die Problemdomäne nicht in kleinere, vereinfachte Einheiten unterteilt, bevor Sie begonnen haben.

Meine andere Annahme ist, dass der eigentliche Schlüssel darin besteht, in Ihrem Code vernünftige Muster und Konventionen zu verwenden. Das ist ein weitaus größeres Thema, als ein kleiner Beitrag behandeln kann. Aber suchen Sie nach guter Literatur zu diesem Thema, einschließlich einiger der alten Standbys wie den Büchern "Code Complete" und "Writing Solid Code".

Implementierungsdetails ändern sich. Die einzige echte Konstante ist das funktionale Ziel des Codes. Wenn Sie jemals mehr als eine Funktion schreiben, werden Sie mit der Zeit bestimmte, detaillierte Implementierungsdetails vergessen. Aber Sie sollten auf jeden Fall verstehen, wie die Teile funktionieren, wenn Sie sie konstruieren, und Sie sollten in der Lage sein, ein Diagramm des Ganzen zu zeichnen und zu verstehen, wie die Teile zusammenarbeiten.

Wenn Sie Muster verwenden und die Common-Sense-Konventionen befolgen, ist es viel einfacher, die spezifischen Implementierungsdetails wiederzuerlangen, wenn Sie den Code erneut betrachten. Oder wenn jemand, der den Code noch nie gesehen hat, ihn zum ersten Mal ansieht. Das Befolgen dieser Konventionen und Muster im Laufe der Zeit bedeutet auch, dass sich Implementierungsdetails von den Konventionen und Mustern selbst abheben. Dies ist ein weiterer Faktor, der das Verständnis des Codes erleichtert.

Die meisten Probleme, die wir mit Software angehen, sind von Natur aus komplex. Software-Design ist eine Übung im Umgang mit Komplexität.

Craig
quelle
1

Ich würde es nicht normal nennen , aber es kann definitiv passieren. Wenn es Ihnen passiert, kurz nachdem Sie den fraglichen Code geschrieben haben, denke ich, dass Ihr Code unnötig komplex ist und vereinfacht werden sollte, oder Sie einfach nur leicht abgelenkt werden. :)

Aber wenn Sie Ihren Code weglegen, sich auf andere Projekte konzentrieren und nach Wochen, Monaten oder sogar Jahren wieder darauf zugreifen, ist es keine große Überraschung, dass Sie alles noch einmal herausfinden müssen.

Aber Sie können etwas dagegen tun. Nach allem, was Sie sagen, denken Sie anscheinend nicht genug über Ihren Code nach, während Sie ihn schreiben, und Sie erschweren es Ihrem zukünftigen Selbst, zu verstehen, was vor sich geht. Nutzen Sie dieses Wissen zu Ihrem Vorteil: Dies ist die beste Motivation, um gut strukturierten, gut dokumentierten und verständlichen Code zu erstellen. Sie wissen aus erster Hand, was passiert, wenn Sie sich nicht um die Qualität Ihres Codes kümmern. Wenn Sie das wissen, sollten Sie auf lange Sicht ein besserer Programmierer sein. Wenn Sie an Softwareprojekten mitarbeiten, werden Ihre Kollegen Ihnen dafür danken, dass Sie verständlichen Code erstellt haben. Und die Fehlerrate Ihres Codes wird sich ebenfalls verbessern.

Mindriot
quelle