Das Beste ist der Feind des Guten

Bild 12

In diesem Artikel geht es darum, wie wir uns einmal entschlossen haben, das interne Tool SelfTester, mit dem die Qualität des PVS-Studio-Analysators überprüft wurde, leicht zu verbessern. Die Verbesserung war einfach und sah nützlich aus, aber sie verursachte uns viele Probleme, und später stellte sich heraus, dass es besser wäre, wenn wir dies nicht tun würden.

Selftester


Wir entwickeln und fördern den statischen Code-Analysator PVS-Studio für C, C ++, C # und Java. Um die Qualität des Analysators zu überprüfen, verwenden wir interne Tools, die zusammen als SelfTester bezeichnet werden. Jede der unterstützten Sprachen verfügt über eine eigene Version von SelfTester. Dies liegt an den Testfunktionen und ist nur bequemer. Daher verwendet unser Unternehmen derzeit drei interne SelfTester-Tools für C \ C ++, C # und Java. Als nächstes werde ich über die Windows-Version von SelfTester für C \ C ++ Visual Studio-Projekte sprechen und sie einfach SelfTester nennen. Dieser Tester war der erste in der Reihe solcher internen Tools, er ist der fortschrittlichste und komplexeste von allen.

Wie funktioniert SelfTester? Die Idee ist einfach: Nehmen Sie einen Pool von Testprojekten (wir verwenden echte Projekte mit Open Source Code) und analysieren Sie sie mit PVS-Studio. Als Ergebnis wird für jedes Projekt ein Warnprotokoll für den Analysator erstellt. Dieses Protokoll wird mit dem Referenzprotokoll für dasselbe Projekt verglichen. Beim Vergleichen von Protokollen erstellt SelfTester ein Protokollvergleichsprotokoll in einer Form, die Entwickler gerne wahrnehmen können.

Nach dem Studium des Logbuchs zieht der Entwickler eine Schlussfolgerung über Änderungen im Verhalten des Analysators: Anzahl und Art der Warnungen, Betriebsgeschwindigkeit, interne Analysatorfehler usw. All diese Informationen sind sehr wichtig, damit Sie verstehen, wie gut der Analysator seine Arbeit erledigt.

Basierend auf dem Protokollvergleichsprotokoll nimmt der Entwickler Änderungen am Analysatorkern vor (z. B. beim Erstellen einer neuen Diagnoseregel) und steuert sofort die Auswirkung seiner Änderungen. Wenn der Entwickler keine Fragen mehr zum nächsten Vergleich der Protokolle hat, erstellt er das aktuelle Warnprotokoll für das Projekt als Referenz . Ansonsten geht die Arbeit weiter.

Die Aufgabe von SelfTester besteht also darin, mit einem Pool von Testprojekten zu arbeiten (übrigens gibt es bereits mehr als 120 davon für C / C ++). Projekte für den Pool werden als Visual Studio-Lösungen ausgewählt. Dies geschieht, um den Analysator zusätzlich auf verschiedenen Versionen von Visual Studio zu testen, die der Analysator unterstützt (derzeit von Visual Studio 2010 bis Visual Studio 2019).

Hinweis : Ich werde die Konzepte von Lösung und Projekt weiter trennen und das Projekt als Teil der Lösung verstehen, wie es in Visual Studio üblich ist.

Die SelfTester-Oberfläche sieht folgendermaßen aus:

Bild 3

Links finden Sie eine Liste der Lösungen, rechts die Testergebnisse für jede Version von Visual Studio.

Die grauen Markierungen "Nicht unterstützt" zeigen an, dass die Lösung die ausgewählte Version von Visual Studio nicht unterstützt oder für diese Version nicht konvertiert wurde. Einige Lösungen im Pool verfügen über eine Einstellung, die die zu überprüfende Version von Visual Studio angibt. Wenn die Version nicht angegeben wird, wird die Lösung auf alle nachfolgenden Versionen von Visual Studio aktualisiert. Ein Beispiel für eine solche Lösung im Screenshot ist "smart_ptr_check.sln" (die Überprüfung wurde für alle Versionen von Visual Studio durchgeführt).

