it-swarm.dev

Wie definieren Sie eleganten Code?

Mögliches Duplikat:
Was bedeutet es, „guten Code“ zu schreiben?

In einer Diskussion über die Codierungsqualität und wie Sie sie identifizieren, stieß ich auf eine Diskussion über das Testen der Codierungsfähigkeit von Personen, indem sie zeigten, wie sie zwei Werte mithilfe eines Codetauschs austauschen würden, um das Ziel zu erreichen. Es wurden zwei Schlüssellösungen hergestellt:

  1. Führen Sie eine Ersatzvariable ein, um das Paket der Werte zu übergeben, oder:
  2. Verwenden Sie einige bitweise Operatoren.

Es folgte dann ein Argument, das tatsächlich die bessere Lösung war (ich würde mich der ersten Option zuwenden, während ich mir bewusst wäre, dass die zweite existiert, aber abhängig von den fraglichen Werten möglicherweise nicht immer wie erwartet bewertet wird).

In Anbetracht der Geschichte von Mel the Real Programmer bin ich daran interessiert zu wissen, wie Sie Code als elegant bewerten oder nicht, und Prägnanz ist ein Schlüsselmerkmal von elegantem Code.

70
temptar

Guter Code sollte zuallererst sauber, einfach und leicht verständlich sein. Je einfacher und sauberer es ist, desto geringer ist die Wahrscheinlichkeit, dass Insekten eindringen. Wie Saint-Exupery prägte, wird "Perfektion erreicht, nicht wenn nichts mehr hinzuzufügen ist, sondern wenn nichts mehr wegzunehmen ist. "

Darüber hinaus ist eleganter Code normalerweise das Ergebnis einer sorgfältigen Analyse des Problems und der Suche nach einem Algorithmus und Design, die den Code erheblich vereinfachen (und ihn häufig beschleunigen) zu). Z.B. Programming Pearls zeigt einige Beispiele, bei denen ein während der Analyse gewonnener Einblick einen völlig anderen Anstellwinkel ergab, was zu einer sehr einfachen, eleganten und kurzen Lösung führte.

Zu zeigen, wie klug der Autor ist, kommt erst danach ;-) Die Leistungsmikrooptimierung (wie die Verwendung der von Ihnen erwähnten bitweisen Operationen) sollte nur verwendet werden, wenn man (mit konkreten Messungen) beweisen kann, dass der fragliche Code der Engpass ist und dass die Änderung tatsächlich die Leistung verbessert (ich habe gegenteilige Beispiele gesehen).

77
Péter Török

Eleganter Code ist eine Kombination aus:

  • Richtigkeit. IMHO kann kein falscher Code wirklich elegant sein.
  • Prägnanz. Weniger Code bedeutet weniger Fehler, weniger Verständnis *.
  • Lesbarkeit. Je einfacher es ist, Code zu verstehen, desto einfacher ist die Wartung.
  • Performance. Bis zu einem Punkt. Vorzeitig pessimierter Code kann nicht wirklich elegant sein.
  • Befolgen Sie die festgelegten Standards der Plattform oder des Projekts. Bei zwei gleich eleganten Optionen ist diejenige die beste, die dem etablierten Standard am nächsten kommt.
  • Genau so würde ich es machen. Okay, ich mache Witze, aber es ist einfach, Code so zu kennzeichnen, wie Sie es NICHT als "unelegant" bezeichnen würden. Bitte tun Sie das nicht - seien Sie offen für anderen Code.

Natürlich gibt es auch das allzu oft wahre Sprichwort: "Für jedes Problem gibt es eine Lösung, die einfach, elegant und falsch ist.".

* Wie die folgenden Kommentare zeigen, gibt es einige Streitigkeiten über kürzeren Code. "Prägnant" bedeutet nicht "in so wenigen Zeichen wie möglich", sondern "kurz und klar ausgedrückt".

47

Einfacher Code ist Code, der so lesbar ist, dass selbst unerfahrene Programmierer (zumindest allgemein) herausfinden können, was der Code tut. (Siehe: Ruby-Ausdruckssyntax )

Beeindruckend komplexer Code ist Code, der in möglichst wenigen Zeilen so viel wie möglich macht, ohne die Lesbarkeit wirklich zu berücksichtigen (siehe: Perl )

