Was ist schöner Code in C ++ und warum kümmern sich die meisten Programmierer so sehr darum? [geschlossen]

8

Da die meisten Projekte eine C ++ - API verwenden, behandeln sie Einschränkungen der API und Einschränkungen des Projekts selbst.

Ich bin ein Anfänger in der Programmierung, ich benutze OOP überhaupt nicht, weil es niemandem klar gelungen ist, mir zu erklären, WARUM es so wichtig ist, sich auf den privaten Bereich zu beschränken, um zu verhindern, dass andere Programmierer die Konsistenz der Datenorganisation brechen.

Ich kann mit OOP immer noch einverstanden sein, da es immer noch erlaubt, einige großartige Dinge wie Qt und Ogre3D zu machen, aber das sind nur APIs, keine Anwendungen, und diese Codes müssen perfekt sein, damit niemand die Arbeit kritisieren kann.

Ich verstehe nicht, warum die meisten Programmierer, da sie Apps und keine APIs erstellen, perfekten Code erstellen möchten, wie sie einen genialen Code entwerfen, und Zeit damit verschwenden.

Jokoon
quelle
19
Nehmen Sie sich ein paar Jahre Zeit, um zu Ihrem alten, nicht perfekten Code zurückzukehren und zu versuchen, Funktionen hinzuzufügen, Fehler darin zu beheben usw. Sie werden sehen, warum es den Leuten gleich wichtig ist, ihn so richtig und klar wie möglich zu machen Zeit um.
R0MANARMY
Siehe (diese Frage) [ programmers.stackexchange.com/q/65216/8823] . Nicht weil Sie kein Programmierer sind, sondern weil es eine gute Beschreibung dafür gibt, warum schöner Code gut ist
Austin Hyde
2
Handelt es sich bei dieser Frage um schönen Code, OOP oder privaten Bereich? Ich kann es wirklich nicht sagen.
Sean McMillan
1
Wow ... ich weiß nicht, wo ich anfangen soll. Ich hoffe, ich muss Ihren Code nie sehen oder damit arbeiten ...
Rig
1
Guter Code und eine gute API haben viele Gemeinsamkeiten. Guter OOP-Code sollte eine Schnittstelle haben, die genau wie eine gut gestaltete API aussieht.
Rwong

Antworten:

12

Haben Sie jemals das Sprichwort "Niemand ist eine Insel" gehört ?

Für die meisten Programmierer gilt dies. Kaum jemand schreibt Code, der "nur eine App" ist. Bei vielen nicht trivialen Apps schreibt ein Programmierer die Benutzeroberfläche, die von einem Designer leicht geändert werden muss. Es muss auch eine eindeutige Datenbindung an die Geschäftslogik (Controller, ViewModel oder wie auch immer Sie es nennen möchten) ermöglichen. Ein anderer Programmierer schreibt diesen Controller, der oft sehr komplex sein kann, aber einfach genug sein muss, um vom Front-End-Programmierer problemlos verwendet zu werden. Dieser Geschäftslogikcodierer verbraucht Code von demjenigen, der die Datenschicht geschrieben hat (Modell, Repository usw.). Sie müssen OOP nicht verwenden. OOP ist jedoch ziemlich gut darin, Logik hinter einer Schnittstelle zu kapseln, damit andere Personen, mit denen Sie arbeiten, Ihren Code verwenden können, ohne ihn zu beschädigen (vorausgesetzt, Sie haben diese Schnittstelle getestet!). Abstraktion ist nicht die Silberkugel,

