principles of object-oriented software development application development

59
Principles of Object- Oriented Software Development Application Development

Post on 19-Dec-2015

231 views

Category:

Documents


1 download

TRANSCRIPT

Principles of Object-Oriented Software Development

Application Development

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

The drawtool application

Subsections:

A simple drawing canvas in hush The drawtool application

A simple drawing canvas in hush

The hush class hierarchy

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"); } };

Drawing canvas

The drawtool application

A (partial) class diagram

Widget containment path ::= '.' | '.'string | path'.'string

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); } };

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();

The drawtool application

Guidelines for design

Subsections:

Individual class design Establishing invariants An objective sense of style

Development process

• model -> realize -> refine

cognitive factors

Design criteria

• abstraction -- types

• modularity -- strong cohesion (class)

• structure -- subtyping

• information hiding -- narrow interfaces

• complexity -- weak coupling

natural, flexible, reusable

Individual class design

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

Inheritance and invariance

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

An objective sense of style

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

Object-oriented modeling

• is-a -- inheritance

• has-a, uses -- delegation

• uses -- templates

Model-based specification

State and operations

Change and invariance

Verification

Model-based specification

State

The specification of a Counter in Z

Counter

Bounded counter

Z

State

The specification of a Library

Operations

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 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; };

Summary

The drawtool application

• drawing canvas -- in hush

• drawtool -- compound widgets

1

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].