Ein grünes „OK“ zeigt an, dass bei der nächsten Prüfung keine Unterschiede zum Referenzprotokoll festgestellt wurden. Eine rote „Diff“ -Markierung zeigt Unterschiede an. Auf solchen Etiketten sollte der Entwickler aufpassen. Dazu muss er auf das gewünschte Etikett doppelklicken. Die ausgewählte Lösung wird in der gewünschten Version von Visual Studio geöffnet, und dort wird auch ein Fenster mit einem Warnprotokoll geöffnet. Mit den folgenden Steuertasten können Sie die Analyse der ausgewählten oder aller Entscheidungen neu starten, das ausgewählte Protokoll (oder alle gleichzeitig) den Standardprotokollen zuweisen usw.

Die präsentierten Ergebnisse der SelfTester-Arbeit werden immer im HTML-Bericht (Differenzprotokoll) dupliziert.

Zusätzlich zur grafischen Benutzeroberfläche verfügt SelfTester über automatisierte Modi für die Ausführung während nächtlicher Builds. Das übliche Verwendungsmuster wird jedoch vom Entwickler während des Arbeitstages wiederholt gestartet. Daher ist eine der wichtigen Eigenschaften von SelfTester die Geschwindigkeit .

Warum Geschwindigkeit wichtig ist:

  1. Um während der Nachttests ausgeführt zu werden, ist die Zeit, die für jeden Schritt benötigt wird, entscheidend. Je schneller die Tests bestehen, desto besser. Die durchschnittliche Betriebszeit von SelfTester beträgt derzeit mehr als 2 Stunden.
  2. Wenn SelfTester tagsüber gestartet wird, muss der Entwickler weniger auf das Ergebnis warten, was die Arbeitsproduktivität erhöht.

Es war der Wunsch, die Arbeit von SelfTester zu beschleunigen, der diesmal die Verbesserungen verursachte.

Multithreading in SelfTester


SelfTester wurde ursprünglich als Multithread-Anwendung mit der Möglichkeit erstellt, mehrere Lösungen gleichzeitig zu überprüfen. Die einzige Einschränkung bestand darin, dass Sie nicht gleichzeitig dieselbe Lösung für verschiedene Versionen von Visual Studio überprüfen können, da viele Lösungen vor der Überprüfung auf bestimmte Versionen von Visual Studio aktualisiert werden müssen. Währenddessen werden Änderungen direkt an den .vcxproj- Projektdateien vorgenommen, was bei paralleler Ausführung zu Fehlern führt.

Um die Arbeit effizienter zu gestalten, verwendet SelfTester einen intelligenten Taskplaner, mit dem Sie einen streng begrenzten Wert für parallele Threads festlegen und verwalten können.

Der Scheduler wird auf zwei Ebenen verwendet. Die erste ist die Lösungsebene , mit der die Überprüfung der SLN- Lösung mit dem Dienstprogramm PVS-Studio_Cmd.exe gestartet wird . In PVS-Studio_Cmd.exe (auf der Ebene der Überprüfung von Quellcodedateien) wird derselbe Scheduler verwendet, jedoch mit einem anderen Grad an Parallelitätseinstellung .

Der Parallelitätsgrad ist ein Parameter, der angibt, wie viele parallele Threads gleichzeitig ausgeführt werden sollen. Für Werte des Parallelitätsgrades auf Entscheidungsebene und für Dateien wurden die Standardwerte von vier bzw. acht ausgewählt. Daher sollte die Anzahl der parallelen Threads für diese Implementierung 32 betragen (vier gleichzeitig getestete Lösungen und acht Dateien). Diese Einstellung scheint uns optimal für den Analysator zu sein, um auf einem Acht-Kern-Prozessor zu arbeiten.

Der Entwickler kann unabhängig andere Werte für den Grad der Parallelität festlegen, wobei er sich auf die Leistung seines Computers oder auf aktuelle Aufgaben konzentriert. Wenn er diesen Parameter nicht einstellt, wird standardmäßig die Anzahl der logischen Prozessoren des Systems ausgewählt.

Hinweis : Außerdem werden wir berücksichtigen, dass die Arbeit mit den Standardwerten für den Parallelitätsgrad ausgeführt wird.

Der LimitedConcurrencyLevelTaskScheduler-Scheduler wird von System.Threading.Tasks.TaskScheduler geerbt und verfeinert, um ein Höchstmaß an Parallelität bei der Arbeit mit ThreadPool zu gewährleisten . Vererbungshierarchie:

LimitedConcurrencyLevelTaskScheduler : PausableTaskScheduler { .... } PausableTaskScheduler: TaskScheduler { .... } 