Sie könnten jetzt sagen: "Im Ernst, ich bin eine Ausnahme und niemand wird meinen Code sehen oder überhaupt damit arbeiten." Fair genug, aber wenn Sie in einigen Monaten einen Fehler in dieser App beheben müssen oder ein paar Funktionen hinzufügen möchten, werden Sie wahrscheinlich feststellen, dass die Person, die diesen Code damals geschrieben hat, und die Person, die ihn jetzt ändert, es sind zwei völlig verschiedene Leute. Wir gehen oft davon aus, dass wir uns an Dinge erinnern werden, was der Grund dafür ist, warum wir schlampigen Code schreiben, aber die Wahrheit ist, dass Sie sich in sechs Monaten nicht mehr an die Hacks erinnern werden, die Sie jetzt in Ihre Anwendung eingefügt haben. Ihr zukünftiges Ich wird genug zu tun haben, warum also nicht ihm / ihr eine Pause geben?

Morgan Herlocker
quelle
43

Jeder Dummkopf kann Code schreiben, den ein Computer verstehen kann. Gute Programmierer schreiben Code, den Menschen verstehen können. ~ Martin Fowler

Kurz gesagt, deshalb möchten Sie sich für schönen Code interessieren.

Sie schreiben keinen Code für den Computer. Der Computer versteht ohnehin nur Binärcode (der aus Ihrem Quellcode über Compiler und Interpreter erzeugt wird). Es geht nicht um Schönheit oder Klarheit oder darum, ob Ihr Code das tut, was er tun soll.

Sie schreiben Code für Ihre Programmierkollegen. Und sie tun dasselbe für dich. Wenn Sie einen von jemand anderem geschriebenen Code nicht verstehen können, wie hoch ist Ihrer Meinung nach Ihre Chance, einen Fehler zu finden und zu beheben oder neue Funktionen hinzuzufügen?

wolfgangsz
quelle
1
Ich würde hinzufügen, dass es besonders einfach ist, vollständig kryptischen Code in C ++ zu schreiben, und deshalb ist dies in dieser Sprache noch wichtiger!
Deadalnix
1
Nun, ich stimme diesem Zitat nicht wirklich zu, wiederverwendbarer Code ist zwar guter Code, aber Sprachen werden so erstellt, dass Programmierer schneller arbeiten können und nicht unbedingt von anderen Programmierern gelesen werden müssen. Es ist schmerzhaft, Code zu lesen. Geben Sie also entweder Kommentare ein oder ändern Sie das Design, um es für einen Menschen verständlicher zu machen. Ja, aber gutes Design ist nicht immer mit "leicht verständlich" verbunden. Ein Programm kann sowohl einfache als auch komplizierte Aufgaben ausführen, und Programmiersprachen können einschränken, wie gut Sie anspruchsvolle Apps entwerfen können. Programmiersprache macht die Dinge einfacher, nicht schicker.
Jokoon
3

Was andere gesagt haben, als ob Sie nie wissen, ob Sie Ihren Code in Zukunft möglicherweise wieder benötigen, ist natürlich richtig.

Aber für mich gibt es einen wichtigen Punkt, warum ich immer versuche, schönen Code zu schreiben:

Es ist Training, um besser zu werden.

Wenn ich etwas Neues über eine von mir verwendete Sprache oder über einige allgemeine Programmierkonzepte lerne, versuche ich sofort, sie zu nutzen und sie zu einem Teil meines täglichen Workflows und meiner mentalen Toolchain zu machen.

Wenn Sie nur über so etwas wie OOP lesen, werden Sie das meiste innerhalb weniger Wochen vergessen. Und Sie werden nie lernen, wie man es richtig auf große Probleme anwendet, solange Sie sich nicht selbst beibringen, indem Sie es auf kleine Probleme anwenden.

Beispiel:

Warum ist es wichtig, sich auf den privaten Bereich zu beschränken?

In kleinen Projekten ist es nicht. Einige Sprachen (zum Beispiel Ruby) raten sogar bis zu einem gewissen Grad von dieser Art der Kapselung ab. Aber es gibt Verwendungen dafür. Viele.

