Warum glauben so viele Entwickler, dass Leistung, Lesbarkeit und Wartbarkeit nicht zusammen existieren können?


34

Während ich auf diese Frage antwortete , begann ich mich zu fragen, warum so viele Entwickler der Meinung sind, dass ein gutes Design nicht für die Leistung verantwortlich sein sollte, da dies die Lesbarkeit und / oder Wartbarkeit beeinträchtigen würde.

Ich glaube, dass ein gutes Design auch die Leistung zum Zeitpunkt der Erstellung berücksichtigt und dass ein guter Entwickler mit einem guten Design ein effizientes Programm schreiben kann, ohne die Lesbarkeit oder Wartbarkeit zu beeinträchtigen.

Ich gebe zwar zu, dass es extreme Fälle gibt, aber warum bestehen viele Entwickler darauf, dass ein effizientes Programm / Design zu schlechter Lesbarkeit und / oder schlechter Wartbarkeit führt und die Leistung daher nicht in Betracht gezogen werden sollte?


9
Es wäre fast unmöglich, darüber in großem Maßstab zu argumentieren, aber für kleine Codestücke ist es ziemlich offensichtlich. Vergleichen Sie einfach die lesbaren und die effizienten Versionen von QuickSort.
SK-logic

7
Mu. Beginnen Sie mit Ihrer Aussage, dass viele Entwickler darauf bestehen, dass Effizienz zu Unverwaltbarkeit führt.
Peter Taylor

2
SK-Logik: Meiner Meinung nach ist das einer der besten Teile aller Stack-Exchange-Sites, da man das Offensichtliche hinterfragen kann, was von Zeit zu Zeit gesund sein kann. Was für Sie möglicherweise offensichtlich ist, ist für andere möglicherweise nicht offensichtlich und umgekehrt. :) Teilen ist Kümmern.
Andreas Johansson

2
@ Justin, nein. Dieser Thread scheint mir eine Situation vorauszusetzen, in der eine erzwungene Wahl zwischen effizientem Code oder wartbarem Code besteht. Der Fragesteller sagt nicht, wie oft er sich in dieser Situation befindet, und die Antwortenden scheinen nicht zu behaupten, häufig in dieser Situation zu sein.
Peter Taylor

2
-1 für die Frage. Als ich es las, dachte ich, dies sei ein Strohmann, um die einzig wahre Antwort zu vertreiben: "Weil sie keine Python benutzen."
Ingo

Antworten:


38

Ich denke, solche Ansichten sind normalerweise Reaktionen auf Versuche zur vorzeitigen (Mikro-) Optimierung , die immer noch vorherrschen und in der Regel mehr schaden als nützen. Wenn man versucht, solchen Ansichten entgegenzuwirken, fällt man leicht in das andere Extrem - oder sieht zumindest so aus.

Es ist jedoch richtig, dass mit der enormen Entwicklung der Hardwareressourcen in den letzten Jahrzehnten für die meisten der heute geschriebenen Programme die Leistung nicht mehr einschränkend wirkte. Natürlich sollte man die erwartete und erreichbare Leistung während der Entwurfsphase berücksichtigen, um die Fälle zu identifizieren , in denen die Leistung ein Hauptproblem sein kann . Und dann ist es in der Tat wichtig, von Anfang an auf Leistung zu achten. Die allgemeine Einfachheit, Lesbarkeit und Wartbarkeit ist jedoch immer noch wichtiger . Wie bereits erwähnt, ist leistungsoptimierter Code komplexer, schwerer zu lesen und zu warten und fehleranfälliger als die einfachste funktionierende Lösung. Daher muss jeder Optimierungsaufwand bewiesen werden - nicht nur geglaubt- echte Vorteile zu erzielen und gleichzeitig die langfristige Wartbarkeit des Programms so wenig wie möglich zu beeinträchtigen. So isoliert ein gutes Design die komplexen, leistungsintensiven Teile vom Rest des Codes , der so einfach und sauber wie möglich gehalten wird.


8
"Wenn man versucht, solchen Ansichten entgegenzuwirken, fällt man leicht in das andere Extrem - oder sieht zumindest so aus" Ich habe die ganze Zeit Probleme mit Leuten, die meinen, ich vertrete die gegenteilige Ansicht, wenn ich nur die Profis mit denen ausbalanciere Die Nachteile. Nicht nur in der Programmierung, in allem.
jhocking