Eleganter Code ist Code, der andere Entwickler dazu bringt zu sagen: "Oh Mann, warum habe ich nicht daran gedacht?!" Es liegt irgendwie zwischen den ersten beiden, mit Code, der möglicherweise nicht so leicht zu erkennen ist, dass Ihre Eltern ihn lesen können, aber nicht mit arkanen Kritzeleien, für deren Interpretation ein Codex erforderlich ist. Es macht den Job, macht es na ja und lässt die Leute, die den Code pflegen, nicht am Kopf kratzen.

28
asfallows

Fred Brooks unterteilt die Komplexität einer Lösung in die Kategorien "wesentliche Komplexität" und "zufällige Komplexität" . Perfekt eleganter Code ist für mich das, was all "wesentliche Komplexität" und nein "zufällige Komplexität" ist. Der Trick ist, dass verschiedene Programmierer unterschiedliche Vorstellungen davon haben, was "komplex" ist. Daher sind wir uns wahrscheinlich nicht einig, ob ein bisschen Code elegant ist.

Zum Beispiel finde ich die Struktur von LISP-Code wesentlich eleganter als die Struktur von Code in C-ähnlichen Sprachen. Andererseits verletzen die Präfixnotation von LISP und die explizite Analyse des Analysebaums unsere Intuition darüber, wie mathematische Ausdrücke aussehen sollten, was das Lesen von LISP-Code für Menschen erschweren kann. Infolgedessen halten viele Programmierer all diese Klammern in LISP überhaupt nicht für "elegant", sondern für ziemlich hässlich. Für jemanden, der wirklich besorgt darüber ist, wie der Compiler den Code interpretiert, kann LISP elegant erscheinen. Für jemanden, der sich mehr Gedanken darüber macht, wie die Leute den Code interpretieren, kann LISP hässlich erscheinen.

14
Aidan Cully

Prägnanz ist eine wichtige Komponente, aber für mich muss Code, um als elegant bezeichnet zu werden, auch so leicht verständlich sein, dass Sie sagen: "Natürlich ist das der offensichtliche Weg, dies zu tun!" Auch wenn es paradoxerweise nicht der erste Weg ist, an den Sie gedacht haben. Wenn es diesen Test nicht besteht, kann es als "klug" oder "effizient" bezeichnet werden, aber nicht elegant.

11
Karl Bielefeldt

Es ähnelt der Poesie, die eine elegante Sprache ist.

Dichter können in sehr wenigen Worten sagen, was andere Seiten und Seiten brauchen würden, um zu sagen, und nicht so gut. Elegante Codierer können dasselbe mit Code tun.

Ein typisches Beispiel ist der Vergleich einer typischen Implementierung von Quicksort in C mit Quicksort in Haskell:

quicksort :: Ord a => [a] -> [a]
quicksort []     = []
quicksort (p:xs) = (quicksort lesser) ++ [p] ++ (quicksort greater)
    where
        lesser  = filter (< p) xs
        greater = filter (>= p) 

(kleiner und größer kann für eine dreizeilige Lösung eingefügt werden).

10
user1249

Der XOR Swap ist ziemlich bekannt. Und jeder, der zumindest ein bisschen von der Demut hat, die Dijkstra verlangt, wird Ihnen sagen, es ist der falsche Weg, Dinge zu tun. Es ist nicht nur schwieriger Lesen Sie für Menschen, aber auch für Compiler. Compiler sind relativ gut in der Flussanalyse und Registerzuordnung und in allen möglichen Dingen. Mit einem guten Compiler können Sie nicht erwarten, dass jede von Ihnen erstellte Variable tatsächlich auf dem Stapel/in einem Register unter existiert Jeder Zeitpunkt. Was Sie tun müssen, ist, die Dinge klar auszudrücken. In einer Sprache, die den Aufruf als Referenz unterstützt, ist dies der Weg: swap(x, y);.
Dies ist die beste Lösung (ich wage es zu sagen, zumindest angesichts der von Ihnen bereitgestellten Alternativen). Es ist eine Aussage und es ist selbsterklärend. Es verwendet kein Voodoo wie das XOR Swap). Es führt nicht das Rauschen einer temporären Variablen und 3 Zuweisungsanweisungen ein. Das passiert im Swap. Angenommen, es ist eine Funktion. Ein anständiger Compiler wird diesen Aufruf einbinden. Sie können ihn auch zu einem Makro machen.