Mit PausableTaskScheduler können Sie Aufgaben anhalten , und LimitedConcurrencyLevelTaskScheduler bietet darüber hinaus eine intelligente Steuerung der Aufgabenwarteschlange und der Planung ihrer Ausführung unter Berücksichtigung des Parallelitätsgrads, der Anzahl der geplanten Aufgaben und anderer Faktoren. Der Scheduler wird beim Starten von System.Threading.Tasks.Task- Tasks verwendet.

Voraussetzungen für Verbesserungen


Die Umsetzung der oben beschriebenen Arbeit hat einen Nachteil: Sie ist nicht optimal, wenn mit Lösungen unterschiedlicher Größe gearbeitet wird. Die Größe der Lösungen im Testpool ist sehr unterschiedlich: 8 KB bis 4 GB für die Größe des Ordners mit der Lösung und jeweils eine bis mehrere tausend Quellcodedateien.

Der Scheduler stellt die Entscheidungen einfach in der richtigen Reihenfolge ohne intellektuelle Komponente in die Warteschlange. Ich möchte Sie daran erinnern, dass standardmäßig nicht mehr als vier Lösungen gleichzeitig überprüft werden können. Wenn derzeit vier große Lösungen überprüft werden (die Anzahl der Dateien in jeder ist mehr als acht), wird davon ausgegangen, dass wir effizient arbeiten, da wir die maximal mögliche Anzahl von Threads verwenden (32).

Stellen Sie sich jedoch eine ziemlich häufige Situation vor, in der mehrere kleine Lösungen getestet werden. Beispielsweise ist eine Lösung groß und enthält 50 Dateien (maximal acht Threads sind beteiligt), und die anderen drei enthalten jeweils drei, vier und fünf Dateien. In diesem Fall verwenden wir nur 20 Threads (8 + 3 + 4 + 5). Die Prozessorzeit wird nicht ausreichend genutzt, und die Gesamtleistung nimmt ab.

Hinweis : Tatsächlich ist der Engpass in der Regel immer noch das Festplattensubsystem und nicht der Prozessor.

Verbesserungen


Eine Verbesserung, die sich in diesem Fall selbst anbietet, ist die Rangfolge der Liste der zur Überprüfung eingereichten Lösungen. Es ist notwendig, eine bestimmte Anzahl gleichzeitig ausgeführter Threads (32) optimal zu nutzen, indem Projekte mit der „richtigen“ Anzahl von Dateien zur Überprüfung eingereicht werden.

Schauen wir uns noch einmal unser Beispiel an, wenn vier Lösungen mit jeweils der folgenden Anzahl von Dateien getestet werden: 50, 3, 4 und 5. Eine Aufgabe, die eine Lösung aus drei Dateien überprüft, wird wahrscheinlich bald funktionieren. Und stattdessen wäre es optimal, eine Lösung hinzuzufügen, in der acht oder mehr Dateien vorhanden sind (um maximal acht verfügbare Streams für diese Lösung zu verwenden). Dann werden wir insgesamt bereits 25 Threads verwenden (8 + 8 + 4 + 5). Nicht schlecht. Sieben Threads wurden jedoch noch nicht verwendet. Und hier entsteht die Idee einer weiteren Verfeinerung, die sich auf die Aufhebung der Beschränkung auf vier Threads zur Überprüfung von Lösungen bezieht. In der Tat können Sie im obigen Beispiel nicht eine, sondern mehrere Lösungen hinzufügen, wobei Sie so viel wie möglich alle 32 Threads verwenden. Stellen wir uns vor, wir haben zwei weitere Lösungen, jeweils drei und vier Dateien. Durch Hinzufügen dieser Aufgaben wird die „Lücke“ in nicht verwendeten Threads vollständig geschlossen, und es werden 32 (8 + 8 + 4 + 5 + 3 + 4 ) vorhanden sein.

Ich denke, die Idee ist klar. Tatsächlich erforderte die Umsetzung dieser Verbesserungen auch keinen großen Aufwand. Alles war an einem Tag erledigt.

Es war notwendig, die Taskklasse : Vererbung von System.Threading.Tasks.Task zu verfeinern und das Feld "weight" hinzuzufügen. Um das Gewicht der Lösung festzulegen, wird ein einfacher Algorithmus verwendet: Wenn die Anzahl der Dateien in der Lösung weniger als acht beträgt, wird das Gewicht gleich diesem Wert gesetzt (z. B. 5). Wenn die Anzahl der Dateien größer oder gleich acht ist, wird das Gewicht gleich acht gewählt.

