Design Patterns in Eiffel Dr. Till Bay design patterns? [Design - - PowerPoint PPT Presentation

design patterns in eiffel
SMART_READER_LITE
LIVE PREVIEW

Design Patterns in Eiffel Dr. Till Bay design patterns? [Design - - PowerPoint PPT Presentation

Design Patterns in Eiffel Dr. Till Bay design patterns? [Design Patterns] are descriptions of communicating objects and classes that are customized to solve a general design problem in a particular context. Design Patterns,


slide-1
SLIDE 1

Design Patterns in Eiffel

  • Dr. Till Bay
slide-2
SLIDE 2

Comerge AG

design patterns?

  • “[Design Patterns] are descriptions of

communicating objects and classes that are customized to solve a general design problem in a particular context.”

  • “Design Patterns”, GOF

2

slide-3
SLIDE 3

Comerge AG

hierarchy of reuse

Ad-hoc Solution Communicated Solution (“CutʼnʼPaste”) Documented Solution Design Pattern Wizard / Tool Language Library Bottleneck

3

slide-4
SLIDE 4

Comerge AG

reuse and quality

  • Reuse increases quality
  • Only by reuse, the extra effort of quality pays off
  • “Given enough eyeballs, all bugs are

shallow” (Eric Raymond)

  • Quality increases reuse
  • Understandable
  • Trust gained by quality

Reuse Quality

4

slide-5
SLIDE 5

Comerge AG

  • bserver pattern
  • Loose coupling between caller and call

target.

  • Implement a publish-subscribe and MVC

architecture.

5

slide-6
SLIDE 6

Comerge AG

  • bserver example

OBSERVER SUBJECT

  • bservers

CONCRETE_ OBSERVER CONCRETE_ SUBJECT LIST[OBSERVER]

6

slide-7
SLIDE 7

Comerge AG

  • bserver pattern

CLICK_ OBSERVER CLICKABLE

  • bservers

ON_CLICK_ ACTION BUTTON LIST[OBSERVER]

7

slide-8
SLIDE 8

Comerge AG

  • bserver as library

EVENT_TYPE SUBJECT event_x PROCEDURE (“agent”) subscribers OBSERVER target

8

Library class Language feature

slide-9
SLIDE 9

Comerge AG

class EVENT_TYPE [G -> TUPLE] feature -- Subscription subscribers: LIST [PROCEDURE [ANY, G]] subscribe (an_action: PROCEDURE [ANY, G])

  • - Add `an_actionʼ to the subscription list.

require not_void: an_action /= Void ensure subscribed: subscribers.has (an_action) feature -- Publish publish (arguments: G)

  • - Publish event with `argumentsʼ.

require not_void: arguments /= Void end

EVENT_TYPE

9

slide-10
SLIDE 10

Comerge AG

class DATABASE ... feature -- Slots remove_customer is ... end ... end class BUTTON ... feature -- Signals clicked: EVENT_TYPE [TUPLE []] ... end gui_remove_button.clicked.subscribe (agent db.remove_customer)

events in MVC

10

slide-11
SLIDE 11

Comerge AG

class DATABASE ... feature -- Slots remove_customer is ... end ... end class BUTTON ... feature -- Signals clicked: EVENT_TYPE [TUPLE [INTEGER]] ... end gui_remove_button.clicked.subscribe (agent db.remove_customer)

dropping arguments

11

TUPLE[INTEGER] TUPLE[]

slide-12
SLIDE 12

Comerge AG

type system caveat 1

PROCEDURE [ANY,TUPLE[INTEGER]] PROCEDURE [ANY,TUPLE[ANY]] clicked: EVENT_TYPE [TUPLE [INTEGER]] ... clicked.subscribe (print (?)) Does not type check! not print (what:ANY) ...

12

slide-13
SLIDE 13

Comerge AG

type system caveat

PROCEDURE [ANY,TUPLE[ANY]] PROCEDURE [ANY,TUPLE[INTEGER]] network.received: EVENT_TYPE [TUPLE [ANY]] ... received.subscribe (print_integer (?)) Compiles with type error (CAT call!) print_integer (v: INTEGER) ...

13

slide-14
SLIDE 14

Comerge AG

  • bserver: summary
  • Not needed as pattern
  • Language powerful enough (agents,

generics, tuple) to implement as library

  • Available library classes:
  • ACTION_SEQUENCE (used by Vision2)
  • EVENT_TYPE (early implementation at ETH)
  • Not yet in GOBO
  • GOBO did support compilers w. o. agents
  • will change in the future

14

slide-15
SLIDE 15

Comerge AG

factory

  • Remove create instructions from the code.
  • Relocate them to a single feature (factory

method) or class (abstract factory).

  • Make it easy to change the dynamic type of
  • bjects.

15

slide-16
SLIDE 16

Comerge AG

class ET_AST_FACTORY ... feature -- Factory method new_class: (a_name: ET_CLASS_NAME): ET_CLASS is

  • - New Eiffel class

require ... do create Result.make (a_name) ensure ... end end

factory method

16

slide-17
SLIDE 17

Comerge AG

abstract factory

17

CLIENT

WIDGET_FACTORY

GDI_W_FACTORY AQUA_W_FACTORY

WINDOW GDI_WINDOW AQUA_WINDOW SCROLL_BAR GDI_SCROLL_B AQUA_SCROLL_B

slide-18
SLIDE 18

Comerge AG

factories and generics

18

ABSTRACT_FACTORY [G -> CREATABLE]

GDI_W_FACTORY AQUA_W_FACTORY

CREATABLE default_create

slide-19
SLIDE 19

Comerge AG

factory summary

  • Remove create instructions from the code.
  • Relocate them to a single feature (factory

method) or class (abstract factory).

  • Make it easy to change the dynamic type of
  • bjects.

19

slide-20
SLIDE 20

Comerge AG

singleton

  • Class that should only have a single, global

instance.

20

slide-21
SLIDE 21

Comerge AG

reasons for singleton

1.Because some environment constraint makes it necessary: OPERATING_SYSTEM, STANDARD_FILES, COMMAND_LINE_ARGUMENTS 2.To get a stateless functional infrastructure URL_ENCODING, MATH_SUPPORT 3.To access shared data PARSED_AST, DATABASE, SESSION_DATA

21

slide-22
SLIDE 22

Comerge AG

class FILE_SYSTEM ... end class SHARED_FILE_SYSTEM feature -- Access File_system: FILE_SYSTEM is

  • - Operating system file system
  • nce

create Result ensure not_void: Result /= Void end end

singletons in Eiffel

22

slide-23
SLIDE 23

Comerge AG

shared data

Does it work?

23

  • Using singletons for shared data creates

problems with reuse:

local application1: MY_APPLICATION application2: MY_APPLICATION do create application1 application1.do_something create application2 application2.do_something_else end

slide-24
SLIDE 24

Comerge AG

universe objects

  • A “universe object” stores global data for the

system.

  • Positive: fine-grained sharing
  • Negative: significant extra work and

increased “noise” in the code

24

slide-25
SLIDE 25

Comerge AG

local u1,u2: MY_UNIVERSE application1: MY_APPLICATION application2: MY_APPLICATION do create u1 create application1.make (u1) application1.do_something create u2 create application2.make (u2) application2.do_something_else end

universe example

25

slide-26
SLIDE 26

Comerge AG

class MY_APPLICATION feature -- Initialization make (u: MY_UNIVERSE) is

  • - Initialize application.

do universe := u create my_subsystem.make (u) ensure universe_set: universe = u end feature -- Access universe: MY_UNIVERSE

  • - Shared application resources

my_subsystem: MY_SUBSYSTEM

  • - Subsystem of application

end

universe example

26

slide-27
SLIDE 27

Comerge AG

universe stacks

  • Idea: use once to reference a stack of

universes.

class SHARED_UNIVERSE_STACK feature -- Access Universe_stack: LINKED_STACK [MY_UNIVERSE] is

  • - Global stack of universes.

local default_universe: MY_UNIVERSE

  • nce

create Result create default_universe Result.extend (default_universe) ensure not_void: Result /= Void end

27

slide-28
SLIDE 28

Comerge AG

feature -- Universe universe: MY_UNIVERSE is

  • - Global stack of universes.

do Result := Universe_stack.item end push_universe is

  • - Create a new universe.

local new_universe: MY_UNIVERSE

  • nce

create new_universe Result.extend (new_universe) end pop_universe is

  • - Return to an old universe.

do ... end

universe stacks

28

Some contracts skipped for brevity!

slide-29
SLIDE 29

Comerge AG

local application1: MY_APPLICATION application2: MY_APPLICATION do create application1.make application1.do_something push_universe create application2.make application2.do_something_else pop_universe end

universe stack ex.

29

slide-30
SLIDE 30

Comerge AG

singleton summary

30

  • Identify the reason for the singleton.
  • Only use singletons for functional libraries

and environment constraints.

  • If it is shared data, reconsider using a

universe object.

  • Important global shared data for a large

application creating a lot of noise can benefit from using a universe stack.

slide-31
SLIDE 31

comerge AG

flyweight

  • Reuse existing objects by aliasing the objects

during object creation.

  • Requires an object factory and a shared

repository of objects.

  • Works if the object identity follows from the
  • bject value.

Value semantics

slide-32
SLIDE 32

Comerge AG

class FLYWEIGHT_FACTORY feature -- Factory make_new_flyweight (a: SOME_ARG): FLYWEIGHT is

  • - Create a new flyweight, initialized with `aʼ.

do if flyweight_pool.has_index (a) then Result := flyweight_pool.item (a) else create Result.make (a) flyweight_pool.extend (Result, a) end end flyweight_pool: HASH_TABLE [FLYWEIGHT,SOME_ARG] is once ... end end

coding flyweight

32

slide-33
SLIDE 33

comerge AG

expanded types

  • “Expanded types”: Define classes with value

semantics

  • Much improved through ECMA
  • No explicit instance creation necessary
  • No recursive data structures
  • No subtyping
  • No aliasing: copy semantics
  • Reference equality (=) becomes value

equality (is_equal, ~)

slide-34
SLIDE 34

comerge AG

flyweight vs. expanded

  • Expanded classes cover nearly all cases

where you would have used flyweight for Java or .NET

  • Use flyweight only if you need one of the

following:

  • Complex type hierarchy
  • Unbounded data
  • Recursive data structure with value semantics
slide-35
SLIDE 35

comerge AG

flyweight examples

Expanded Type Flyweight

  • characters
  • pairs
  • currency values
  • enumeration

types

  • string labels
  • tokens
  • sets
  • (some) units
slide-36
SLIDE 36

comerge AG

flyweight summary

  • Flyweight implements value semantics
  • Straight forward implementation
  • Use a once container as flyweight pool
  • Choose:
  • Flyweight: Needs hierarchy, unbounded data or

recursive data structure

  • Otherwise use expanded type
slide-37
SLIDE 37

Comerge AG

composite

37

  • Tree structure for “whole/part” hierarchies
  • Abstract tree node type defined
  • Leaf nodes:
  • implement abstract tree node type
  • Non-leaf nodes: implement
  • implement abstract tree node type
  • have a number of attributes of tree node type
  • Nothing special for Eiffel
slide-38
SLIDE 38

Comerge AG

composite

38

LEAF * NODE NON_LEAF sub_node: NODE

slide-39
SLIDE 39

Comerge AG

deferred class EXPRESSION end

composite example

39

slide-40
SLIDE 40

Comerge AG

class INTEGER_EXPRESSION inherit EXPRESSION feature -- Access value: INTEGER

  • - Representation of expression

end

composite example

40

slide-41
SLIDE 41

Comerge AG

class ADDITION_EXPRESSION inherit EXPRESSION feature -- Access left: EXPRESSION

  • - Left subexpression

right: EXPRESSION

  • - Right subexpression

invariant left_not_void: left /= Void right_not_void: right /= Void end

composite example

41

slide-42
SLIDE 42

Comerge AG

class MULTIPLICATION_EXPRESSION inherit EXPRESSION feature -- Access left: EXPRESSION

  • - Left subexpression

right: EXPRESSION

  • - Right subexpression

invariant left_not_void: left /= Void right_not_void: right /= Void end

composite example

42

slide-43
SLIDE 43

Comerge AG

composite summary

43

  • Use composite pattern for structures that are

(recursively) built from parts.

  • Donʼt over-engineer.
  • Donʼt put any recursive computation into the

nodes.

  • Compute on “composite object structures” by

using visitors (next pattern).

slide-44
SLIDE 44

Comerge AG

visitor

  • Process the elements of an (unbounded)

data structure.

  • Apply computations depending on the type of

data node.

  • Store the code outside of the data structure.
  • Most of the time used together with the

composite pattern.

44

slide-45
SLIDE 45

Comerge AG

visitor example

INTEGER_ EXPRESSION ADDITION_ EXPRESSION MULTIPLICATION_ EXPRESSION EXPRESSION_ COMPUTATION_ VISITOR Return the integer value. Compute the left and right subtree, then add the values. Compute the left and right subtree, then multiply the values. CODE_ GENERATOR_ VISITOR Generate code that stores the value on the stack. Generate code for the left and right subtree, then code that pops two elements off the stack and adds them. Generate code for the left and right subtree, then code that pops two elements off the stack and multiplies them.

Double dispatch

45

slide-46
SLIDE 46

Comerge AG

double dispatch

  • “Double dispatch” is code selection based on

the dynamic type of two objects.

  • Available in some languages like Dylan,

MultiJava, LISP, Python (via language extensions)

  • Not available in Eiffel
  • Can be emulated by dispatching twice:

dynamic binding on the visitor and the subject

  • Caveat: Preparation needed

46

slide-47
SLIDE 47

Comerge AG

double dispatch

EXPRESSION_ COMPUTATION_ VISITOR ADDITION_ EXPRESSION process (Current) process_addition (Current)

47

slide-48
SLIDE 48

Comerge AG

deferred class EXPRESSION_VISTOR feature -- Processing process_integer (e: INTEGER_EXPRESSION) is

  • - Process integer constants.

deferred end process_addition (e: ADDITION_EXPRESSION) is

  • - Process additions.

deferred end process_multiplication (e: MULTIPLICATION_EXPRESSION) is

  • - Process multiplications.

deferred end end

abstract visitor

48

Some contracts skipped for brevity!

slide-49
SLIDE 49

Comerge AG

deferred class EXPRESSION feature -- Processing process (v: EXPRESSION_VISITOR) is

  • - Process this node by visitor `vʼ.

require not_void: v /= Void deferred end end

process features

49

slide-50
SLIDE 50

Comerge AG

class INTEGER_EXPRESSION inherit EXPRESSION feature -- Access value: INTEGER

  • - Representation of expression

feature -- Processing process (v: EXPRESSION_VISITOR) is

  • - Process this node by visitor `vʼ.

do v.process_integer (Current) end end

process features

50

slide-51
SLIDE 51

Comerge AG

class ADDITION_EXPRESSION inherit EXPRESSION ... feature -- Processing process (v: EXPRESSION_VISITOR) is

  • - Process this node by visitor `vʼ.

do v.process_addition (Current) end ... end

process features

51

slide-52
SLIDE 52

Comerge AG

class EXPRESSION_COMPUTATION_VISTOR feature -- Access last_result: INTEGER feature -- Processing process_integer (e: INTEGER_EXPRESSION) is

  • - Process integer constants.

do last_result := e.value end

concrete visitor

52

slide-53
SLIDE 53

Comerge AG

process_addition (e: ADDITION_EXPRESSION) is

  • - Process additions.

local right_value, left_value: INTEGER do e.left.process (Current) left_value := last_result e.right.process (Current) right_value := last_result last_result := right_value + left_value end

  • - (same for process_multiplication)

end

concrete visitor

53

slide-54
SLIDE 54

Comerge AG

class EXPRESSION_ITERATOR inherit EXPRESSION_VISITOR feature -- Processing process_integer (e: INTEGER_EXPRESSION) is

  • - Process integer constants.

do end process_addition (e: ADDITION_EXPRESSION) is

  • - Process additions.

do e.left.process (Current) e.right.process (Current) end ... end

iterating visitor

54

slide-55
SLIDE 55

Comerge AG

visitor summary

  • Elegant solution to traverse unbounded data

structures

  • Emulating double dispatch
  • Needs preparation
  • Introducing new node types requires the

adaptation of the abstract visitor and its children

  • Result values are stored in attributes

55

slide-56
SLIDE 56

Comerge AG

iterator

  • “Provide a way to access the elements of an

aggregate object sequentially without exposing its underlying representation.”

  • Four types of iterators:
  • Internal iterators
  • External iterators without bookkeeping-reference
  • External iterators with bookkeeping-reference
  • Higher-order procedures and functions

56

slide-57
SLIDE 57

Comerge AG

deferred class LINEAR [G] feature -- Access item: G is

  • - Current item

require not_off: not off deferred end feature -- Cursor movement forth is

  • - Move to next element.

require not_off: not off deferred end feature -- Status

  • ff: BOOLEAN

end

simple iterators

57

NOT like Java: hasNext() next()

slide-58
SLIDE 58

Comerge AG

  • ther features
  • Rollback to the start of the data structure:
  • start, ...
  • Bilinear movement:
  • back, finish, before, after, ...
  • Index and direct access:
  • count, index, i_th, goto, ...
  • Manipulate the underlying structure:
  • remove, put, replace, ...

58

slide-59
SLIDE 59

comerge AG

internal iterators

LINKED_LIST [G] LINKABLE [G] LINKABLE [G] LINKABLE [G] right cursor_position first right class LINKED_LIST [G] inherit LINEAR [G]

slide-60
SLIDE 60

comerge AG

external iterators

LINKED_LIST [G] LINKABLE [G] LINKABLE [G] LINKABLE [G] right cursor_position first right LINKED_LIST_ CURSOR [G]

slide-61
SLIDE 61

comerge AG

external iterators

LINKED_LIST [G] LINKABLE [G] LINKABLE [G] LINKABLE [G] right cursor_position first right LINKED_LIST_ CURSOR [G] iterators

slide-62
SLIDE 62

Comerge AG

feature -- Iterators do_all (c: PROCEDURE [ANY, TUPLE [G]])

  • - Call `cʼ with on all elements

for_all (q: FUNCTION [ANY, TUPLE [G], BOOLEAN]): BOOLEAN

  • - Does `qʼ yield true on all elements?

there_exists (q: FUNCTION [ANY, TUPLE [G], BOOLEAN]): BOOLEAN

  • - Does `qʼ yield true on all elements?

higher-order

62

slide-63
SLIDE 63

comerge AG

iterator summary

  • Integrated iterator:

+ easy to track and contract

  • dangerous side-effects, multiple iterators
  • External iterators without bookkeeping:

+ independent operations, less side-effects

  • Access to “dead nodes”
  • External iterators with bookkeeping:

+ No dead nodes, well-defined behavior

  • potential memory leak
  • Integrated iterator:

+ powerful, very expressive, safe

  • limited, no change of underlying container
slide-64
SLIDE 64

Comerge AG

bridge

64

WINDOW

GDI_WINDOW AQUA_WINDOW

WINDOW

GDI_WINDOW FULLSCREEN_ WINDOW AQUA_WINDOW

FULLSCREEN_ GDI_WINDOW FULLSCREEN_ AQUA_WINDOW

slide-65
SLIDE 65

Comerge AG

bridge

65

WINDOW FULLSCREEN_ WINDOW WINDOW_IMP

GDI_ WINDOW_IMP AQUA_ WINDOW_IMP FULLSCREEN_ WINDOW_IMP

FULLSCREEN_ GDI_WINDOW_IMP FULLSCREEN_ AQUA_WINDOW_IMP

slide-66
SLIDE 66

Comerge AG

bridge in Vision2

66

EV_BUTTON EV_BUTTON_I

EV_BUTTON _IMP EV_BUTTON _IMP

Selection done in .ecf files

slide-67
SLIDE 67

Comerge AG

class EV_BUTTON feature {EV_ANY, EV_ANY_I } -- Implementation implementation: EV_BUTTON_I feature {NONE } -- Implementation feature -- Cursor movement create_implementation is

  • - Do something.

do create { EV_BUTTON_IMP } implementation.make (Current) end end

implementing bridge

67

slide-68
SLIDE 68

Comerge AG

bridge summary

  • No permanent binding of abstraction and

implementation

  • Abstraction and implementation extendible by

subclassing

  • Changing Implementation: no impact on

clients

  • Implementation completely hidden from

clients

68

slide-69
SLIDE 69

Comerge AG

wrapping up

  • Why?
  • Patterns.
  • Dark corners!

69