Was Code wirklich elegant macht, ist das Fehlen von Redundanzen, die Orthogonalität und die Einfachheit. Es sorgt für robuste Systeme, die übereinander wachsen. Wenn überall wiederkehrende Anweisungsgruppen vorhanden sind, wann immer Sie einen Austausch wünschen, führt dies zu Redundanz, mangelnder Orthogonalität und fehlgeschlagener Einfachheit.

7
back2dos

Es ist leicht zu erkennen, was eleganter Code bewirkt. Sie erhalten die Frage: "Warum habe ich nicht daran gedacht?" Stimmung. Dies hängt davon ab, wie komplex das Problem und die verwendete Sprache sind.

Dies bedeutet nicht, dass die beste oder einfachste Lösung automatisch elegant ist. Einfach ist oft eine seiner Eigenschaften. Obwohl Änderungen normalerweise einfacher sind, behalten sie nicht immer die Elaganz bei.

4
JeffO

Ich vergleiche hier gerne Code mit Printmedien.

Sie wissen, dass Sie es hassen, wenn Sie vereinfachte Artikel lesen. Verdummt. Wenige Fakten, einfache Sätze. Dies führt zu Code, den ich mit Anfängern verknüpfe: Trivial, naiv, Implementierung, nichts ist zu kompliziert, aber langwierig und voller unnötiger Schritte.

Auf der anderen Seite kennen Sie diesen Elfenbeinturmstil. Sie lesen ein Buch von bekannten Philosophen. Sie lesen eine wissenschaftliche Arbeit über eine komplizierte Angelegenheit: Der Stil scheint oft sehr lang zu sein. Wörter werden nicht wiederverwendet, Sie müssen zeigen, dass Sie ein Dutzend Synonyme kennen. Während der eigentliche Inhalt rein, gut und interessant sein mag, macht es der Schreibstil schwierig, ihm zu folgen. Dieser Stil verwischt die ursprüngliche Gedankenlinie. Dies ist clever Code.

Eleganter Code ist irgendwo in der Mitte und genauso subjektiv wie Präferenzen sein können. Sie können schlimme Fälle leicht erkennen und beschreiben, aber Perfektion ist für die meisten von uns anders.

2

Gut ist das Fehlen von Schlecht. Es gilt für alles im Leben und Code ist keine Ausnahme. Somit,

Guter Code ist einer, der keinen Geruch hat! Daher ist es wichtig, dass Sie sehen und verstehen, was ein Codegeruch ist. Kein Witz beabsichtigt.

Denk darüber nach. Du sagst, du bist nur glücklich, weil du NICHT traurig bist oder von deiner Traurigkeit geritten wurdest. Ebenso nennen Sie etwas einen guten Code, wenn Sie im Code nichts Schlechtes sehen. Jeder Qualitätsaspekt des Codes (Wartbarkeit, Lesbarkeit usw.) kann erreicht werden, indem der Codegeruch beseitigt wird. Und ob Sie es glauben oder nicht, das passiert nicht beim ersten Mal - es passiert iterativ :)

2
karthiks

Eleganz ist die Minimierung der Komplexität. Wenn Sie den Code schnell an einen anderen Programmierer mit angemessenen Fähigkeiten weitergeben können und dieser in der Lage ist, die Arbeit fortzusetzen (und hoffentlich seinem ursprünglichen Standard gerecht zu werden), ist der Code wahrscheinlich elegant.

Gut geschriebene Software sollte mindestens zehn Jahre lang verfügbar sein. Die anfängliche Eleganz kann durch spätere Hacks erschreckt werden, aber die Zeitdauer, in der der Code überlebt, ist oft eine vernünftige Messgröße dafür, wie gut er ursprünglich geschrieben wurde. Schlecht geschriebener Code stagniert entweder (und die Leute hacken ihn herum) oder wird überarbeitet (obwohl ich in der Praxis gesehen habe, dass Leute eleganten Code durch weniger gute Lösungen ersetzen, weil sie ihn nicht genau betrachtet haben).

2
Paul W Homer

Meine Definition ist einfach, leider können Sie nicht (alles) selbst bestimmen.

Eleganter Code hat die folgenden Funktionen:

  • Es löst das Problem.
  • Ich kann den Tests so vertrauen, dass ein Test unterbrochen wird, wenn ich ein Verhalten ändere.
  • Wenn ich oder ein anderer Entwickler den Code öffne, ist es sofort einfach zu folgen. Alle nicht trivialen Logikblöcke werden durch einen Kommentar beschrieben.
  • Einfache Dinge sind einfach, harte Dinge sind möglich.
  • Jemand anderes ist bereit, die Entwicklung des Codes zu übernehmen, obwohl ich noch da bin. Ohne gezwungen zu werden.