Es war auch notwendig, den Scheduler zu verfeinern: ihm beizubringen, Lösungen mit dem richtigen Gewicht auszuwählen, um einen Maximalwert von 32 Threads zu erreichen. Es war auch notwendig, die Zuweisung von mehr als vier Threads für die gleichzeitige Überprüfung von Lösungen zuzulassen.

Schließlich war ein erster Schritt erforderlich, um alle Poollösungen zu analysieren (Auswertung mit der MSBuild-API), um die Lösungsgewichte zu berechnen und festzulegen (Anzahl der Dateien mit Quellcode ermitteln).

Ergebnis


Ich denke, nach einer so langen Einführung haben Sie bereits vermutet, dass das Ergebnis Null war.

Bild 15

Es ist gut, dass die Verbesserungen einfach und schnell waren.

Nun beginnt tatsächlich der Teil des Artikels über "viele Probleme für uns geschaffen", und das ist alles.

Nebenwirkungen


Ein negatives Ergebnis ist also auch ein Ergebnis. Es stellte sich heraus, dass die Anzahl der großen Lösungen im Pool die Anzahl der kleinen (weniger als acht Dateien) erheblich übersteigt. Unter diesen Bedingungen machen sich die vorgenommenen Verbesserungen nicht bemerkbar, da sie praktisch unsichtbar sind: Ihre Überprüfung nimmt im Vergleich zu großen Projekten eine mikroskopische Zeit in Anspruch.

Trotzdem wurde beschlossen, die Überarbeitung als "nicht störend" und potenziell nützlich zu belassen. Darüber hinaus wird der Pool an Testlösungen ständig aufgefüllt, sodass sich die Situation in Zukunft möglicherweise ändern wird.

Und dann ...

Bild 5

Einer der Entwickler beschwerte sich über den "Fall" von SelfTester. Nun, es passiert. Um zu verhindern, dass dieser Fehler verloren geht, wurde ein interner Vorfall (Ticket) mit dem Namen „Ausnahme bei der Arbeit mit SelfTester“ gestartet. Der Fehler trat während der Evaluierung des Projekts auf. Eine solche Fülle von Fenstern hat das Problem auch im Fehlerbehandler bestätigt. Dies wurde jedoch schnell beseitigt, und in der nächsten Woche brach nichts zusammen. Plötzlich beschwerte sich ein anderer Benutzer über SelfTester. Und noch einmal zum Fehler der Projektevaluierung:

Bild 8

Der Stapel enthielt diesmal nützlichere Informationen - ein Fehler im XML-Format. Wahrscheinlich ist bei der Verarbeitung der Projektdatei Proto_IRC.vcxproj (ihrer XML-Darstellung) etwas mit der Datei selbst passiert, sodass XmlTextReader sie nicht verarbeiten konnte.

Das Vorhandensein von zwei Fehlern in relativ kurzer Zeit hat uns veranlasst, das Problem genauer zu betrachten. Darüber hinaus wird SelfTester, wie oben erwähnt, von Entwicklern sehr aktiv genutzt.

Zunächst wurde der letzte Ort des Sturzes analysiert. Leider konnte nichts Verdächtiges festgestellt werden. Für alle Fälle haben sie Entwickler (SelfTester-Benutzer) gebeten, auf der Hut zu sein und mögliche Fehler zu melden.

Ein wichtiger Punkt: Der Code, bei dem der Fehler aufgetreten ist, wurde in SelfTester wiederverwendet. Zunächst werden damit Projekte im Analysator selbst ( PVS-Studio_Cmd.exe ) ausgewertet . Deshalb ist die Aufmerksamkeit auf das Problem gewachsen. Im Analysator traten jedoch keine ähnlichen Tropfen auf.

In der Zwischenzeit wurde ein Ticket über Probleme mit SelfTester mit neuen Fehlern aufgefüllt:

Bild 9

