Stimmen Sie nicht zu, etwas zu entwickeln, das Sie nicht verstehen

Stimmen Sie nicht zu, etwas zu entwickeln, das Sie nicht verstehen

Seit Anfang 2018 bekleide ich die Position des Lead/Boss/Lead Developer im Team – nennen Sie es wie Sie wollen, aber der Punkt ist, dass ich die volle Verantwortung für eines der Module und für alle Entwickler, die arbeiten, trage darauf. Diese Position gibt mir eine neue Perspektive auf den Entwicklungsprozess, da ich in mehr Projekte involviert und aktiver in die Entscheidungsfindung eingebunden bin. Dank dieser beiden Dinge wurde mir kürzlich plötzlich klar, wie sehr sich das Maß an Verständnis auf den Code und die Anwendung auswirkt.

Ich möchte darauf hinweisen, dass die Qualität des Codes (und des Endprodukts) eng damit zusammenhängt, wie bewusst die Leute sind, die den Code entwerfen und schreiben, was sie tun.

Vielleicht denken Sie gerade: „Danke, Cap. Natürlich wäre es schön zu verstehen, was Sie im Allgemeinen schreiben. Andernfalls könnten Sie genauso gut eine Gruppe Affen anheuern, um beliebige Tasten zu drücken, und es dabei belassen.“ Und Sie haben völlig Recht. Dementsprechend gehe ich davon aus, dass Sie erkennen, dass es notwendig ist, eine allgemeine Vorstellung davon zu haben, was Sie tun. Dies kann als Nullebene des Verständnisses bezeichnet werden und wird nicht im Detail analysiert. Wir schauen uns im Detail an, was Sie genau verstehen müssen und welche Auswirkungen es auf Ihre täglichen Entscheidungen hat. Wenn ich diese Dinge im Voraus gewusst hätte, hätte mir das viel Zeitverschwendung und fragwürdigen Code erspart.

Obwohl Sie unten keine einzige Codezeile sehen werden, glaube ich dennoch, dass alles, was hier gesagt wird, von großer Bedeutung für das Schreiben von qualitativ hochwertigem, ausdrucksstarkem Code ist.

Erste Ebene des Verstehens: Warum funktioniert es nicht?

Normalerweise erreichen Entwickler dieses Niveau sehr früh in ihrer Karriere, manchmal sogar ohne die Hilfe anderer – zumindest meiner Erfahrung nach. Stellen Sie sich vor, Sie haben einen Fehlerbericht erhalten: Eine Funktion in der Anwendung funktioniert nicht und muss behoben werden. Wie gehen Sie vor?

Das Standardschema sieht so aus:

  1. Finden Sie den Codeabschnitt, der das Problem verursacht (wie das geht, ist ein separates Thema, ich behandle es in meinem Buch über Legacy-Code)
  2. Nehmen Sie Änderungen an diesem Snippet vor
  3. Stellen Sie sicher, dass der Fehler behoben ist und keine Regressionsfehler aufgetreten sind

Konzentrieren wir uns nun auf den zweiten Punkt – Änderungen am Code vornehmen. Es gibt zwei Ansätze für diesen Prozess. Die erste besteht darin, herauszufinden, was genau im aktuellen Code passiert, den Fehler zu identifizieren und ihn zu beheben. Zweitens: Bewegen Sie sich nach Gefühl – fügen Sie beispielsweise +1 zu einer bedingten Anweisung oder Schleife hinzu, prüfen Sie, ob die Funktion im gewünschten Szenario funktioniert, probieren Sie dann etwas anderes aus und so weiter bis ins Unendliche.

Der erste Ansatz ist richtig. Wie Steve McConnell in seinem Buch „Code Complete“ erklärt (das ich übrigens wärmstens empfehle), sollten wir jedes Mal, wenn wir etwas im Code ändern, in der Lage sein, mit Sicherheit vorherzusagen, wie sich dies auf die Anwendung auswirken wird. Ich zitiere aus dem Gedächtnis, aber wenn ein Bugfix nicht so funktioniert, wie Sie es erwartet haben, sollten Sie sehr alarmiert sein und Ihren gesamten Aktionsplan in Frage stellen.