1
Dmitriy Likhten

Eleganter Code ist nicht dasselbe wie elegantes Design, obwohl es eine Kreuzung zwischen den beiden gibt.

Wie definieren Sie ein elegantes Gemälde? Es ist schön anzusehen, perfekt lesbar, macht Sinn, ist leicht zu warten und macht einfach den Job.

Elegantes Design hilft bei elegantem Code. Sie können keinen eleganten Code ohne gutes Design haben, aber Sie können hässlichen Code mit gutem Design haben. Es ist viel besser zu schreiben, wenn can_can_add_apples_to_my_basket (20) dann add_apples_to_basket (20), sonst render_not_enough_room_to_add_apples (20) endet und dann die 2 if-Bedingungen schreibt, die möglicherweise überall dort wiederverwendbar sind, wo Sie sie für das benötigen, wofür Sie sie benötigen (das ist das Entwurfsbit)

code, der sagt, wenn b.count + 20 <= b.max, dann b + = 20 sonst erhöhen ("zu viele Äpfel") Ende

Sie haben immer noch die 2 Methoden (count und max), so dass Sie immer noch ein gutes Design haben, aber der Code ist hässlich und bedeutungslos, ohne Systemkenntnisse schwer zu pflegen und völlig mehrdeutig

0
jamesc

Um ehrlich zu sein, gibt es selten einen guten Grund, den Wert zweier Variablen zu tauschen, und es ist nicht wirklich eine "elegante" Sache, egal wie Sie es tun.

Bei elegantem Code geht es nicht um den Code an und für sich, sondern um was der Code tut und wie er tut es. Ich persönlich denke, dass dies ein schlechtes Beispiel ist, um festzustellen, was "eleganter Code" ist, da das, was getan wird, selbst nicht elegant ist. Ich finde Haskell-Code typisch elegant, weil er (größtenteils) nveränderliche Werte behandelt. Algorithmen, die einen veränderlichen Zustand verwenden, können jedoch auch elegant geschrieben werden (und sehen in Haskell normalerweise nicht so heiß aus).

0
Dan Burton

Wie leicht können die meisten Entwickler es lesen? Wie leicht ist es zu ändern?

Daher würde ich Ihnen definitiv zustimmen, dass Opton 1 wesentlich eleganter ist.

Option 2 ist clever und zeigt gute Kenntnisse der Bediener. Es spart auch ein sehr kleines Stück Speicher. Nützlich vielleicht in Ausnahmefällen und es lohnt sich, wenn ein Entwickler dazu in der Lage ist. Aber nicht in einem durchschnittlichen Fall von 99%.

0
pdr

Es musste konsistent sein. Es musste eine Art Muster darin sein. Und wenn Sie dieses Muster brechen müssen, brechen Sie es auf konsistente Weise, damit insgesamt immer noch eine Art Muster darin ist.

Wenn jemand auf Ihren Code zeigt und Sie fragt, warum Sie das so machen und Ihre Antwort lautet "Ich weiß nicht, ich mache es einfach so, weil ich es so mache." Wurde gelehrt/weil genau so alle anderen tun ", dann kann dieser Code entweder elegant sein oder nicht elegant . Wenn Sie jedoch erklären können, warum der Code so ist, warum Sie ihn so codiert haben, warum die anderen Alternativen nicht so ansprechend sind, können Sie sicher sein, dass der Code elegant ist .

0
Pacerier

Ich war in meinem Kommentar oben blasiert, aber für mich ist eleganter Code das, was meine Sinne viel mehr beeinflusst als die meisten anderen.

Es erzeugt eine positive Reaktion beim Erreichen von Zielen, während es kurz und präzise ist, einfach, aber mit Zweck und Kraft, stilvoll, symmetrisch und ein wenig "out of the box" im Ansatz. Es ist überraschend. Die Methode und der Algorithmus sind (zumindest oberflächlich) nicht so komplex, dass sie ihrem Verständnis im Wege stehen.

