Wie man den Fluch der vorzeitigen Optimierung vermeidet
Veröffentlicht: 2022-03-11Es ist wirklich fast garantiewürdig. Vom Anfänger bis zum Experten, von der Architektur bis zum ASM und der Optimierung von allem, von der Maschinenleistung bis zur Entwicklerleistung, stehen die Chancen gut, dass Sie und Ihr Team Ihre eigenen Ziele kurzschließen.
Was? Mir? Mein Team?
Das ist eine ziemlich heftige Anschuldigung zu nivellieren. Lassen Sie mich erklären.
Optimierung ist nicht der heilige Gral, aber genauso schwer zu erreichen. Ich möchte mit Ihnen ein paar einfache Tipps (und einen Berg von Fallstricken) teilen, um die Erfahrung Ihres Teams von einer Erfahrung der Selbstsabotage in eine der Harmonie, der Erfüllung, des Gleichgewichts und schließlich der Optimierung zu verwandeln.
Was ist vorzeitige Optimierung?
Die vorzeitige Optimierung versucht, die Leistung zu optimieren:
- Beim ersten Codieren eines Algorithmus
- Vor Benchmarks müssen Sie bestätigen
- Vor dem Profiling wird genau aufgezeigt, wo es sinnvoll ist, sich um die Optimierung zu kümmern
- Auf einem niedrigeren Niveau, als es Ihr Projekt derzeit vorschreibt
Nun, ich bin ein Optimist, Optimus.
Zumindest werde ich vorgeben, ein Optimist zu sein, während ich diesen Artikel schreibe. Sie für Ihren Teil können so tun, als wäre Ihr Name Optimus, damit dies direkter zu Ihnen spricht.
Als jemand in der Technik fragen Sie sich wahrscheinlich manchmal, wie es möglich ist, dass $year trotz all unserer Fortschritte ein akzeptabler Standard für $task ist, so ärgerlich zeitaufwändig zu sein. Sie wollen schlank sein. Effizient. Fantastisch. Jemand wie die Rockstar-Programmierer, nach denen diese Stellenausschreibungen schreien, aber mit Führungsqualitäten. Wenn Ihr Team also Code schreibt, ermutigen Sie es, es beim ersten Mal richtig zu machen (auch wenn „richtig“ hier ein sehr relativer Begriff ist). Sie wissen, dass dies der Weg des cleveren Programmierers ist, und auch der Weg derer, die später keine Zeit mit Refactoring verschwenden müssen.
Ich fühle, dass. Die Kraft des Perfektionismus ist manchmal auch in mir stark. Sie möchten, dass Ihr Team jetzt ein wenig Zeit verbringt, um später viel Zeit zu sparen, denn jeder hat sich durch seinen Anteil an „Beschissener Code, den andere Leute geschrieben haben (Was zum Teufel haben sie sich dabei gedacht?)“ gequält. Das ist kurz SCOPWWHWTT, weil ich weiß, dass Sie unaussprechliche Akronyme mögen.
Ich weiß auch, dass Sie nicht wollen, dass der Code Ihres Teams das für sich selbst oder irgendjemand anderen auf der ganzen Linie ist.
Sehen wir uns also an, was getan werden kann, um Ihr Team in die richtige Richtung zu lenken.
Was zu optimieren ist: Willkommen bei This Being an Art
Erstens, wenn wir an Programmoptimierung denken, denken wir oft sofort, dass es um Performance geht. Selbst das ist bereits vager, als es scheinen mag (Geschwindigkeit? Speicherverbrauch? usw.), also hören wir genau dort auf.
Machen wir es noch zweideutiger! Nur am Anfang.
Mein Spinnweben-Gehirn schafft gerne Ordnung, wo immer es möglich ist, also braucht es jedes Quäntchen Optimismus, damit ich betrachte, was ich gleich sagen werde, als eine gute Sache .
Es gibt eine einfache Regel zur (Leistungs-)Optimierung, die lautet: Tun Sie es nicht . Das hört sich ziemlich einfach an, strikt zu befolgen, aber nicht jeder ist damit einverstanden. Ich stimme dem auch nicht ganz zu. Einige Leute werden einfach besseren Code von Anfang an schreiben als andere. Hoffentlich wird sich die Qualität des Codes, den sie in einem brandneuen Projekt schreiben würden, im Allgemeinen mit der Zeit verbessern. Aber ich weiß, dass dies für viele Programmierer nicht der Fall sein wird, denn je mehr sie wissen, desto mehr Möglichkeiten werden sie verführen, vorzeitig zu optimieren.
Für viele Programmierer … je mehr sie wissen, desto mehr Möglichkeiten werden sie verführen, vorzeitig zu optimieren.
Dieses Don't do it kann also keine exakte Wissenschaft sein, sondern soll nur dem inneren Rätseldrang des typischen Technikfreaks entgegenwirken. Schließlich ist es das, was viele Programmierer überhaupt zu diesem Handwerk hinzieht. Ich verstehe das. Aber bitte sie, es zu retten , um der Versuchung zu widerstehen. Wenn man gerade jetzt ein Ventil zum Lösen von Rätseln braucht, kann man sich jederzeit im Sudoku der Sonntagszeitung versuchen, ein Mensa-Buch nehmen oder mit einem künstlichen Problem zum Code-Golfen gehen. Aber lassen Sie es bis zum richtigen Zeitpunkt aus dem Repo heraus. Fast immer ist dies ein klügerer Weg als die Voroptimierung.
Denken Sie daran, dass diese Praxis so berüchtigt ist, dass die Leute fragen, ob vorzeitige Optimierung die Wurzel allen Übels ist. (Ich würde nicht ganz so weit gehen, aber ich stimme dem Gefühl zu.)
Ich sage nicht, dass wir auf jeder Designebene den hirntotesten Weg wählen sollten, den wir uns vorstellen können. Natürlich nicht. Aber anstatt die klügsten auszuwählen, können wir andere Werte berücksichtigen:
- Das ist Ihrem neuen Mitarbeiter am einfachsten zu erklären
- Der am ehesten eine Codeüberprüfung durch Ihren erfahrensten Entwickler bestehen wird
- Am wartungsfreundlichsten
- Am schnellsten zu schreiben
- Am einfachsten zu testen
- Das tragbarste
- usw.
Aber hier erweist sich das Problem als schwierig. Es geht nicht nur darum, die Optimierung auf Geschwindigkeit, Codegröße, Speicherbedarf, Flexibilität oder Zukunftssicherheit zu vermeiden. Es geht um Balance und darum, ob das, was man tut, tatsächlich mit seinen Werten und Zielen übereinstimmt. Es ist völlig kontextabhängig und manchmal sogar unmöglich, es objektiv zu messen.
Warum ist das gut? Weil das Leben so ist. Es ist unordentlich. Unser programmierorientiertes Gehirn möchte manchmal so sehr Ordnung in das Chaos bringen, dass wir am Ende das Chaos ironischerweise vervielfachen. Es ist wie das Paradox, jemanden dazu zu zwingen, dich zu lieben. Wenn du denkst, dass dir das gelungen ist, ist es keine Liebe mehr; während Sie der Geiselnahme angeklagt sind, brauchen Sie wahrscheinlich mehr Liebe als je zuvor, und diese Metapher muss eine der umständlichsten sein, die ich hätte wählen können.
Wie auch immer, wenn Sie denken, dass Sie das perfekte System für etwas gefunden haben, nun ja ... genießen Sie die Illusion, solange sie anhält, denke ich. Es ist okay, Misserfolge sind wunderbare Gelegenheiten zu lernen.
Behalten Sie die UX im Hinterkopf
Lassen Sie uns untersuchen, wie sich die Benutzererfahrung zwischen diese potenziellen Prioritäten einfügt. Schließlich geht es in gewisser Weise auch um UX, wenn man will, dass etwas gut funktioniert.
Wenn Sie an einer Benutzeroberfläche arbeiten, gibt es unabhängig davon, welches Framework oder welche Sprache der Code verwendet, eine gewisse Menge an Boilerplates und Wiederholungen. Es kann in Bezug auf Programmiererzeit und Codeklarheit definitiv wertvoll sein, zu versuchen, dies zu reduzieren. Um bei der Kunst des Abwägens von Prioritäten zu helfen, möchte ich ein paar Geschichten erzählen.
Bei einem Job verwendete das Unternehmen, für das ich arbeitete, ein Closed-Source-Unternehmenssystem, das auf einem rechthaberischen Tech-Stack basierte. Tatsächlich war es so eigensinnig, dass der Anbieter, der es uns verkaufte, sich weigerte, UI-Anpassungen vorzunehmen, die nicht den Meinungen des Stacks entsprachen, weil es für seine Entwickler so schmerzhaft war. Ich habe ihren Stack nie benutzt, also verurteile ich sie nicht dafür, aber Tatsache war, dass dieser Kompromiss „gut für den Programmierer, schlecht für den Benutzer“ für meine Kollegen in bestimmten Kontexten so umständlich war, dass ich endete ein Drittanbieter-Add-On zu schreiben, das diesen Teil der Benutzeroberfläche des Systems neu implementiert. (Es war ein enormer Produktivitätsschub. Meine Kollegen waren begeistert! Über ein Jahrzehnt später spart es allen dort immer noch Zeit und Frustration.)
Ich sage nicht, dass Meinungsäußerungen ein Problem an sich sind; nur dass zu viel davon in unserem Fall zu einem Problem wurde. Als Gegenbeispiel ist einer der großen Vorteile von Ruby on Rails, dass es eigensinnig ist, in einem Front-End-Ökosystem, in dem man leicht Schwindel bekommt, wenn man zu viele Optionen hat. (Geben Sie mir etwas mit Meinungen, bis ich meine eigene herausfinden kann!)
Im Gegensatz dazu könnten Sie versucht sein, UX in Ihrem Projekt zum King of Everything zu krönen. Ein würdiges Ziel, aber lassen Sie mich meine zweite Geschichte erzählen.
Ein paar Jahre nach dem Erfolg des oben genannten Projekts kam einer meiner Kollegen zu mir und bat mich, die UX zu optimieren, indem er ein bestimmtes chaotisches Szenario aus dem wirklichen Leben automatisierte, das manchmal auftrat, sodass es mit einem einzigen Klick gelöst werden konnte. Ich begann zu analysieren, ob es überhaupt möglich war, einen Algorithmus zu entwerfen, der aufgrund der vielen und seltsamen Randfälle des Szenarios keine falsch positiven oder negativen Ergebnisse hätte. Je mehr ich mit meinem Kollegen darüber sprach, desto mehr wurde mir klar, dass sich die Anforderungen einfach nicht auszahlen würden. Das Szenario tauchte nur hin und wieder auf – sagen wir einmal im Monat – und es dauerte derzeit eine Person ein paar Minuten, um es zu lösen. Selbst wenn wir es ohne Fehler erfolgreich automatisieren könnten, würde es Jahrhunderte dauern, bis sich die erforderliche Entwicklungs- und Wartungszeit in Form der Zeitersparnis meiner Kollegen auszahlt. Der Menschenfreund in mir hatte einen schwierigen Moment, um „nein“ zu sagen, aber ich musste das Gespräch abbrechen.
Lassen Sie also den Computer tun, was er kann, um dem Benutzer zu helfen, aber nur in einem vernünftigen Umfang. Woher weißt du aber, in welchem Umfang das ist?
Ein Ansatz, den ich gerne verfolge, besteht darin, die UX so zu profilieren, wie Ihre Entwickler ihren Code profilieren. Finden Sie von Ihren Benutzern heraus, wo sie die meiste Zeit damit verbringen, immer wieder dasselbe zu klicken oder einzugeben, und prüfen Sie, ob Sie diese Interaktionen optimieren können. Kann Ihr Code einige fundierte Vermutungen darüber anstellen, was sie am wahrscheinlichsten eingeben werden, und dies zu einer Standardeinstellung ohne Eingabe machen? Abgesehen von bestimmten verbotenen Kontexten (EULA-Bestätigung ohne Klick?) kann dies die Produktivität und Zufriedenheit Ihrer Benutzer wirklich verbessern. Führen Sie, wenn möglich, einige Flur-Usability-Tests durch. Manchmal fällt es Ihnen vielleicht schwer zu erklären, was für Computer einfach zu unterstützen ist und was nicht ... aber insgesamt ist dieser Wert für Ihre Benutzer wahrscheinlich von ziemlich hoher Bedeutung.
Vorzeitige Optimierung vermeiden: Wann und wie optimieren
Ungeachtet unserer Erforschung anderer Kontexte wollen wir jetzt ausdrücklich annehmen, dass wir für den Rest dieses Artikels einige Aspekte der Rohleistung der Maschine optimieren. Mein vorgeschlagener Ansatz gilt auch für andere Ziele, wie z. B. Flexibilität, aber jedes Ziel hat seine eigenen Fallstricke; Der Hauptpunkt ist, dass eine vorzeitige Optimierung für irgendetwas wahrscheinlich fehlschlagen wird.
Welche Optimierungsmethoden gibt es also in Bezug auf die Leistung tatsächlich zu verfolgen? Lassen Sie uns eintauchen.
Das ist keine Grassroots-Initiative, das ist Triple-Eh
Die TL;DR lautet: Von oben nach unten arbeiten. Optimierungen auf höherer Ebene können früher im Projekt vorgenommen werden, und Optimierungen auf niedrigerer Ebene sollten für später aufgehoben werden. Das ist alles, was Sie brauchen, um die Bedeutung des Ausdrucks „vorzeitige Optimierung“ am besten zu verstehen; Wenn Sie Dinge in dieser Reihenfolge tun, verschwenden Sie mit hoher Wahrscheinlichkeit die Zeit Ihres Teams und wirken sich kontraproduktiv aus. Schließlich schreiben Sie nicht von Anfang an das gesamte Projekt in Maschinencode, oder? Unser AAA -Modus Operandi besteht also darin, in dieser Reihenfolge zu optimieren:

