6894 · workshop in software design lecture 5 · october 14, 1998 · design patterns

23
daniel jackson mit lab for computer science 6894 · workshop in software design lecture 5 · october 14, 1998 · design patterns

Upload: ishmael-burks

Post on 31-Dec-2015

24 views

Category:

Documents


2 download

DESCRIPTION

6894 · workshop in software design lecture 5 · october 14, 1998 · design patterns. topics. schedule October 19 reading on concurrent design patterns catalog of about 10 design patterns http://gee.cs.oswego.edu/dl/cpj/index.html October 21 instead of Problem Frames, discuss design proposals - PowerPoint PPT Presentation

TRANSCRIPT

daniel jacksonmit lab for computer science

6894 · workshop in software designlecture 5 · october 14, 1998 · design patterns

04/19/23 daniel jackson 2

topics

schedule· October 19

reading on concurrent design patternscatalog of about 10 design patterns

http://gee.cs.oswego.edu/dl/cpj/index.html

· October 21instead of Problem Frames, discuss design proposalseach team bring a 5-10 minute presentation

design proposals· scope

can be on some aspect of the CMon an entire redesign of the CM

· form1. problem addressed2. solution proposed3. strategy, esp. minimal subset

04/19/23 daniel jackson 3

origins

motivation· capture expertise of experienced designers· reuse of design practice and form· provide vocabulary for design

history· Christopher Alexander et al: A Pattern Language (1977)· Erich Gamma’s PhD thesis (1991): about half of the GOF patterns· Coplien: Advanced C++ Styles and Idioms (1992)· Helm, Vlissides, Johnson: summary of pattern catalog in ECOOP (1993)· Gamma et al: Design Patterns (1995)

often referred to as the Gang of Four Book (GOF)

04/19/23 daniel jackson 4

how patterns help

flexibility· make code less susceptible to changes· confine changes as much as possible· examples: confine changes in …

representation (Factory, Bridge, Memento, Proxy)algorithm (Builder, Iterator, Strategy, Template, Visitor)platform (Factory, Bridge)adding new features (Observer, State, Mediator)

documentation· patterns are familiar to programmers· name alone says a lot

archaeology· patterns record best practices· target for research ideas, language evaluation, etc

04/19/23 daniel jackson 5

what’s in a pattern?

GOF style presentation· name

very important!· problem

difficulty addressed by patternmotivating example

· solutiongeneral form of patternimplementation advicevariants

· consequencesnot just benefits – liabilities tooall patterns add complexitymost reduce efficiency

04/19/23 daniel jackson 6

how patterns work

standard use of language constructs· algebraic datatypes (Composite)· closures (Factory)· class variables (Singleton)· inheritance (Template) – but maybe not standard use?

ad hoc tricks· hand-coded dispatch (Visitor)· dynamic reclassification (State)· cloning + cursor (Iterator)

opaque association· (my term)· Adapter, Bridge, Mediator, Observer, Proxy

04/19/23 daniel jackson 7

GOF bias: delegation over inheritance

example· Window and Rectangle· with inheritance

Window subclass of RectanglegetArea method of Window is inheritedresize method of Window calls methods and uses instance vars of

Rectangle· with delegation

Window’s rep includes a RectanglegetArea method of Window just invokes getArea of Rectangle

advantages of delegation· runtime composition: Window can become circular by switching Rep· better modularity: avoid abstraction violations of inheritance

disadvantages of delegation· a bit clumsier than inheritance· objects have distinct types: can’t pass Window to method expecting Rectangle

but Window is probably not a subtype of Rectangle anywayless of an issue in dynamically-typed languages, eg. Scheme

04/19/23 daniel jackson 8

GOF bias: others

no parametric polymorphism· most useful at lower level of abstraction?

notion of association (from OMT) hides representation of set or table

objects, not functions· closures rarely used

with exception of Visitor, State, …?· patterns are very imperative in flavour

04/19/23 daniel jackson 9

opaque association

motivation· behaviour of two objects A and B is tightly coupled· want coupling only at runtime, not compile time

change to B’s code should not affect A’s

basic idea· loosen compile time coupling by

having A access B through an opaque associationA’s code no longer depends on B’s interface

two ways to achieve· indirection

A accesses B through another object, X· specification

A accesses B as if it has a specification S that is weaker than its actual specification

consequences of this style of design· more complex compile-time structure· greater disparity between compile-time and runtime structures· more elaborate runtime invariants

04/19/23 daniel jackson 10

class models

elements· a box represents a class· a bar represents a specification· an arrow from box A to box B means

A’s code calls a method on a B object· an arrow from A to B through spec S

A’s code calls a method of a B object, but views B as having spec S

if arrow is dotted, association is transient: B object not in rep of A

A B

A B

S

04/19/23 daniel jackson 11

why yet another notation?

object model plays two roles· abstract state

what objects exist, what invariants hold, etc· class structure

what code modules exist, dependences, namespace, etc

shouldn’t be conflated· specs are not just sets of objects!

spec describes what properties are expected in the future· class structure should be postponed

abstract state description is a specification activityallocation of methods and state to classes is a design activity

· design patterns suggest major deviation from problem domain structure

snags caused by shared notation· OCL’s typecasts: much more complex than Alloy’s simple set ops· no superclass/interface distinction· only one occurrence of an interface node with a given name

so Enumeration, eg, can only occur once!but different Enumerations often unrelated

04/19/23 daniel jackson 12

disentangling design patterns: observer

essential feature· ConcreteSubject views ConcreteObserver through Observer· code sharing in Subject is a minor detail

Subject

Attach (Observer)Detach (Observer)Notify ()

Concrete Subject

GetState ()SetState ()

subjectState

Concrete Observer

Update ()

observerState