Eleganter Code ist mehr als die Summe seiner Teile. Manchmal scheint eleganter Code fast mit den Daten zu funktionieren, sich mit ihnen zu verbiegen, anstatt Brute Force anzuwenden oder die Daten in eine andere Form abzubilden. Für mich kommt Eleganz oft in einem eigenständigen Paket - einer einzelnen Funktion, wenigen oder keinen externen Anrufen, weder zu lang noch zu kurz.

Zum Beispiel habe ich Sortiermethoden gesehen, die ich als elegant bezeichnen würde. Und eleganter Code/Algorithmen zum Zeichnen von Fraktalen auf ungewöhnliche, aber hocheffiziente Weise - Kombination von visueller Schönheit nd Codierung von Eleganz!

0
Roger Attrill

Eleganter Code verwendet Cleverness, um etwas in viel weniger Code zu erreichen, als die meisten Menschen für möglich halten, aber auf eine Weise, die im Nachhinein lesbar und offensichtlich ist und nicht wie Code-Golf aussieht.

0
dsimcha

Es kommt wirklich darauf an, wen Sie fragen. Jemand mit mathematischem Hintergrund bevorzugt häufig Code, den ein erfahrener Programmierer möglicherweise als problematisch empfindet. Dies lässt es sehr subjektiv erscheinen.

Darüber hinaus werden Sie feststellen, dass verschiedene Sprachen unterschiedliche Möglichkeiten haben, dasselbe Problem zu lösen. In Python ist es beispielsweise trivial, zwei Variablen auszutauschen: x, y = y, x

In der Praxis stimmen die meisten Programmierer darin überein, dass es einige gemeinsame Kriterien gibt:

  • eleganter Code muss so kurz wie möglich sein
  • aber so ausführlich wie nötig
  • es sollte leicht zu folgen sein
  • jede Aussage sollte leicht zu verstehen sein
  • keine Aussage sollte überflüssig oder überflüssig erscheinen
  • der Code sollte den Redewendungen der Sprache folgen
  • es darf keine undichten Abstraktionen verwenden

Dies ist eine sehr pragmatische Sicht der Eleganz. Code darf nicht "clever" sein oder er erfüllt diese Kriterien nicht. Es ist jedoch wartbar und einfacher einzustellen und zu erweitern.

Das heißt, es gibt Code, der ein Kunstwerk sein kann, obwohl die meisten Regeln in dieser Liste absolut nicht eingehalten werden. "Cleverer" Code fällt häufig in diese Kategorie. Es ist sehr dicht, beruht häufig auf einem gründlichen Verständnis der zugrunde liegenden Implementierungen (z. B. Speicherverwaltung oder der genauen Implementierung des Compilers), ruft jedoch eine überragende Faszination hervor.

Es gibt einen Unterschied zwischen der Eleganz, die Sie in den Skripten von Yet Another Perl Hacker finden würden, und dem Code, den Sie tatsächlich in der Produktion verwenden möchten. Dies ist der Grund, warum Sie niemals möchten, dass Mel in Ihrem Team ist, obwohl Sie sein Hauptwerk als elegant bezeichnen könnten.

0
Alan Plum

Persönlich finde ich eleganten Code überbewertet. Aber ich arbeite in der Datenbankwelt, in der performanter Code von entscheidender Bedeutung ist und "eleganter" Code im Kontext von SQL-Code häufig (zumindest meiner Erfahrung nach) eine schlechte Leistung erbringt. Ich erschrecke jedes Mal, wenn ich jemanden höre, der eleganten SQL-Code schreiben möchte.

Im Allgemeinen halte ich das Streben nach Eleganz jedoch immer noch für lächerlich. Erstens kann es niemand richtig definieren. Was Sie wollen, ist Code, der korrekt funktioniert, gut funktioniert, wartbar ist und dann elegant ist ein weit entfernter vierter, wenn er überhaupt in die Liste aufgenommen wird.

0
HLGEM

Das Verstehen von elegantem Code sollte wie das Lösen eines Puzzles sein. Es sollte zuerst schwer zu verstehen sein, dann sehr leicht zu verstehen, wenn Sie es "verstanden" haben.

Es gibt einen Kompromiss: Leute, die es nicht verstehen, kratzen sich am Kopf, während Leute, die es verstehen, es im Nachhinein offensichtlich finden.

Was das Austauschen von Variablen betrifft, ist keines besonders elegant. Hier gibt es keine Komplexität zu zähmen, daher gibt es keinen Spielraum für eine "elegante" Lösung.

0
wisty