Design By Contract in Java

April 14, 2017 | Author: Kajetan Blau | Category: N/A
Share Embed Donate


Short Description

Download Design By Contract in Java...

Description

Design By Contract in Java Seminarbericht WS06/07

Fachhochschule Nordwestschweiz Hochschule für Technik Studiengang Informatik

Seminarbericht von Matthias Hausherr

Betreuender Dozent Prof. Dr. Dominik Gruntz

Windisch, 15. November 2006

Design By Contract in Java

Abstract Die Idee von Design By Contract (DBC) ist, so exakt wie möglich zu definieren, was ein Softwaremodul tun soll. Die Bedeutung einer ausführlichen Spezifikation für Software kann kaum stark genug betont werden. Wartungskosten machen einen grossen Teil der Kosten im Lebenszyklus einer Software aus und präzise Spezifikation und Dokumentation hilft mit, diese Kosten zu senken. Design By Contract treibt diese Idee auf die Spitze: Es wird so exakt wie möglich definiert, was das Softwaremodul tun soll. Die Firma Eiffel, quasi die Erfinder von Design By Contract, beschreibt ihre Motivation unter anderem mit folgendem Satz: “If we don't state what a module should do, there is little likelihood that it will do it.”- Eiffel.com Im ersten Teil dieses Berichtes wird erläutert wie Design By Contract funktioniert und welche Ziele damit verfolgt werden. Im zweiten Teil werden die Assertions, die seit JDK 1.4 von Java angeboten werden, näher betrachtet. Anschliessend wird in einem Kapitel Refinement eingeführt, welches erläutert, wie Vererbung und Design By Contract zusammenspielen. Als Kernstück des Berichtes werden zwei verschiedene Design By Contract Implementationen für Java vorgestellt und kleine Codesnippets präsentiert. Abschliessend wird eine Empfehlung zum Einsatz von Design By Contract in Java abgegeben.

Matthias Hausherr

Seite 2 / 22

Design By Contract in Java

Inhaltsverzeichnis 1.

Der Ansatz Design By Contract ...................................................................................... 4 1.1. Definition................................................................................................................ 4 1.2. Entstehung............................................................................................................. 4 1.3. Idee und DBC-Begriffe ........................................................................................... 4 1.4. Hauptziele.............................................................................................................. 5 1.4.1. Steigerung der Qualität .................................................................................. 5 1.4.2. Contracts als Dokumentation ......................................................................... 5 1.4.3. Debugging und Testing Hilfe .......................................................................... 5 2. Java Assertions.............................................................................................................. 6 2.1. Das Assert Statement ............................................................................................ 6 2.2. Verwendungszweck ............................................................................................... 6 2.3. Assertions und DBC............................................................................................... 6 3. Refinement (Contract Inheritance in DBC)...................................................................... 7 3.1. Regeln ................................................................................................................... 7 3.2. Beispiel .................................................................................................................. 7 4. Erweiterte Assertion Support Implementationen............................................................. 8 4.1. Erläuterung zu den Codebeispielen ....................................................................... 8 4.2. Erläuterung zu den Refinement Codebeispielen .................................................... 9 4.3. Jass ......................................................................................................................10 4.3.1. Facts .............................................................................................................10 4.3.2. Beschreibung ................................................................................................10 4.3.3. Syntaktische Elemente..................................................................................11 4.3.4. JavaDoc Erweiterung ....................................................................................13 4.3.5. Refinement....................................................................................................13 4.3.6. Codebeispiel .................................................................................................14 4.3.7. Refinement Codebeispiel ..............................................................................15 4.4. C4J .......................................................................................................................16 4.4.1. Facts .............................................................................................................16 4.4.2. Beschreibung ................................................................................................16 4.4.3. Framework Elemente ....................................................................................17 4.4.4. Refinement....................................................................................................17 4.4.5. Codebeispiel .................................................................................................18 4.4.6. Refinement Codebeispiel ..............................................................................20 5. Empfehlung ...................................................................................................................21 6. Quellenangaben............................................................................................................22

Matthias Hausherr

Seite 3 / 22

Design By Contract in Java

1.

Der Ansatz Design By Contract 1.1.

Definition

