Lass es funktionieren, mach es sauber, mach es FEST, dann mach es so schnell, wie es funktionieren muss .
Das sollte die normale Reihenfolge sein. Ihre allererste Priorität ist es, etwas zu schaffen, das die Abnahmetests besteht, die die Anforderungen nicht erfüllen. Dies ist Ihre erste Priorität, da dies die erste Priorität Ihres Kunden ist. Erfüllung der funktionalen Anforderungen innerhalb der Entwicklungsfristen. Die nächste Priorität besteht darin, sauberen, lesbaren Code zu schreiben, der leicht zu verstehen ist und daher von Ihrer Nachwelt ohne WTFs gepflegt werden kann, wenn dies erforderlich wird (es ist fast nie eine Frage des "Wenn"; Sie oder jemand, nachdem Sie gehen müssen) wieder rein und etwas ändern / reparieren). Die dritte Priorität besteht darin, den Code an die SOLID-Methode anzupassen (oder GRASP, wenn Sie dies bevorzugen), die Code in modulare, wiederverwendbare, austauschbare Blöcke unterteilt, die wiederum die Wartung unterstützen (sie können nicht nur verstehen, was Sie getan haben und warum). Es gibt jedoch klare Linien, entlang derer ich Codeteile chirurgisch entfernen und ersetzen kann. Die letzte Priorität ist die Leistung; Wenn Code wichtig genug ist, um den Leistungsspezifikationen zu entsprechen, ist er mit ziemlicher Sicherheit wichtig genug, um zuerst korrekt, sauber und FEST gemacht zu werden.
In Anlehnung an Christopher (und Donald Knuth) ist "vorzeitige Optimierung die Wurzel allen Übels". Darüber hinaus sind die von Ihnen in Betracht gezogenen Optimierungen sowohl geringfügig (ein Verweis auf Ihr neues Objekt wird auf dem Stapel erstellt, unabhängig davon, ob Sie ihm im Quellcode einen Namen geben oder nicht) als auch von einem Typ, der möglicherweise keinen Unterschied bei der Kompilierung verursacht IL. Variablennamen werden nicht in die IL übertragen. Da Sie die Variable also unmittelbar vor ihrer ersten (und wahrscheinlich einzigen) Verwendung deklarieren, würde ich etwas Biergeld darauf wetten, dass die IL zwischen Ihren beiden Beispielen identisch ist. Ihr Mitarbeiter hat also 100% Recht. Sie suchen an der falschen Stelle, wenn Sie die benannte Variable im Vergleich zur Inline-Instanziierung suchen, um etwas zu optimieren.
Mikrooptimierungen in .NET sind es fast nie wert (ich spreche von 99,99% der Fälle). In C / C ++ vielleicht, WENN Sie wissen, was Sie tun. Wenn Sie in einer .NET-Umgebung arbeiten, sind Sie bereits weit genug vom Metall der Hardware entfernt, sodass die Codeausführung einen erheblichen Aufwand verursacht. Angesichts der Tatsache, dass Sie sich bereits in einer Umgebung befinden, die angibt, dass Sie die Geschwindigkeit der Blasenbildung aufgegeben haben und stattdessen "richtigen" Code schreiben möchten, ist die Komplexität einer .NET-Umgebung nicht schnell genug zu hoch, oder Sie sollten überlegen, es zu parallelisieren. Hier sind einige grundlegende Hinweise zur Optimierung. Ich garantiere Ihnen, dass Ihre Produktivität bei der Optimierung (Geschwindigkeit, die für die aufgewendete Zeit gewonnen wird) in die Höhe schnellen wird:
- Das Ändern der Funktionsform ist wichtiger als das Ändern der Koeffizienten - WRT Big-Oh-Komplexität. Sie können die Anzahl der Schritte, die in einem N 2 -Algorithmus ausgeführt werden müssen, um die Hälfte reduzieren , und Sie haben immer noch einen Algorithmus mit quadratischer Komplexität, obwohl er ausgeführt wird die halbe Zeit früher. Wenn dies die untere Grenze der Komplexität für diese Art von Problem ist, sei es auch so, aber wenn es eine NlogN-, lineare oder logarithmische Lösung für dasselbe Problem gibt, werden Sie mehr gewinnen, wenn Sie Algorithmen wechseln, um die Komplexität zu reduzieren, als wenn Sie diejenige optimieren, die Sie haben.
- Nur weil man nicht die Komplexität sehen kann, bedeutet nicht , dass es nicht Sie kostet - Viele des eleganteste Einzeiler im Wort führen schrecklich (zum Beispiel der Regex prime - Checker ist eine exponentielle Komplexität Funktion, während eines effizienten Die Primbewertung, bei der die Zahl durch alle Primzahlen geteilt wird, die kleiner als ihre Quadratwurzel sind, liegt in der Größenordnung von O (Nlog (sqrt (N))). Linq ist eine großartige Bibliothek, da sie den Code vereinfacht, im Gegensatz zu einer SQL-Engine jedoch das .Net Der Compiler wird nicht versuchen, den effizientesten Weg zur Ausführung Ihrer Abfrage zu finden. Sie müssen wissen, was passiert, wenn Sie eine Methode verwenden, und warum eine Methode möglicherweise schneller ist, wenn sie früher (oder später) in der Kette platziert wird, während sie produziert die gleichen Ergebnisse.
- OTOH, es gibt fast immer einen Kompromiss zwischen Quellkomplexität und Laufzeitkomplexität - SelectionSort ist sehr einfach zu implementieren; Sie könnten es wahrscheinlich in 10LOC oder weniger tun. MergeSort ist etwas komplexer, Quicksort noch komplexer und RadixSort noch komplexer. Wenn jedoch die Codierungskomplexität der Algorithmen (und damit die Entwicklungszeit im Voraus) zunimmt, nimmt die Laufzeitkomplexität ab. MergeSort und QuickSort sind NlogN, und RadixSort wird im Allgemeinen als linear betrachtet (technisch gesehen ist es NlogM, wobei M die größte Zahl in N ist).
- Schnell brechen - Wenn es eine Prüfung gibt, die kostengünstig durchgeführt werden kann, die mit großer Wahrscheinlichkeit wahr ist und bedeutet, dass Sie weitermachen können, führen Sie diese Prüfung zuerst durch. Wenn sich Ihr Algorithmus beispielsweise nur um Zahlen kümmert, die mit 1, 2 oder 3 enden, ist der wahrscheinlichste Fall (bei vollständig zufälligen Daten) eine Zahl, die mit einer anderen Ziffer endet. Testen Sie also, dass die Zahl NICHT mit endet 1, 2 oder 3, bevor überprüft wird, ob die Zahl mit 1, 2 oder 3 endet. Wenn für eine Logik A & B erforderlich ist und P (A) = 0,9, während P (B) = 0,1 ist, überprüfen Sie B zuerst, es sei denn, wenn! A dann! B (wie
if(myObject != null && myObject.someProperty == 1)
) oder B mehr als 9-mal länger als A benötigt, um ( if(myObject != null && some10SecondMethodReturningBool())
) zu bewerten .
- Stellen Sie keine Frage, auf die Sie bereits die Antwort kennen. Wenn Sie eine Reihe von "Durchfall" -Bedingungen haben und eine oder mehrere dieser Bedingungen von einer einfacheren Bedingung abhängen, die ebenfalls überprüft werden muss, überprüfen Sie niemals beide diese unabhängig voneinander. Wenn Sie beispielsweise einen Scheck haben, für den A erforderlich ist, und einen Scheck, für den A & B erforderlich ist, sollten Sie A prüfen, und wenn dies zutrifft, sollten Sie B prüfen. Wenn! A, dann! A && B, also kümmern Sie sich nicht einmal darum.
- Je öfter Sie etwas tun, desto mehr sollten Sie darauf achten, wie es gemacht wird. Dies ist auf vielen Ebenen ein allgemeines Thema in der Entwicklung. Im allgemeinen Entwicklungssinn: "Wenn eine gemeinsame Aufgabe zeitaufwändig oder umständlich ist, machen Sie sie so lange, bis Sie sowohl frustriert als auch kompetent genug sind, um einen besseren Weg zu finden." Je öfter ein ineffizienter Algorithmus ausgeführt wird, desto mehr an Code gewinnen Sie durch Optimierung. Es gibt Profiling-Tools, die eine binäre Assembly und ihre Debug-Symbole verwenden und Ihnen nach Durchlaufen einiger Anwendungsfälle zeigen können, welche Codezeilen am häufigsten ausgeführt wurden. Diese Linien und die Linien, die diese Linien führen, sollten Sie am meisten beachten, da jede Effizienzsteigerung, die Sie dort erzielen, vervielfacht wird.
- Ein komplexerer Algorithmus sieht aus wie ein weniger komplexer Algorithmus, wenn Sie genügend Hardware darauf werfen . Manchmal müssen Sie nur feststellen, dass sich Ihr Algorithmus den technischen Grenzen des Systems (oder des Teils davon) nähert, auf dem Sie ihn ausführen. Von diesem Punkt an, wenn es schneller sein muss, gewinnen Sie mehr, indem Sie es einfach auf besserer Hardware ausführen. Dies gilt auch für die Parallelisierung; Ein N 2 -Komplexitätsalgorithmus sieht linear aus, wenn er auf N Kernen ausgeführt wird. Wenn Sie also sicher sind, dass Sie die geringere Komplexität für den Typ des Algorithmus erreicht haben, den Sie schreiben, suchen Sie nach Möglichkeiten zum "Teilen und Erobern".
- Es ist schnell, wenn es schnell genug ist. Wenn Sie die Baugruppe nicht von Hand verpacken, um auf einen bestimmten Chip abzuzielen, gibt es immer etwas zu gewinnen. Wenn Sie jedoch nicht von Hand verpacken möchten, müssen Sie immer bedenken, was der Kunde als "gut genug" bezeichnen würde. Wiederum "ist vorzeitige Optimierung die Wurzel allen Übels"; Wenn Ihr Kunde es schnell genug anruft, sind Sie fertig, bis er nicht mehr glaubt, dass es schnell genug ist.