Um das Gesagte zusammenzufassen: Um eine gute Fehlerbehebung durchzuführen, die die Qualität des Codes nicht beeinträchtigt, müssen Sie sowohl die gesamte Struktur des Codes als auch die Ursache des spezifischen Problems verstehen.

Zweite Ebene des Verstehens: Warum funktioniert es?

Diese Ebene ist viel weniger intuitiv zu verstehen als die vorherige. Ich habe es als unerfahrener Entwickler dank meines Chefs gelernt und anschließend den Neulingen immer wieder das Wesentliche erklärt.

Stellen wir uns dieses Mal vor, dass Sie zwei Fehlerberichte gleichzeitig erhalten: Der erste bezieht sich auf Szenario A, der zweite auf Szenario B. In beiden Szenarien passiert etwas Falsches. Dementsprechend packen Sie zuerst den ersten Fehler an. Mithilfe der Prinzipien, die wir für das Verständnis der Stufe XNUMX entwickelt haben, tauchen Sie tief in den für das Problem relevanten Code ein, finden heraus, warum er dazu führt, dass sich die Anwendung so verhält wie in Szenario A, und nehmen sinnvolle Anpassungen vor, die das gewünschte Ergebnis liefern. erwartet . Alles läuft super.

Dann fahren Sie mit Szenario B fort. Sie wiederholen das Szenario, um einen Fehler zu provozieren, aber – Überraschung! – jetzt funktioniert alles wie es soll. Um Ihre Vermutung zu bestätigen, machen Sie die Änderungen rückgängig, die Sie bei der Arbeit an Fehler A vorgenommen haben, und Fehler B tritt wieder auf. Ihr Bugfix hat beide Probleme gelöst. Glücklich!

Damit haben Sie überhaupt nicht gerechnet. Sie haben eine Möglichkeit gefunden, den Fehler in Szenario A zu beheben, haben aber keine Ahnung, warum dies bei Szenario B funktioniert hat. In diesem Stadium ist es sehr verlockend zu glauben, dass beide Aufgaben erfolgreich abgeschlossen wurden. Das ist durchaus logisch: Es ging doch darum, Fehler zu beseitigen, nicht wahr? Aber die Arbeit ist noch nicht abgeschlossen: Sie müssen noch herausfinden, warum Ihre Aktionen den Fehler in Szenario B behoben haben. Warum? Weil es möglicherweise nach den falschen Prinzipien funktioniert und Sie dann nach einem anderen Ausweg suchen müssen. Hier einige Beispiele für solche Fälle:

  • Da die Lösung unter Berücksichtigung aller Faktoren nicht auf Fehler B zugeschnitten war, haben Sie möglicherweise unwissentlich Funktion C beschädigt.
  • Es ist möglich, dass irgendwo noch ein dritter Fehler lauert, der mit derselben Funktion zusammenhängt, und dass Ihr Bugfix für den korrekten Betrieb des Systems in Szenario B davon abhängt. Jetzt sieht alles gut aus, aber eines Tages wird dieser dritte Fehler bemerkt und behoben. Dann tritt in Szenario B der Fehler erneut auf, und wenn er nur da ist, ist er gut.

All dies fügt dem Code Chaos hinzu und wird Ihnen eines Tages auf den Kopf fallen – höchstwahrscheinlich im ungünstigsten Moment. Sie müssen Ihre Willenskraft aufbringen, um sich Zeit zu nehmen, um zu verstehen, warum alles zu funktionieren scheint, aber es lohnt sich.

Dritte Verständnisebene: Warum funktioniert es?

