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”, GOF 2 Comerge AG
hierarchy of reuse Library Bottleneck Language Wizard / Tool Design Pattern Documented Solution Communicated Solution (“Cut ʼ n ʼ Paste”) Ad-hoc Solution 3 Comerge AG
reuse and quality Reuse 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 4 Comerge AG
observer pattern • Loose coupling between caller and call target. • Implement a publish-subscribe and MVC architecture. 5 Comerge AG
observer example observers OBSERVER SUBJECT LIST[OBSERVER] CONCRETE_ CONCRETE_ OBSERVER SUBJECT 6 Comerge AG
observer pattern observers CLICK_ CLICKABLE OBSERVER LIST[OBSERVER] ON_CLICK_ BUTTON ACTION 7 Comerge AG
observer as library Library class event_x SUBJECT EVENT_TYPE subscribers Language feature target PROCEDURE OBSERVER (“agent”) 8 Comerge AG
EVENT _ TYPE 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 9 Comerge AG
events in MVC 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) 10 Comerge AG
dropping arguments class DATABASE TUPLE[] ... feature -- Slots remove_customer is ... end ... end class BUTTON TUPLE[INTEGER] ... feature -- Signals clicked: EVENT_TYPE [TUPLE [INTEGER]] ... end gui_remove_button.clicked.subscribe ( agent db.remove_customer) 11 Comerge AG
type system caveat 1 print (what:ANY) PROCEDURE [ANY,TUPLE[INTEGER]] ... clicked: EVENT_TYPE [TUPLE [INTEGER]] not ... clicked.subscribe (print (?)) PROCEDURE [ANY,TUPLE[ANY]] Does not type check! 12 Comerge AG
type system caveat print_integer (v: INTEGER) PROCEDURE ... [ANY,TUPLE[ANY]] network.received: EVENT_TYPE [TUPLE [ANY]] ... PROCEDURE received.subscribe [ANY,TUPLE[INTEGER]] (print_integer (?)) Compiles with type error (CAT call!) 13 Comerge AG
observer: 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 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 objects. 15 Comerge AG
factory method 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 16 Comerge AG
abstract factory CLIENT WIDGET_FACTORY WINDOW AQUA_WINDOW GDI_WINDOW GDI_W_FACTORY AQUA_W_FACTORY SCROLL_BAR AQUA_SCROLL_B GDI_SCROLL_B 17 Comerge AG
factories and generics ABSTRACT_FACTORY CREATABLE [G -> CREATABLE] default_create GDI_W_FACTORY AQUA_W_FACTORY 18 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 objects. 19 Comerge AG
singleton • Class that should only have a single, global instance. 20 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 Comerge AG
singletons in Eiffel class FILE_SYSTEM ... end class SHARED_FILE_SYSTEM feature -- Access File_system: FILE_SYSTEM is -- Operating system file system once create Result ensure not_void: Result /= Void end end 22 Comerge AG
shared data • 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 Does it work? 23 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 Comerge AG
universe example 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 25 Comerge AG
universe example 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 26 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 once create Result create default_universe Result.extend (default_universe) ensure not_void: Result /= Void end 27 Comerge AG
universe stacks feature -- Universe universe: MY_UNIVERSE is Some -- Global stack of universes. contracts do skipped for Result := Universe_stack.item brevity! end push_universe is -- Create a new universe. local new_universe: MY_UNIVERSE once create new_universe Result.extend (new_universe) end pop_universe is -- Return to an old universe. do ... end 28 Comerge AG
universe stack ex. 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 29 Comerge AG
singleton summary • 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 . 30 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 object value. Value semantics comerge AG
coding flyweight 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 32 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, ~) 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 comerge AG
flyweight examples Expanded Type Flyweight • characters • string labels • pairs • tokens • currency values • sets • enumeration • (some) units types 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 comerge AG
composite • 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 37 Comerge AG
composite sub_node: NODE * NODE LEAF NON_LEAF 38 Comerge AG
composite example deferred class EXPRESSION end 39 Comerge AG
composite example class INTEGER_EXPRESSION inherit EXPRESSION feature -- Access value: INTEGER -- Representation of expression end 40 Comerge AG
Recommend
More recommend