1
Ich habe es so satt, dass alle darüber diskutieren, dass ich wütend werde und Extreme sehe.
Thomas Bonini

Es gab mehrere gute Antworten, aber ich denke, Sie haben den besten Versuch unternommen, die Ursprünge dieser Mentalität zu beschreiben. Vielen Dank an alle Beteiligten!
Justin

Meine Antwort ... die meisten Entwickler sind schlecht in ihren Jobs
TheCatWhisperer

38

Bei Ihrer Frage von Seiten eines Entwicklers, der an Hochleistungscode arbeitet, gibt es mehrere Dinge, die beim Entwurf berücksichtigt werden müssen.

  • Nicht vorzeitig pessimisieren. Wenn Sie zwischen zwei Designs mit gleicher Komplexität wählen können, wählen Sie das Design mit den besten Leistungseigenschaften. Eines der bekanntesten C ++ - Beispiele ist die Prävalenz des Nachinkrements von Zählern (oder Iteratoren) in Schleifen. Dies ist eine völlig unnötige vorzeitige Pessimisierung, die Sie möglicherweise nichts kostet, aber es KÖNNTE, also tun Sie es nicht.
  • In vielen Fällen haben Sie noch keine Chance, sich der Mikrooptimierung zu nähern. Algorithmische Optimierungen sind weniger wichtig und fast immer viel einfacher zu verstehen als Optimierungen auf sehr niedriger Ebene.
  • Wenn und NUR wenn Leistung absolut kritisch ist, erhalten Sie unten und schmutzig. Tatsächlich isolieren Sie den Code so weit wie möglich, und DANN werden Sie kaputt und schmutzig. Und es wird wirklich schmutzig, mit Caching-Schemata, verzögerter Auswertung, Speicherlayoutoptimierung für das Caching, Blöcken von Inline-Inhalten oder Assemblierungen, Layer-on-Layer-Vorlagen usw. Sie testen und dokumentieren hier wie verrückt, Sie wissen, dass es geht zu verletzen, wenn Sie irgendwelche Wartungsarbeiten in diesem Code durchführen müssen, aber Sie müssen, weil die Leistung absolut kritisch ist. Bearbeiten: Übrigens, ich sage nicht, dass dieser Code nicht schön sein kann, und er sollte so schön wie möglich gemacht werden, aber er wird im Vergleich zu weniger optimiertem Code immer noch sehr komplex und oft verwickelt sein.

Mach es richtig, mach es schön, mach es schnell. In dieser Reihenfolge.


Ich mag die Faustregel: „Mach es schön, mach es schnell. In dieser Reihenfolge'. Ich werde damit anfangen.
Martin York

Genau. Isolieren Sie den Code so weit wie möglich im dritten Punkt. Denn wenn Sie auf andere Hardware umsteigen, auch auf einen Prozessor mit einer anderen Cache-Größe, können sich diese Dinge ändern.
KeithB

@ KeithB - ​​Sie machen einen guten Punkt, ich werde es zu meiner Antwort hinzufügen.
Joris Timmermans

+1: "Mach es richtig, mach es schön, mach es schnell. In dieser Reihenfolge." Sehr schöne Zusammenfassung, der ich zu 90% zustimme. Manchmal kann ich bestimmte Fehler nur beheben (richtig machen), wenn ich sie schön (und verständlicher) habe.
Giorgio

+1 für "Nicht vorzeitig pessimisieren". Der Rat, vorzeitige Optimierung zu vermeiden, ist nicht die Erlaubnis, nur Algorithmen ohne Kopf zu verwenden. Wenn Sie Java schreiben und über eine Sammlung verfügen, die Sie häufig aufrufen contains, verwenden Sie a HashSet, nicht an ArrayList. Die Leistung mag keine Rolle spielen, aber es gibt keinen Grund, dies nicht zu tun. Nutzen Sie die Übereinstimmungen zwischen gutem Design und Leistung - wenn Sie eine Sammlung bearbeiten, versuchen Sie, alles in einem einzigen Durchgang zu erledigen, der wahrscheinlich besser lesbar und (wahrscheinlich) schneller ist.
Tom Anderson