- Die Architektur
- Algorithmen
- Montage
Es ist allgemein bekannt, dass Algorithmen und Datenstrukturen oft die effektivsten Stellen zur Optimierung sind, zumindest was die Leistung betrifft. Beachten Sie jedoch, dass die Architektur manchmal bestimmt, welche Algorithmen und Datenstrukturen überhaupt verwendet werden können.
Ich habe einmal eine Software entdeckt, die einen Finanzbericht erstellt, indem sie eine SQL-Datenbank mehrmals für jede einzelne Finanztransaktion abgefragt und dann eine sehr einfache Berechnung auf der Clientseite durchgeführt hat. Das kleine Unternehmen, das die Software nutzte, brauchte nur wenige Monate, bis selbst die relativ geringe Menge an Finanzdaten dazu führte, dass die Berichterstellungszeit mit brandneuen Desktops und einem ziemlich robusten Server bereits mehrere Minuten betrug, und das war es auch eine, die sie ziemlich häufig verwenden mussten. Am Ende schrieb ich eine einfache SQL-Anweisung, die die Summierungslogik enthielt – und ihre Architektur vereitelte, indem ich die Arbeit auf den Server verlagerte, um alle Duplizierungen und Netzwerk-Roundtrips zu vermeiden – und sogar Daten im Wert von mehreren Jahren später konnte meine Version die generieren gleichen Bericht in nur Millisekunden auf der gleichen alten Hardware.
Manchmal haben Sie keinen Einfluss auf die Architektur eines Projekts, weil es im Projekt zu spät ist, um eine Architekturänderung durchführbar zu machen. Manchmal können Ihre Entwickler es umgehen, wie ich es im obigen Beispiel getan habe. Aber wenn Sie am Anfang eines Projekts stehen und bei der Architektur etwas mitbestimmen können, ist es jetzt an der Zeit, dies zu optimieren.
Die Architektur
In einem Projekt ist die Architektur der teuerste Teil, der nachträglich geändert werden muss, daher kann es an dieser Stelle sinnvoll sein, von Anfang an zu optimieren. Wenn Ihre App beispielsweise Daten über Strauße liefern soll, sollten Sie sie in Richtung von Paketen mit niedriger Frequenz und hoher Nutzlast strukturieren, um zu vermeiden, dass ein schlechter Engpass noch schlimmer wird. In diesem Fall sollten Sie besser über eine vollständige Tetris-Implementierung verfügen, um Ihre Benutzer zu unterhalten, da ein Ladespinner einfach nicht ausreicht. (Spaß beiseite: Vor Jahren installierte ich meine erste Linux-Distribution, Corel Linux 2.0, und war erfreut, dass der langwierige Installationsprozess genau das beinhaltete. Nachdem ich die Infomercial-Bildschirme des Windows 95-Installationsprogramms so oft gesehen hatte, dass ich sie mir eingeprägt hatte, das hier war damals ein Hauch frischer Luft.)
Als Beispiel dafür, dass Architekturänderungen teuer sind, ist der Grund dafür, dass der oben erwähnte SQL-Bericht überhaupt so hochgradig unskalierbar ist, aus seiner Geschichte ersichtlich. Die App hatte sich im Laufe der Zeit weiterentwickelt, ausgehend von ihren Wurzeln in MS-DOS und einer selbst entwickelten, benutzerdefinierten Datenbank, die ursprünglich nicht einmal mehrbenutzerfähig war. Als der Anbieter schließlich auf SQL umgestellt hat, scheinen das Schema und der Berichtscode eins zu eins portiert worden zu sein. Dadurch konnten sie über Jahre beeindruckende Leistungsverbesserungen von über 1.000 % erzielen, die sie in ihre Updates streuen konnten, wann immer sie dazu kamen, den Architekturwechsel abzuschließen, indem sie tatsächlich die Vorteile von SQL für einen bestimmten Bericht nutzten. Gut für das Geschäft mit gebundenen Kunden wie meinem damaligen Arbeitgeber und dem klaren Versuch, die Codierungseffizienz während des anfänglichen Übergangs zu priorisieren. Aber die Bedürfnisse der Kunden zu erfüllen, ist in manchen Fällen ungefähr so effektiv wie ein Hammer eine Schraube dreht.
Bei der Architektur geht es zum Teil darum, vorherzusehen, in welchem Maße und auf welche Weise Ihr Projekt skalierbar sein muss. Da Architektur ein so hohes Niveau hat, ist es schwierig, unsere „Dos and Don'ts“ konkret zu machen, ohne unseren Fokus auf bestimmte Technologien und Domänen zu verengen.
Ich würde es nicht so nennen, aber alle anderen tun es
Zum Glück ist das Internet voll von gesammeltem Wissen über fast jede Art von Architektur, die jemals erdacht wurde. Wenn Sie wissen, dass es an der Zeit ist, Ihre Architektur zu optimieren, läuft die Untersuchung von Fallstricken darauf hinaus, das Schlagwort herauszufinden, das Ihre brillante Vision beschreibt. Die Chancen stehen gut, dass jemand in die gleiche Richtung gedacht hat wie Sie, es versucht hat, gescheitert ist, iteriert und darüber in einem Blog oder einem Buch veröffentlicht hat.
Die Identifizierung von Schlagwörtern kann schwierig sein, wenn Sie nur suchen, denn für das, was Sie FLDSMDFR nennen, hat jemand anderes bereits den Begriff SCOPWWHWTT geprägt, und sie beschreiben dasselbe Problem, das Sie lösen, verwenden jedoch ein völlig anderes Vokabular als Sie. Entwicklergemeinschaften zur Rettung! Wenden Sie sich an StackExchange oder HashNode mit einer möglichst gründlichen Beschreibung und allen Schlagworten, die Ihre Architektur nicht enthält, damit sie wissen, dass Sie ausreichend vorab recherchiert haben. Jemand wird Sie gerne aufklären.
In der Zwischenzeit könnten einige allgemeine Ratschläge ein guter Denkanstoß sein.
Algorithmen und Versammlung
Angesichts einer förderlichen Architektur erhalten die Programmierer in Ihrem Team hier das meiste T-Bling für ihre Zeit. Auch hier gilt die grundsätzliche Vermeidung voreiliger Optimierungen, aber Ihre Programmierer täten gut daran, einige Besonderheiten auf dieser Ebene zu berücksichtigen. Es gibt so viel zu bedenken, wenn es um Implementierungsdetails geht, dass ich einen separaten Artikel über Codeoptimierung geschrieben habe, der sich an Frontline- und erfahrene Programmierer richtet.
Aber sobald Sie und Ihr Team etwas leistungsmäßig nicht optimiertes implementiert haben, belassen Sie es dann wirklich bei Don't do it ? Du optimierst nie ?
Du hast recht. Die nächste Regel ist, nur für Experten, tun Sie es noch nicht .
Zeit zum Benchmarken!
Dein Code funktioniert. Vielleicht ist es so langsam, dass Sie bereits wissen , dass Sie optimieren müssen, da es sich um Code handelt, der häufig ausgeführt wird. Vielleicht sind Sie sich nicht sicher, oder Sie haben einen O(n)-Algorithmus und denken, dass es wahrscheinlich in Ordnung ist. Egal was der Fall ist, wenn dieser Algorithmus jemals eine Optimierung wert sein sollte, ist meine Empfehlung an dieser Stelle dieselbe: Führen Sie einen einfachen Benchmark durch.
Warum? Ist es nicht klar, dass mein O(n³)-Algorithmus unmöglich schlechter sein kann als alles andere? Nun, aus zwei Gründen:
- Sie können den Benchmark Ihrer Testsuite als objektives Maß für Ihre Leistungsziele hinzufügen, unabhängig davon, ob sie derzeit erreicht werden.
- Selbst Experten können Dinge versehentlich langsamer machen. Auch wenn es offensichtlich erscheint. Wirklich offensichtlich.
Glauben Sie mir beim zweiten Punkt nicht?
So erzielen Sie bessere Ergebnisse mit 1.400-Dollar-Hardware als mit 7.000-Dollar-Hardware
Jeff Atwood von StackOverflow hat einmal darauf hingewiesen, dass es manchmal (normalerweise seiner Meinung nach) kostengünstiger sein kann, einfach bessere Hardware zu kaufen, als wertvolle Programmierzeit für die Optimierung aufzuwenden. Angenommen, Sie sind zu einem einigermaßen objektiven Schluss gekommen, dass Ihr Projekt in dieses Szenario passen würde. Nehmen wir weiter an, dass Sie versuchen, die Kompilierungszeit zu optimieren, da Sie an einem umfangreichen Swift-Projekt arbeiten und dies zu einem ziemlich großen Engpass für Entwickler geworden ist. Hardware-Shopping-Zeit!
Was sollten Sie kaufen? Nun, offensichtlich, Yen für Yen, tendiert teurere Hardware dazu, eine bessere Leistung zu erbringen als billigere Hardware. Ein 7.000-Dollar-Mac Pro sollte Ihre Software also offensichtlich schneller kompilieren als ein Mac Mini der Mittelklasse, oder?
Falsch!
Es stellt sich heraus, dass manchmal mehr Kerne eine effizientere Kompilierung bedeuten … und in diesem speziellen Fall hat LinkedIn auf die harte Tour herausgefunden, dass das Gegenteil für ihren Stack gilt.
Aber ich habe Management gesehen, die einen weiteren Fehler gemacht haben: Sie haben vorher und nachher nicht einmal Benchmarks durchgeführt und festgestellt, dass sich ihre Software durch ein Hardware-Upgrade nicht schneller „anfühlt“. Aber es gab keine Möglichkeit, es genau zu wissen; Außerdem hatten sie immer noch keine Ahnung, wo der Engpass war, und blieben mit der Leistung unzufrieden, da sie die Zeit und das Geld aufgebraucht hatten, die sie bereit waren, dem Problem zu widmen.
OK, ich habe bereits einen Benchmark durchgeführt. Kann ich eigentlich noch optimieren ??
Ja, vorausgesetzt, Sie haben sich entschieden, dass Sie dies tun müssen. Aber vielleicht wartet diese Entscheidung, bis auch mehr/alle anderen Algorithmen implementiert sind, damit Sie sehen können, wie die beweglichen Teile zusammenpassen und welche am wichtigsten sind, indem Sie ein Profil erstellen. Dies kann bei einer kleinen App auf App-Ebene erfolgen oder nur für ein Subsystem gelten. Denken Sie in jedem Fall daran, dass ein bestimmter Algorithmus für die gesamte App wichtig erscheinen mag, aber selbst Experten – insbesondere Experten – neigen dazu, dies falsch zu diagnostizieren.
Denken Sie nach, bevor Sie stören
„Ich weiß nicht, wie es euch geht, aber …“
Überlegen Sie als letzten Denkanstoß, wie Sie die Idee der falschen Optimierung auf eine viel breitere Sichtweise anwenden können: Ihr Projekt oder Unternehmen selbst oder sogar einen Wirtschaftssektor.
Ich weiß, es ist verlockend zu glauben, dass Technologie den Tag retten wird und dass wir die Helden sein können, die dies möglich machen.
Plus, wenn wir es nicht tun, wird es jemand anderes tun.
Aber denken Sie daran, dass Macht trotz der besten Absichten korrumpiert. Ich werde hier nicht auf bestimmte Artikel verlinken, aber wenn Sie keinen gefunden haben, lohnt es sich, nach etwas über die umfassenderen Auswirkungen von Störungen der Wirtschaft zu suchen und darüber, wem dies manchmal letztendlich dient. Sie werden überrascht sein, welche Nebeneffekte es gibt, wenn Sie versuchen, die Welt durch Optimierung zu retten.
Nachtrag
Ist dir etwas aufgefallen, Optimus? Das einzige Mal, dass ich dich Optimus genannt habe, war am Anfang und jetzt am Ende. Sie wurden im gesamten Artikel nicht Optimus genannt. Ich bin ehrlich, ich habe es vergessen. Ich habe den ganzen Artikel geschrieben, ohne Sie Optimus zu nennen. Am Ende, als mir klar wurde, dass ich zurückgehen und deinen Namen in den Text streuen sollte, sagte eine kleine Stimme in mir, tu es nicht .
