Application development

4


Additional keywords and phrases: hush framework, interactive editors, law of Demeter, formal specification in Z, abstract systems


slide: Application development

subsections:


hush class hierarchy">

slide: The



slide: Drawing canvas


  public interface widget { 
widget
public String path(); public void eval(String cmd); public void pack(String s); public void bind(handler h,String s); public void bind(String p, handler h,String s); public void configure(String cmd); public void geometry(int x, int y); public void xscroll(widget w); public void yscroll(widget w); public widget self(); // to define compound widgets public void redirect(widget inner); };

  import hush.dv.api.event;
  import hush.dv.widgets.canvas;
  
  class draw extends canvas { 
draw go.java
boolean dragging; public draw(String path) { super(path); dragging = false; bind(this); } public void press(event ev) { dragging = true; } public void release(event ev) { dragging = false; } public void motion(event ev) { if (dragging) circle(ev.x(),ev.y(),2,"-fill black"); } };


slide: Drawing canvas



slide: Drawing canvas


drawtool interface">

slide: The



slide: A (partial) class diagram



slide: Widget containment


   path ::= '.' | '.'string | path'.'string
  


slide: An interaction diagram


  import hush.dv.api.*;
  import hush.dv.widgets.frame;
  
  public class toolbox extends frame {  
toolbox
tablet tablet; public toolbox(widget w, tablet t) { super(w,"toolbox"); tablet = t; new toolbutton(this,"draw"); new toolbutton(this,"move"); new toolbutton(this,"box"); new toolbutton(this,"circle"); new toolbutton(this,"arrow"); } public int operator() { tablet.mode(_event.arg(1)); // reset tablet mode return OK; } };


  import hush.dv.api.*;
  import hush.dv.widgets.button;
  
  public class toolbutton extends button { 
toolbutton
public toolbutton(widget w, String name) { super(w,name); text(name); bind(w,name); pack("-side top -fill both -expand 1"); } };


  import hush.dv.api.widget;
  
  public class menubar extends hush.dv.widgets.menubar { 
menubar
public menubar(widget w, tablet t, toolbox b) { super(w,"bar"); configure("-relief sunken"); new FileMenu(this,t); new EditMenu(this,b); new HelpButton(this); } };


slide: Tablet


  import hush.dv.api.*;
  import hush.dv.widgets.*;
  
  public class tablet extends canvas { 
tablet
int _mode; canvas canvas; handler[] handlers; final int DRAW = 0; final int MOVE = 1; final int CIRCLE = 2; final int BOX = 3; final int ARROW = 5; public tablet(widget w, String name, String options) { super(w,name,"*"); handlers = new handler[12]; init(options); redirect(canvas); // to delegate to canvas bind(this); // to intercept user actions handlers[DRAW] = new DrawHandler(canvas); handlers[MOVE] = new MoveHandler(canvas); handlers[BOX] = new BoxHandler(canvas); handlers[CIRCLE] = new CircleHandler(canvas); handlers[ARROW] = new ArrowHandler(canvas); _mode = 0; // drawmode.draw; } public int operator() { handlers [mode].dispatch(_event); return OK; } public int mode(String s) { int m = -1; if ("draw".equals(s)) m = DRAW; if ("move".equals(s)) m = MOVE; if ("box".equals(s)) m = BOX; if ("circle".equals(s)) m = CIRCLE; if ("arrow".equals(s)) m = ARROW; if (m >= 0) _mode = m; return _mode; } void init(String options) { widget root = new frame(path(),"-class tablet"); canvas = new canvas(root,"canvas",options); canvas.configure("-relief sunken -background white"); canvas.geometry(200,100); scrollbar scrollx = new Scrollbar(root,"scrollx"); scrollx.orient("horizontal"); scrollx.pack("-side bottom -fill x -expand 0"); scrollbar scrolly = new Scrollbar(root,"scrolly"); scrolly.orient("vertical"); scrolly.pack("-side right -fill y -expand 0"); canvas.pack("-side top -fill both -expand 1"); canvas.xscroll(scrollx); scrollx.xview(canvas); canvas.yscroll(scrolly); scrolly.yview(canvas); } };

  import hush.dv.api.*;
  import hush.dv.widgets.frame;
  import hush.dv.widgets.canvas;
  
  public class drawtool extends canvas { 
drawtool
widget root; tablet tablet; public drawtool() { System.out.println("meta handler created"); } public drawtool(String p, String options) { super(p,"*"); // create empty tablet init(options); } public int operator() { System.out.println("Calling drawtool:" + _event.args(0) ); String[] argv = _event.argv(); if ("self".equals(argv[1])) tk.result(self().path()); else if ("drawtool".equals(argv[0])) create(argv[1],_event.args(2)); else if ("path".equals(argv[1])) tk.result(path()); else if ("pack".equals(argv[1])) pack(_event.args(2)); else self().eval( _event.args(1) ); // send through return OK; } void create(String name, String options) { drawtool m = new drawtool(name,options); } void init(String options) { root = new frame(path(),"-class Meta"); frame frame = new frame(root,"frame"); tablet = new tablet(frame,"tablet",options); toolbox toolbox = new toolbox(frame,tablet); menubar menubar = new menubar(root,tablet,toolbox); toolbox.pack("-side left -fill y -expand 0"); tablet.pack("-side left -fill both -expand 1"); menubar.pack(); frame.pack("-expand 1 -fill both"); redirect( tablet ); // the widget of interest } };


  	Canvas c = new DrawTool("draw","");
  	tk.bind("drawtool",c);
  	c.circle(20,20,20,"-fill red");
  	c.rectangle(30,30,70,70,"-fill blue");
  	c.pack();
  

subsections:


Development process -- cognitive factors

  • model -> realize -> refine

Design criteria -- natural, flexible, reusable

  • abstraction -- types
  • modularity -- strong cohesion (class)
  • structure -- subtyping
  • information hiding -- narrow interfaces
  • complexity -- weak coupling

slide: Criteria for design


Class design -- guidelines


slide: Individual class design


Invariant properties -- algebraic laws


  class employee { 
employee
public: employee( int n = 0 ) : sal(n) { } employee* salary(int n) { sal = n; return this; } virtual long salary() { return sal; } protected: int sal; };

Invariant


     k == (e->salary(k))->salary() 
  

slide: Invariant properties as algebraic laws


Problem -- hidden bonus


  class manager : public employee { 
manager
public: long salary() { return sal + 1000; } };

Invariant


      k =?= (m->salary(k))->salary() 
  

slide: Violating the invariant


Solution -- explicit bonus


  class manager : public employee { 
manager'
public: manager* bonus(int n) { sal += n; return this; } };

Invariant -- restored


       k + n == ((m->salary(k))->bonus(n))->salary() 
  

slide: Restoring the invariant


Good Object-Oriented Design

  • organize and reduce dependencies between classes
  • Client

    -- A method m is a client of C if m calls a method of C

    Supplier

    -- If m is a client of C then C is a supplier of m

    Acquaintance

    -- C is an acquaintance of m if C is a supplier of m but not (the type of) an argument of m or (of) an instance variable of the object of m

    • C is a preferred acquaintance of m if an object of C is created in m or C is the type of a global variable
    • C is a preferred supplier of m if C is a supplier and C is (the type of) an instance variable, an argument or a preferred acquaintance

    slide: Clients, suppliers and acquaintances


Law of Demeter

ignorance is bliss


Do not refer to a class C in a method m unless C is (the type of)


   1. an instance variable
   2. an argument of m
   3. an object created in m
   4. a global variable
  

  • Minimize the number of acquaintances!

Class transformations

  • lifting -- make structure of the class invisible
  • pushing -- push down responsibility

slide: The Law of Demeter

subsections:


Object-oriented modeling


slide: Relations between objects


State and operations

Z


  • state == [ decls | constraints ]
  • op == [ %D state; decls | constraints ]

Change and invariance

  • %D state == state /\ state'
  • %X state == state = state'

Verification

  • state /\ pre( op ) => op

slide: Model-based specification


Counter in Z">

State

Counter


  
  \begin{schema}{Counter}
  n : \nat
  \where
  n \geq 0
  \end{schema}
    

Operations

  
  \begin{schema}{Incr}
  \Delta Counter
  \where
  \mbox{  n' = n + 1  }
  \end{schema}
  
  \begin{schema}{Decr}
  \Delta Counter
  \where
  n > 0 \\
  \mbox{  n' = n - 1  }
  \end{schema}
    

slide: The specification of a


Counter">

Counter

Z


   Counter \defs [ n : \nat | n \geq 0 ] 
   Counter::Incr \defs [ \%D Counter, v? : \nat | n' = n + v? ]
   Counter::Decr \defs [ \%D Counter | n > 0;  n' = n - 1 ]
   Counter::Value \defs [ \%X Counter; v! : \nat | v! = n ]
  

Bounded counter


   Bounded::Counter \defs [ Counter | n \leq Max ]
   Bounded::Incr \defs [ Counter::Incr | n < Max ]
  

slide: An alternative specification of the


State

Library (1)


  
  \begin{schema}{Library}
  books : \power Book \\
  borrowed : Book \pfun Person
  \where
  \dom borrowed \subseteq books
  \end{schema}
    

slide: The specification of a library


Operations

Library (2)


  
  \begin{schema}{Borrow}
  \Delta Library; b? : Book; p? : Person
  \where
  b? \not\in \dom borrowed \\
  b? \in books \\
  borrowed' \mbox{  =  } borrowed \cup { b? \mapsto p? }
  \end{schema}
  
  \begin{schema}{Return}
  \Delta Library; b? : Book; p? : Person
  \where
  b? \in \dom borrowed \\
  borrowed' \mbox{  =  } borrowed \hide { b? \mapsto p? }
  \end{schema}
  
  
  \begin{schema}{Has}
   \Xi Library; p? : Person; bks : \power Book
  \where
  bks! \mbox{  =  } borrowed ^{-1} \limg { p? } \rimg
  \end{schema}
  

slide: The library operations


Abstract systems -- design methodology

  • abstract system = abstract data types + protocol

Events -- high level glue

  • realization of the interaction protocol

slide: Abstract systems and events


Abstract system -- exemplary interface

library



  p = new person();
  b = new book();
  p = b->borrower;
  s = p->books;
  tf = b->inlibrary();
  b->borrow(p);
  p->allocate(b);
  p->deallocate(b);
  b->_return(p);
  

For person* p; book* b; set<book>* s; bool tf;


slide: The library system


  class book { 
book
public: person* borrower; book() {} void borrow( person* p ) { borrower = p; } void _return( person* p ) { borrower = 0; } bool inlibrary() { return !borrower; } };


  class person { 
person
public: person() { books = new set(); } void allocate( book* b ) { books->insert(b); } void deallocate( book* b ) { books->remove(b); } set* books; };


  book* Stroustrup = new book(); 
example
book* ChandyMisra = new book(); book* Smalltalk80 = new book(); person* Hans = new person(); person* Cees = new person(); Stroustrup->borrow(Hans); Hans->allocate(Stroustrup); ChandyMisra->borrow(Cees); Cees->allocate(ChandyMisra); Smalltalk80->borrow(Cees); Cees->allocate(Smalltalk80);


  class Event { 
Event
public: virtual void operator()() = 0; };


  class Borrow : public Event { 
Borrow
public: Borrow( person* _p, book* _b ) { _b = b; _p = p; } void operator()() { require( _b && _p ); // _b and _p exist _b->borrow(p); _p->allocate(b); } private: person* _p; book* _b; };


  class Return : public Event { 
Return
public: Return( person* _p, book* _b ) { _b = b; _p = p; } void operator()() { require( _b && _p ); _b->_return(p); _p->deallocate(b); } private: person* _p; book* _b; };

drawtool application">

The drawtool application

1


  • drawing canvas -- in hush
  • drawtool -- compound widgets

slide: Section 4.1: The


Guidelines for design

2



slide: Section 4.2: Guidelines for design


From specification to implementation

3


  • structure versus behavior
  • model-based specification
  • abstract systems

slide: Section 4.3: From specification to implementation

  1. Give an example of your choice to describe OO application development.
  2. Discuss possible guidelines for individual class design.
  3. Discuss how inheritance may affect class invariants.
  4. What would be your rendering of the Law of Demeter? Can you phrase its underlying intuition? Explain.
  5. Define the notions of client, supplier and acquaintance. What restrictions must be satisfied to speak of a preferred acquaintance and a preferred supplier?
  6. Characterize the differences between semantic modeling and object-oriented modeling.
  7. How would you characterize the notion of abstract systems?
  8. Explain how events may be employed to maintain system integrity. Give an example!

The original paper on hush is  [HUSH]. A veritable catalogue of object-oriented applications can be found in  [Harmon93]. A classical paper on class design is  [JF88]. For the Law of Demeter, consult  [LH89]. The notion of abstract systems was introduced in  [Henderson93], which also gives a good account of a formal approach to object-oriented design. For an introduction to formal methods and Z, consult  [Diller94]. For object-oriented extensions of Z, see  [Stepney].