16

Wenn ich davon ausgehen kann, dass ich @ greengits nettes Diagramm "ausleihen" und eine kleine Ergänzung machen kann:

|
P
E
R
F
O  *               X <- a program as first written
R   * 
M    *
A      *
N        *
C          *  *   *  *  *
E
|
O -- R E A D A B I L I T Y --

Uns allen wurde "beigebracht", dass es Kompromisskurven gibt. Außerdem haben wir alle angenommen, dass wir so optimale Programmierer sind, dass jedes Programm, das wir schreiben, so knapp ist, dass es auf der Kurve liegt . Befindet sich ein Programm in der Kurve, verursacht jede Verbesserung in einer Dimension notwendigerweise Kosten in der anderen Dimension.

Nach meiner Erfahrung kommen Programme nur dann in die Nähe einer Kurve, wenn sie gestimmt, optimiert, gehämmert, gewachst und im Allgemeinen in "Codegolf" umgewandelt werden. Die meisten Programme bieten in allen Dimensionen viel Raum für Verbesserungen. Hier ist was ich meine.


Persönlich denke ich, dass es ein anderes Ende der Kurve gibt, wo sie auf der rechten Seite wieder ansteigt (solange Sie sich weit genug nach rechts bewegen (was wahrscheinlich bedeutet, dass Sie Ihren Algorithmus überdenken)).
Martin York

2
+1 für "Die meisten Programme bieten in allen Dimensionen viel Raum für Verbesserungen."
Steven

5

Gerade weil leistungsfähige Softwarekomponenten in der Regel um Größenordnungen komplexer sind als andere Softwarekomponenten (alle anderen Dinge sind gleich).

Selbst dann ist es nicht so eindeutig, wenn Leistungsmetriken eine kritisch wichtige Anforderung sind, ist es unerlässlich, dass das Design eine Komplexität aufweist, um solchen Anforderungen gerecht zu werden. Die Gefahr ist ein Entwickler, der einen Sprint mit einem relativ einfachen Feature verschwendet, das versucht, ein paar zusätzliche Millisekunden aus seiner Komponente herauszuholen.

Unabhängig davon steht die Komplexität des Designs in direktem Zusammenhang mit der Fähigkeit eines Entwicklers, ein solches Design schnell zu erlernen und sich damit vertraut zu machen. Weitere Änderungen an der Funktionalität einer komplexen Komponente können zu Fehlern führen, die möglicherweise nicht von Komponententests erfasst werden. Komplexe Entwürfe haben viele weitere Facetten und mögliche Testfälle, um das Ziel einer 100% igen Testabdeckung noch mehr zu verwirklichen.

Vor diesem Hintergrund sollte angemerkt werden, dass eine schlecht funktionierende Softwarekomponente schlecht funktionieren kann, nur weil sie dumm geschrieben und unnötig komplex ist, basierend auf der Unkenntnis des ursprünglichen Autors (8 Datenbankaufrufe, um eine einzelne Entität zu erstellen, wenn nur eine dies tun würde) , völlig unnötiger Code, der unabhängig davon zu einem einzigen Codepfad führt, etc ...) In diesen Fällen geht es eher darum, die Codequalität zu verbessern und die Leistung zu steigern, die als Folge des Refaktors und NICHT der beabsichtigten Konsequenz erforderlich ist.

Vorausgesetzt, eine gut gestaltete Komponente ist immer weniger komplex als eine ähnlich gut gestaltete, auf Leistung abgestimmte Komponente (alle anderen Dinge sind gleich).


3

Es ist nicht so sehr, dass diese Dinge nicht koexistieren können. Das Problem ist, dass der Code aller Benutzer bei der ersten Iteration langsam, unleserlich und nicht verwaltbar ist. Der Rest der Zeit wird für die Verbesserung des Wichtigsten aufgewendet. Wenn das Leistung ist, dann machen Sie es. Schreiben Sie keinen schrecklichen Code, aber wenn es nur X-schnell sein muss, dann machen Sie es X-schnell. Ich glaube, dass Leistung und Sauberkeit im Grunde genommen nichts miteinander zu tun haben. Performanter Code verursacht keinen hässlichen Code. Wenn Sie jedoch Ihre Zeit damit verbringen, jeden Teil des Codes schnell zu optimieren, raten Sie mal, was Sie nicht getan haben? Machen Sie Ihren Code sauber und wartbar.


