References Last update: 18 April 2007 Erich Gamma, Ralph Johnson, Richard Helms, John Software Architecture Vlissides: Design Patterns , Addison-Wesley, 1994 Bertrand Meyer Jean-Marc Jezequel, Michel Train, Christine Mingins: Design Patterns and Contracts , Addison-Wesley, 1999 ETH Zurich, March-July 2007 Lecture 7: Patterns, Observer, MVC Karine Arnout: From Patterns to Components , 2004 ETH thesis, http://se.inf.ethz.ch/people/arnout/patterns/ Patterns in software development Benefits of design patterns Design pattern: � Capture the knowledge of experienced developers � A document that describes a general solution to a � Publicly available repository design problem that recurs in many applications. � Common pattern language � Newcomers can learn & apply patterns Developers adapt the pattern to their specific application. � Yield better software structure � Facilitate discussions: programmers, managers Some design patterns A pattern is not a reusable solution Behavioral Creational Solution to a particular recurring design issue in a � Chain of Responsibility � Abstract Factory particular context: � Command (undo/redo) � Builder � Interpreter � Factory Method � “ Each pattern describes a problem that occurs over � Iterator � Prototype and over again in our environment, and then describes � Mediator � Singleton the core of the solution to this problem in such a way � Memento that you can use this solution a million times over, Structural � Observer � Adapter without ever doing it the same way twice. ” � State � Bridge � Strategy Gamma et al. � Composite � Template Method � Decorator � Visitor NOT REUSABLE � Façade � Flyweight � Proxy 1
A step backwards? Our first set of patterns & componentization Patterns are not reusable solutions: Observer pattern � You must implement every pattern every time Model-View Controller � Pedagogical tools, not components Improving on Observer: a more general & flexible approach We have done work at ETH to correct this situation: “ A successful pattern cannot just be a book description: Implementing the solution in C#/.NET it must be a software component ” Implementing the solution in Eiffel Result: Pattern Library and Pattern Wizard (see following lectures) Karine Arnout Pattern componentization Handling input through traditional techniques ETH PhD, 2004 Classification of design patterns: Program drives user: � Fully componentizable � Partially componentizable End of input from � Wizard- or library-supported read_line � Non-componentizable count := 0 until exhausted loop Fully componentizable (48%) count := count + 1 -- Store last_line at -- position count in Result Result [ count ] := last_line read_line end Pattern componentization: references Handling input with modern GUIs Bertrand Meyer: The power of abstraction, reuse and simplicity: an User object-oriented library for event-driven design , in From Object- drives Orientation to Formal Methods: Essays in Memory of Ole-Johan Dahl , Lecture Notes in Computer Science 2635, Springer-Verlag, 2004, program: pages 236-271 se.ethz.ch/~meyer/ongoing/events.pdf “ When a user Karine Arnout and Bertrand Meyer: Pattern Componentization: the Factory Example , in Innovations in Systems and Software Technology presses (a NASA Journal) (Springer-Verlag), 2006 this se.ethz.ch/~meyer/publications/nasa/factory.pdf button, execute Bertrand Meyer and Karine Arnout: Componentization: the Visitor Example , in Computer (IEEE), vol. 39, no. 7, July 2006, pages 23-30 that action se.ethz.ch/~meyer/publications/computer/visitor.pdf from my program ” Karine Arnout’s thesis: From Patterns to Components , March 2004 se.inf.ethz.ch/people/arnout/patterns/ 2
Multiple observers Event-driven programming: example scenario or subscribers Observers One of your classes has a routine my_procedure Save file? Your application has a GUI object OK! Cancel OK_button Whenever the user clicks the mouse the underlying GUI library returns the mouse coordinates or subject, or publisher A = 50% You want to ensure that a mouse click at coordinates B = 30% [ h , v ] calls my_procedure ( h , v ) C = 20% Observed Model-View Controller Event-driven design (Trygve Reenskaug, 1979) Publishers Subscribers Routine Routine Routine Routine Routine Routine Routine Confusion Event Event type Uncertain MVC references Events Overview (from .NET documentation) Reenskaug’s MVC page: Events have the following properties: heim.ifi.uio.no/~trygver/themes/mvc/mvc-index.html 1. The publisher determines when an event is raised; the subscribers determine what action is taken in response to the event. His original MVC paper: 2. An event can have multiple subscribers. A subscriber can handle multiple events from multiple publishers. heim.ifi.uio.no/~trygver/1979/mvc-2/1979-12-MVC.pdf 3. Events that have no subscribers are never called. 4. Events are commonly used to signal user actions such as button clicks or menu selections in graphical user interfaces. 5. When an event has multiple subscribers, the event handlers are invoked synchronously when an event is raised. To invoke events asynchronously, see [another section]. 6. Events can be used to synchronize threads. 7. In the .NET Framework class library, events are based on the EventHandler delegate and the EventArgs base class. 3
(selective Architecture: avoiding glue code Attaching an observer export) In class PUBLISHER : feature { SUBSCRIBER } attach ( s : SUBSCRIBER ) Event producer -- Register s as subscriber to current publisher. require (e.g. GUI) subscriber_exists : s /= Void do subscribed . extend ( s ) s Direct Connection subscription objects end sub n sub1 sub2 subscribers Model The invariant of PUBLISHER includes the clause subscribed /= Void Model View Controller (MVC) Design Pattern ( subscribed is created by creation procedures of PUBLISHER ) A solution: the Observer Pattern Triggering an event attach publish is detach attach * update * * * update* detach * PUBLISHER -- Ask all observers to SUBSCRIBER PUBLISHER SUBSCRIBER subscribe + -- react to current event. subscribed subscribed: LIST [ … ] unsubscribe + do from (secret) subscribed . start PUB_3 SUB_2 + + SUB_3 SUB_4 until PUB_1 PUB_2 SUB_1 update + subscribed . after + + SUB_2 Dynamic binding! PUB_1 SUB_1 loop subscribed . item . update + update subscribers subscribed . forth sub n sub1 sub2 end * Deferred (abstract) Inherits from end + Effective (implemented) update Client (uses) Each descendant of SUBSCRIBER defines its own version of update Observer pattern Observer pattern Each publisher keeps a list of subscribers: (secret) feature { NONE } � Subscriber may subscribe to at most one publisher subscribed : LINKED_LIST [ SUBSCRIBER ] To register itself, a subscriber may execute: � May subscribe at most one operation subscribe ( some_publisher ) � Publishers internally know about subscribers where subscribe is defined in SUBSCRIBER as: subscribe ( p: PUBLISHER ) is � Not reusable — must be coded anew for each application -- Make current object observe p . require publisher_exists : p /= Void do p . attach (Current) end 4
Another approach: event-context-action table Example scenario (reminder) Set of triples One of your classes has a routine [Event type, Context, Action] my_procedure Save file? Your application has a GUI object OK! Cancel Event type: any kind of event we track known as OK_button Example: left mouse click Whenever the user clicks the mouse the underlying GUI Context: object for which these events are interesting library returns the mouse coordinates Example: a particular button Action: what we want to do when an event occurs in the context You want to ensure that a mouse click at coordinates Example: save the file [ h , v ] calls my_procedure ( h , v ) Event-context-action table may be implemented as e.g. a hash table. Event-context-action table With .NET delegates: publisher (1) P1. Introduce new class ClickArgs inheriting from EventArgs, repeating arguments types of my_procedure: Event type Context Action public class ClickArgs {... int x, y; … } OK_button Save_file Left_ click Reset Cancel_button Left_ click P2. Introduce new type ClickDelegate (delegate type) based on … Left_ click … that class Right_ click Display_Menu public void delegate ClickDelegate (Object sender, e) … … … P3. Declare new type Click (event type) based on the type ClickDelegate: public event ClickDelegate Click Language mechanisms With .NET delegates: publisher (2) P4. Write new procedure OnClick to wrap handling: C and C++: function pointers protected void OnClick (ClickArgs ca) {if (Click != null) {Click (this, ca . x, ca . y);}} P5. To publish an event of the given type, create new object C#: delegates (instance of ClickArgs), passing arguments to constructor: ClickArgs myClickArgs = new ClickArgs (h, v); Eiffel: agents P6. To publish an event of the given type, trigger event: OnClick (myClickArgs) 5
Recommend
More recommend