Præsentation er lastning. Vent venligst

Præsentation er lastning. Vent venligst

FEN 2013-05-01KbP/seminar2: design11 Kontraktbaseret programmering Seminar 2 Klassedesign – grundprincipper Eksempler: Stack Dictionary.

Lignende præsentationer


Præsentationer af emnet: "FEN 2013-05-01KbP/seminar2: design11 Kontraktbaseret programmering Seminar 2 Klassedesign – grundprincipper Eksempler: Stack Dictionary."— Præsentationens transcript:

1 FEN 2013-05-01KbP/seminar2: design11 Kontraktbaseret programmering Seminar 2 Klassedesign – grundprincipper Eksempler: Stack Dictionary

2 FEN 2013-05-01KbP/seminar2: design12 De seks grundprincipper: 1.Adskil forespørgsler og kommandoer 2.Adskil basale forespørgsler fra afledte 3.Specificer postbetingelser for de afledte forespørgsler vha. de basale 4.Specificer kommandoers postbetingelser gennem deres effekt på de basale forespørgsler 5.Specificer prebetingelser på alle operationer 6.Specificer invariante egenskaber i en klasseinvariant Kun de basale forespørgsler er afhængige af datarepræsentationen Konstruktører skal etablere klasseinvarianten. Tilføj repræsentationsinvariant i implementerende klasser

3 FEN 2013-05-01KbP/seminar2: design13 Stakke --Eiffel: Stack[G] Grundlæggende operationer: –count:INTEGER –is_empty:BOOLEAN –intialize –push(g: G) –pop(out g: G) //Java < 1.5 Stack // of Object Stack // fra 1.5 Grundlæggende operationer: –int count() –boolean isEmpty() –Stack() //constructor –void push(Object o) –Object pop()

4 FEN 2013-05-01KbP/seminar2: design14 1: Adskil forespørgsler og kommandoer Postbetingelse på push(Object e): e = = Hvordan udtrykkes dette? e = = pop() dur ikke. Stakken ændres af pop() Vi har brug for at kunne forespørge uden at ændre. (pop gør egentlig to ting: returnerer topelementet og fjerner det)

5 FEN 2013-05-01KbP/seminar2: design15 I stedet top() og remove(): Object top() – returnerer topelementet. Stakken er uændret. (top kaldes item i Eiffel) void remove() – fjerner elementet. Returnerer ikke noget. Forespørgsler returnerer noget, men ændrer ikke objektets tilstand Kommandoer returnerer ikke noget, men kan (gør det som regel) ændre objektets tilstand.

6 FEN 2013-05-01KbP/seminar2: design16 2:Adskil basale forespørgsler fra afledte forespørgsler isEmpty kan udtrykkes vha. count –Postbetingelse på isEmpty: /*@ ensures \result == (count()==0); @*/ 3:For hver afledt forespørgsel udtryk postbetingelsen ved basale forespørgsler Basale forespørgsler tilgår datarepræsentationen direkte isEmpty() bliver en afledt forespørgsel