Und wieder XmlException . Offensichtlich gibt es irgendwo konkurrierende Threads, die mit Lese- und Schreibprojektdateien arbeiten. SelfTester arbeitet in folgenden Fällen mit Projekten:

  1. Bewertung von Projekten während der vorläufigen Berechnung von Entscheidungsgewichten: ein neuer Schritt, der zunächst Verdacht erregte;
  2. Aktualisieren von Projekten auf die erforderlichen Versionen von Visual Studio: Wird unmittelbar vor der Überprüfung durchgeführt (Projekte überschneiden sich in keiner Weise) und sollten die Arbeit nicht beeinträchtigen.
  3. Bewertung von Projekten während der Überprüfung: Debugging eines thread-sicheren Mechanismus, der von PVS-Studio_Cmd.exe wiederverwendet wurde;
  4. Wiederherstellen von Projektdateien (Ersetzen geänderter .vcxproj- Dateien durch die ursprünglichen Referenzdateien) beim Beenden von SelfTester, da Projektdateien dabei auf die erforderlichen Versionen von Visual Studio aktualisiert werden können: der letzte Schritt, der auch andere Mechanismen nicht beeinflusst.

Der Verdacht fiel auf den neuen Code, der zur Optimierung hinzugefügt wurde (Berechnung der Gewichte). Die Untersuchung dieses Codes ergab jedoch, dass der Tester immer korrekt auf das Ende der vorläufigen Bewertung wartete, wenn der Benutzer die Analyse unmittelbar nach dem Start von SelfTester startete. Dieser Ort sah sicher aus.

Auch hier konnten wir die Ursache des Problems nicht identifizieren.

Schmerz


Im Laufe des nächsten Monats fiel SelfTester von Zeit zu Zeit weiter. Das Ticket wurde mit Daten aufgefüllt, aber es war nicht klar, was mit diesen Daten zu tun ist. Die meisten Abstürze waren alle mit derselben XmlException . Gelegentlich gab es noch etwas anderes, aber denselben wiederverwendeten Code aus PVS-Studio_Cmd.exe .

Bild 1

Traditionell werden keine so hohen Anforderungen an interne Tools gestellt, so dass die Arbeit mit SelfTester-Fehlern dennoch auf Restbasis durchgeführt wurde. Von Zeit zu Zeit waren verschiedene Personen miteinander verbunden (während der gesamten Zeit des Vorfalls arbeiteten sechs Personen an dem Problem, darunter zwei Praktikanten). Trotzdem musste die Aufgabe abgelenkt werden.

Unser erster Fehler. Tatsächlich war es hier bereits möglich, das Problem ein für alle Mal zu lösen. Wie? Es war klar, dass der Fehler durch eine neue Optimierung verursacht wurde. Immerhin hat vorher alles gut funktioniert, und wiederverwendeter Code konnte offensichtlich nicht so schlecht sein. Darüber hinaus brachte diese Optimierung keine Vorteile. Was musste also getan werden? Entfernen Sie diese Optimierung . Wie Sie wissen, wurde dies nicht getan. Wir arbeiteten weiter an einem Problem, das wir selbst geschaffen hatten. Die Suche nach der Antwort auf die Frage "WIE ???" wurde fortgesetzt. Wie fällt es? Dennoch scheint es richtig geschrieben zu sein.

Unser zweiter Fehler. Andere Menschen waren mit der Lösung des Problems verbunden. Ein sehr, sehr großer Fehler. Leider hat dies nicht nur das Problem nicht gelöst, sondern es wurden zusätzliche Ressourcen aufgewendet. Ja, neue Leute brachten neue Ideen mit, aber für ihre Umsetzung wurde viel Arbeitszeit benötigt (absolut verschwendet). Zu einem bestimmten Zeitpunkt wurden Testprogramme (von denselben Auszubildenden) geschrieben, die die Bewertung desselben Projekts in verschiedenen Threads mit paralleler Änderung des Projekts in einem anderen Thread emulieren. Es hat nicht geholfen. Zusätzlich zu dem, was wir bereits zuvor wussten, ist die MSBuild-API im Inneren threadsicher. Sie haben nichts Neues herausgefunden. In SelfTester wurde ein Mini-Dump hinzugefügt, als eine XmlException ausgelöst wurde. Dann hat das alles jemand entsetzt, Entsetzen. Es wurden Diskussionen geführt, viele andere unnötige Dinge wurden getan.

Endlich unser dritter Fehler . Wissen Sie, wie viel Zeit vergangen ist, seit das Problem mit SelfTester aufgetreten ist und wie es gelöst wurde? Obwohl nein, zählen Sie sich. Der Vorfall wurde am 17.09.2008 erstellt und am 20.02.2019 geschlossen. Dort gibt es mehr als 40 (vierzig!) Nachrichten. Leute, das ist viel Zeit! Wir haben uns erlaubt , fünf Monate lang IT zu betreiben. Zur gleichen Zeit (parallel) haben wir Visual Studio 2019 unterstützt, die Java-Sprache hinzugefügt, mit der Implementierung des MISRA C / C ++ - Standards begonnen, den C # -Analysator verbessert, aktiv an Konferenzen teilgenommen, eine Reihe von Artikeln geschrieben usw. Und all diese Arbeiten haben den Entwicklern aufgrund des dummen Fehlers SelfTester keine Zeit gegeben.