Und die Verwendung bringt bestimmte Probleme und viele Details mit sich, die Sie lernen müssen. Wenn Sie es in kleinen Projekten verwenden, lernen Sie dies. Sie werden einige Fehlermeldungen von Ihrem Compiler sehen, die für Sie neu sind, und in einem kleinen Projekt können Sie die Ursache des Problems leichter finden.

Sie lernen Namespaces in C ++ kennen. Sie werden in kleinen Projekten nicht so dringend benötigt. Gleiches gilt für die allgemeine Struktur von Header-Dateien und enthält. All dies können Sie frühzeitig beim Schutz einer kleinen Codebasis lernen.

thorsten müller
quelle
1

Es geht darum, Legacy-Code pflegen zu müssen. Und in ein paar Monaten wird der Code, den Sie jetzt schreiben, zu Legacy-Code, den Sie auch pflegen müssen.

Codierung für gewalttätige Psychos

Schlüsselfertig
quelle
1
  1. Was R0MANARMY in seinem Kommentar gesagt hat. Sauberer und "schöner" Code erleichtert das Lesen, Verstehen, Verwalten, Ändern und Korrigieren in der Zukunft, nicht nur für Sie selbst, sondern auch für andere, die nach Ihnen kommen.

  2. Manche Menschen versuchen, wenn sie etwas tun, es so gut wie möglich zu machen, so dass es "perfekt" oder in diesem Fall "schön" ist. Ich habe festgestellt, dass es eine große Überschneidung zwischen dieser Gruppe von Leuten und Entwicklern gibt (ich selbst eingeschlossen!).

Beachten Sie jedoch, dass "schön", "sauber" oder "elegant" höchst subjektive Begriffe sind, die für verschiedene Menschen unterschiedliche Bedeutungen haben. Nach allem, was ich gesehen habe, wird Code, der allgemein als schön, sauber und / oder elegant angesehen wird,

  • Ist leicht zu lesen und zu verstehen
  • Es liegt kein oder nur wenig unnötiger Code herum
  • Ist leicht erweiterbar und / oder modular
  • Ist gut dokumentiert
  • Befolgen Sie alle Standards für verwandte Sprachen / Technologien
  • Und macht nichts Unerwartetes (zB Nebenwirkungen bei einer Accessor-Methode)
Austin Hyde
quelle
1

Ich stimme der Wartbarkeitssache zu. Versuchen Sie einfach, selbst ein relativ großes Projekt zu erstellen, und Sie werden all das Durcheinander sehen, das Ihnen beim Beheben von Fehlern, Hinzufügen neuer Funktionen usw. die Hände bindet. Aber um über Schönheit zu sprechen:

Schöner Code ist die gewünschte Produktqualität, da (zumindest C ++) Programmierung eine KUNST ist.

Reben
quelle
1
Obwohl mit der Einführung von Lambdas jetzt weniger Haie in Formaldahyd involviert sind
Martin Beckett
1

[...] niemand hat es klar geschafft, mir zu erklären, WARUM es so wichtig ist, sich auf den privaten Bereich zu beschränken, um zu verhindern, dass andere Programmierer die Konsistenz der Datenorganisation brechen.

In einem ausreichend kleinen Team mit einer ausreichend kleinen Codebasis, die wirklich gut auf gute Standards abgestimmt ist (möglicherweise nur eine Person), finden Sie häufig zuverlässige Software, die alle Daten offen lässt, damit jeder mit allen Datenfeldern in Kontakt treten kann eines structexponierten weit geöffneten und mit der structDefinition weit offen für jeden, der diesen Header enthält, um darauf zuzugreifen. Murphys Gesetz gilt in diesen Fällen nicht immer.

Aber ich habe im umgekehrten Szenario einer riesigen Codebasis mit vielen Millionen LOC aus den 80er Jahren mit einem großen Team von Entwicklern aus der ganzen Welt gearbeitet, bei denen wir uns nur alle paar Monate persönlich getroffen haben, manchmal lose koordiniert kaum die gleiche Sprache sprechen, keine Codierungsstandards außer dem SDK, dem die Leute sowieso oft nicht gefolgt sind, keine Unit- / Integrationstests, SVN ohne Verzweigung verwenden und manchmal 6 Wochen ohne Code einchecken, nur um uns mit Fehlern zu bombardieren, und Erst dann verstand ich wirklich den Wert von Informationen, die Invarianten verstecken und aufrechterhalten .