2
    |
    P
    E
    R
    F
    O *
    R * 
    M *
    EIN *
    N *
    C * * * * *
    E
    |
    O - LESBARKEIT -

Wie du siehst...

  • Wenn die Lesbarkeit geopfert wird, kann die Leistung gesteigert werden - aber nur so viel. Ab einem bestimmten Punkt muss man auf "echte" Mittel wie bessere Algorithmen und Hardware zurückgreifen.
  • Ein Leistungsverlust auf Kosten der Lesbarkeit ist nur bedingt möglich. Danach können Sie Ihr Programm so lesbar machen, wie Sie möchten, ohne die Leistung zu beeinträchtigen. Wenn Sie beispielsweise weitere hilfreiche Kommentare hinzufügen, wird die Leistung nicht beeinträchtigt.

Leistung und Lesbarkeit sind also nur bescheiden miteinander verbunden - und in den meisten Fällen gibt es keine wirklich großen Anreize, die ersteren gegenüber letzteren vorzuziehen. Und ich spreche hier über Hochsprachen.


1

Meiner Meinung nach sollte Leistung eine Überlegung sein, wenn es sich um ein tatsächliches Problem (oder z. B. eine Anforderung) handelt. Wenn Sie dies nicht tun, kann dies zu Mikrooptimierungen führen, die dazu führen können, dass der Code nur vereinzelt verschleiert wird, um hier und da ein paar Mikrosekunden zu sparen, was wiederum zu weniger wartbarem und weniger lesbarem Code führt. Stattdessen sollte man sich bei Bedarf auf die tatsächlichen Engpässe des Systems konzentrieren und die Leistung dort hervorheben.


1

Der Punkt ist nicht die Lesbarkeit sollte immer die Effizienz übertreffen. Wenn Sie von Anfang an wissen, dass Ihr Algorithmus hocheffizient sein muss, wird er einer der Faktoren sein, die Sie für die Entwicklung verwenden.

Die Sache ist, dass die meisten Anwendungsfälle keinen schnellen Code benötigen. In vielen Fällen verursachen E / A- oder Benutzerinteraktionen wesentlich mehr Verzögerungen als die Ausführung Ihres Algorithmus. Der Punkt ist, dass Sie sich nicht die Mühe machen sollten, etwas effizienter zu machen, wenn Sie nicht wissen, dass es der Flaschenhals ist.

Durch die Optimierung des Codes für die Leistung wird dies häufig komplizierter, da die Dinge im Allgemeinen clever und nicht intuitiv ausgeführt werden. Komplizierterer Code ist schwieriger zu warten und für andere Entwickler schwieriger zu erfassen (beides sind Kosten, die berücksichtigt werden müssen). Gleichzeitig können Compiler häufig vorkommende Fälle sehr gut optimieren. Es ist möglich, dass Ihr Versuch, einen allgemeinen Fall zu verbessern, dazu führt, dass der Compiler das Muster nicht mehr erkennt und Ihnen daher nicht helfen kann, Ihren Code schnell zu machen. Es sollte beachtet werden, dass dies nicht bedeutet, dass Sie schreiben, was Sie wollen, ohne sich um die Leistung zu kümmern. Sie sollten nichts tun, was eindeutig ineffizient ist.

Es geht darum, sich keine Sorgen um kleine Dinge zu machen, die die Dinge verbessern könnten . Verwenden Sie einen Profiler und sehen Sie, dass 1) das, was Sie jetzt haben, ein Problem ist und 2) das, worauf Sie es geändert haben, eine Verbesserung war.


1

Ich denke, die meisten Programmierer haben dieses Bauchgefühl, einfach weil der Performance-Code die meiste Zeit auf viel mehr Informationen basiert (über den Kontext, Hardware-Kenntnisse, globale Architektur) als jeder andere Code in Anwendungen. Der meiste Code drückt nur einige Lösungen für bestimmte Probleme aus, die in einigen Abstraktionen modular eingekapselt sind (z. B. Funktionen), und dies bedeutet, dass das Wissen über den Kontext nur auf das beschränkt wird, was in diese Kapselung eingeht (z. B. Funktionsparameter).