Observer

Update ()

subject

observers

for all o in observers { o.Update (); }

observerState = subject.GetState ()

return subjectState

*

!

04/19/23 daniel jackson 13

examples of opaque association (1)

CLIENT ADAPTER ADAPTEE

TARGETadapter

CLIENT PROXY SERVICE

SERVICEproxy

CLIENT REFINEDIMPL-A

ABSTRACTION IMPL-Bbridge

04/19/23 daniel jackson 14

examples of opaque association (2)

COLL-1 CMEDIATOR COLL-2

MEDIATORmediator

CSUBJECT COBSERVER

OBSERVERobserver

CLIENT CONTEXTSTATE-A

STATE-Bstate STATE

04/19/23 daniel jackson 15

examining a DP: visitor

visitor is unusual· designed to overcome OO-ness of OO language· a great idea or a clever hack?· discussed in detail in

Felleisen & Friedman, A Little Java, A Few Patterns

ELEMENT-A

ELEMENT-B

VISITOR-X

04/19/23 daniel jackson 16

visitor example

AST for arithmetic expressions· suppose language is

expr ::= literal | variable | expr + expr | expr * expr | - expr· might implement as AST with:

interface Exprclass Literal implements Exprclass Variable implements Exprabstract class BinaryExpr implements Exprclass MinusExpr implements Expr

operations on AST· evaluate for given binding of variables to literals· pretty print· reduce (eg, replace e + 0 by e)

observation· many involve similar traversals· awkward to implement each new operation by adding method to each class· would rather add a new class for each operation

04/19/23 daniel jackson 17

sample Visitor code

interface Visitor { void for_Literal (Literal x); void for_Variable (Variable x); void for_BinaryExpr (BinaryExpr x); void for_MinusExpr (MinusExpr x); }

class Literal implements Expr { … void accept (Visitor v) { v.for_Literal (this); } }

class PrettyPrintV implements Visitor { PrettyPrintV () {}; void for_Literal (Literal x) { System.out.println (x.toString()); } void for_BinaryExpr (BinaryExpr x) { x.left.accept (this); System.out.println (x.op.toString()); x.right.accept (this); } }

note· Visitor accesses representation of visited class!

04/19/23 daniel jackson 18

visitor as closure

basic idea· visitor provides convenient context for state to be maintained over traversal

examples· encapsulate output stream

PrettyPrintV (Stream s) {stream = s;}void for_Literal (Literal x) {stream.println (x.toString());}

· encapsulate Variable -> Literal bindingEvaluateV (Binding b) {…}

Object for_Variable (Variable x) {return b.get (x);}

· other examplesinstrumentation/debugging

04/19/23 daniel jackson 19

functional visitor

basic idea· a kind of ‘map’· transforms one AST to another with nodes of different types· operation types

C’ Visitor::for_C (C)C’ C::accept (Visitor)

· inflexibility of Java’s subtyping rules a painlots of unnecessary downcasts; C’ must be Object

sample codeclass C {

D d; E e; Object accept _functional (FunctionalVisitor v) { return v.for_C (this); }

class VisitorX implements FunctionalVisitor { Object for_C (C c) { DD dd = (DD) c.d.accept_functional (this); EE ee = (EE) c.e.accept _functional (this); return someFunction (dd, ee); }

04/19/23 daniel jackson 20

imperative visitor

basic idea· mutates each element of AST· operation types

void Visitor::for_C (C)void C::accept (Visitor)

sample codeclass C {

D d; E e; void accept_imperative (ImperativeVisitor v) { v.for_C (this); }

class VisitorX implements ImperativeVisitor { void for_C (C c) { c.d.accept_imperative (this); c.e.accept_imperative (this); … return; }

04/19/23 daniel jackson 21

replacing visitor

replacing visitor· type structure of functional visitor, but mutates like imperative visitor· operation types

C’ Visitor::for_C (C)C’ C::accept (Visitor)

sample codeclass C {

D d; E e; Object accept _replacer (ReplacingVisitor v) { return v.for_C (this); }

class VisitorX implements ReplacingVisitor { Object for_C (C c) { if (…) return new C (…) else { c.d = (D) c.d.accept_replacer (this); c.e = (E) c.e.accept_replacer (this); return c; } }

04/19/23 daniel jackson 22

exploiting subclassing

basic idea· make Visitor a superclass, not an interface· dummy implementation for each element type

imperative visitor: applies the visitor to the subelementsreplacing visitor: replaces the subelements using the visitor

· each visitor implementation only overrides behaviour for some elements

examples· imperative: to print out all literals

class PrintLiteralV extends ImperativeVisitor { void for_Literal (Literal x) {stream.println (x.toString());} }

· replacing: replace all variables by dummy literalsclass InstantiateR extends ReplacingVisitor {

Object for_Variable (Variable x) {return new Literal ();} }

· then all you need is the first callexpr.accept (new FooVisitor (…));

this is a major advantage of Visitors!

04/19/23 daniel jackson 23

but … subclassing snags

can’t subclass in the element hierarchy· suppose we have

abstract class BinaryExprclass PlusExpr extends BinaryExprclass TimesExpr extends BinaryExpr

· now suppose we want a visitor that prints out binary exprs only· will this work?

class PrintBinExprV implements Visitor { for_BinaryExpr (BinaryExpr x) { stream.println (x.toString ()); } }

· no!for_BinaryExpr is never calledit’s a method associated only with the abstract class, which has no

objects

a flawed solution· default implementation of for_PlusExpr calls for_BinaryExpr

can now override for_BinaryExpr and get intended behaviour for this PrintBinExprV

· but cannot write PrintLiteralV by overriding for_Literal alonefor_PlusExpr calls for_BinaryExpr and not left.accept!