Design By Contract, abgekürzt DBC, oder Programming By Contract ist ein Ansatz um Software zu entwerfen. Der Ansatz beschreibt, dass der Software Engineer formale und messbare Conditions an Schnittstellen anknüpft, im Sinne eines Vertrages zwischen Client und Server. Diese Conditions werden zusätzlich zu den von der Programmiersprache verwendeten Sicherungsmethoden (z.B. Typenkontrolle) verwendet und ermöglichen eine semantische Prüfung und damit sehr präzis definierte Schnittstellen.

1.2.

Entstehung

Der geistige Vater des DBC ist Bertrand Meyer (geboren im Jahre 1950 in Frankreich). Prof. Meyer ist vor allem deshalb vielen Informatikern ein Begriff, weil er um 1985 die Sprache Eiffel entwickelt hat, die DBC konsequent verwendet. Prof. Meyer legt den Fokus auf Qualität und geht davon aus, dass darauf automatisch auch eine hohe Produktivität folgt. Bertrand Meyer hat seinen Bachelor in Engineering an der École Polytechnique in Paris, seinen Master in Standford und den Ph. D. an der Université de Nancy absolviert. Heute arbeitet Meyer an der ETHZ im Bereich Software Engineering. Diplom- und Bachelorabgänger der Fachhochschule Nordwestschweiz, die den Master machen möchten, haben also die Möglichkeit, bei Herr Meyer im Rahmen eines Masterstudiums diverse Software Engineering Kurse zu besuchen und somit DBC aus erster Hand zu lernen.

1.3.

Prof. Bertrand Meyer

Idee und DBC-Begriffe

Die Idee des Contracts zwischen Client und Server stammt aus dem Geschäftsleben: Zuerst erklärt sich der Kunde bereit, dem Dienstleister eine gewisse Summe zu zahlen (entspricht Obligation des Clients). Der Dienstleister wiederum verpflichtet sich dem Kunden dafür etwas Bestimmtes zu liefern (entspricht Obligation des Servers). Dieses Schema wird nun auf den Software Engineering Prozess übertragen. Der Server (z.B. eine Methode oder ein Modul) bestimmt sogenannte Preconditions. Diese stellen Bedingungen bzw. Obligationen dar, die der Client des Servers erfüllen muss und jeweils vor Ausführung des Server Codes geprüft werden. Der Vorteil für den Server liegt darin, dass er sich nicht mit Fällen ausserhalb der Precondition befassen muss. Ein denkbares Beispiel hierfür wäre ein gültiger Wertebereich für eine Integer Variable. Im Gegensatz zu den Preconditions werden die Postconditions jeweils nach der Ausführung des Server Codes geprüft und müssen vom Server selber erfüllt werden. Sie stellen Bedingungen bzw. Obligationen dar, die der Server erfüllen muss und garantieren dem Aufrufer, dass gewisse Arbeiten verrichtet wurden. Oft greifen Postconditions dabei auf Werte zu, die vor der Ausführung der Methode galten. Matthias Hausherr

Seite 4 / 22

Design By Contract in Java Zusätzlich zu Pre- und Postconditions spielen Invariants eine Rolle. Invariants sorgen dafür, dass bei Eintritts- und Austrittspunkten des Server Codes gewisse Conditions erfüllt bzw. Zustände gewahrt sind. Invariants sind in gewisser Weise also Pre- und Postconditions. Pre- und Postconditions sowie Invariants bilden einen Contract zwischen Client und Server. Der Contract selber ist die Formalisierung der Conditions die beide Seiten erfüllen müssen. Der Entwickler, der den Contract entwirft, muss sich sehr genau Gedanken machen, was der Server erwartet (Preconditions), was er liefert bzw. garantiert (Postconditions) und was der Server unterhaltet (Invariants). Die Contracts stellen auch ein Teil der Dokumentation dar, sie dokumentieren nämlich das Verhalten der einzelnen Software Komponenten. Durch Einsatz von DBC entsteht eine Kette von Verträgen, die schlussendlich für robustere Software sorgt. Wenn jedes einzelne Element der Kette garantieren kann, die Postcondition zu erfüllen sofern die Precondition eingehalten wurde, so entstehen weniger Fehler durch falsche Annahmen seitens der Entwickler. Ein Prinzip des DBC ist es, ein Programm bei Nichteinhaltung eines Contracts sofort zu terminieren. Die Idee dahinter ist es, das die Probleme sofort angegangen werden und nicht auf die lange Bank geschoben werden. Somit kann es nicht passieren, dass ein Bug, dessen Behebung man auf später verschoben hat, vergessen wird und somit als Bug im Endprodukt landet. Während des Deployment selber werden die Contracts oft ausgeschaltet. Einerseits möchte man unter Umständen ein Programmabbruch im Problemfall verhindern und andererseits lässt sich damit die Performance erhöhen.