Wenn Sie für eine hohe Leistung schreiben, gehen Sie, nachdem Sie algorithmische Optimierungen korrigiert haben, auf Details ein, die weitaus mehr Kenntnisse über den Kontext erfordern. Das könnte natürlich jeden Programmierer überwältigen, der sich für die Aufgabe nicht fokussiert genug fühlt.


1

Denn die Kosten für die globale Erwärmung (aufgrund der zusätzlichen CPU-Zyklen, die durch Hunderte Millionen PCs und massive Rechenzentrumsfunktionen skaliert werden) und die mittelmäßige Akkulaufzeit (auf den Mobilgeräten der Benutzer), die für die Ausführung ihres schlecht optimierten Codes erforderlich sind, treten bei den meisten nur selten auf Programmierer Leistung oder Peer-Reviews.

Es ist eine ökonomisch negative Externalität, ähnlich einer Form ignorierter Umweltverschmutzung. Das Kosten-Nutzen-Verhältnis, wenn man überhaupt über Leistung nachdenkt, ist also mental von der Realität abgewichen.

Hardware-Entwickler haben hart daran gearbeitet, den neuesten CPUs Funktionen für Stromsparmodus und Taktskalierung hinzuzufügen. Es liegt an den Programmierern, die Hardware diese Funktionen häufiger nutzen zu lassen, indem sie nicht jeden verfügbaren CPU-Takt zerkaut.

HINZUGEFÜGT: In früheren Zeiten waren die Kosten für einen Computer Millionen, daher war die Optimierung der CPU-Zeit sehr wichtig. Dann wurden die Kosten für die Entwicklung und Pflege des Codes höher als die Kosten für die Computer, so dass die Optimierung im Vergleich zur Produktivität des Programmierers in Ungnade fiel. Jetzt jedoch werden andere Kosten höher als die Kosten für Computer, und die Kosten für die Stromversorgung und Kühlung all dieser Rechenzentren werden höher als die Kosten aller Prozessoren im Inneren.


Abgesehen von der Frage, ob PCs zur globalen Erwärmung beigetragen haben, auch wenn sie real waren: Es ist ein Trugschluss, dass mehr Energieeffizienz zu weniger Energiebedarf führt. Fast das Gegenteil ist der Fall, wie man vom ersten Tag an sieht, an dem ein PC auf den Markt kam. Davor haben einige hundert oder tausend Mainframes (von denen jeder virtuell mit einem eigenen Kraftwerk ausgestattet ist) viel weniger Energie verbraucht als heute, wo 1 CPU-Minute viel mehr als damals zu einem Bruchteil der Kosten und des Energiebedarfs berechnet wird. Der Gesamtenergiebedarf für Computing ist jedoch höher als zuvor.
Ingo

1

Ich denke, es ist schwer, alle drei zu erreichen. Zwei, denke ich, können machbar sein. Zum Beispiel denke ich, dass es in einigen Fällen möglich ist, Effizienz und Lesbarkeit zu erreichen, aber die Wartbarkeit kann mit mikrooptimiertem Code schwierig sein. Der effizienteste Code auf dem Planeten fehlt im Allgemeinen sowohl die Wartbarkeit und Lesbarkeit als wahrscheinlich offensichtlich für die meisten ist, es sei denn , Sie die Art sind, die die Hand SoA-vektorisiert verstehen kann, multithreaded SIMD - Code , dass Intel mit inlined schreibt Montage oder den cutting -edge-Algorithmen, die in der Industrie mit 40-seitigen mathematischen Artikeln verwendet werden, die erst vor zwei Monaten veröffentlicht wurden, und 12 Bibliotheken mit Code für eine unglaublich komplexe Datenstruktur.

Mikroeffizienz

Eine Sache, die meiner Meinung nach der gängigen Meinung widerspricht, ist, dass der intelligenteste algorithmische Code oft schwieriger zu warten ist als der am besten abgestimmte, unkomplizierte Algorithmus. Diese Idee, dass Verbesserungen der Skalierbarkeit im Vergleich zu mikrooptimiertem Code (z. B. cachefreundliche Zugriffsmuster, Multithreading, SIMD usw.) mehr Erfolg bringen, würde ich in Frage stellen, zumindest wenn ich in einer Branche mit extrem komplexen Branchen gearbeitet habe Datenstrukturen und -algorithmen (die Visual FX-Branche), insbesondere in Bereichen wie der Netzverarbeitung, weil der Knall zwar groß sein kann, aber der Preis extrem hoch ist, wenn Sie neue Algorithmen und Datenstrukturen einführen, von denen noch niemand etwas gehört hat, seit sie Marken sind Neu. Weiter, ich '