Ich habe mich mit Fehlern befasst, bei denen ich das Problem nicht einmal konsistent auf meinem Computer reproduzieren konnte, und manchmal konnte keiner von uns zwischen dem gesamten Team. Und als ich endlich das vom Benutzer gemeldete Problem oder etwas, das ihm nach allen Arten von Versuch und Irrtum ähnelte, reproduzieren konnte (und der Versuch und Irrtum dauerte oft Stunden, weil die Ineffizienz unserer Software mit der Ausführung beim Debuggen gegen die Produktion am Ende des Benutzers verbunden war Daten dauerten oft mehr als 15 Minuten, nur um die Daten zum Laden zu bringen.) Ich verfolgte sie bis zu structeinem String-Typ len, für den eine negative Garbage-Zahl festgelegt war, z. B. eine String-Länge von -921141282.

Das sollte niemals passieren, aber wer hat es getan? Also musste ich Speicher-Haltepunkte setzen und herausfinden, und als ich es schließlich tat, war es wie eine kaskadierende Interaktion von nicht initialisierten Variablen, die arithmetisch verwendet wurden, was letztendlich dazu führte, dass ein Zeichenfolgenfeld lenauf eine negative Müllzahl gesetzt wurde, und dieser Code hatte es nicht wurde in Jahren geändert. Es flog unter dem Radar.

Und die ganze Zeit, nachdem ich auf viele solche Fehler gestoßen war, dachte ich mir, wie viel zuverlässiger wäre unsere Software, wenn sie nur verwendet würde gettersund setters? Getter und Setter weisen im Allgemeinen auf die schlechtesten möglichen Arten von Schnittstellendesigns hin, aber ein Setter könnte zumindest einen Assertionsfehler auslösen, wenn jemand versucht, die Länge eines Strings auf einen negativen Wert zu setzen. Wir hätten diesen Fehler Jahre fangen könnenvorher zu dem genauen Zeitpunkt, zu dem es in Sekunden eingeführt wurde, nicht der Höhepunkt stundenlanger Ermittlungsbemühungen. Und das ist nur egoistisch als Entwickler zu denken; Es deckt nicht alle Stunden der Trauer ab, die es den Benutzern und dem QA-Team hätte ersparen können. Sie wissen, dass Ihr System an einem ziemlich schlechten Ort ist, wenn Sie davon träumen, wie viel besser es sein könnte, wenn es angesichts der letzten 35 Fehler, die Sie die ganze Nacht über behoben haben, Setter und Getter verwendet.

Wir hatten sogar Fälle, in structsdenen dokumentiert wurde, dass niemand sonst auf diese Datenfelder zugreifen sollte, nur um Stellen im System zu finden, die auf diese Datenfelder zugreifen.

Dies sind also die Arten von Dingen, die Sie nur dann wirklich in vollen Zügen genießen können, wenn Sie sich diesem Worst-Case-Szenario stellen, aber Sie werden es oft tun, es sei denn, Sie haben das Glück, den Rest Ihres Lebens damit zu verbringen, an kleineren Codebasen mit gut koordinierten Teams zu arbeiten starke Kodierungsstandards.

Was ist schöner Code in C ++ [...]?

