Software Engineering - Lecture 15: Design Patterns 1 - Anh Dao Nam

Software Design Patterns – What & Why Example Pattern: Publisher-Subscriber (a.k.a. Observer) What Developers Do With Software (besides development) Understand Maintain (fix bugs) Upgrade (add new features)

pdf29 trang | Chia sẻ: candy98 | Lượt xem: 462 | Lượt tải: 0download
Bạn đang xem trước 20 trang tài liệu Software Engineering - Lecture 15: Design Patterns 1 - Anh Dao Nam, để xem tài liệu hoàn chỉnh bạn click vào nút DOWNLOAD ở trên
SOFTWARE ENGINEERING Lecture 15 Design Patterns 1 MBA Course Notes Dr. ANH DAO NAM 1 Software Engineering Slides are from Ivan Marsic and Thomas E. Potok, modified by Anh Dao Nam Textbooks:  Bruegge & Dutoit: Object-Oriented Software Engineering: Using UML, Patterns and Java, Third Edition, Prentice Hall, 2010.  Miles & Hamilton: Learning UML 2.0, O’Reilly Media, 2006. Some interesting books for the advanced material include:  R. Pressman, Software Engineering - A Practitioner's Approach, 6th ed., 2005  C. Ghezzi, M. Jazayeri, and D. Mandriolo, Fundamentals of Software Engineering. Prentice Hall, second ed., 2002  A. Endres and D. Rombach, A Handbook of Software and Systems Engineering. The Fraunhofer IESE Series on Software Engineering, Pearson Education Ltd., 2003.  S. Robertson and J. C. Robertson, Mastering the Requirements Process. Addison-Wesley Professional, second ed., 2006.  I. Jacobson, G. Booch, and J. Rumbaugh, The Unified Software Development Process. Addison-Wesley Professional, 1999.  K. Beck and C. Andres, Extreme Programming Explained. Addison-Wesley, 2004. 2 Topics Software Design Patterns – What & Why Example Pattern: Publisher-Subscriber (a.k.a. Observer) 3 What Developers Do With Software (besides development) Understand Maintain (fix bugs) Upgrade (add new features) 4 The Power of Patterns 5 CN NIB MAP PLE The Power of Patterns 6 The Power of Patterns 7 CNN IBM APPLE The Power of Patterns 8 The Power of Patterns 9 CN NIB MAP PLE CNN IBM APPLE Software Design Patterns Design Patterns help anticipate change Change is bad when there are unrelated reasons to change a software module/class  Unrelated reasons are usually because of unrelated responsibilities Another target is complex conditional logic (If-Then-Else statements, etc.) 10 What May Change & How What changes in real world are business rules  customer requests changes in software Changes in the small—changes in object responsibilities towards other objects  Number of responsibilities  Data type, or method signature  Business rules  Conditions for provision/fulfillment of responsibilities Sometimes change is regular (follows simple rules), such as new object state defined, or another object needs to be notified about something 11 Object Responsibilities (toward other objects) Knowing something (memorization of data or object attributes) Doing something on its own (computation programmed in a “method”)  Business rules for implementing business policies and procedures Calling methods of other objects (communication by sending messages)  Calling constructor methods; this is special because the caller must know the appropriate parameters for initialization of the new object. 12 Patterns for Tackling Responsibilities Delegating “knowing” and associated “doing” responsibilities (State) Delegating “calling” responsibilities (Command, Publisher-Subscriber) Delegating non-essential “doing” responsibilities (when “doing” responsibility incrementally modified) (Decorator) 13 Key Issues When a pattern is needed/applicable? How to measure if a pattern-based solution is better? When to avoid patterns because may make things worse?  All of the above should be answered in terms of object responsibilities before/after a pattern is applied 14 Publisher-Subscriber Pattern A.k.a. “Observer” Disassociates unrelated responsibilities Helps simplify/remove complex conditional logic and allow seamless future adding of new cases Based on “Indirect Communication” 15 ? T F Request- vs. Event-Based Comm. 16 Client Server Request: doSomething( info ) Request: getInfo() Info Src Doerinfo (1) Request: subscribe() Info Src Doer (2) event( info ) (a) (b) (c) Direct Communication Indirect Comm. “Before” == A Scenario Suitable for Applying the Pub-Sub Pattern 17 Event Detector detectEvent() Doer1.tellMeWhatToDo() Doer2.tellMeWhatToDo() DoerType1 tellMeWhatToDo() DoerType2 tellMeWhatToDo() Responsibilities Doing: • Detect events Calling: • Tell Doer-1 what to do • Tell Doer-2 what to do unrelated! ⇒ unrelated reasons to change the Event Detector: •When event detection needs to change or extend •When new doer types need to be told what to do “After” == Responsibilities After Applying the Pub-Sub Pattern 18 Publisher detectEvent() subscriber.receive(Event) Subscriber receiveEvent() subscribers : List Unrelated responsibilities of the Event Detector (now Publisher) are dissociated: •When event detection needs to change or extend → change Publisher •When new doer types need to be added → add an new Subscriber type (Subscribers need not be told what to do – they know what to do when a given event occurs! Publisher-Subscriber Pattern Focused on classifying events  The focus in on the “Publisher” object and the “environment” that it is observing  Example key events in safe home access:  Entered key is valid  Entered key is invalid Instead of making decisions & issuing orders to Doers/Subscribers  Focusing on other objects’ work: deciding when it is appropriate to call each one 19 Publisher-Subscriber Pattern Controller (receives key-code) Key Checker (checks validity, i.e., classifies: valid/invalid)  Publishes the classification result to “subscribers” Lock Control Light Control Alarm Control  Do the work based on the event classification outcome 20 PUBLISHER SUBSCRIBERS ( Assumed: subscription step first ) Pub-Sub Pattern 21 (a) (b) Publisher Knowing Responsibilities: • Knows event source(s) • Knows interested obj’s (subscribers) Doing Responsibilities: • Registers/Unregisters subscribers • Notifies the subscribers of events Subscriber Knowing Responsibilities: • Knows event types of interest • Knows publisher(s) Doing Responsibilities: • Registers/Unregisters with publishers • Processes received event notifications Type1Subscriber + receive() «interface» Subscriber + receive() «interface» Publisher + subscribe() + unsubscribe() Type1Publisher + subscribe() + unsubscribe() Type2Publisher + subscribe() + unsubscribe() subscribers * Unlock Use Case 22 From Chapter 2 «destroy» opt k := create() sk := getNext() logTransaction(k, val) activate(“lock”) : Controller : Checker : KeyStorage : DeviceCtrl : Logger: PhotoObsrv dl := isDaylight() alt [else] enterKey() k : Key val := checkKey(k) loop activate(“bulb”) val == true dl == false compare() [for all stored keys] numOfAttempts++ alt numOfAttempts == maxNumOfAttempts activate(“alarm”) denyMoreAttempts() [else] prompt: "try again" Refactoring to Publisher-Subscriber 23 1. Subscribe for appropriate events Pub Sub-1 Sub-n Pub Sub-1 2. When event occurs: (a) Classify: keyIsValid / keyIsInvalid (b) Notify only the subscribers for the detected event class Sub-n If a new device is added -- just write a new class; NO modification of the Publisher! No need to consider the “appropriateness” of calling the “servers” SubscriberEvent type keyIsValid keyIsInvalid itIsDarkInside . . . LockCtrl, LightCtrl AlarmCtrl LightCtrl Conditional logic is decided here, at design time, instead of run time Design-time decisions are better than runtime decisions, because they can be easier checked if they “work” (before the product is developed) Pub-Sub: Unlock Use Case 24 soundAlarm() opt opt k := create() sk := getNext() : Controller : Checker : KeyStorage : LockCtrl : Logger: PhotoSObs dl := isDaylight() alt [else] enterKey() k : Key checkKey(k) loop : LightCtrl : AlarmCtrl setLit(true) valid == true compare() dl == false keyIsValid()loop keyIsValid() loop keyIsInvalid() keyIsInvalid() keyIsValid() for all KeyIsValid subscribers for all KeyIsInvalid subscribers keyIsInvalid()prompt: "try again" numOfAttempts++ numOfAttempts == maxNumOfAttempts From Hub-and-Spokes (Star) to Token Passing (Cascading) Architecture 25 create() getNext() : Checker : KeyStorage : LockCtrl : Logger : PhotoSObs : Key checkKey() : LightCtrl : AlarmCtrl : Controller logTransaction() setOpen() isDaylight() setLit()soundAlarm() (a) create() getNext(): Checker : KeyStorage : LockCtrl : Logger : PhotoSObs : Key checkKey() : LightCtrl : AlarmCtrl : Controller keyIsValid() isDaylight() keyIsInvalid() (b) Pub-Sub reduced the class coupling: Before: After: Design Patterns: Delegation 26 Client asks for service Custodian initializes the pattern Instantiation of the Design Pattern collection of objects working to provide service Alternative names for Custodian are Assembler or Initializer Pub-Sub: Initialization 27 : Controller : Checker : LockCtrl : Logger: LightCtrl : AlarmCtrl subscribeKeyIsValid() subscribeKeyIsValid() subscribeKeyIsInvalid() subscribeKeyIsValid() subscribeKeyIsInvalid() create() subscribeKeyIsInvalid() A method call that passes a reference to the Checker Practical Issues 1. Do not design for patterns first  Reaching any kind of solution is the priority; solution optimization should be secondary 2. Refactor the solution to patterns  E.g., to reduce the complexity of the program’s conditional logic Uncritical use of patterns may yield worse solutions! 28 Q&A 29