Ich habe kürzlich Design by Contract (DbC) entdeckt und finde es eine äußerst interessante Art, Code zu schreiben. Unter anderem scheint es folgendes zu bieten:
- Bessere Dokumentation. Da der Vertrag die Dokumentation ist, ist es unmöglich, dass einer nicht mehr aktuell ist. Da im Vertrag genau angegeben ist, was eine Routine tut, kann die Wiederverwendung unterstützt werden.
- Einfacheres Debuggen. Da die Programmausführung in dem Moment stoppt, in dem ein Vertrag fehlschlägt, können sich Fehler nicht verbreiten, und die bestimmte verletzte Behauptung wird vermutlich hervorgehoben. Dies bietet Unterstützung bei der Entwicklung und bei der Wartung.
- Bessere statische Analyse. DbC ist im Grunde genommen nur eine Implementierung der Hoare-Logik, und die gleichen Prinzipien sollten gelten.
Die Kosten scheinen im Vergleich eher gering zu sein:
- Extra Fingertippen. Da müssen die Verträge präzisiert werden.
- Benötigt einige Schulungen, um sich mit dem Schreiben von Verträgen vertraut zu machen.
Jetzt, da ich in erster Linie mit Python vertraut bin, ist mir klar, dass es tatsächlich möglich ist, Vorbedingungen aufzuschreiben (nur Ausnahmen für unangemessene Eingaben auszulösen), und es ist sogar möglich, Assertions zu verwenden, um bestimmte Nachbedingungen erneut zu testen. Es ist jedoch nicht möglich, bestimmte Funktionen wie "alt" oder "Ergebnis" ohne zusätzliche Magie zu simulieren, die letztendlich als unpythonisch angesehen werden würde. (Außerdem gibt es einige Bibliotheken, die Unterstützung bieten, aber letztendlich ist es falsch, sie zu verwenden, da die meisten Entwickler dies nicht tun.) Ich gehe davon aus, dass dies ein ähnliches Problem für alle anderen Sprachen ist (außer natürlich) , Eiffel).
Meine Intuition sagt mir, dass der Mangel an Unterstützung auf eine Art Ablehnung der Praxis zurückzuführen sein muss, aber die Online-Suche war nicht fruchtbar. Ich frage mich, ob jemand erklären kann, warum die meisten modernen Sprachen so wenig Unterstützung bieten? Ist DbC fehlerhaft oder zu teuer? Oder ist es aufgrund von Extreme Programming und anderen Methoden einfach veraltet?
quelle
Antworten:
Möglicherweise werden sie in praktisch jeder Programmiersprache unterstützt.
Was Sie brauchen, sind "Behauptungen".
Diese können leicht als "if" -Anweisungen codiert werden:
Mit dieser Option können Sie Verträge schreiben, indem Sie solche Zusicherungen für Eingabeeinschränkungen oben in Ihren Code einfügen. Diese an den Rückgabepunkten sind Ausgabeeinschränkungen. Sie können sogar Invarianten im gesamten Code hinzufügen (obwohl dies nicht Teil von "Design by Contract" ist).
Ich behaupte, sie sind nicht weit verbreitet, weil Programmierer zu faul sind, um sie zu programmieren, und nicht, weil man das nicht kann.
Sie können diese in den meisten Sprachen ein wenig effizienter gestalten, indem Sie eine boolesche Konstante zur Kompilierungszeit "checking" definieren und die Anweisungen ein wenig überarbeiten:
Wenn Ihnen die Syntax nicht gefällt, können Sie auf verschiedene Sprachabstraktionstechniken wie Makros zurückgreifen.
Einige moderne Sprachen bieten dafür eine gute Syntax, und ich denke, Sie meinen das mit "Unterstützung moderner Sprachen". Das ist Unterstützung, aber es ist ziemlich dünn.
Was die meisten modernen Sprachen nicht geben, sind "zeitliche" Aussagen (über beliebige vorherige oder folgende Zustände [zeitlicher Operator "eventuell"], die Sie benötigen, wenn Sie wirklich interessante Verträge schreiben möchten. IF-Anweisungen helfen nicht du hier.
quelle
super
Methode aufrufen und möglicherweise die Ergebnisse wegwerfen, wenn Sie nur die Verträge ohne Duplikation überprüfen möchten. Dies hilft wirklich bei der Implementierung von sauberem LSP-konformen Code.Wie Sie sagen, Design by Contract ist ein Merkmal in Eiffel, die lange eine dieser Programmiersprachen gewesen ist , die gut in der Gemeinde respektiert wird , aber die auf nie gefangen hat.
DbC ist in keiner der beliebtesten Sprachen verfügbar, da die Mainstream-Programmierer erst seit relativ kurzer Zeit akzeptieren, dass das Hinzufügen von Einschränkungen / Erwartungen zu ihrem Code eine "vernünftige" Sache für Programmierer ist. Heutzutage ist es für Programmierer üblich zu verstehen, wie wertvoll Unit-Tests sind, und dies führte dazu, dass Programmierer eher akzeptieren, Code einzugeben, um ihre Argumente zu validieren und Vorteile zu erkennen. Aber vor einem Jahrzehnt haben wahrscheinlich die meisten Programmierer gesagt: "Das ist nur zusätzliche Arbeit für Dinge, von denen Sie wissen, dass sie immer in Ordnung sind."
Ich denke, wenn Sie heute zum durchschnittlichen Entwickler gehen und über Nachbedingungen sprechen, nicken sie begeistert und sagen: "OK, das ist wie Unit-Testing." Und wenn Sie über Vorbedingungen sprechen, sagen sie "OK, das ist wie eine Parametervalidierung, was wir nicht immer tun, aber, weißt du, ich denke, es ist in Ordnung ..." Und wenn Sie dann über Invarianten sprechen Sie fingen an zu sagen: "Gee, wie viel Overhead ist das? Wie viele weitere Bugs werden wir fangen?" usw.
Ich denke, es ist noch ein langer Weg, bis DbC sehr weit verbreitet ist.
quelle
Falsch.
Es ist eine Designpraxis . Es kann explizit im Code (Eiffel-Stil) oder implizit im Code (in den meisten Sprachen) oder in Komponententests enthalten sein. Die Designpraxis existiert und funktioniert gut. Die Sprachunterstützung ist überall auf der Karte. Es ist jedoch in vielen Sprachen im Unit-Test-Framework vorhanden.
Es ist teuer. Und. Noch wichtiger ist, dass es einige Dinge gibt, die in einer bestimmten Sprache nicht bewiesen werden können. Die Schleifenbeendigung kann beispielsweise in einer Programmiersprache nicht bewiesen werden, sondern erfordert eine Beweisfähigkeit "höherer Ordnung". Einige Arten von Verträgen sind technisch unbeschreiblich.
Nein.
Wir verwenden meist Unit-Tests, um nachzuweisen, dass DbC erfüllt ist.
Für Python gibt es, wie Sie bereits bemerkt haben, mehrere Möglichkeiten für die DbC.
Die Docstring- und die Docstring-Testergebnisse.
Aussagen zur Validierung von Ein- und Ausgängen.
Unit-Tests.
Des Weiteren.
Sie können gebildete Tools im Programmierstil verwenden, um ein Dokument zu schreiben, das Ihre DbC-Informationen enthält und das saubere Python plus-Komponententestskripte generiert. Der Ansatz der Lese- und Schreibprogrammierung ermöglicht es Ihnen, ein schönes Stück Literatur zu schreiben, das die Verträge und die vollständige Quelle enthält.
quelle
there are some things which cannot be proven
. Die formale Verifizierung mag großartig sein, aber nicht alles ist verifizierbar! Diese Funktion schränkt also tatsächlich ein, was die Programmiersprache tatsächlich kann!Einfach raten. Vielleicht ist ein Teil des Grundes, warum es nicht so beliebt ist, weil "Design by Contract" von Eiffel als Warenzeichen eingetragen ist.
quelle
Eine Hypothese ist, dass für ein ausreichend großes komplexes Programm, insbesondere für ein Programm mit sich bewegenden Zielen, die Masse der Verträge selbst so fehlerhaft und schwer zu debuggen sein kann, oder mehr als der Programmcode allein. Wie bei jedem Muster kann es durchaus zu einer Nutzung kommen, die über sinkende Renditen hinausgeht, sowie zu deutlichen Vorteilen, wenn sie gezielter eingesetzt werden.
Eine andere mögliche Schlussfolgerung ist, dass die Popularität von "verwalteten Sprachen" der aktuelle Beweis für die vertragliche Unterstützung dieser ausgewählten verwalteten Funktionen ist (Array-Grenzen nach Vertrag usw.).
quelle
Der Grund dafür, dass die meisten gängigen Sprachen keine DbC-Funktionen in der Sprache haben, ist das Kosten-Nutzen-Verhältnis der Implementierung, das für den Sprachimplementierer zu hoch ist.
Eine Seite davon wurde bereits in den anderen Antworten betrachtet. Unit-Tests und andere Laufzeitmechanismen (oder sogar einige Kompilierungszeitmechanismen mit Template-Metaprogrammierung) können Ihnen bereits einen Großteil der DbC-Güte verleihen. Daher wird es, obwohl es einen Vorteil gibt, wahrscheinlich als recht bescheiden angesehen.
Die andere Seite ist der Preis, die nachträgliche Anpassung von DbC an eine vorhandene Sprache ist wahrscheinlich eine zu große Änderung und sehr komplex. Es ist schwierig, eine neue Syntax in einer Sprache einzuführen, ohne den alten Code zu beschädigen. Das Aktualisieren Ihrer vorhandenen Standardbibliothek zur Verwendung einer so weitreichenden Änderung wäre teuer. Daher können wir den Schluss ziehen, dass die Implementierung von DbC-Funktionen in einer vorhandenen Sprache hohe Kosten verursacht.
Ich würde auch bemerken, dass Konzepte, die so ziemlich Verträge für Vorlagen sind und daher etwas mit DbC zu tun haben, aus dem neuesten C ++ - Standard gestrichen wurden, da selbst nach jahrelanger Arbeit davon ausgegangen wurde, dass sie noch jahrelange Arbeit benötigten. Diese großen, umfassenden und umfassenden Änderungen an den Sprachen sind einfach zu schwer umzusetzen.
quelle
DbC würde umfassender genutzt, wenn die Verträge zum Zeitpunkt der Kompilierung überprüft werden könnten, sodass es nicht möglich wäre, ein Programm auszuführen, das gegen einen Vertrag verstößt.
Ohne Compiler-Unterstützung ist "DbC" nur ein anderer Name für "Invarianten / Annahmen überprüfen und bei Verletzung eine Ausnahme auslösen".
quelle
Ich habe eine einfache Erklärung, die meisten Leute (einschließlich Programmierer) wollen keine zusätzliche Arbeit, es sei denn, sie sehen es als notwendig an. Avionik-Programmierung, bei der Sicherheit für sehr wichtig gehalten wird Ich habe die meisten Projekte ohne sie nicht gesehen.
Wenn Sie jedoch die Programmierung von Websites, Desktops oder Mobilgeräten in Betracht ziehen - Abstürze und unerwartetes Verhalten werden manchmal nicht als so schlimm angesehen, und Programmierer vermeiden nur zusätzliche Arbeit, wenn Fehler gemeldet und später behoben werden.
Dies ist wahrscheinlich der Grund, warum Ada außerhalb der Luftfahrtprogrammierungsbranche meiner Meinung nach nie aufgehört hat, weil es mehr Programmierarbeit erfordert, obwohl Ada eine großartige Sprache ist und wenn Sie ein zuverlässiges System erstellen möchten, ist es die beste Sprache für den Job (mit Ausnahme von SPARK, das proprietär ist) Sprache basierend auf Ada).
Design by Contract Libraries für C # wurden von Microsoft experimentell getestet und sind sehr nützlich für die Erstellung zuverlässiger Software. Sie haben jedoch noch nie eine Dynamik auf dem Markt aufgenommen, da Sie sie sonst als Teil der Kernsprache von C # gesehen hätten.
Behauptungen sind nicht dasselbe wie eine voll funktionsfähige Unterstützung für Vor- / Nachbedingungen und Invarianten. Obwohl es versuchen kann, sie zu emulieren, führt ein Language / Compiler mit entsprechender Unterstützung eine Analyse des abstrakten Syntaxbaums durch und prüft auf logische Fehler, die einfach nicht behauptet werden können.
Bearbeiten: Ich habe eine Suche durchgeführt und folgende Diskussion ist hilfreich: https://stackoverflow.com/questions/4065001/are-there-any-provable-real-world-languages-scala
quelle
Meistens sind die Gründe wie folgt:
quelle