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?
Antworten:
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.
quelle
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.
quelle
Ich würde sagen, es kommt häufiger vor, als die Leute zugeben. Sogar Brian Kernighan spielte darauf an:
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.
quelle
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 :)
quelle
"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:
quelle
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.
quelle
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.
quelle
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.
quelle