Meine jüngste Erkenntnis bezieht sich genau auf diese Ebene und es ist wahrscheinlich diejenige, die mir den größten Nutzen gebracht hätte, wenn ich früher auf diese Idee gekommen wäre.

Чтобы было понятнее, разберем на примере: ваш модуль нужно сделать совместимым с функцией X. Вы не особенно близко знакомы с функцией X, но вам сказали, что для совместимости с ней нужно использовать фреймворк F. Другие модули, которые интегрируются с X, работают именно mit ihm.

Ihr Code stand seit dem ersten Tag seines Lebens überhaupt nicht mehr mit dem F-Framework in Kontakt, sodass die Implementierung nicht so einfach sein wird. Dies wird schwerwiegende Folgen für einige Teile des Moduls haben. Allerdings stürzen Sie sich in die Entwicklung: Sie verbringen Wochen damit, Code zu schreiben, zu testen, Pilotversionen auszurollen, Feedback einzuholen, Regressionsfehler zu beheben, unvorhergesehene Komplikationen zu entdecken, die ursprünglich vereinbarten Fristen nicht einzuhalten, noch mehr Code zu schreiben, zu testen, Rückmeldungen einzuholen, Korrigieren von Regressionsfehlern – all dies, um das F-Framework zu implementieren.

Und irgendwann wird Ihnen plötzlich klar – oder Sie hören vielleicht von jemandem –, dass Framework F Ihnen möglicherweise überhaupt keine Kompatibilität mit Feature X bietet. Vielleicht wurde die ganze Zeit und Mühe völlig falsch investiert.

Etwas Ähnliches passierte einmal während der Arbeit an einem Projekt, für das ich verantwortlich war. Warum ist das passiert? Weil ich wenig Verständnis dafür hatte, was Funktion X ist und wie sie mit Framework F zusammenhängt. Was hätte ich tun sollen? Bitten Sie die Person, die die Entwicklungsaufgabe zuweist, klar zu erklären, wie die beabsichtigte Vorgehensweise zum gewünschten Ergebnis führt, anstatt einfach zu wiederholen, was für andere Module getan wurde, oder sich beim Wort zu verlassen, dass dies das ist, was Feature X tun muss.

Die Erfahrung dieses Projekts hat mich gelehrt, den Beginn des Entwicklungsprozesses zu verweigern, bis wir klar verstehen, warum wir zu bestimmten Dingen aufgefordert werden. Lehne es komplett ab. Wenn Sie eine Aufgabe erhalten, ist der erste Impuls, diese sofort anzunehmen, um keine Zeit zu verlieren. Aber die Richtlinie „Das Projekt einfrieren, bis wir uns mit allen Details befassen“ kann die verschwendete Zeit um Größenordnungen reduzieren.

Auch wenn sie versuchen, Druck auf Sie auszuüben, Sie zu zwingen, mit der Arbeit zu beginnen, obwohl Sie die Gründe dafür nicht verstehen, widerstehen Sie. Überlegen Sie zunächst, warum Ihnen eine solche Aufgabe übertragen wird und entscheiden Sie, ob dies der richtige Weg zum Ziel ist. Ich musste das alles auf die harte Tour lernen – ich hoffe, mein Beispiel wird denjenigen, die dies lesen, das Leben erleichtern.

Vierte Ebene des Verstehens: ???

Beim Programmieren gibt es immer mehr zu lernen, und ich glaube, ich habe beim Thema Verstehen nur an der Oberfläche gekratzt. Welche anderen Ebenen des Verständnisses haben Sie im Laufe der Jahre der Arbeit mit Code entdeckt? Welche Entscheidungen haben Sie getroffen, die sich positiv auf die Qualität des Codes und der Anwendung ausgewirkt haben? Welche Entscheidungen erwiesen sich als falsch und haben Ihnen eine wertvolle Lektion erteilt? Teilen Sie Ihre Erfahrungen in den Kommentaren.

Source: habr.com

Kommentar hinzufügen