1.4. Hauptziele 1.4.1. Steigerung der Qualität Um die Reliability der Software zu verbessern sollte man Schnittstellen sehr genau definieren. DBC zwingt den Software Engineer dies schon früh im Design Prozess zu tun. Durch diese exakten Spezifikationen, welche Aufgaben ein Softwaremodul hat und welche Preconditions es stellt, erhöht sich auch die Wahrscheinlichkeit, dass es diesen Anforderungen später auch gerecht wird. Die Umkehrung dieser Überlegung ist ebenfalls einleuchtend: Wenn wir nicht genau spezifizieren was ein Modul tun soll, so wird es kaum das Richtige tun.

1.4.2. Contracts als Dokumentation Das API eines Softwaremoduls entspricht einem Contract zwischen Client und Server. Alle Obligationen und Rechte müssen öffentlich ersichtlich sein. Um Inkonsistenzen zwischen Source und Dokumentation zu vermeiden ist es zudem wichtig, dass das API direkt aus dem Source generiert wird. Ähnlich wie Java dieses Prinzip mit JavaDoc umsetzt, sollen auch die Contracts durch generierte Dokumentation beschrieben werden. Bereits Eiffel hatte hierfür ein entsprechendes Tool, das aus dem Source automatisch eine entsprechende Dokumentation inklusive Contracts generiert. Ziel ist es, den Fokus der Entwickler auf die Schnittstellen zu lenken.

1.4.3. Debugging und Testing Hilfe Dank Contracts können potentielle Fehler früh aufgedeckt werden. Wird ein Contract gebrochen, wird das Programm sofort mit einer Exception terminiert und der Fehler für den Entwickler schnell ersichtlich. Durch DBC lassen sich viele abnormale Fälle in einer Art behandeln, die Exception Handling vereinfachen und Fehlerquellen eliminieren.

Matthias Hausherr

Seite 5 / 22

Design By Contract in Java

2.

Java Assertions

Schon früh gab es Entwickler die DBC Support im JDK forderten. Dieser Wunsch stand an zweiter Stelle auf der Request For Enhancement Liste auf bugs.sun.com. Mit Java 1.4 wurde schliesslich das assert Statement zur Verfügung gestellt und der Request geschlossen. Dieser Abschnitt beleuchtet Java Assertions und weshalb diese keine Implementation von Design By Contract darstellen.

2.1.

Das Assert Statement