Diese Vorstellung, dass algorithmische Optimierungen beispielsweise Optimierungen im Zusammenhang mit Speicherzugriffsmustern immer übertreffen, stimmte mir also nicht ganz zu. Natürlich, wenn Sie eine Blasensorte verwenden, kann Ihnen dort keine Mikrooptimierung weiterhelfen ... aber innerhalb der Vernunft denke ich nicht, dass es immer so eindeutig ist. Und algorithmische Optimierungen sind wahrscheinlich schwieriger zu pflegen als Mikrooptimierungen. Ich finde es viel einfacher, beispielsweise Intels Embree zu warten, das einen klassischen und einfachen BVH-Algorithmus verwendet und den Mist nur im Mikromaßstab herausarbeitet, als Dreamworks OpenVDB-Code für innovative Methoden zur algorithmischen Beschleunigung der Flüssigkeitssimulation. Zumindest in meiner Branche würde ich gerne mehr Leute sehen, die mit der Mikrooptimierung von Computerarchitekturen vertraut sind, so wie es Intel getan hat, als sie in die Szene eingetreten sind. im Gegensatz zu Tausenden und Abertausenden neuer Algorithmen und Datenstrukturen. Mit effektiven Mikrooptimierungen könnten Menschen möglicherweise immer weniger Gründe finden, neue Algorithmen zu erfinden.

Ich habe zuvor in einer alten Codebasis gearbeitet, in der fast jeder einzelne Benutzervorgang über eine eigene Datenstruktur und einen eigenen Algorithmus verfügte (insgesamt Hunderte exotischer Datenstrukturen). Und die meisten von ihnen hatten sehr verzerrte Leistungsmerkmale und waren sehr eng anwendbar. Es wäre so viel einfacher gewesen, wenn sich das System um ein paar Dutzend allgemeiner anwendbare Datenstrukturen drehen könnte, und ich denke, dass dies der Fall gewesen wäre, wenn sie viel besser mikrooptimiert worden wären. Ich erwähne diesen Fall, weil die Mikrooptimierung in einem solchen Fall möglicherweise die Wartbarkeit erheblich verbessern kann, wenn es sich um den Unterschied zwischen Hunderten von mikropessimierten Datenstrukturen handelt, die nicht einmal sicher für reine Lesezwecke verwendet werden können, bei denen Cachefehler übrig bleiben richtig gegen

Funktionssprachen

In der Zwischenzeit war einer der wartbarsten Codes, die mir je begegnet sind, einigermaßen effizient, aber äußerst schwer zu lesen, da sie in funktionalen Sprachen geschrieben waren. Im Allgemeinen sind Lesbarkeit und Wartungsfreundlichkeit meiner Meinung nach widersprüchliche Vorstellungen.

Es ist wirklich schwierig, Code gleichzeitig lesbar, wartbar und effizient zu machen. In der Regel müssen Sie bei einem dieser drei Punkte Kompromisse eingehen, wenn nicht bei zwei, z. B. bei der Lesbarkeit oder bei der Wartbarkeit, um die Effizienz zu beeinträchtigen. Es ist in der Regel Wartbarkeit, die leidet, wenn Sie viele der beiden anderen suchen.

Lesbarkeit vs. Wartbarkeit

