Ich habe ein Projekt, das so groß ist, dass ich nicht mehr jeden Aspekt im Kopf behalten kann. Ich beschäftige mich mit einer Reihe von Klassen und Funktionen darin und gebe Daten weiter.
Mit der Zeit bemerkte ich, dass ich immer wieder Fehler bekam, weil ich vergaß, welche genaue Form die Daten haben müssen, wenn ich sie an verschiedene Funktionen übergebe ( z. B. eine Funktion akzeptiert und gibt ein Array von Zeichenfolgen aus, eine andere Funktion, die ich viel später geschrieben habe). Akzeptiert Zeichenfolgen, die in einem Wörterbuch usw. gespeichert sind. Daher muss ich die Zeichenfolgen, mit denen ich arbeite, von einem Array in ein Wörterbuch umwandeln .
Um nicht immer herausfinden zu müssen, was wo kaputt gegangen ist, habe ich begonnen, jede Funktion und Klasse als "isolierte Entität" in dem Sinne zu behandeln, dass sie sich nicht darauf verlassen kann, dass externer Code die richtige Eingabe liefert, und dass sie selbst Eingabeprüfungen durchführen muss (oder) In einigen Fällen müssen die Daten neu gefasst werden, wenn die Daten in der falschen Form angegeben wurden.
Dies hat die Zeit, die ich damit verbringe, sicherzustellen, dass die Daten, die ich weitergebe, in jede Funktion "passen", erheblich reduziert, da mich die Klassen und Funktionen selbst jetzt warnen, wenn einige Eingaben schlecht sind (und dies manchmal sogar korrigieren), und ich nicht Ich muss mit einem Debugger den gesamten Code durchgehen, um herauszufinden, wo etwas durcheinander geraten ist.
Andererseits hat dies auch den Gesamtcode erhöht.
Meine Frage ist, ob dieser Codestil zur Lösung dieses Problems geeignet ist.
Die beste Lösung wäre natürlich, das Projekt komplett umzugestalten und sicherzustellen, dass die Daten für alle Funktionen eine einheitliche Struktur haben. Da dieses Projekt jedoch ständig wächst, würde ich am Ende mehr Geld ausgeben und mir Sorgen um sauberen Code machen, als tatsächlich neues Material hinzuzufügen .
(Zu Ihrer Information: Ich bin noch ein Anfänger. Bitte entschuldigen Sie, wenn diese Frage naiv war. Mein Projekt ist in Python.)
quelle
Antworten:
Eine bessere Lösung besteht darin, die Funktionen und Werkzeuge der Python-Sprache besser zu nutzen.
Dieses Problem wird durch a gemildert
namedtuple
. Es ist leichtgewichtig und gibt den Mitgliedern Ihres Arrays eine einfache semantische Bedeutung.Um die Vorteile einer automatischen Typprüfung zu nutzen, ohne die Sprache zu wechseln, können Sie die Typhinweise nutzen . Eine gute IDE kann dies verwenden, um Sie zu informieren, wenn Sie etwas Dummes tun.
Sie scheinen auch besorgt darüber zu sein, dass Funktionen veraltet sind, wenn sich Anforderungen ändern. Dies kann durch automatisierte Tests erfasst werden .
Ich sage zwar nicht, dass eine manuelle Überprüfung niemals angemessen ist, aber eine bessere Verwendung der verfügbaren Sprachfunktionen kann Ihnen helfen, dieses Problem auf eine wartbarere Weise zu lösen.
quelle
namedtuple
und all die anderen schönen Dinge. Ich habe nicht darüber nachgedachtnamedtuple
- und obwohl ich über automatisierte Tests Bescheid wusste, habe ich es nie wirklich oft benutzt und wusste nicht, wie sehr es mir in diesem Fall helfen würde. All dies scheint wirklich so gut zu sein wie eine statische Analyse. (Automatisierte Tests sind möglicherweise sogar besser, da ich alle subtilen Dinge erfassen kann, die bei einer statischen Analyse nicht erfasst würden!) Wenn Sie andere kennen, lassen Sie es mich bitte wissen. Ich werde die Frage noch eine Weile offen halten, aber wenn keine anderen Antworten kommen, werde ich Ihre akzeptieren.OK, das eigentliche Problem wird in einem Kommentar unter dieser Antwort beschrieben:
Das Problem hierbei ist die Verwendung einer Liste von Zeichenfolgen, bei denen die Reihenfolge die Semantik bedeutet. Dies ist ein wirklich fehleranfälliger Ansatz. Stattdessen sollten Sie eine benutzerdefinierte Klasse mit zwei Feldern mit dem Namen
title
und erstellenbibliographical_reference
. Auf diese Weise werden Sie sie nicht verwechseln und dieses Problem in Zukunft vermeiden. Dies erfordert natürlich einige Umgestaltungen, wenn Sie bereits an vielen Stellen Listen mit Zeichenfolgen verwenden, aber glauben Sie mir, es wird auf lange Sicht billiger sein.Der gängige Ansatz in Sprachen mit dynamischer Typisierung ist "Ententypisierung". Dies bedeutet, dass Sie sich nicht wirklich für den "Typ" des übergebenen Objekts interessieren. Es ist Ihnen nur wichtig, ob er die von Ihnen aufgerufenen Methoden unterstützt. In Ihrem Fall lesen Sie einfach das aufgerufene Feld,
bibliographical_reference
wenn Sie es benötigen. Wenn dieses Feld für das übergebene Objekt nicht vorhanden ist, wird eine Fehlermeldung angezeigt. Dies zeigt an, dass der falsche Typ an die Funktion übergeben wurde. Dies ist eine ebenso gute Typprüfung wie jede andere.quelle
Zuallererst erleben Sie gerade Code-Geruch - versuchen Sie sich zu erinnern, was dazu geführt hat, dass Sie sich des Geruchs bewusst werden, und versuchen Sie, Ihre "mentale" Nase zu schärfen. Je früher Sie einen Code-Geruch bemerken, desto schneller - und einfacher - Sie können das zugrunde liegende Problem beheben.
Defensive Programmierung - wie diese Technik genannt wird - ist ein gültiges und häufig verwendetes Werkzeug. Wie bei allen Dingen ist es jedoch wichtig, die richtige Menge zu verwenden, zu wenig Schecks und Sie werden keine Probleme bemerken, zu viele und Ihr Code wird überfüllt sein.
Das könnte eine weniger gute Idee sein. Wenn Sie feststellen, dass ein Teil Ihres Programms eine Funktion mit falsch formatierten Daten aufruft, FIX THAT PART , ändern Sie die aufgerufene Funktion nicht, um trotzdem fehlerhafte Daten verarbeiten zu können.
Die Verbesserung der Qualität und Wartbarkeit Ihres Codes spart auf lange Sicht Zeit (in diesem Sinne muss ich erneut vor der Selbstkorrekturfunktion warnen, die Sie in einige Ihrer Funktionen integriert haben - sie können eine heimtückische Quelle für Fehler sein. Nur weil Ihre Programm stürzt nicht ab & brennen heißt nicht, dass es richtig funktioniert ...)
Um Ihre Frage endgültig zu beantworten: Ja, defensive Programmierung (dh Überprüfung der Gültigkeit der bereitgestellten Parameter) ist - in einem gesunden Maße - eine gute Strategie. , Daß das , wie Sie selbst gesagt, Ihr Code ist inconsitent, und ich würde stark reccommend , dass Sie einige Zeit damit verbringen , um die Teile Refactoring , die riechen - Sie sagen , Sie wollen nicht zu befürchten sauberen Code die ganze Zeit, verbringen mehr Zeit auf "Bereinigen" als bei neuen Funktionen ... Wenn Sie Ihren Code nicht sauber halten, verbringen Sie möglicherweise doppelt so viel Zeit mit "Speichern", wenn Sie keinen sauberen Code zum Beseitigen von Fehlern aufbewahren UND es schwierig sein wird, neue Funktionen zu implementieren - technische Schulden können zerquetschen Sie.
quelle
Das ist okay. Ich habe in FoxPro programmiert, wo ich fast in jeder großen Funktion einen TRY..CATCH-Block hatte. Jetzt codiere ich in JavaScript / LiveScript und überprüfe selten Parameter in "internen" oder "privaten" Funktionen.
"Wie viel zu überprüfen ist" hängt mehr vom gewählten Projekt / der gewählten Sprache ab als von Ihren Code-Fähigkeiten.
quelle