7 FEN 2013-05-01KbP/seminar2: design17 Stakkens interface public interface Stack { // Basic queries: public int count(); public Object itemAt(int i); // Derived queries: public boolean isEmpty(); public Object item(); // Commands: public void put(Object e); public void remove(); } Af hensyn til specifikationen er det nødvendigt at have en metode, så man kan tale om alle stakkens elementer Bemærk: item() definerer en logisk rækkefølge mellem elementerne – ikke en fysisk: Vi skal altid kunne returnere sidst ankomne element, så der må være en eller anden logisk orden mellem elementerne svarende til deres ”ankomsttid”.

8 FEN 2013-05-01KbP/seminar2: design18 4:Specificer kommandoer ved deres effekt på basale forespørgsler. 5:Formulér prebetingelser for hver forespørgsel og kommando.

9 FEN 2013-05-01KbP/seminar2: design19 public interface Stack { /*@ public invariant count()>=0; @*/ // Basic queries public /*@ pure @*/ int count(); /*@ requires 0<=i && i<count(); @*/ public /*@ pure @*/ Object itemAt(int i); // Derived queries /*@ ensures \result == (count()==0); @*/ public /*@ pure @*/ boolean isEmpty(); /*@ requires count()>0; @ ensures \result == itemAt(count()-1); @*/ public /*@ pure @*/ Object item(); // Commands /*@ ensures count()==\old(count()+1); @ ensures itemAt(count()-1)==e; @*/ public void put(Object e); /*@ requires count()>0; @ ensures count()==\old(count()-1); @*/ public void remove(); } typeinvariant

10 FEN 2013-05-01KbP/seminar2: design110 Klasseinvariant (typeinvariant og repræsentationsinvariant) Udtrykker egenskaber, som ikke ændrer sig i hele objektets levetid For stakkens vedkommende: count() >= 0 Der skal argumenteres for, at klasseinvarianten faktisk er en invariant, dvs. at ingen operation efterlader den falsk: –Objektet skal oprettes i en tilstand, som tilfredsstiller invarianten, dvs. den bliver en del af postbetingelsen på konstruktøren –Kun put og remove har postbetingelser, som siger, at count er ændret: put forøger count remove trækker 1 fra count, men prebetingelser garanterer, at remove kun kaldes med count>=1

11 FEN 2013-05-01KbP/seminar2: design111 Klasseinvarianter Bør udtrykke egenskaber, som går på tværs af operationer Må gerne være redundant i forhold til operationernes specifikationer Bliver en del af både pre- og postbetingelse på alle operationer Skal etableres ved objektoprettelse

12 FEN 2013-05-01KbP/seminar2: design112 Implementation public class LinkedStack implements Stack { /*@ private invariant ((top==null)==(count==0)); @*/ private int count; private Node top; /*@ ensures count()==0; @*/ public LinkedStack() { top = null; count = 0; } Repræsentations- invariant Specifikation arves fra interfacet Constructor skal etablere invarianten

13 FEN 2013-05-01KbP/seminar2: design113 public /*@ pure @*/ int count() { return count; } public Object itemAt(int i) { Node n = top; while (i<count()-1) { n = n.next; i = i+1; } return n.element; } public boolean isEmpty() { return count==0; } public Object item() { return top.element; } public void put(Object e) { top = new Node(e,top); count = count+1; } public void remove() { top.element = null; top = top.next; count = count-1; } Specifikation er arvet fra interfacet

14 FEN 2013-05-01KbP/seminar2: design114 Object itemAt(int i) Er denne metode ikke et brud med indkapslingen og stakprincippet? Bør den i så fald ikke være private? Nej, en klient kan nemt selv konstruere Object clientItemAt(int i) vha.count, item, remove og put Øvelse: gør det! Løsning1.ppt

15 FEN 2013-05-01KbP/seminar2: design115 Afprøvning af Stack public class StackMain { public static void main(String[] args) { Stack s= new LinkedStack(); for(int i= 0; i<10; i++) s.put(new Integer(i)); System.out.println(s.item()); for(int i= 0; i<10; i++) System.out.println(s.itemAt(i)); } System.out.println(s.itemAt(11)); Hvad sker der her?

16 FEN 2013-05-01KbP/seminar2: design116 De seks principper: 1.Adskil forespørgsler og kommandoer 2.Adskil basale forespørgsler fra afledte 3.Specificer postbetingelser for de afledte forespørgsler vha. de basale 4.Specificer kommandoers postbetingelser gennem deres effekt på de basale forespørgsler 5.Specificer prebetingelser på alle operationer 6.Specificer invariante egenskaber i en klasseinvariant Kun de basale forespørgsler er afhængige af datarepræsentationen Konstruktører skal etablere klasseinvarianten Implementerende klasser skal specificere en repræsentationsinvariant Programmer mod et interface. Specificer en typeinvariant

17 FEN 2013-05-01KbP/seminar2: design117 A side: Programmér altid mod interfaces ArrayList l = new ArrayList(); List l = new ArrayList(); List l = ListFactory.createList(); class ListFactory{//FactoryMethod public static List createList(){ return new ArrayList(); } }

18 FEN 2013-05-01KbP/seminar2: design118 Dictionary: (Map – værdibaseret container, lagrer par af (key, value)) public interface Dictionary { /*@ invariant count()>=0; @*/ // Basic queries public /*@ pure @*/ int count(); /*@ ensures (count()==0) ==> (!\result); @*/ public /*@ pure @*/ boolean has(Object key); /*@ requires has(key); @*/ public /*@ pure @*/ Object valueFor(Object key); // Derived queries /*@ ensures \result == (count()==0); @*/ public boolean isEmpty(); // Commands /*@ requires !has(key); @ ensures has(key); @ ensures valueFor(key)==value; @ ensures count()==(\old(count())+1); @*/ public void put(Object key, Object value); /*@ requires has(key); @ ensures !has(key); @ ensures count()==(\old(count())-1); @*/ public void remove(Object key); }

19 FEN 2013-05-01KbP/seminar2: design119 Designvalg /*@ requires !has(key); @ ensures has(key); @ ensures valueFor(key)==value; @ ensures count()==(\old(count())+1); @*/ public void put(Object key, Object value); Må key være null? Hvad hvis vi tillader, at key er der i forvejen? /*@ ensures (count()==0) ==> (!\result); @*/ public /*@ pure @*/ boolean has(Object key); /*@ requires has(key); @ ensures !has(key); @ ensures count()==(\old(count())-1); @*/ public void remove(Object key); Hvad hvis vi tillader, at key ikke findes?


Download ppt "FEN 2013-05-01KbP/seminar2: design11 Kontraktbaseret programmering Seminar 2 Klassedesign – grundprincipper Eksempler: Stack Dictionary."

Lignende præsentationer


Annoncer fra Google