Ich programmiere seit ein paar Jahren und bin oft in ein Dilemma geraten.
Es gibt zwei Lösungen -
- Einer ist einfach, dh einfacher Ansatz, einfacher zu verstehen und zu pflegen. Dies erfordert Redundanz und zusätzlichen Arbeitsaufwand (zusätzliche E / A, zusätzliche Verarbeitung) und ist daher nicht die optimalste Lösung.
- Andere verwenden jedoch einen komplexen Ansatz, der schwierig zu implementieren ist, häufig die Interaktion mehrerer Module umfasst und eine leistungsfähige Lösung darstellt.
Welche Lösung sollte ich anstreben, wenn ich keine SLA mit hoher Leistung zu erfüllen habe und selbst die einfache Lösung die SLA mit Leistung erfüllen kann? Ich habe mich unter meinen Mitentwicklern für eine einfache Lösung verachtet gefühlt.
Ist es empfehlenswert, eine optimale komplexe Lösung zu finden, wenn Ihre Leistungs-SLA durch eine einfache Lösung erfüllt werden kann?
design
programming-practices
coding-style
code-quality
performance
Beweg dich schnell
quelle
quelle
Antworten:
Die einfache. Es entspricht den Spezifikationen, ist einfacher zu verstehen, einfacher zu warten und wahrscheinlich viel weniger fehleranfällig.
Sie setzen sich für eine leistungsfähige Lösung ein, indem Sie spekulative Allgemeingültigkeit und vorzeitige Optimierung in Ihren Code integrieren. Tu es nicht! Die Leistung widerspricht nahezu jeder anderen Softwareentwicklungsfunktionalität (Zuverlässigkeit, Wartbarkeit, Lesbarkeit, Testbarkeit, Verständlichkeit usw.). Verfolgungsjagd beim Testen zeigt, dass es wirklich notwendig ist, nach der Leistung zu jagen.
Jagen Sie nicht nach Leistung, wenn die Leistung keine Rolle spielt. Auch wenn es wichtig ist, sollten Sie die Leistung nur in den Bereichen verfolgen, in denen der Test auf einen Leistungsengpass hinweist. Lassen Sie sich nicht von Leistungsproblemen entschuldigen, die
simple_but_slow_method_to_do_X()
durch eine schnellere Version ersetzt werden könnten, wenn diese einfache Version nicht als Engpass erscheint.Eine verbesserte Leistung ist fast zwangsläufig mit einer Vielzahl von Code-Geruchsproblemen behaftet. Sie haben mehrere in der Frage erwähnt: Ein komplexer Ansatz, schwer umzusetzen, höhere Kopplung. Sind diese wirklich einen Besuch wert?
quelle
Kurze Antwort: Ziehen Sie die einfachen Lösungen komplexen vor und erinnern Sie sich an die Prinzipien von KISS und YAGNI
Da anfängliche Projektanforderungen und Software niemals perfekt sind, sind Änderungen erforderlich, wenn eine Anwendung entwickelt / verwendet wird. Ein iterativer Ansatz in den Entwicklungsphasen passt sehr gut dazu, Dinge einfach anzufangen und bei Bedarf zu erweitern. Die einfachsten Lösungen bieten Raum für Flexibilität und sind wartungsfreundlicher.
Darüber hinaus ist es keine gute Praxis, klug zu sein und eine Add-Hoc-Optimierung vorzunehmen, während Ihre Anwendung noch erstellt wird. Dies kann Ihre Lösung überkomplizieren. Wie es bekannt ist,
"premature optimization is the root of all evil"
- von Knuths Buchquelle
Nehmen Sie hier eine Lehre von Knuth: "Wir sollten kleine Wirkungsgrade vergessen, sagen wir in 97% der Fälle: Vorzeitige Optimierung ist die Wurzel allen Übels."
Denken Sie über Ihre Lösungen in dieser Reihenfolge nach: Zuerst immer die Richtigkeit. Zweitens verbessern Sie Klarheit und Einfachheit. Drittens und nur, wenn Sie die Notwendigkeit, Effizienz demonstrieren können.
Das Hinzufügen von Effizienz kostet Sie fast immer etwas Wichtiges und sollte daher nur dann fortgesetzt werden, wenn Sie wissen, dass dies erforderlich ist.
quelle
Einfachheit ist die Voraussetzung für Zuverlässigkeit . Wenn Sie eine einfache Lösung haben, die funktioniert, machen Sie es auf jeden Fall! Es ist viel einfacher, ein Arbeitsprogramm zu optimieren, als ein optimiertes Programm zum Laufen zu bringen. Vergessen Sie auch nicht über Moores Gesetz : Wenn Ihre einfache Lösung erfüllen die Leistungsziele heute, wird es wahrscheinlich zerdrücken 1 in einem Jahr oder zwei.
1 Da gibt es keine Garantie, denn wie Jimmy Hoffa in seinem Kommentar unten feststellte, hat Moores Gesetz seine Grenzen.
quelle
Optimal ist ein mehrdeutiges Wort!
Letztendlich würde ich mich immer auf die Seite des Einfachen irren, wenn das Risiko groß ist, den Komplexen warten zu müssen, und wenn der Einfache "gut genug" ist.
Fügen Sie das Risiko hinzu, dass der Komplex nicht gut genug ist, dann ist KISS wahrscheinlich die richtige Antwort.
quelle
Ich würde die einfache vorziehen. Meiner Meinung nach verursachen die vorzeitigen Optimierungen so viele Probleme, wie sie lösen. In vielen Fällen können Sie durch gutes Design bestimmte Implementierungen in Zukunft ändern, wenn sie zu Engpässen werden.
Unterm Strich also - ich werde es so flexibel wie möglich gestalten, aber nicht zu sehr auf Einfachheit und Flexibilität verzichten.
quelle
Welches kostet weniger?
In den meisten Fällen ist eine einfache Lösung, die etwas langsamer ist, in Bezug auf die Leistung vollkommen akzeptabel, und durch die Einfachheit wird die Entwicklung, Wartung und eventuelles Ersetzen billiger.
Auf der anderen Seite ist die Geschwindigkeit manchmal sehr wichtig, und der finanzielle Gewinn, der durch kleine Geschwindigkeitsverbesserungen erzielt wird, kann weitaus größer sein als die höheren Kosten einer komplizierteren Lösung. Wenn Sie beispielsweise 0,01 Sekunden vor dem Abschluss einer Transaktion sparen, kann ein Wertpapierhandelssystem erheblich rentabler werden. Eine 10% ige Verbesserung der Effizienz eines Systems, das mehrere Millionen Benutzer unterstützt, könnte zu einer erheblichen Reduzierung der Serverkosten führen.
Die Frage, die Sie sich stellen müssen, lautet also: Hat die Verwendung der komplexen Lösung eine ausreichende Auswirkung auf das Endergebnis, um die zusätzlichen Kosten zu tragen? Eigentlich sollten Sie Ihren Kunden wahrscheinlich bitten, sich zu entscheiden, da er die Rechnungen bezahlt und den potenziellen Nutzen daraus zieht. Eine gute Option ist, zuerst die einfache Lösung zu wählen und die komplexere Lösung als mögliche Verbesserung anzubieten. Auf diese Weise können Sie Ihr System in Betrieb nehmen und Ihren Kunden die Möglichkeit geben, mit dem Testen zu beginnen. Diese Erfahrung kann die Entscheidung für die Implementierung (oder Nichtimplementierung) der komplizierteren Lösung beeinflussen.
quelle
Bei der Bewertung von zwei Ansätzen, von denen einer einfacher, aber weniger effizient ist, während der andere komplexer und effizienter ist, müssen das Problem und der Projektbereich berücksichtigt werden.
Betrachten Sie ein milliardenschweres Softwareprojekt für das Gesundheitswesen, dessen Lebensdauer auf über 15 Jahre Wartung und über 20 Jahre Nutzung ausgelegt ist. In einem solchen Projekt wird die Leistung definitiv kein Problem sein, aber die Komplexität und Struktur des Projekts kann zu großen Problemen bei der Aufrechterhaltung des Projekts führen, die mindestens 15 Jahre dauert. Wartbarkeit und Einfachheit stehen an erster Stelle.
Betrachten Sie dann ein anderes Beispiel. Eine Konsolenspiel-Engine, die die kommenden Spiele des Unternehmens für die nächsten 5+ Jahre antreiben soll. Da Spiele äußerst ressourcenbeschränkte Programme sind, geht die Effizienz in vielen Fällen vor der Wartbarkeit. Das Schreiben eigener, sehr spezifischer Datenstrukturen und Algorithmen für eine bestimmte Aufgabe kann sehr wichtig sein, auch wenn dies gegen jegliche Art von "Best Practices" der Softwareentwicklung verstößt. Ein gutes Beispiel hierfür ist Data Oriented Design, bei dem Sie Ihre Daten in ähnlichen Datenfeldern statt in tatsächlichen Objekten speichern. Dies dient dazu, die Lokalitätsreferenz zu erhöhen und somit die CPU-Cache-Effizienz zu erhöhen. Nicht praktisch, aber in der gegebenen Domäne sehr wichtig.
quelle
Dies ist immer eine schwierige Frage, und ich sehe, dass die Antworten in die eine oder andere Richtung schwanken. Daher spiele ich das Spiel für die andere Seite, auch wenn ich nicht behaupte, dass beide Antworten richtig sind.
Bei einer komplexen, aber leistungsstarken Lösung können Sie immer nur das allgegenwärtige Problem dokumentieren. Ich bin im Allgemeinen ein Fan von selbstdokumentierendem Code, aber ich bin auch ein Fan von Software, die in einer Zeitspanne reagiert, in der ich das Gefühl habe, dass sie mich nicht verlangsamt. Wenn Sie sich für die komplexe, aber leistungsstarke Lösung entscheiden, überlegen Sie, was Sie tun können, um sie nicht so schlecht zu machen:
Binden Sie es in eine Schnittstelle ein, fügen Sie es in eine eigene Assembly ein, möglicherweise sogar in einen eigenen Prozess. Machen Sie es so locker wie möglich mit einer möglichst dicken Abstraktionswand, um Undichtigkeiten zu vermeiden . Schreiben Sie viele Komponententests, um zukünftige Regressionen zu vermeiden.
Dokumentieren Sie es im Code, und erwägen Sie sogar, eine echte Dokumentation zu verfassen. Denken Sie an komplexe Datenstrukturen und wie sie dokumentiert sind. Stellen Sie sich vor, Sie würden versuchen, die Implementierung von Code ohne einen Datenstruktur-Buch- / Wikipedia-Artikel zu verstehen, um dies zu erklären. Und doch sind wir uns alle einig, dass diese komplexen Datenstrukturen in der Tat gute Dinge sind und es von Vorteil ist, dass jemand sie in unseren Sprachen implementiert hat.
Denken Sie daran, dass wir alle Nachrichten auf einem TCP / IP-Stack senden, der wahrscheinlich so umfangreich ist, wie es der Code nur kann, wenn einer von uns ihn sich ansieht. Vielleicht erfordert Ihr Problem nicht diese Optimierungsstufe, vielleicht auch nicht, aber seien Sie vorsichtig, wenn Sie diese Frage angehen, da wir alle von Zeit zu Zeit müssen: Es gibt dort Drachen.
quelle
Ich arbeite in Bereichen, in denen es keine Leistungs-SLA gibt. Wenn es um Offline-Renderer in der Computergrafik geht, gibt es für Benutzer keine "zufriedenstellende Leistung", da sie bereits enorme Summen für die Verteilung von Computing auf Clouds und das Rendern von Farmen ausgeben, selbst mit den modernsten Renderern um Bilder und Rahmen in Produktionsqualität für Filme auszugeben, z
Aber ich muss sagen, dass jede Lösung, die die Wartbarkeit zugunsten der Effizienz erheblich beeinträchtigt, tatsächlich gegen die sich ständig ändernden Leistungsanforderungen arbeitet. Denn wenn Sie Ihre Lösung jahrelang nicht effektiv warten können, da sich die Dinge unter Ihren Füßen verschieben (sowohl in Bezug auf den Umgebungscode als auch auf das, was die Benutzer von Konkurrenten erwarten, die sich gegenseitig übertreffen), dann arbeitet Ihre Lösung bereits in Richtung Veralterung und In Notwendigkeit des Großhandelsersatzes.
Ich sehe den ultimativen Zweck von Profilern wie VTune nicht darin, meinen Code schneller laufen zu lassen. Ihr größter Wert ist es, sicherzustellen, dass ich meine Produktivität nicht einschränke, um den ständig steigenden Leistungsanforderungen gerecht zu werden. Wenn ich absolut etwas grob aussehende Mikro-Optimierung anwenden müssen, dann den Profiler, kombiniert mit ihm gegen reale Benutzer Fällen läuft (und nicht einige Testfall stelle ich mir vielleicht wichtig sein), stellt sicher , bewerbe ich mich so zwangsläufig grob aussehenden Optimierungen werden sehr, sehr vernünftig nur für die Top-Hotspots durchgeführt, die angezeigt werden, und sie werden sehr sorgfältig dokumentiert, da ich sie in den kommenden Jahren unweigerlich überarbeiten und warten sowie optimieren und ändern muss, wenn diese Lösung funktionsfähig bleibt.
Und vor allem, wenn Ihre optimierte Lösung mehr Kopplung beinhaltet, würde ich sie nur ungern verwenden. Zu den wertvollsten Messwerten, die ich in den leistungskritischsten Bereichen der Codebasis zu schätzen gelernt habe, gehört das Entkoppeln (wie bei der Minimierung der Informationsmenge, die benötigt wird, um zu funktionieren, was ebenfalls die Wahrscheinlichkeit minimiert, dass Änderungen erforderlich sind, sofern keine direkten Änderungen erforderlich sind) ), weil diese kritischen Bereiche die Gründe für Änderungen erheblich vervielfachen. Das heißt, je weniger Informationen für die Arbeit benötigt werden, desto weniger Gründe für Änderungen und die Minimierung der Änderungsgründe tragen wesentlich zur Verbesserung der Produktivität in meinen speziellen Schwerpunktbereichen bei, da sich die Dinge sowieso ständig ändern müssen (wir) veraltet sonst in einem Jahr),
Für mich sind die besten und effektivsten Lösungen, die ich gefunden habe, diejenigen, bei denen sich Effizienz, Wartbarkeit und Produktivität nicht diametral gegenüberstehen. Mir geht es darum, diese Konzepte so harmonisch wie möglich zu gestalten.
quelle