Assert Statements prüfen gewisse Conditions und sind entweder true oder false. Wird z.B. die Prüfung einer Inputvariable vergessen, so kann es unter Umständen passieren, dass das Programm vorerst weiterläuft, dann aber an einem späteren Punkt zur Runtime abstürzt. Um dies zu verhindern kann man mit einem assert Statement früh eine gewünschte Condition prüfen. Ein mögliches Beispiel einer Prüfung eines Inputparameters: public int temp(double t) { assert(-273.15 >= t): "Temperature must be greater than -273.15"; // Weiterführender Code … }

Resultiert ein false aus java.lang.AssertionError ab.

2.2.

der

Assertion,

so

bricht

das

Programm

mit

einem

Verwendungszweck

Assertions sind in erster Linie ein Mittel zur frühen Detektion von Fehlern während der Software Entwicklung. Assertions sind syntaktisch einfach gestrickt und erlauben dem Entwickler deshalb zügig und ohne grossen Overhead seine Annahmen als Conditions zu codieren. Was auf den ersten Blick nicht allzuwichtig erscheint, stellt eine wesentliche Hilfe bei der frühen Lokalisation von Bugs dar. Ein Vorteil von Assertions gegenüber üblichen if-Anweisungen ist die Möglichkeit Assertions zu deaktiveren. Bei deaktivierten Assertions werden die assert Anweisungen nicht ausgewertet und es entsteht keine Effizienzeinbusse. AssertionErrors haben etwa die gleiche Bedeutung wie RuntimeExceptions. Es ist wichtig zu unterscheiden zwischen den unchecked AssertionErrors bzw. RuntimeExceptions und den checked Exceptions die deklariert und behandelt werden müssen. Assertions sind per default in JDK 1.5 disabled. Mit den VM tag –ea oder –enableassertions kann man diese aktivieren. Da man Assertions einfach deaktivieren kann eignen sie sich nicht für produktiven Code. Ein Vorteil von Exceptions gegenüber Assertions ist die Möglichkeit, ein Exception Handling zu definieren für abnormale Fälle, von denen man weiss, dass sie eintreten und behandelt werden können.

2.3.

Assertions und DBC

Wie man leicht erkennen kann, sind Assertions in Java sehr eingeschränkt. Preconditions, Postconditions und Invariants werden als solche nicht unterstützt und lassen sich mit dem assert Statement allenfalls etwas leichter abbilden. Wer DBC in Java verwenden möchte ist gezwungen, auf andere Lösungen zurückzugreifen. Wer möchte, dass Sun DBC in Java integriert wird, kann an der Diskussion des Bug mit ID 4449383 und Subjekt „Support For Design by Contract, beyond a simple assertion facility“ auf bugs.sun.com teilnehmen und mehr dazu erfahren (Link siehe Quellenangaben).

Matthias Hausherr

Seite 6 / 22

Design By Contract in Java

3.

Refinement (Contract Inheritance in DBC) 3.1.

Regeln

Ist eine Basisklasse an einen Contract gebunden, wird der Contract automatisch an alle Subklassen vererbt. Die Subklasse kann fakultativ zusätzliche Contracts definieren. Für die Vererbung von Contracts gelten einige Regeln und Überlegungen: 1. Die Precondition der Subklasse darf nicht strenger sein als die Precondition der Basisklasse (entspricht einer logischen OR Verknüpfung). Damit wird sichergestellt, dass ein Zustand der die Precondition der Basisklasse erfüllt auch die Precondition der Subklasse erfüllt. 2. Die Postcondition der Subklasse darf nicht schwächer sein als die Postcondition der Basisklasse (entspricht einer logischen AND Verknüpfung). Damit wird sichergestellt, dass ein Zustand der die Postcondition der Subklasse erfüllt auch die Postcondition der Basisklasse erfüllt. 3. Eine Subklasse übernimmt den Invariant der Basisklasse und hat diese zu erfüllen. Diese Regeln sorgen dafür, dass eine Subklasse den Contract der Basisklasse einhält und vielleicht sogar verbessert (mehr dazu im Folgeabschnitt Beispiel). Wie vom Liskov’schen Substitutionsprinzip vorgeschrieben darf überall wo eine Basisklasse erwartet wird auch eine Subklasse deren eingesetzt werden. Die obigen Regeln ermöglichen eine Handhabung wie es sich Java Entwickler gewohnt sind, z.B. mit dem Statement BaseClass myBaseClass = new SubClass( );

3.2.

Beispiel

Das folgende Beispiel zeigt auf, dass es sinnvoll sein kann die Precondition in der Subklasse gegenüber jener der Basisklasse zu schwächen. In diesem Beispiel kann mit der Methode addElement der Klasse Buffer ein Objekt einem limitierten Buffer hinzugefügt werden. Die Methode kann nur aufgerufen werden, sofern der Buffer nicht bereits voll ist und das hinzufügende Objekt keine null Referenz ist: public void addElement (Object o) { /** Precondition !isFull(); o != null; **/ buffer[in % buffer.length] = o; in++; /** Postcondition … **/ }

Eine denkbare Subklasse könnte nun mit null Referenzen umgehen, indem es anstelle von null ein Defaultobjekt erzeugt und dem Buffer hinzufügt: public void addElement (Object o) { /** Precondition !isFull(); **/ if (o==null) buffer[in % buffer.length] = new Default(); else buffer[in % buffer.length] = o; in++; /** Postcondition … **/ }

Für die Spezialisierung gilt gemäss den Regeln für Refinement die verknüpfte Precondition (!isFull() AND o != null) OR !isFull(), die vereinfacht werden kann zu !isFull(). Matthias Hausherr

Seite 7 / 22

Design By Contract in Java

4.

Erweiterte Assertion Support Implementationen 4.1.

Erläuterung zu den Codebeispielen

In diesem Kapitel werden zwei verschiedene DBC Implementationen für Java vorgestellt. Für jede näher vorgestellte Implementation wird ein Codebeispiel mitgeliefert. Die Idee ist, einen simplen Buffer mit Pre- und Postconditions sowie einem Invariant zu sichern und dem Leser einen Eindruck zu geben wie der Code aussieht. Die Codebeispiele basieren auf einem Beispiel von der Jass Website. Die noch ungesicherte Klasse, von der jeweils ausgegangen wird, sieht wie folgt aus: package standardtest; public class Buffer { protected int in, out; private Object[] buf; public Buffer (int capacity) { // Precondition buf = new Object[capacity]; // Postcondition } public boolean empty() { return in - out == 0; // Postcondition } public boolean full() { return in - out == buf.length; // Postcondition } public void add(Object o) { // Precondition buf[in % buf.length] = o; in++; // Postcondition } public Object remove() { // Precondition Object o = buf[out % buf.length]; out++; return o; // Postcondition } // Invariant } Buffer.java

Legende für alle Codebeispiele: // Precondition: Wird bei Methodeneintritt geprüft. // Postcondition: Wird bei Methodenaustritt geprüft. // Invariant: Wird vor und nach der Ausführung der Methode geprüft.

Matthias Hausherr

Seite 8 / 22

Design By Contract in Java

4.2.

Erläuterung zu den Refinement Codebeispielen

Für jede näher dargestellte Implementation wird zudem ein Beispiel eines RefinedBuffer vorgestellt. Diese Subklasse erweitert die Klasse Buffer und erweitert die Basisklasse um folgende drei Punkte: • •



Die Methode contains(Object o) prüft, ob ein Objekt bereits im Buffer vorhanden ist. Die Methode add(Object o) soll neu null Parameter erlauben und damit die Precondition der Basisklasse schwächen. Wird ein null Parameter detektiert wird mit new Object() ein Object erzeugt und in den Buffer eingefügt. Die Postcondition der Methode add wird um eine Prüfung erweitert und damit gestärkt. Diese prüft ob das Object tatsächlich eingefügt wurde. Hierfür wird die Methode contains(Object o) des RefinedBuffer verwendet.

Die noch ungesicherte Klasse, von der jeweils ausgegangen wird, sieht wie folgt aus: package refinementtest; public class RefinedBuffer extends Buffer { public RefinedBuffer(int capacity) { super(capacity); } public void add(Object o) { // Precondition if (o == null) { o = new Object(); } super.add(o); // Postcondition } public boolean contains(Object o) { // Precondition for (int i = 0; i < in % buf.length; i++) { if (buf[i].equals(o)) { return true; } } return false; } } RefinedBuffer.java

Legende für alle Codebeispiele: // Precondition: Wird bei Methodeneintritt geprüft. // Postcondition: Wird bei Methodenaustritt geprüft. // Invariant: Wird vor und nach der Ausführung der Methode geprüft.

Matthias Hausherr

Seite 9 / 22

Design By Contract in Java

4.3.

Jass

4.3.1. Facts Erster Release: Aktuelle Version: Entwicklungsstatus: Next Release Date: Kosten: Website:

1999 2.0.14 Production/Stable Jass 3.0 / Datum unbekannt Freeware http://csd.informatik.uni-oldenburg.de/~jass/

4.3.2. Beschreibung Jass benutzt für die Definition der DBC Elemente eine eigene Inputsprache, die jedoch für jeden Javaentwickler leicht zu erlernen ist, da die Syntax simpel ist und die Anzahl der keywords gering. An dieser Stelle sei darauf hingewiesen, dass die kommende Jass Version 3.0 über keine eigene Inputsprache mehr verfügen wird sondern JML hierfür verwenden wird. Um die eigene Inputsprache zu verarbeiten und in reguläre Java Befehle umzuwandeln, benutzt Jass einen Precompiler der komplett in Java programmiert ist. Der Entwickler ergänzt seinen Javacode mit Jass Input und stellt dem Precompiler ein File wie z.B. sample.jass zur Verfügung. Dabei muss der Programmierer Preconditions am Anfang der Methode und Postconditions am Schluss der Methode platzieren. Invariants werden am Schluss des Klassensources platziert. Nach dem Preprocessorstep liegt ein kompiliertes sample.java File vor. Dieses kann wie gewohnt mit den üblichen Java Tools kompiliert und ausgeführt werden. Das Kompilat des Precompilers ersetzt die Inputsprache durch verschiedene Elemente. Für Invariants wird zu Beginn und beim Ende der Methode jeweils ein Aufruf der Jass Methode JassCheckInvariant(String errorLocation) eingefügt und als Parameter eine Kurzbeschreibung mitgegeben, wo die Invariant Prüfung ausgelöst wurde. Diese Methode sowie weitere von Jass intern benötigte Methoden stehen in einem vom Precompiler generierten Abschnitt am Schluss des Sourcecodes. Wird bei der Postcondition auf die sogenannte Old Variable zugegriffen, welche den Zustand des Objektes bei Methodeneintritt speichert, wird zu Beginn der Methode das Objekt cloned. Aus diesem Grund müssen Klassen, deren Postconditions auf die Variable Old zugreifen, auch das Interface cloneable implementieren. Es müssen dabei nur jene Variablen effektiv kopiert werden, die auch tatsächlich mit Old referenziert werden. Die Pre- bzw. Postconditions werden vom Precompiler in if Statements umgewandelt, die sofern sie false returnen, Exceptions werfen. Namentlich handelt es sich um die (jass.runtime.) PreconditionException, PostconditionException und die InvariantException. Bei ihrer Erzeugung per Konstruktor wird der Auftretensort des Fehlers sowie eine kurze Fehlermeldung mitgegeben. Zusätzlich ist es möglich, Conditions mit einem Label zu versehen, das beim Werfen der Exception angezeigt wird. Bei der Definition von Preconditions dürfen nur öffentlich einsehbare Variablen und Methoden verwendet werden. Dies entspricht der availability Regel, die Bertrand Meyer eingeführt hat und es dem Client der Klasse erleichtern soll zu verstehen, unter welchen Bedingungen die Methode aufgerufen werden kann. Auf der Jass Website gibt es viele kleine Beispiele und Tutorials. Eine ausführliche Dokumentation gibt es nicht. Die von Jass mitgelieferten Beispiele sind ansehnlich und erleichtern den Einstieg, gehen aber nicht über einfache Examples hinaus.

Matthias Hausherr

Seite 10 / 22

Design By Contract in Java

4.3.3. Syntaktische Elemente In diesem Abschnitt werden verschiedene syntaktische Elemente der Jass Inputsprache kurz erklärt mit dem Ziel, dem Leser die Arbeit mit Jass näherzubringen. Die Codebeispiele in diesem Abschnitt stammen von der offiziellen Jass Website. Für präzisere Beschreibungen der Inputsprache und dessen Anwendung möge sich der geneigte Leser auf der offiziellen Jass Website informieren. require Preconditions müssen am Beginn einer Methode platziert werden und werden durch das keyword require gekennzeichnet. Require Statements prüfen die angegebenen Conditions und werfen eine entsprechende Exception, falls diese nicht eingehalten werden. public void addElement (Object o) { /** require !isFull(); o != null; **/ ... }

ensure Postconditions müssen am Schluss einer Methode platziert und durch das keyword ensure gekennzeichnet werden. Ensure ist identisch zu require, ausser dass es Post- und nicht Preconditions kennzeichnet. In einer Postcondition kann mit dem keyword Result auf den Returnwert der Methode zugegriffen werden. public void addElement (Object o) { ... /** ensure !isEmpty() && contains(o); **/ }

Old Mit der speziellen Variable Old kann auf den Zustand des Objektes vor Methodenausführung zugegriffen werden. Um auf Old zugreifen zu können, muss die Klasse der Postcondition zwingend das Interface Cloneable implementieren. Es müssen dabei nur jene Variablen effektiv kopiert werden, die auch tatsächlich mit Old referenziert werden. public void addElement (Object o) { ... /** ensure !isEmpty() && contains(o); count == Old.count+1; **/ }

changeonly Mit dem Konstrukt changeonly{…} können Attribute spezifiziert werden, die sich verändert haben dürfen. Attribute, die nicht in changeonly aufgelistet sind, dürfen keinen veränderten Wert aufweisen. Ein changeonly mit einer leeren Liste steht entsprechend dafür, dass keine der Variablen ihren Wert verändert haben darf. Damit lässt sich einfach immutability sicherstellen analog den const Methoden aus C++. Für den Gebrauch dieses Konstruktes muss das Interface Cloneable in der Klasse der Postcondition implementiert werden. public void addElement (Object o) { ... /** ensure !isEmpty() && contains(o); Old.count == count-1; changeonly{count,buffer}; **/ }

Matthias Hausherr

Seite 11 / 22

Design By Contract in Java invariant Ein Invariant muss am Ende der Klasse spezifiziert werden und wird durch das keyword invariant gekennzeichnet. public class Buffer { ... /** invariant 0
View more...

Comments

Copyright � 2017 SILO Inc.