principles of object-oriented software development application development
Post on 19-Dec-2015
234 views
TRANSCRIPT
Application Development
Introduction
The drawtool application Guidelines for design From specification to implementation
Summary Q/A Literature
Application Development
• the drawtool applications
• guidelines for design
• from specification to implementation
Additional keywords and phrases:hush framework, interactive editors, law of Demeter,formal specification in Z, abstract systems
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"); } };
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); } };
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();
The drawtool application
Guidelines for design
Subsections:
Individual class design Establishing invariants An objective sense of style
Design criteria
• abstraction -- types
• modularity -- strong cohesion (class)
• structure -- subtyping
• information hiding -- narrow interfaces
• complexity -- weak coupling
natural, flexible, reusable
Class design
• only methods public -- information hiding
• do not expose implementation details
• public members available to all classes -- strong cohesion
• as few dependencies as possible -- weak coupling
• explicit information passing
• root class should be abstract model -- abstraction
guidelines
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()
Problem -- hidden bonus
class manager : public employee { manager
public: long salary() { return sal + 1000; } };
Invariant
k =?= (m->salary(k))->salary()
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()
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
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!
From specification to implementation
Subsections:
Structure versus behavior Model-based specification Abstract systems
Structural versus behavioralencapsulation
Semantic modeling -- constructing types
aggregation, grouping by association
Abstract systems and events
Abstract systems -- design methodology
abstract system = abstract data types + protocol
Events -- high level glue
realization of the interaction protocol
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;
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 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; };
Guidelines for design
• individual class design
• establishing invariants
• an objective sense of style
2
From specification toimplementation
• structure versus behavior
• model-based specification
• abstract systems
3
Questions1. 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!
Further reading
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].