Design Patterns and Frameworks for Object-oriented Communication Systems Douglas C. Schmidt http://www.cs.wustl.edu/schmidt/ [email protected] Washington University, St. Louis Motivation Developing ecient, robust, extensible, and reusable communication software is hard It is essential to understand successful techniques that have proven eective to solve common development challenges Design patterns and frameworks help to capture, articulate, and instantiate these successful techniques 2 1 Observations Developers of communication software confront recurring challenges that are largely application-independent { Design Patterns e.g., service initialization and distribution, error handling, ow control, event demultiplexing, concurrency control Successful developers resolve these challenges by applying appropriate design patterns Design patterns represent solutions to problems that arise when developing software within a particular context { Patterns capture the static and dynamic structure and collaboration among key participants in software designs { However, these patterns have traditionally been either: 1. Locked inside heads of expert developers 2. Buried in source code 3 i.e., \Patterns == problem/solution pairs in a context" They are particularly useful for articulating how and why to resolve non-functional forces Patterns facilitate reuse of successful software architectures and designs 4 Proxy Pattern Graphical Notation 1: METHOD : BROKER CALL 4: METHOD RETURN : QUOTER PROXY OBJECT PROCESS THREAD 2: FORWARD : CLASS REQUEST 3: RESPONSE CLIENT CLASS : QUOTER TEMPLATE CLASS CLASS UTILITY NETWORK CLASS CATEGORY SERVER INHERITS ABSTRACT CLASS CONTAINS A Intent: provide a surrogate for another object that controls access to it INSTANTIATES USES 6 5 Frameworks More Observations Patterns enable reuse of architecture and design knowledge, but not code (directly) A framework is: { Reuse of patterns alone is not sucient { \An integrated collection of components that collaborate to produce a reusable architecture for a family of related applications" Frameworks dier from conventional class libraries: 1. Frameworks are \semi-complete" applications To be productive, developers must also reuse detailed designs, algorithms, interfaces, implementations, etc. 2. Frameworks address a particular application domain 3. Frameworks provide \inversion of control" Application frameworks are an eective way to achieve broad reuse of software 7 Typically, applications are developed by inheriting from and instantiating framework components 8 Dierences Between Class Libraries and Frameworks Tutorial Outline NETWORKING APPLICATION SPECIFIC LOGIC MATH INVOKES ADTS USER INTERFACE EVENT LOOP APPLICATION SPECIFIC LOGIC ADTS Present the key reusable design patterns in a distributed medical imaging system { NETWORKING INVOKES Outline key challenges for developing communication software DATA BASE CLASS LIBRARIES MATH USER INTERFACE CALL BACKS EVENT LOOP Both single-threaded and multi-threaded solutions are presented Discuss lessons learned from using patterns on production software systems DATABASE OBJECT-ORIENTED FRAMEWORK 9 Stand-alone vs. Distributed Application Architectures 10 Concurrency vs. Parallelism SERVER maxfdp1 PRINTER read_fds CLIENT COMPUTER CD ROM WORK REQUEST FILE SYSTEM CLIENT (1) STAND-ALONE APPLICATION ARCHITECTURE WORK REQUEST WORK REQUEST CLIENT DISPLAY SERVICES FI LE SERVICE PRINT SERVICE CLIENT CONCURRENT SERVER CYCLE SERVICE WORK REQUEST SERVER CPU1 NETWORK CPU2 CPU3 CPU4 CLIENT WORK REQUEST PRINTER CD ROM FILE SYSTEM CLIENT WORK REQUEST (2) DISTRIBUTED APPLICATION ARCHITECTURE WORK REQUEST CLIENT WORK REQUEST CLIENT PARALLEL SERVER 11 12 Sources of Complexity Distributed application development exhibits both inherent and accidental complexity Sources of Complexity (cont'd) Inherent complexity results from fundamental challenges, e.g., { { Accidental complexity results from limitations with tools and techniques, e.g., { Distributed systems . Latency Low-level tools . e.g., Lack of type-secure, portable, re-entrant, and extensible system call interfaces and component libraries . Error handling { Inadequate debugging support . Service partitioning and load balancing { Widespread use of algorithmic decomposition Concurrent systems . Race conditions . Deadlock avoidance . Fair scheduling . Performance optimization and tuning . { Fine for explaining network programming concepts and algorithms but inadequate for developing large-scale distributed applications Continuous rediscovery and reinvention of core concepts and components 13 14 OO Contributions { { { { { Distributed Medical Imaging Example Concurrent and distributed programming has traditionally been performed using low-level OS mechanisms, e.g., fork/exec Shared memory Signals Sockets and select POSIX pthreads, Solaris threads, Win32 threads OO design patterns and frameworks elevate development to focus on application concerns, e.g., Service functionality and policies { Service conguration { Concurrent event demultiplexing and event handler dispatching { Service concurrency and synchronization { 15 This example illustrates the reusable design patterns and framework components used in an OO architecture for a distributed medical imaging system Application clients uses Blob Servers to store and retrieve medical images Clients and Servers communicate via a connectionoriented transport protocol { e.g., TCP/IP, IPX/SPX, TP4 16 Distributed Electronic Medical Imaging Architecture MODALITIES BLOB SERVER LOCAL STORE (CT, MR, CR) Architecture of the Blob Server svc_run svc_run svc_run svc_run ATM LAN DIAGNOSTIC STATIONS NAME SERVER ATM MAN ROUTING SERVICE : Blob Handler ATM LAN MODALITIES 17 Design Patterns in the Blob Server TACTICAL PATTERNS Reactor Proxy Strategy Proxy Service Configurator Adapter Singleton \Convert the interface of a class into another interface client expects" Singleton { 19 \Dene a family of algorithms, encapsulate each one, and make them interchangeable" Adapter { Double Checked Locking \Provide a surrogate or placeholder for another object to control access to it" Strategy { Connector STRATEGIC PATTERNS : Blob Acceptor Tactical Patterns { Acceptor Half-Sync/ Half-Async : Blob Handler * Manage short-term and long-term blob persistence * Respond to queries from Blob Locators 18 Thread-per Session Active Object Thread Pool : Reactor : Options LOCATION SERVICE SERVICE (CT, MR, CR) Thread-per Request : Blob Handler CLUSTER STORE TIME SERVER CENTRAL STORE : Msg : Blob Processor Queue \Ensure a class only has one instance and provide a global point of access to it" 20 Concurrency Patterns Reactor { Active Object { \Decouples synchronous I/O from asynchronous I/O in a system to simplify concurrent programming eort without degrading execution eciency" \Allows each client request to run concurrently" Thread-Pool { \Allows up to N requests to execute concurrently" Thread-per-Session { Double-Checked Locking Pattern { Thread-per-Request { \Decouples method execution from method invocation and simplies synchronized access to shared resources by concurrent threads" Half-Sync/Half-Async { Concurrency Architecture Patterns \Decouples event demultiplexing and event handler dispatching from application services performed in response to events" \Allows each client session to run concurrently" \Ensures atomic initialization of objects and eliminates unnecessary locking overhead on each access" 21 Service Initialization Patterns Connector { Concurrency Patterns in the Blob Server The following example illustrates the design patterns and framework components in an OO implementation of a concurrent Blob Server There are various architectural patterns for structuring concurrency in a Blob Server Acceptor { \Decouples active connection establishment from the service performed once the connection is established" 22 \Decouples passive connection establishment from the service performed once the connection is established" 2. Thread-per-request Service Congurator { 1. Reactive \Decouples the behavior of network services from point in time at which services are congured into an application" 23 3. Thread-per-session 4. Thread-pool 24 Reactive Blob Server Architecture 2: HANDLE INPUT 3: CREATE PROCESSOR 4: ACCEPT CONNECTION 5: ACTIVATE PROCESSOR BLOB SERVER : Blob Processor 6: PROCESS BLOB SERVER : Blob Processor : Blob Processor : Blob Processor : Blob Acceptor : Blob Processor : Reactor 6: PROCESS 1: CONNECT CLIENT 2: HANDLE INPUT 3: CREATE PROCESSOR 4: ACCEPT CONNECTION 5: SPAWN THREAD : Blob Acceptor : Reactor BLOB REQUEST CLIENT Thread-per-Request Blob Server Architecture BLOB REQUEST SERVER 1: CONNECT CLIENT CLIENT CLIENT SERVER CLIENT 25 Thread-per-Session Blob Server Architecture BLOB SERVER 3: SPAWN 2: CREATE, ACCEPT, AND ACTIVATE BLOB_PROCESSOR THREAD : Blob : Blob Processor Processor : Blob Processor : Blob Acceptor : Reactor 4: PROCESS 26 Thread-Pool Blob Server Architecture BLOB SERVER worker thread worker thread : Msg : Blob Queue Processor 5: DEQUEUE & PROCESS REQUEST worker thread worker thread 2: HANDLE INPUT 3: ENQUEUE REQUEST : Blob Handler : Blob Handler : Blob Handler : Blob Acceptor : Reactor BLOB REQUEST 1: BIND CLIENT CLIENT SERVER 6: PROCESS BLOB REQUEST 1: BLOB REQUEST SERVER CLIENT CLIENT CLIENT 27 CLIENT 28 The ADAPTIVE Communication Environment (ACE) The Reactor Pattern GATEWAY SERVER DISTRIBUTED SERVICES FRAMEWORKS AND CLASS ACCEPTOR CATEGORIES C++ WRAPPERS TOKEN SERVER THREAD MANAGER LOG MSG SPIPE SAP SOCK_SAP/ TLI_SAP STREAM PIPES SOCKETS/ TLI PROCESS/THREAD SUBSYSTEM UNIX AND { CORBA HANDLER SERVICE CONFIGURATOR REACTOR SHARED MALLOC SYSV MEM MAP WRAPPERS ADAPTATION LAYER NAMED PIPES Intent \Decouples event demultiplexing and event handler dispatching from the services performed in response to events" (ASX) SELECT/ POLL COMMUNICATION SUBSYSTEM GENERAL TIME SERVER FIFO SAP OS THREAD LIBRARY NAME SERVER SERVICE HANDLER CONNECTOR ADAPTIVE SERVICE EXECUTIVE SYNCH WRAPPERS C APIS LOGGING SERVER DYNAMIC LINKING MEMORY MAPPING SYSTEM V IPC This pattern resolves the following forces for event-driven software: { How to demultiplex multiple types of events from multiple sources of events eciently within a single thread of control { How to extend application behavior without requiring changes to the event dispatching framework VIRTUAL MEMORY SUBSYSTEM WIN32 SERVICES A set of C++ wrappers and frameworks based on common design patterns 29 Structure of the Reactor Pattern select (handles); foreach h in handles { if (h is output handler) table[h]->handle_output () ; if (h is input handler) table[h]->handle_input (); if (h is signal handler) table[h]->handle_signal (); } this->expire_timers (); Reactor n n 1 1 1 Timer_Queue schedule_timer(h) cancel_timer(h) expire_timer(h) Handles 1 n Participants in the Reactor pattern INITIALIZATION MODE AP P IN LICA DE PE TION ND EN T EVENT HANDLING MODE handle_input() handle_output() handle_signal() handle_timeout() get_handle() A 1 AP PL DE ICA T PE ND IONEN T Event_Handler 1 1 Collaboration in the Reactor Pattern Concrete Event_Handler n handle_events() register_handler(h) remove_handler(h) expire_timers() 30 main program INITIALIZE REGISTER HANDLER EXTRACT HANDLE START EVENT LOOP FOREACH EVENT DO DATA ARRIVES OK TO SEND SIGNAL ARRIVES TIMER EXPIRES REMOVE HANDLER CLEANUP 31 callback : reactor Concrete : Reactor Event_Handler Reactor() register_handler(callback) get_handle() handle_events() select() handle_input() handle_output() handle_signal() handle_timeout() remove_handler(callback) handle_close() 32 Using the Reactor in the Blob Server 4: getq(msg) 5:svc(msg) svc_run The Blob Handler is the Proxy for communicating with clients { svc_run svc_run : Blob Handler : Blob Handler : Message : Blob : Event : Blob Queue Handler Processor Handler : Event Handler : Event 2: recv_request(msg) Handler3: putq(msg) Together with Reactor, it implements the asynchronous task portion of the Half-Sync/Half-Async pattern // Reusable Svc Handler. class Blob_Handler : public Event_Handler { public: // Entry point into Blob Handler. virtual int open (void) { // Register with Reactor to handle client input. Reactor::instance ()->register_handler (this, READ_MASK); } 1: handle_input() : Handle Table protected: // Notified by Reactor when client requests arrive. virtual int handle_input (void); : Reactor OS EVENT DEMULTIPLEXING INTERFACE KERNEL LEVEL FRAMEWORK LEVEL APPLICATION LEVEL REGISTERED OBJECTS The Blob Handler Interface // Receive and frame client requests. int recv_request (Message_Block &*); SOCK_Stream peer_stream_; // IPC endpoint. }; 33 34 Structure of the Active Object Pattern The Active Object Pattern Intent { \Decouples method execution from method invocation and simplies synchronized access to shared resources by concurrent threads" This pattern resolves the following forces for concurrent communication software: { ResultHandle m1() ResultHandle m2() ResultHandle m3() VISIBLE TO CLIENTS How to allow blocking read and write operations on one endpoint that do not detract from the quality of service of other endpoints { How to simplify concurrent access to shared state { How to simplify composition of independent services 35 loop { m = actQueue.remove() dispatch (m) } Client Interface INVISIBLE TO CLIENTS Scheduler dispatch() m1'() m2'() m3'() 1 1 1 Resource Representation 1 Activation Queue insert() remove() 1 n Method Objects The Scheduler determines the sequence that Method Objects are executed 36 Using the Active Object Pattern in the Blob Server Collaboration in the Active Object Pattern m1() INVOKE CREATE METHOD OBJECT RETURN RESULT HANDLE cons(m1') future() INSERT IN PRIORITY QUEUE insert(m1') DEQUEUE NEXT METHOD OBJECT remove(m1') EXECUTE dispatch(m1') reply_to_future() KERNEL LEVEL RETURN RESULT APPLICATION LEVEL CONSTRUCTION : Client : Activation : Represent: Scheduler Interface Queue ation FRAMEWORK LEVEL METHOD OBJECT EXECUTION COMPLETION SCHEDULING/ client REGISTERED OBJECTS 4: getq(msg) 5:svc(msg) svc_run svc_run svc_run : Blob : Message : Blob : Blob Handler Queue Handler Processor : Blob : Event Handler : Event Handler 2: recv_request(msg) Handler : Event 3: putq(msg) Handler 1: handle_input() : Handle Table : Reactor OS EVENT DEMULTIPLEXING INTERFACE 37 38 The Blob Processor Class Processes Blob requests using the \ThreadPool" concurrency model { Implement the synchronous task portion of the Half-Sync/Half-Async pattern Using the Singleton Pattern The Blob Processor is implemented as a Singleton that is created \on demand" Blob_Processor * Blob_Processor::instance (void) { // Beware race conditions! if (instance_ == 0) { instance_ = new Blob_Processor; } return instance_; } class Blob_Processor : public Task { public: // Singleton access point. static Blob_Processor *instance (void); // Pass a request to the thread pool. virtual put (Message_Block *); // Event loop for the pool thread virtual int svc (int) { Message_Block *mb = 0; // Message buffer. // Wait for messages to arrive. for (;;) { getq (mb); // Inherited from class Task; // Identify and perform Blob Server // request processing here... protected: Blob_Processor (void); // Constructor. 39 Constructor creates the thread pool Blob_Processor::Blob_Processor (void) { Thread_Manager::instance ()->spawn_n (num_threads, THR_FUNC (svc_run), (void *) this, THR_NEW_LWP); } 40 The Double-Checked Locking Pattern Intent { Using the Double-Checked Locking Pattern for the Blob Server \Ensures atomic initialization of objects and eliminates unnecessary locking overhead on each access" if (instance_ == NULL) { mutex_.acquire (); if (instance_ == NULL) instance_ = new Blob_Processor; mutex_.release (); } return instance_; This pattern resolves the following forces: 1. Ensures atomic initialization or access to objects, regardless of thread scheduling order 2. Keeps locking overhead to a minimum { Blob Processor static instance() static instance_ e.g., only lock on rst access Mutex Note, this pattern assumes atomic memory access ::: 42 41 { \Decouples synchronous I/O from asynchronous I/O in a system to simplify programming eort without degrading execution eciency" This pattern resolves the following forces for concurrent communication systems: { How to simplify programming for higher-level communication tasks . { These are performed synchronously How to ensure ecient lower-level I/O communication tasks . These are performed asynchronously 43 SYNCHRONOUS TASK LAYER Intent QUEUEING LAYER ASYNCHRONOUS TASK LAYER Half-Sync/Half-Async Pattern Structure of the Half-Sync/Half-Async Pattern SYNC SYNC TASK 3 TASK 1 SYNC TASK 2 1, 4: read(data) MESSAGE QUEUES 3: enqueue(data) ASYNC TASK 2: interrupt EXTERNAL EVENT SOURCES 44 Using the Half-Sync/Half-Async Pattern in the Blob Server RECV MSG PROCESS MSG ENQUEUE MSG Message Queue Sync Task notification() read(msg) 4: getq(msg) 5:svc(msg) work() QUEUEING LEVEL EXTERNAL EVENT Async Task svc_run enqueue(msg) DEQUEUE MSG EXECUTE TASK read(msg) work() ASYNC TASK LEVEL SYNC QUEUEING ASYNC PHASE PHASE PHASE External Event Source SYNCH TASK LEVEL Collaborations in the Half-Sync/Half-Async Pattern This illustrates input processing (output processing is similar) svc_run svc_run : Blob Processor : Blob Handler : Message : Blob Queue Handler : Event : Blob Handler Handler 2: recv_request(msg) : Event 3: putq(msg) Handler : Event Handler 1: handle_input() : Reactor 46 45 Joining Async and Sync Tasks in the Blob Server The following methods form the boundary between the Async and Sync layers int Blob_Handler::handle_input (void) { Message_Block *mb = 0; } The Acceptor Pattern Intent { \Decouples passive initialization of a service from the tasks performed once the service is initialized" This pattern resolves the following forces for network servers using interfaces like sockets or TLI: // Receive and frame message // (uses peer_stream_). recv_request (mb); 1. How to reuse passive connection establishment code for each new service // Insert message into the Queue. Blob_Processor::instance ()->put (mb); 2. How to make the connection establishment code portable across platforms that may contain sockets but not TLI, or vice versa // Task entry point. Blob_Processor::put (Message_Block *msg) { // Insert the message on the Message_Queue // (inherited from class Task). putq (msg); } 47 3. How to ensure that a passive-mode descriptor is not accidentally used to read or write data 4. How to enable exible policies for creation, connection establishment, and concurrency 48 Collaboration in the Acceptor Pattern Svc Handler Svc Handler peer_stream_ open() Acceptor ES IVAT ACT peer_acceptor_ handle_input() Reactor handle_input() SERVICE SERVICE ENDPOINT PROCESSING INITIALIZATION INITIALIZATION PHASE PHASE PHASE Structure of the Acceptor Pattern peer_acceptor_ acc : sh: reactor : : SOCK Acceptor Svc_Handler Reactor Acceptor open() open() Server INITIALIZE PASSIVE ENDPOINT REGISTER HANDLER EXTRACT HANDLE START EVENT LOOP register_handler(acc) get_handle() handle_events() select() handle_input() FOREACH EVENT DO CONNECTION EVENT CREATE, ACCEPT, AND ACTIVATE OBJECT REGISTER HANDLER FOR CLIENT I/O sh = make_svc_handler() accept_svc_handler (sh) activate_svc_handler (sh) register_handler(sh) EXTRACT HANDLE DATA EVENT PROCESS MSG get_handle() handle_input() svc() CLIENT SHUTDOWN handle_close() SERVER SHUTDOWN handle_close() is a factory that creates, connects, and activates a Svc Handler Acceptor 49 Using the Acceptor Pattern in the Blob Server : Blob Acceptor : Blob Handler : Acceptor : Svc Handler 1: handle_input() 2: sh = make_svc_handler() 3: accept_svc_handler(sh) 4: activate_svc_handler(sh) PASSIVE LISTENER : Blob Handler : Svc Handler ACTIVE CONNECTIONS : Reactor : Blob Handler : Svc Handler : Blob Handler : Svc Handler 50 The Acceptor Class The Acceptor class implements the Acceptor pattern // Reusable Factor template <class SVC_HANDLER> class Acceptor : public Service_Object // Subclass of Event_Handler. { public: // Notified by Reactor when clients connect. virtual int handle_input (void) { // The strategy for initializing a SVC_HANDLER. SVC_HANDLER *sh = new SVC_HANDLER; peer_acceptor_.accept (*sh); sh->open (); } // ... protected: // IPC connection factory. SOCK_Acceptor peer_acceptor_; } 51 52 The Service Congurator Pattern The Blob Acceptor Class Interface Intent { The Blob Acceptor class accepts connections and initializes Blob Handlers class Blob_Acceptor : public Acceptor<Blob_Handler> // Inherits handle_input() strategy from Acceptor. { public: // Called when Blob_Acceptor is dynamically linked. virtual int init (int argc, char *argv); // Called when Blob_Acceptor is dynamically unlinked. virtual int fini (void); \Decouples the behavior of communication services from the point in time at which these services are congured into an application or system" This pattern resolves the following forces for highly exible communication software: { How to defer the selection of a particular type, or a particular implementation, of a service until very late in the design cycle . i.e., at installation-time or run-time { How to build complete applications by composing multiple independently developed services { How to optimize, recongure, and control the behavior of the service at run-time 54 53 APPLICATION LAYER Structure of the Service Congurator Pattern Collaboration in the Service Congurator Pattern Concrete Service Object main() suspend() resume() init() A fini() info() 1 1 1 n 1 Event Handler n FOREACH SVC ENTRY DO DYNAMICALLY LINK SERVICE INITIALIZE SERVICE REGISTER SERVICE EXTRACT HANDLE : Reactor : Service : Service Config Repository Service_Config() process_directives() link_service() init(argc, argv) register_handler(svc) get_handle() insert() STORE IN REPOSITORY START EVENT LOOP Service Repository 1 CONFIGURATION MODE Service Config Service Object EVENT HANDLING MODE REACTIVE LAYER CONFIGURATION LAYER CONFIGURE svc : Service_Object FOREACH EVENT DO INCOMING EVENT SHUTDOWN EVENT CLOSE SERVICE UNLINK SERVICE run_event_loop() handle_events() handle_input() handle_close() remove_handler(svc) fini() unlink_service() remove() Reactor 55 56 Using the Service Congurator Pattern in the Blob Server The Blob Acceptor Class Implementation // Initialize service when dynamically linked. SERVICE CONFIGURATOR RUNTIME : Service Repository : Service Config : Reactive Blob Server : TP Blob Server : Service Object : Reactor SHARED OBJECTS : Service Object int Blob_Acceptor::init (int argc, char *argv[]) { Options::instance ()->parse_args (argc, argv); // Set the endpoint into listener mode. Acceptor::open (local_addr); : TPR Blob Server : Service Object } // Initialize the communication endpoint. Reactor::instance ()->register_handler (this, READ_MASK) // Terminate service when dynamically unlinked. Existing service is based on Half-Sync/HalfAsync pattern Other versions could be single-threaded or use other concurrency strategies ::: int Blob_Acceptor::fini (void) { // Unblock threads in the pool so they will // shutdown correctly. Blob_Processor::instance ()->close (); } // Wait for all threads to exit. Thread_Manager::instance ()->wait (); 57 58 Conguring the Blob Server with the Service Congurator The concurrent Blob Server is congured and initialized via a conguration script % cat ./svc.conf dynamic TP_Blob_Server Service_Object * blob_server.dll:make_TP_Blob_Server() "-p $PORT -t $THREADS" Main Program for Blob Server Dynamically congure and execute the Blob Server { Note that this is totally generic! int main (int argc, char *argv[]) { Service_Config daemon; // Initialize the daemon and dynamically // configure the service. daemon.open (argc, argv); Factory function that dynamically allocates a Half-Sync/Half-Async Blob Server object // Loop forever, running services and handling // reconfigurations. extern "C" Service_Object *make_TP_Blob_Server (void); Service_Object *make_TP_Blob_Server (void) { return new Blob_Acceptor; // ACE dynamically unlinks and deallocates this object. } 59 daemon.run_event_loop (); } /* NOTREACHED */ 60 The Connector Pattern { Structure of the Connector Pattern Intent \Decouples active initialization of a service from the task performed once a service is initialized" Service Handler This pattern resolves the following forces for network clients that use interfaces like sockets or TLI: Service Handler Connector peer_stream_ open() n 1. How to reuse active connection establishment code for each new service ACTIVATES 1 connect(sh, addr) complete() HANDLE ASYNC CONNECTION COMPLETION 2. How to make the connection establishment code portable across platforms that may contain sockets but not TLI, or vice versa Reactor 3. How to enable exible service concurrency policies 4. How to actively establish connections with large number of peers eciently 62 61 Collaboration in the Connector Pattern connect_svc_handler(sh, addr) INITIATE CONNECTION SYNC CONNECT reactor : Reactor connect() activate_svc_handler(sh) ACTIVATE OBJECT open() INSERT IN REACTOR EXTRACT HANDLE START EVENT LOOP FOREACH EVENT DO DATA ARRIVES PROCESS DATA register_handler(sh) get_handle() handle_events() select() handle_input() svc() CONNECTION INITIATION PHASE FOREACH CONNECTION peer_stream_ con : sh: : SOCK Svc_Handler Connector Connector connect(sh, addr) SERVICE INITIALIZATION PHASE Client Client SERVICE PROCESSING PHASE SERVICE PROCESSING PHASE CONNECTION INITIATION/ INITIATION/ SEVICE INITIALIZATION PHASE Collaboration in the Connector Pattern FOREACH CONNECTION peer_stream_ con : sh: Connector : SOCK Svc_Handler Connector connect(sh, addr) connect_svc_handler(sh, addr) INITIATE CONNECTION ASYNC CONNECT connect() INSERT IN REACTOR select() handle_output() activate_svc_handler(sh) FOREACH EVENT DO CONNECTION COMPLETE ACTIVATE OBJECT EXTRACT HANDLE DATA ARRIVES PROCESS DATA register_handler(con) handle_events() START EVENT LOOP INSERT IN REACTOR reactor : Reactor open() register_handler(sh) get_handle() handle_input() svc() Synchronous mode 63 Asynchronous mode 64 Using the Connector in the Blob Clients : Blob Handler: Blob : Blob Handler Handler : Svc Handler: Svc : Svc Handler Handler PENDING CONNECTIONS : Blob Handler : Blob Handler : Svc Handler : Svc Handler A C TIVE CONNECTIONS : Blob Connector : Connector : Reactor : Blob Handler Benets of Design Patterns Design patterns enable large-scale reuse of software architectures Patterns explicitly capture expert knowledge and design tradeos Patterns help improve developer communication Patterns help ease the transition to objectoriented technology : Svc Handler : Blob Handler : Svc Handler 65 66 Suggestions for Using Patterns Eectively Drawbacks to Design Patterns Patterns do not lead to direct code reuse Patterns are deceptively simple Teams may suer from pattern overload Patterns are validated by experience and discussion rather than by automated testing Integrating patterns into a software development process is a human-intensive activity 67 Do not recast everything as a pattern { Instead, develop strategic domain patterns and reuse existing tactical patterns Institutionalize rewards for developing patterns Directly involve pattern authors with application developers and domain experts Clearly document when patterns apply and do not apply Manage expectations carefully 68 Books and Magazines on Patterns Books { Gamma et al., \Design Patterns: Elements of Reusable Object-Oriented Software" Addison-Wesley, Reading, MA, 1994. { \Pattern Languages of Program Design," editors James O. Coplien and Douglas C. Schmidt, AddisonWesley, Reading, MA, 1995 Special Issues in Journals { \Theory and Practice of Object Systems" (guest editor: Stephen P. Berczuk) { \Communications of the ACM" (guest editors: Douglas C. Schmidt, Ralph Johnson, and Mohamed Fayad) Magazines { C++ Report and Journal of Object-Oriented Programming, columns by Coplien, Vlissides, and De Souza 69 Obtaining ACE The ADAPTIVE Communication Environment (ACE) is an OO toolkit designed according to key network programming patterns All source code for ACE is freely available { Anonymously ftp to wuarchive.wustl.edu { Transfer the les /languages/c++/ACE/*.gz and gnu/ACE-documentation/*.gz Mailing lists * [email protected] * [email protected] * [email protected] * [email protected] WWW URL { http://www.cs.wustl.edu/~schmidt/ACE.html 71 Conferences and Workshops on Patterns 1st EuroPLoP { 3rd Pattern Languages of Programs Conference { July 10,14, 1996, Kloster Irsee, Germany September 4,6, 1996, Monticello, Illinois, USA Relevant WWW URLs http://www.cs.wustl.edu/~schmidt/jointPLoP,96.html/ http://st-www.cs.uiuc.edu/users/patterns/patterns.html 70
© Copyright 2024