Nun, wie gesagt, glaube ich, dass Lesbarkeit und Wartbarkeit keine harmonischen Konzepte sind. Schließlich bildet der für die meisten von uns Sterblichen am besten lesbare Code sehr intuitiv menschliche Gedankenmuster ab, und menschliche Gedankenmuster sind von Natur aus fehleranfällig: " Wenn dies geschieht, tun Sie dies. Wenn dies geschieht, tun Sie dies. Andernfalls tun Sie dies. Hoppla Ich habe etwas vergessen! Wenn diese Systeme miteinander interagieren, sollte dies geschehen, damit dieses System dies tun kann ... Oh, was ist mit diesem System, wenn dieses Ereignis ausgelöst wird?"Ich habe das genaue Zitat vergessen, aber jemand hat einmal gesagt, wenn Rom wie eine Software gebaut wäre, müsste nur ein Vogel auf einer Wand landen, um es zum Umfallen zu bringen. Dies ist bei den meisten Programmen der Fall. Es ist zerbrechlicher, als wir es oft tun." Ein paar Zeilen scheinbar harmlosen Codes könnten hier und da dazu führen, dass wir das gesamte Design überdenken, und Hochsprachen, die so gut wie möglich lesbar sein sollen, sind keine Ausnahmen für solche menschlichen Designfehler .

Reine funktionale Sprachen sind dem so nahe wie möglich (nicht annähernd unverwundbar, aber relativ viel näher als die meisten). Und das liegt zum Teil daran, dass sie sich nicht intuitiv auf das menschliche Denken abbilden lassen. Sie sind nicht lesbar. Sie zwingen uns Denkmuster auf, die es uns ermöglichen, Probleme mit möglichst wenigen Sonderfällen mit möglichst geringem Wissen und ohne Nebenwirkungen zu lösen. Sie sind extrem orthogonal und ermöglichen es, den Code häufig zu ändern und zu ändern, ohne dass Überraschungen auftreten, die so episch sind, dass wir das Design auf einem Zeichenbrett überdenken müssen, bis wir unsere Meinung über das Gesamtdesign ändern müssen, ohne alles neu zu schreiben. Es scheint nicht einfacher zu sein, als das zu warten ... aber der Code ist immer noch sehr schwer zu lesen,


1
"Micro-Efficiency" ist so etwas wie "Es gibt keinen O (1) Speicherzugriff"
Caleth

0

Ein Problem ist, dass die begrenzte Zeit für Entwickler bedeutet, dass Sie sich nicht mehr mit den anderen Problemen befassen müssen, um sie zu optimieren.

Es gibt ein ziemlich gutes Experiment, auf das in Meyers Code Complete verwiesen wird. Verschiedene Entwicklergruppen wurden gebeten, die Geschwindigkeit, Speichernutzung, Lesbarkeit, Robustheit usw. zu optimieren. Es stellte sich heraus, dass ihre Projekte in allen Punkten, in denen sie optimiert werden sollten, eine hohe Punktzahl erzielten, in allen anderen Qualitäten jedoch eine geringere.


Natürlich können Sie mehr Zeit
investieren,

0

Weil erfahrene Programmierer gelernt haben, dass es wahr ist.

Wir haben mit schlankem Code gearbeitet, der keine Leistungsprobleme aufweist.

Wir haben an einer Menge Code gearbeitet, der zur Behebung von Leistungsproblemen SEHR komplex ist.

Ein unmittelbares Beispiel ist, dass mein letztes Projekt 8.192 manuell gesplittete SQL-Tabellen enthielt. Dies wurde aufgrund von Leistungsproblemen benötigt. Das Setup für die Auswahl aus einer Tabelle ist viel einfacher als für die Auswahl und Verwaltung von 8.192 Shards.


0

Es gibt auch einige berühmte Teile von hochoptimiertem Code, die das Gehirn der meisten Menschen beugen und den Fall unterstützen, dass hochoptimierter Code schwer zu lesen und zu verstehen ist.

Hier ist der berühmteste, denke ich. Entnommen aus der Quake III Arena und John Carmak zugeschrieben, obwohl ich denke, dass es mehrere Iterationen dieser Funktion gab und sie ursprünglich nicht von ihm erstellt wurde ( ist Wikipedia nicht großartig? ).

float Q_rsqrt( float number )
{
    long i;
    float x2, y;
    const float threehalfs = 1.5F;

    x2 = number * 0.5F;
    y  = number;
    i  = * ( long * ) &y;                       // evil floating point bit level hacking
    i  = 0x5f3759df - ( i >> 1 );               // what the fuck?
    y  = * ( float * ) &i;
    y  = y * ( threehalfs - ( x2 * y * y ) );   // 1st iteration
    //      y  = y * ( threehalfs - ( x2 * y * y ) );   // 2nd iteration, this can be removed

    return y;
}
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.