Bürger, lernen aus unseren Fehlern und tun das niemals. Und wir werden nicht.

Ich habe alles

Bild 17

Natürlich ist dies ein Witz und ich werde Ihnen sagen, was das Problem mit SelfTester war :)

Bingo!


Glücklicherweise war unter uns eine Person mit dem am wenigsten getrübten Bewusstsein (mein Kollege Sergey Vasiliev), die das Problem nur aus einem ganz anderen Blickwinkel betrachtete (und auch ein wenig Glück hatte). Was ist, wenn in SelfTester wirklich alles in Ordnung ist und Projekte etwas von außen brechen? Parallel zu SelfTester wurde normalerweise nichts gestartet. In einigen Fällen haben wir die Laufzeit streng kontrolliert. In diesem Fall könnte dieses „Etwas“ nur SelfTester selbst sein, aber eine weitere Instanz davon.

Nach dem Beenden von SelfTester funktioniert der Stream, der Projektdateien aus den Standards wiederherstellt, noch einige Zeit. Zu diesem Zeitpunkt können Sie den Tester neu starten. Der Schutz gegen das gleichzeitige Ausführen mehrerer Instanzen von SelfTester wurde später hinzugefügt und sieht nun folgendermaßen aus:

Bild 16

Aber dann war sie weg.

Unglaublicherweise hat fast ein halbes Jahr lang niemand darauf geachtet. Das Wiederherstellen von Projekten aus Standards ist ein Hintergrundverfahren, das schnell genug ist, aber leider nicht schnell genug, um den Neustart von SelfTester nicht zu beeinträchtigen. Und was passiert beim Start? Das ist richtig, Entscheidungsgewichte zu berechnen. Ein Prozess überschreibt .vcxproj- Dateien, während ein anderer versucht, sie zu lesen. Hallo, XmlException .

Sergey fand dies alles heraus, als er dem Tester die Möglichkeit hinzufügte, in den Arbeitsmodus mit einem anderen Satz von Standardprotokollen zu wechseln. Die Notwendigkeit hierfür ergab sich nach dem Hinzufügen des MISRA-Regelsatzes zum Analysegerät. Sie können direkt in der Benutzeroberfläche wechseln, während der Benutzer das Fenster sieht:

Bild 14

Danach wird SelfTester neu gestartet. Nun, anscheinend haben Benutzer das Problem früher selbst emuliert und den Tester erneut gestartet.

Nachbesprechung und Schlussfolgerungen


Natürlich haben wir die zuvor erstellte Optimierung gelöscht oder vielmehr deaktiviert. Außerdem war es viel einfacher als eine Art Synchronisation zwischen dem Rest des Testers selbst durchzuführen. Und alles begann nach wie vor einwandfrei zu funktionieren. Als zusätzliche Maßnahme wurde der oben beschriebene Schutz gegen das gleichzeitige Starten des Testers hinzugefügt.

Ich habe oben bereits über unsere Hauptfehler bei der Suche nach dem Problem geschrieben, daher reicht es aus, sich selbst zu kennzeichnen. Wir sind auch Menschen, und deshalb irren wir uns. Es ist wichtig, aus Ihren Fehlern zu lernen und Schlussfolgerungen zu ziehen. Die Schlussfolgerungen hier sind recht einfach:

  • Es ist notwendig, das Wachstum der Aufgabenkomplexität zu verfolgen und zu bewerten.
  • Stoppen Sie rechtzeitig;
  • Versuchen Sie, das Problem breiter zu betrachten, da die Ansicht mit der Zeit „verschwommen“ und der Blickwinkel verengt wird.
  • Haben Sie keine Angst, alten oder unnötigen Code zu löschen.

Nun sicher - das war's. Danke fürs Lesen. An alle hoffnungslosen Codes!



Wenn Sie diesen Artikel einem englischsprachigen Publikum zugänglich machen möchten, verwenden Sie bitte den Link zur Übersetzung: Sergey Khrenov. Das Beste ist der Feind des Guten .

Source: https://habr.com/ru/post/de466741/


All Articles