Das ist eine schwierige Frage. Ich versuche immer noch, das herauszufinden. Der größte Teil des Codes, den ich für schön halte, den ich im Laufe der Jahre geschrieben habe, oder zumindest zuverlässig und relativ zeitlos und stabil (ohne Änderungen zu benötigen / zu wollen), wurde in C und kürzlich in Lua geschrieben. Ich habe immer noch Schwierigkeiten, C ++ - Code zu schreiben, der den Test der Zeit so weit zu bestehen scheint, dass ich einige Jahre später nicht mehr darüber nachdenke und mir zumindest wünsche, ich könnte ihn ändern. Ich habe das Gefühl, dass es seit C ++ 11 einfacher geworden ist, aber ich brauche einige Jahre, um herauszufinden, wie gut mein Code überlebt, ohne dass Änderungen erforderlich sind, um dies sicher zu sagen. Für mich ist die ultimative "Schönheit" "Stabilität", wie in Code, der keine weiteren Änderungen benötigt und nicht einmal versucht, aber dennoch für die kommenden Jahre relevant und nützlich bleibt.


quelle
0

Bei der Definition sauberer und nützlicher Schnittstellen ("schön" ist ein schlechtes Qualifikationsmerkmal) muss Folgendes sichergestellt werden:

  1. Der Benutzer versteht mit minimalem Aufwand, wie er Ihr Objekt (oder System von Objekten) verwendet, indem er einfach seine Benutzeroberfläche liest.
  2. Der Benutzer wird es schwer haben, das Objekt / System falsch zu verwenden - die Schnittstelle macht es schwierig, etwas falsch zu machen oder Probleme frühzeitig zu signalisieren.
  3. Die Schnittstelle beschreibt eine nützliche Abstraktion.

Die Punkte 1. und 2. erfordern, dass Sie viel über den Vertrag nachdenken, den Sie mit Ihrem Benutzer abschließen. Dieser Vertrag oder dieses Protokoll ist die Möglichkeit, dem Benutzer mitzuteilen, wie er Ihr System verwenden kann. Beispielsweise erzählen schreibgeschützte Elementfunktionen (const-Elementfunktionen) viel darüber, in welchen Situationen Sie diese Funktion aufrufen können sollten. Auf die gleiche Weise können die Attribute der einzelnen Funktionen den Benutzer dazu bringen, die minimalen Informationen zu sammeln und bereitzustellen, die für das Funktionieren des Systems erforderlich sind.

Alle Punkte zusammen legen nahe, dass Ihre Schnittstellen nur Dienste anzeigen sollten, die für den Benutzer nützlich sind. Beschränken Sie zunächst die Verwendung des Systems durch den Benutzer auf das, wofür das System entwickelt wurde. Zweitens, indem er ihn daran hindert, den inneren Zustand falsch zu manipulieren. Der einfachste Weg in C ++, dies zu erreichen, besteht darin, alle Mitglieder privat zu machen und explizit anzugeben, welche Dienste Ihr System mithilfe von Mitgliedsfunktionen oder globalen Funktionen (in Namespace (s)) bereitstellt. Eine andere Möglichkeit ist die Verwendung der PImpl-Sprache.

Drittens und das Wichtigste: Ihre Benutzeroberfläche sollte eine nützliche Abstraktion bieten, sodass der Benutzer die Implementierung nicht verstehen muss. Wenn ich ein Auto oder eine Waschmaschine fahre, möchte ich nicht wissen, wie es im Inneren aufgebaut ist (auch wenn ich ein Technikfreak bin ...). Ich muss es nur benutzen und mich nicht darum kümmern, was drin ist.

Es ist schwer.

Jede Protokolldefinition wie das Entwerfen einer Programmiersprache oder das Entwerfen einer Klasse ist nicht so offensichtlich, wie Sie vielleicht zuerst gedacht haben. Es ist viel Erfahrung erforderlich, um die Feinheiten des Entwerfens von Schnittstellen zu erkennen.

All das ist nicht aufschlussreich, wenn Sie Strukturen oder Klassen definieren, die Konzepte auf sehr niedriger Ebene darstellen. Je höher die Hardware, desto mehr benötigen Sie saubere, klare und nützliche Schnittstellen.

Klaim
quelle