Ich weiß nicht, woher die Behauptung kommt, dass "es keine statische Analyse durchführt und oft nicht kann". Der erste Teil der Behauptung ist eindeutig falsch. Der zweite hängt davon ab, was Sie mit "oft" meinen. Ich würde eher sagen, dass es oft statische Analysen durchführt und selten daran scheitert. In der normalen Geschäftsanwendung wird selten viel näher an nie .
Hier kommt also der erste Vorteil:
Vorteil 1: statische Analyse
Gewöhnliche Behauptungen und Argumentprüfungen haben einen Nachteil: Sie werden verschoben, bis der Code ausgeführt wird. Andererseits manifestieren sich Codeverträge auf einer viel früheren Ebene, entweder beim Codierschritt oder beim Kompilieren der Anwendung. Je früher Sie einen Fehler abfangen, desto günstiger ist es, ihn zu beheben.
Vorteil 2: Sozusagen immer aktuelle Dokumentation
Codeverträge bieten auch eine Art Dokumentation, die immer auf dem neuesten Stand ist. Wenn der XML-Kommentar der Methode SetProductPrice(int newPrice)
angibt, dass newPrice
sie höher oder gleich Null sein sollte, können Sie hoffen, dass die Dokumentation auf dem neuesten Stand ist, Sie können jedoch auch feststellen, dass jemand die Methode so geändert hat, dass newPrice = 0
ein ArgumentOutOfRangeException
, aber niemals die entsprechende Dokumentation geändert wurde. Angesichts der Korrelation zwischen den Codeverträgen und dem Code selbst liegt kein Problem mit der nicht synchronen Dokumentation vor.
Die Art der Dokumentation, die durch Codeverträge bereitgestellt wird, ist auch in einer Weise wertvoll, dass XML-Kommentare die akzeptablen Werte häufig nicht gut erklären. Wie oft war ich frage mich , ob null
oder string.Empty
oder \r\n
ein autorisierter Wert für ein Verfahren und XML - Kommentare schweigen auf das!
Fazit: Ohne Codeverträge sind viele Codeteile wie folgt:
Ich akzeptiere einige Werte, aber keine anderen, aber Sie müssen die Dokumentation erraten oder lesen, falls vorhanden. Lesen Sie die Dokumentation eigentlich nicht, sie ist veraltet. Durchlaufen Sie einfach alle Werte und Sie werden diejenigen sehen, die mich dazu bringen, Ausnahmen zu werfen. Sie müssen auch den Wertebereich erraten, der möglicherweise zurückgegeben wird, denn selbst wenn ich Ihnen ein bisschen mehr darüber erzählen würde, könnte dies angesichts der Hunderte von Änderungen, die ich in den letzten Jahren vorgenommen habe, nicht zutreffen.
Mit Code-Verträgen wird es:
Das title-Argument kann eine Nicht-Null-Zeichenfolge mit einer Länge von 0..500 sein. Die folgende Ganzzahl ist ein positiver Wert, der nur dann Null sein kann, wenn die Zeichenfolge leer ist. Schließlich werde ich ein IDefinition
Objekt zurückgeben, niemals null.
Vorteil 3: Verträge von Schnittstellen
Ein dritter Vorteil ist, dass Codeverträge Schnittstellen ermöglichen. Nehmen wir an, Sie haben etwas wie:
public interface ICommittable
{
public ICollection<AtomicChange> PendingChanges { get; }
public void CommitChanges();
...
}
Wie würden Sie mit Asserts und Exceptions garantieren, dass CommitChanges
nur aufgerufen werden kann, wenn PendingChanges
nicht leer? Wie würden Sie garantieren, dass PendingChanges
das niemals ist null
?
Vorteil 4: Erzwingen Sie die Ergebnisse einer Methode
Schließlich ist der vierte Vorteil, um Contract.Ensure
die Ergebnisse zu können. Was ist, wenn ich beim Schreiben einer Methode, die eine Ganzzahl zurückgibt, sicherstellen möchte, dass der Wert niemals schlechter oder gleich Null ist? Einschließlich fünf Jahre später nach vielen Veränderungen durch viele Entwickler? Sobald eine Methode mehrere Rückgabepunkte hat, wird sie Assert
zu einem Alptraum für die Instandhaltung.
Betrachten Sie Codeverträge nicht nur als Mittel zur Richtigkeit Ihres Codes, sondern auch als strengere Methode zum Schreiben von Code. In ähnlicher Weise kann eine Person, die ausschließlich dynamische Sprachen verwendet, fragen, warum Sie Typen auf Sprachebene erzwingen sollten, während Sie bei Bedarf dasselbe in Behauptungen tun können. Sie können, aber statische Typisierung ist einfacher zu verwenden, weniger fehleranfällig im Vergleich zu einer Reihe von Behauptungen und selbstdokumentierend.
Der Unterschied zwischen dynamischer und statischer Typisierung kommt dem Unterschied zwischen gewöhnlicher Programmierung und vertraglicher Programmierung sehr nahe.