Experience Using to Develop Reuseable Object-Oriented Communication Software

Douglas C. Schmidt [email protected]

http://www.cs.wustl.edu/schmidt/ Department of Computer Science Washington University, St. Louis 63130 (TEL) 314-935-7538, (FAX) 314-935-7302

This article will appear in the Communications of the ACM arise when building software in domains like business data Special Issue on Object-Oriented Experiences, Vol. 38, No. processing, telecommunications, graphical user interfaces, 10, October, 1995. Section 2 illustrates an example pattern databases, and distributed communication software. Patterns description that is a synopsis of material from [1]. Section 3 aid the development of reusable components and frameworks is new material that summarizes the lessons learned while by expressing the structure and collaboration of participants applying a design pattern-based reuse strategy on production in a software architecture at a level higher than (1) source large-scale distributed systems being developed on several code or (2) object-oriented design models that focus on in- commercial systems. dividual objects and classes. Thus, patterns facilitate reuse of software architecture, even when other forms of reuse are infeasible (e.g., due to fundamental differences in operating Abstract system features [3]). Design patterns help to enhance software qualityby address- This article describes how design patterns are being ap- ing fundamental challenges in large-scale system develop- plied on a number of large-scale commercial distributed sys- ment. These challenges include communication of archi- tems. Patterns have been used on these projects to enable tectural knowledge among developers, accommodating new widespread reuse of communication software architectures, design paradigms or architectural styles, and avoiding de- developer expertise, and object-oriented framework compo- velopment traps and pitfalls that are usually learned only nents. These systems include the system control segment by experience. This article describes lessons learned from for the Motorola Iridium global personal communications applying a design pattern-based reuse strategy to develop system [4]; a family of network monitoring applications for object-oriented communication software frameworks for sev- Ericsson telecommunication switches [3]; and a system for eral production distributed systems. Design patterns are in transporting multi-megabyte medical images over high-speed danger of becoming yet another buzzword. This article at- ATM networks [5] being developed at BJC health system and tempts to replacethehypewith insights and recommendations Washington University School of Medicine (BJC/WUSM). gained from several years of experience. This article also presents ways to avoid common traps and pitfalls of applying design patterns in large-scale software development processes. 1 Introduction The remainder of this article is organized as follows: Sec- tion 2 illustrates a design pattern that appears frequently in Despite dramatic increases in network and host performance event-driven communication software frameworks; Section 3 it remains dif®cult to design, implement, and reuse commu- summarizes our experiences (both positive and negative) ap- nication software for complex distributed systems. Exam- plying a design pattern-based reuse strategy in several large- ples of these systems include global personal communication scale commercial distributed systems; and Section 4 outlines systems, network management platforms, enterprise medical pattern-related topics that will be the focus of considerable imaging systems, and real-time market data monitoring and research activities in the next few years. analysis systems. In addition, it is often hard to directly reuse existing algorithms, detailed designs, interfaces, or im- plementations in these systems due to the growing hetero- 2 Example Design Pattern: the Reactor geneity of hardware/software architectures and diversity of operating system platforms. This section describes the . This pattern was Design patterns [2] are a promising technique for achiev- identi®ed while developing reusable event-driven commu- ing widespread reuse of software architectures. Design pat- nication software at Ericsson, Motorola, and BJC/WUSM. terns capture the static and dynamic structures and collabora- Portions of the material below was culled from documenta- tions of components in successful solutions to problems that tion used on these projects.

1 Design patterns have been described using several formats  threading may not be available on an OS platform. [2, 6, 7]. The format used below is based on the work of Often, a more convenient and portable way to develop Gamma et al. [2]; it contains the following parts: event-driven servers is to use the Reactor pattern.TheRe- actor pattern manages a single-threaded event loop that per-

 The intent of the pattern forms event demultiplexing and event handler dispatching in

 The design forces that motivate the pattern response to events from multiple sources. The Reactor pat- tern combines the simplicity and ef®ciency of single-threaded

 The solution to these forces event loops with the extensibility offered by object-oriented

 The structure and roles of classes in the solution programming.

 The responsibilities and collaborations among classes

 The positive and negative consequences of using the 2.3 Applicability pattern Use the Reactor pattern when:

 Implementation guidance

 one or more events may arrive concurrently from mul- 1  Example source code tiple sources, and blocking or continuously polling for

 References to related patterns events on any individual source of events is inef®cient;

 each individual event handler possesses the following 2.1 Intent characteristics: The Reactor pattern dispatches handlers automatically when ± it exchanges ®xed-sized or bounded-sized mes- events occur from multiple sources. This pattern simpli®es sages with its peers without requiring blocking event-driven applications by decoupling event demultiplex- I/O; ing and event handler dispatching from application services ± it processes each message it receives within a rel- performed in response to events. atively short period of time;

 using multi-threading to implement event demultiplex- 2.2 Motivation ing is either: Communication software must respond to events generated ± infeasible ± due to lack of multi-threading support from multiple sources. For example, network management on an OS platform; applications for monitoring and controlling space vehicles in ± undesirable ± due to poor performance on uni- the Motorola Iridium satellite constellation receive traps sent processors or due to the need for overly complex by HP OpenView agents, telemetry data sent via CORBA re- concurrency control schemes; quests, and user interface events generated by Motif. These ± redundant ± due to the use of multi-threading at events arrive on multiple I/O handles that identify resources higher levels of an application's architecture. (such as network connections) managed by an operating sys- tem. Input events from peers may arrive simultaneously on multiple handles. Therefore, single-threaded software must 2.4 Structure not block inde®nitely reading from any individual I/O han- The structure of the Reactor pattern is illustrated in the fol- dle. Blocking can signi®cantly delay the response time for lowing Booch [8] class diagram: handling events from peers associated with other handles. One way to develop this type of event-driven software is to use multi-threading. In this approach, a separate thread select (handles) Concrete foreach h in handles loop is spawned for every connected peer. Each thread blocks APPLICATION Event h->handle_event (event_type) APPLICATION on a read system call. A thread unblocks when it receives end loop Handler - an event from its associated peer. At this point, the event SPECIFIC - is processed within the thread. The thread then re-blocks INDEPENDENT awaiting subsequent input from read. Reactor There are several drawbacks to using multi-threading for dispatch() 1 handling events in communication software: register_handler(h, type) n remove_handler(h, type)  threading may require complex concurrency control Event Handler schemes; 1 handle_event(type) get_handle()  threading may lead to poor performance due to context Handles switching, synchronization, and data movement; n A 1Due to space limitations the sample code has been omitted from this article. See [1] for a complete example of the Reactor pattern.

2 In Booch notation dashed clouds indicate classes, an in- Event Handlers and waits for events to occur on scribed ªAºindicates an abstract class, directed edges indicate the Handles. inheritance relationships between classes, and an undirected  The Reactor triggers Event Handler methods in edge with a small bullet at one end indicates a composition response to events on the Handlers it monitors. When relation between two classes. events occur, the Reactor uses the Handles acti- vated by the events as keys to locate and dispatch the 2.5 Participants appropriate Event Handler methods. This collabo- ration is structured using the method callbacks depicted The participants in the Reactor pattern include the following: in the following object interaction diagram:

 Handles callback : main Concrete reactor : ± Handles identify resources (such as network con- program Event_Handler Reactor : Handles nections, open ®les, and synchronization objects) Reactor() INITIALIZE that are managed by an operating system. register_handler(callback) REGISTER HANDLER get_handle() EXTRACT HANDLE

 Reactor dispatch() RUN EVENT LOOP select() ± De®nes an interface for registering, removing, WAIT FOR EVENTS and dispatching Event Handler objects. An handle_event(event_type) DISPATCH HANDLER(S) implementation of the Reactor interface pro- vides a set of application-independent event de- multiplexing and dispatching mechanisms. These The handle event method is called by the Reactor mechanisms dispatch application-speci®c Event to perform application-speci®c functionalityin response Handlers in response to events occuring on one to an event. The type of the event that occurred is passed or more Handles. as a parameter to the method.

 Event Handler 2.7 Consequences ± Speci®es an interface used by the Reactor to dispatch callback methods de®ned by objects that The Reactor pattern has the following bene®ts:

are pre-registered to handle certain types of events  It improves themodularity,reusability,and con®gurabil- (such as input events, output events, and signals). ity of event-driven application software by decoupling application-independent mechanisms from application-

 Concrete Event Handler speci®c processing policies.

± Implements the customized callback method(s)  It improves application portability by allowing its inter- that process events in an application-speci®c man- face to be reused independently of the underlying OS ner. system calls that perform event demultiplexing.

 It provides applications with coarse-grained concur- 2.6 Collaborations among Participants rency control that serializes the invocation of Event Handlers and minimizes the need for more compli-  Sources of events (such as network adaptors, ®le sys- cated synchronization or locking within an application tems, and transaction managers) communicate with the process. Reactor via Handles. The Reactor pattern has the following drawbacks:

 Developers subclass Event Handlers to imple-

ment application-speci®c event processing. When an  Event Handlers are not preempted while they are execut- Event Handler subclassobject isregistered with the ing. Therefore, a handler should not perform blocking Reactor the application indicates the type of event(s) I/O on a Handle since this will signi®cantly decrease (e.g., input event, output event, signal event, etc.) this the responsiveness to clients connected to other I/O han- Event Handler wants the Reactor to notify it dles. Therefore, for long-duration operations (such as about. transferring a multi-megabyte medical image) the Ac- tive Object pattern [9] (which uses multi-threading or

 To bind the Reactor with Handles, a subclass of multi-processing) may be more effective. Event Handler must override the get handle

method. Hence, when an Event Handler sub-  Applications written using the Reactor pattern can be class object is registered with the Reactor the ob- hard to debug because their ¯ow of control oscillates ject's Handle is obtained by invoking the Event between the lower-level demultiplexing code (supplied Handler::get handle method. The Reactor by the framework) and the higher-level method call- then combines this Handle with other registered backs (supplied by application developers).

3 2.8 Implementation  Synchronization ±TheReactor can serve as a central event dispatcher in multi-threaded applications. In this The Reactor pattern can be implemented in many ways. This case, critical sections within the Reactor must be se- section discusses several topics related to implementing the rialized to prevent race conditions when modifying or Reactor pattern. activating shared variables (such as the table holding the Event Handler subclass objects). A common

 Event demultiplexing ±AReactor maintains a table technique for preventing race conditions uses mutual of objects that are derived from the Event Handler exclusion mechanisms like semaphores or mutex vari- base class. Public methods in the Reactor's interface ables. register and remove these objects from this table at run- To prevent deadlock, mutual exclusion mechanisms time. The Reactor also provides a means to dispatch should use recursive locks. Recursive locks are an ef- the handle event method on an Event Handler ®cient means to prevent deadlock when locks are held object in response to events the application has regis- by the same thread across Event Handler method tered to receive. callbacks within the Reactor. A recursive may The Reactor's dispatch method blocks on an OS be re-acquired by the thread that owns the lock without event demultiplexing system call (such as Windows NT blocking the thread. This property is important since WaitForMultipleObjects or UNIX select) the Reactor's dispatch method performs callbacks until one or more events occur. When events occur, the on application-speci®c Event Handler objects. Ap- Reactor returns from the event demultiplexing system plication callback code may subsequently re-enter the call. It then dispatches the handle event method on Reactor object using its register handler and any Event Handler object(s) that are registered to remove handler methods. handle these events. This callback method executes

 I/O semantics ± The I/O semantics of the underlying user-de®ned code and returns control to the Reactor OS signi®cantly affect the implementation of the Re- when it completes. actor pattern. The standard I/O mechanisms on UNIX

 Registering objects vs. functions ± The Reactor pat- systems provide ªreactiveº semantics. For example, tern shown in Section 2.4 registers Event Handler the UNIX select system call indicates the subset of subclass objects with a Reactor. The use of objects I/O handles that may be read from or written to syn- makes it convenient to subclass Event Handlers in chronously without blocking. order to ¯exibly reuse and extend existing components, Implementing the Reactor pattern using reactive I/O is as well as to integrate data and methods together. An- straightforward. In UNIX, select indicates which other approach is to register a function rather than an handle(s) are ready to perform I/O. The Reactor ob- object. The use of functions makes it convenient to reg- ject then ªreactsº by invoking the Event Handler ister callbacks without having to de®ne a new class that handle event callback method for each ready han- inherits from Event Handler. A hybrid approach dle. This method performs the I/O operation and the can be used to support both objects and functions simul- associated application-speci®c processing. taneously. In contrast, Windows NT provides ªproactiveº I/O

 Event handling interface ±ThediagraminSection2.4 semantics. Proactive I/O operations proceed asyn- illustrates an implementation of the Event Handler chronously and do not cause the caller to block. base class interface that contains a single method An application may subsequently use the WIN32 (handle event)usedbytheReactor to dispatch WaitForMultipleObjects system call to deter- events. In this case, the type of the event (e.g., input mine when its outstanding asynchronous I/O operations event, output event, signal event, etc.) is passed as a have completed. parameter to the method. This approach makes it pos- sible to add new types of events without changing the Variations in the I/O semantics of different operating interface. However, this approach encourages the use systems may cause the class interfaces and class imple- of switch statements in the subclass's handle event mentations of the Reactor pattern to vary across plat- method, which limits extensibility. forms. Schmidt and Stephenson [3] provide a detailed evaluation of how differences between proactive and re- Another way to implement the Event Handler in- active event demultiplexing affect implementations of terface is to de®ne separate virtual methods for each type the Reactor pattern on UNIX and Windows NT. of event (e.g., handle input, handle output, handle signal, etc.). This approach is easier to extend since subclassing does not involve switch state- 2.9 Known Uses ments. However, it requires the framework developer to anticipate the set of Event Handler methods in The Reactor pattern has been used in many object-oriented advance. frameworks and event-driven applications:

4  The X windows toolkit uses a version of the Reactor projects have identi®ed, documented, and applied dozens of pattern to structure its main event loop. This implemen- new or existing design patterns. Patterns were used to lever- tation registers and dispatches function calls, rather than age prior development expertise, as well as to reduce risk by objects. reusing software architectures across diverse OS platforms and subsystems.

 The InterViews window system distribution [10] im- plements the Reactor pattern in its Dispatcher class The Motorola Iridium and Ericsson projects were among category. The Dispatcher is used to de®ne an appli- the ®rst large-scale distributed system projects to adopt a cation's main event loop and to manage connections to software reuse strategy based on the concepts, notations, and one or more physical GUI displays. techniques of design patterns. Patterns identi®ed and applied in these projects have been described in [3, 4, 1, 9, 11, 12].

 The ADAPTIVE Service eXecutive (ASX) framework These projects have clari®ed many of the bene®ts and draw- [1] uses the Reactor pattern as the central event de- backs of using design patterns to systematically capture and multiplexer/dispatcher in an object-oriented toolkit for articulate communication software architectures. experimenting with high-performance parallel commu- This section discusses the lessons learned and outlines nication protocol stacks. workarounds for problems we encountered using design

 The Reactor pattern has been used in a number of com- pattern-based reuse strategies in production software envi- mercial products. These products include the Bellcore ronments. Our experiences using patterns on the Ericsson, and Siemens Q.port ATM signaling software product, Motorola, and BJC/WUSM projects were quite similar. Rec- the Ericsson EOS family of telecommunication switch ognizing these common themes across different projects in- management applications [3], the network management creased our con®dence that these experiences generalize to portion of the Motorola Iridium global personal com- using patterns on other large-scale software systems. munications system [4], and in an enterprise medical

 Patterns enable widespread reuse of of software ar- image delivery system for BJC/WUSM [5]. chitecture even if reuse of algorithms, implementations, interfaces, or detailed designs is not feasible. The constraints 2.10 Related Patterns of the underlying OS and hardware platform signi®cantly affect design and implementation decisions. This is partic- The Reactor pattern may be viewed as a variation on the ularly problematic for communication software, where non- [2]. In the Observer pattern, subscribers are portable OS features are often used to enhance performance updated automatically when a single subject changes. In the and functionality. Reactor pattern, handlers are informed automatically when The Ericsson telecommunication switch management events from multiple sources occur. project [3] illustrated the importance of patterns-based archi- A Reactor provides a Facade [2] for event demultiplex- tectural reuse. This project underwent several major changes ing. A Facade is an interface that shields applications from over three years. The original prototype was developed on complex object relationships within a subsystem. UNIX using sockets, select, and TCP/IP as the commu- The virtual methods provided by the Event Handler nication mechanisms. After six months, however, the OS base class are Template Methods [2]. These template meth- platform changed to Windows NT with WIN32 named pipes, ods are used by the Reactor to trigger callbacks to the NETBEUI, WaitForMultipleObjects,andTCP/IPas appropriate application-speci®c processing functions in re- the communication mechanisms. A year later, the scope of sponse to events. the project changed again to integrate with a much larger The pattern [9] decouples method execution switch management subsystem. All these changes involved from method invocation in order to simplify synchronized extensive porting and modi®cation of existing communica- access to a shared resource by methods invoked in different tion software. threads of control. This pattern is often used in place of In such a volatile environment, reusing design patterns (or in conjunction with) the Reactor pattern when Event was often the only viable means of leveraging previous de- Handlers perform long-duration activities. Likewise, the velopment expertise. For example, fundamental differences Reactor pattern can be used in place of (or in conjunction in the I/O mechanisms available on Windows NT and UNIX with) the Active Object pattern when threads are not available precluded the direct reuse of Reactor pattern implementa- or when the overhead and complexity of managing large tions across those OS platforms. We were, however, able numbers of threads is undesirable. to reuse the Reactor pattern itself, customizing portions of it to conform with the characteristics of the OS platforms. This reduced project risk signi®cantly and simpli®ed our re- 3 Lessons Learned development effort.

This section describes lessons learned from developing  Pattern descriptions should contain concrete examples. object-oriented communication frameworks based on de- Because patterns abstract the properties of successful designs sign patterns at Motorola Iridium [4, 11], Ericsson [3], they are not limited to a single implementation. As described and BJC/WUSM [5]. These large-scale distributed system above, this makes it possible to evolve and adapt patterns to

5 changes in environments and requirements. Although pat- We addressed this problem by publishingmore descriptive terns are inherently abstractions, however, patterns should aliases along with our patterns. For example, the Reactor not be described too abstractly. We found that many devel- pattern's alias was ªdispatch handlers automatically when opers had a hard time understanding precisely how to imple- events occur from multiple sources.º Ensuring names and ment patterns when they were described using only object aliases are used consistently throughout a project reduces diagrams and structured prose. the likelyhood that developers will waste time debating the To overcome this problem, we provided source code ex- consequences, structure, etc. of a pattern, only to realize they amples with our pattern descriptions that gave concrete guid- were actually talking about different patterns, or different ance for implementing the patterns. Whenever possible, we variations of the same pattern. presented multiple implementations of each pattern to help developers overcome the ªtunnel visionº that resulted from a  Patterns explicitly capture knowledge that experienced limited pattern vocabulary. Many examples used in our pat- developers already understand implicitly. Therefore, af- tern descriptions came directly from communication frame- ter being introduced to design patterns, most developers works we built for the projects. This helped developers grasp adopted pattern nomenclature and concepts eagerly. This the key points of each pattern because they already under- enthusiasm stemmed in part from the fact that pattern de- stood the forces and requirements that motivated the pattern. scriptions explicitly codi®ed knowledge they understood in- In addition, this approach helped convince management to tuitively. For example, many developers intuitively under- support the use of patterns because it reinforced our claim stand the forces that cause certain solutions to be preferred that design patterns had direct relevance to their projects. over alternatives. However, these non-functional forces are often not captured adequately with existing design methods

 Patterns improve communication within and across and notations. We found that the use of patterns helped software development teams because they provide devel- experts document, discuss, and reason systematically about opers with shared vocabulary and concepts. Patterns capture sophisticated architectural concepts. essential properties of software architecture, while suppress- In addition, explicitly capturing expertise through patterns ing details that are not relevant at a given level of abstraction. helps to impart this knowledge to less experienced develop- Thus, they provide a comprehensible way of documenting ers. For example, the Reactor pattern reused across OS plat- complex software architectures by expressing the structure forms in the Ericsson project represented knowledge gained and collaboration of participants at a level higher than (1) over years of experience with event-driven communication source code or (2) object-oriented design models that focus software on many projects at different companies. By care- on individual objects and classes. fully documenting key patterns in our domain, we were able We found that patterns helped to elevate the level of dis- to preserve and share this expertise. This saved developers course among team members. For example, once developers a great deal of time that would have otherwise been spent understood patterns like Factory Method [2] and the Reactor rediscovering these patterns in new contexts. they could convey and justify their design and implemen- tation decisions swiftly and clearly to other team members.  Patterns may lead developers to think they know more In addition, patterns helped to bridge the communication about the solution to a problem than they actually do. gap that existed between software developers, managers, and One downside to the intuitive nature of patterns is that de- non-technical team members in marketing and sales. Man- velopers may not fully appreciate the challenges associated agers and non-technical team members often could not un- with implementing a pattern. Simply knowing the structure derstand the system at the level of detailed object models and participants in a pattern (such as the Reactor pattern) is or source code. However, they frequently could understand only the ®rst step. As described in [3], a signi®cant develop- and evaluate the consequences and tradeoffs among software ment effort and commitment of time and resources may be architecture concepts that were expressed as patterns. Their necessary to implement a pattern correctly, ef®ciently, and feedback was valuable to ensure that our technical solutions portably in a particular context. We addressed this problem did not drift away from the overall system requirements. by continually emphasizing to developers that learning pat- terns complements, but does not substitute for, solid design  Pattern names should be chosen carefully and used and implementation skills. consistently. For patterns to achieve widespread use on

a project, developers must share an unambiguous vocabulary  Resist the temptation to recast everything as a pattern. of common patterns. Selecting appropriate pattern names is Another downside to the intuitive nature of patterns is that it hard due to the tension between parsimony and descriptive- may lead to pattern overload. We noticed that the bene®ts of ness. Concise names like Reactor or Iterator are appealing patterns became diluted if too many aspects of a project were because they convey the essence of a pattern with minimal expressed as patterns. This problem arose when development verbal effort. This brevity is conducive to rapid-®re design practices were relabled as patterns without signi®cantly im- brainstorming sessions. However, these verbal shorthands proving them. For example, some developers spent a great can be confusing unless developers have internalized the un- deal of time recasting relatively mundane concepts (such as derlying concepts and can associate them immediately with binary search, building a linked list, or recursion) using the the appropriate patterns. pattern form. Although this was intellectually satisfying,

6 pattern overload became counter productive when it did not ing the experiential basis of useful patterns, we were able markedly improve software quality. to leverage valuable developer expertise from earlier design paradigms [14].

 Focus on developing patterns that are strategic to the

domain and reuse existing tactical patterns. Existing  Patterns are validated by experience rather than by pattern catalogs [2, 7] do an excellent job of documenting testing, in the traditional sense of ªunit testingº or ªinte- many domain-independent, tactical patterns (such as Factory gration testingº of software. This can be problematic because Method, Abstract Factory, and Singleton). Tactical patterns it is hard to determine when a pattern description is complete have a relatively localized impact on a software architecture. and correct. The most effective way we found to validate For instance, the [2] allows elements in a our patterns was through periodic pattern reviews. These collection to be accessed sequentially without violating data reviews helped to enrich the pattern vocabulary within and encapsulation. Although this pattern is widely applicable, across development teams. We modeled these pattern re- the problem it addresses does not have sweeping architec- views as ªwriters workshops.º At these reviews, developers tural implications. from different teams presented useful patterns they observed In contrast, strategic design patterns have an extensive in their software. Group members discussed the strengths and impact on the software architecture for solutionsin a particu- weaknesses of each pattern, accentuating positive aspects of lar domain. For example, the Half-Sync/Half-Async pattern the patterns, sharing their own experience, and suggesting [12] decouples synchronous I/O from asynchronous I/O in improvements in content and style. a system to simplify concurrent programming effort without degrading execution ef®ciency. This pattern greatly sim-  Directly involve pattern authors with application devel- pli®es synchronization strategies in complex concurrent sys- opers and domain experts. We found that isolatingpattern tems (such as BSD UNIX). We focused most of our energy on authors from development teams resulted in overly abstract documenting patterns related to our domain (communication patterns that did not capture the essence of successful de- software) and we reused existing tactical patterns rather than signs. This is similar to the problem that arises in large-scale reinventing them. Focusing on strategic domain patterns also reuse initiatives that become disconnected from application helped to minimize the likelyhood of pattern overload. development. In both cases the resulting software artifacts can be too general to solve the actual domain requirements.

 Institutionalize rewards for developing patterns. Un- We addressed this problem by using the pattern review tech- familiar design paradigms and methods may be perceived niques described above to glean system-level patterns from as threats to the traditional power structure and base of ex- domain experts on the projects. These patterns were incor- pertise in an organization. We observed a manifestation of porated into the project following careful scrutiny in pattern this problem where some developers were reluctant to share reviews. their domain patterns. They viewed this knowledge as a competitive advantage over other developers. These types of  Integrating patterns into a software development pro- problems are indicative of deeper issues related to the reward cess is a human-intensive activity. Like other software structure in a corporate culture, which is often hard to change reuse technologies, reuse of patterns does not come for free [13]. We addressed this problem to the extent possible by [14]. Identifying and documenting useful patterns requires instituting incentives for developing useful pattern descrip- both concrete experience in a domain and the ability to ab- tions. These descriptions were counted as ªdeliverablesº stract away from concrete details to capture the general prop- used to measure individual performance. We measured the erties of patterns. We found that relatively few individuals utility of design patterns by how widely they were adopted possess both these skills with equal pro®ciency. Therefore, and used successfully (particularly by developers other than engaging groups of developers with diverse backgrounds and the original authors). skillsin pattern review sessions was essential to leverage pat- terns effectively.

 Useful patterns arise from practical experience. There- However, pattern reviews required a signi®cant investment fore, we found that it was important to work closely with by organizations. The review process is fundamentally inter- domain experts in order to identify and document key pat- active and creative, rather than automated and rote. Organi- terns in the communication domain. One consequence of zations that do not actively encourage these reviews (e.g., due the experiential basis of patterns is that they are discovered to tight schedules or due to a view that software development ªbottom-upº rather than invented ªtop down.º One sign should be a mechanical process) may devote inadequate time that pattern overload is taking place is when developers start and developer resources to this review process. planning to ªinvent patterns.º While we generally found the educational bene®ts of the

 Patterns help ease the transition to object-oriented tech- pattern reviews justi®ed the costs, we also recognized that nology for developers who were trained in traditional de- this style of review process does not scale up easily. For sign techniques. Many patterns in our communication frame- example, experienced developers with deep knowledge of works (such as the ªpipes and ®lters architectureº [7]) origi- the communication domain were fertile sources of strategic nated in non-object-oriented contexts such as operating sys- and tactical patterns, as well as invaluable mentors in pattern tems and databases. By explicitly recognizing and reward- reviews. However, these experts were often very busy with

7 other tasks, and could not always spare much time to write are collecting additional information on how patterns affect or review pattern descriptions thoroughly. This is another maintenance over the software lifecycle. reason why documenting patterns should be institutionalized in an organization's reward structure.  Implementing patterns ef®ciently requires careful se- lection of language features. Existing patterns literature

 Pattern descriptions explicitly record engineering trade- [2, 6, 7, 15] has focused primarily on software quality factors offs and design alternatives that resolve non-functional other than performance. This may be acceptable in domains forces. Because pattern descriptions explicitly enumerate where non-functional requirements are more important than consequences and implementation tradeoffs they can be used ef®ciency. For example, graphical user interfaces are often to record why certain design choices were selected and oth- judged more in terms of their usability, extensibility, and ers rejected. For example, the description of the Reactor portability than their raw performance. pattern in Section 2 explains precisely when to apply the pat- In contrast, communication software has traditionally em- tern (e.g., when each event can be processed quickly) and phasized high performance more than other software quality when to avoid it (e.g., when transferring large amounts of factors. Thus, we found that many developers were initially bulk data). If this rationale is not captured explicitly it may concerned about the performance costs of using design pat- be lost over time. This loss deprives maintenance teams of terns in the communication domain. To allay these concerns, critical design information, and makes it dif®cult to motivate many of our pattern implementations used C++ parameter- strategic design choices to other groups within a project or ized types extensively, rather than inheritance and dynamic organization. binding. Parameterized types do not degrade the run-time ef®ciency of performance-critical applications because tem-

 Carefully document the contexts where patterns apply plate instantiation occurs at compile-time. In contrast, al- and do not apply. When developers ®rst write pattern de- ternative techniques for extensibility using inheritance and scriptions they tend to emphasize the bene®cial consequences dynamic binding incur a run-time performance penalty in of the patterns without thoroughly covering the drawbacks C++, due to virtual function table dispatching overhead. of using the pattern in certain contexts. For example, as de- scribed in the previous paragraph, the Reactor pattern can  Patterns help to transcend ªprogramming language- be an inef®cient event demultiplexing mechanism on multi- centricº viewpoints. Focusing on design patterns helped processor platforms because it serializes application concur- us to move away from ªprogramming language-centricº rency at a coarse-grained level [9]. If this caveat is not views of the object paradigm. This was bene®cial because explicitly captured in a pattern description, developers may it enabled experienced developers from different language apply the pattern inappropriately. Therefore, pattern descrip- communities (such as Lisp, Smalltalk, Ada, Eiffel, C++, C, tions should enumerate both the bene®ts and the drawbacks and Erlang) to share design insights of mutual interest without of a pattern, as well as motivate the context in which the being distracted by ªlanguage wars.º pattern applies or does not apply. Once we moved beyond language syntax and semantic differences, it was remarkable how much commonality was

 Successful pattern descriptions capture both structure shared by successful software solutions for a given design and behavior. Expressing the behavioral aspects of a pat- problem. However, we also found that many developers tern is hard because behaviors involve dynamic collaboration wanted to see pattern examples illustrated with the program- between participants. However, patterns that do not clearly ming language they were most familiar with (C++ in our describe dynamic behavior are dif®cult to understand and projects). apply. We found object interaction diagrams and object in- teraction graphs were particularly useful for depicting key  Managing expectations is crucial to using patterns effec- collaborations in a design without requiring the attention to tively. One recurring problem we encountered using pat- detail necessary to understand source code. terns centered around managing the expectations of devel- opment team members. Some team members had miscon-

 Patterns facilitate training of new developers by allow- ceptions about precisely how and what design patterns con- ing developers joining the projects to absorb the key strate- tributed to project success. For example, the use of patterns gies and tactics in the software design quickly. We exposed does not guarantee ¯exible and ef®cient software. More- developers to our pattern documentation before having them over, in their abstract form, patterns cannot be used directly delve into the software. We found that the ability to express by programmers in their implementations. Tools do not yet the intent, structure, and behavior of our frameworks in terms exist that transform design patterns into code automatically. of patterns lowered the learning curve for new developers by Custom implementation is often required, unless the patterns giving them a broad understanding of the architecture in our have been integrated into a reusable framework or library. communication frameworks. We worked hard at Ericsson, Motorola, and BJC/WUSM We expect that this aspect of patterns will prove useful for to prevent design patterns from becoming yet another buz- maintenance programmers. However, the projects at Eric- zword. We did this by candidly reporting the bene®ts and sson, Motorola, and BJC/WUSM are all new systems that limitations of patterns and stressing that patterns are just have not yet entered the long-term maintenance phase. We one of many important tools in a development organization's

8 toolkit. Patterns are no silver bullet that will absolve devel- as design pattern catalogs [2, 6, 7]. These catalogs opers from having to wrestle with complex analysis, design, present a collection of individual solutions to common and implementation issues. In our experience, there is simply design problems. As more experience is gained us- no substitute for creativity, experience, and diligence on the ing these patterns, developers will integrate groups of part of developers. related patterns to form pattern systems (also called pat- Over time, the contribution of patterns will become ev- tern languages). These pattern systems will encompass ident as software developers gain experience incorporating a family of related patterns that cover a particular do- patterns into their development practices. Our experience main (such as communication software). applying design patterns in large-scale distributed systems was that they contributed to developing quality software by In the same sense that comprehensive application frame- addressing fundamental challenges in large-scale system de- works support larger-scale reuse of design and code than velopment. These challenges include communication of ar- do class libraries, pattern systems will support larger- chitectural knowledge among developers, accommodating scale reuse of software architecture than individual pat- new design paradigms or architectural styles, and avoiding terns. Developing comprehensive systems of patterns is development traps and pitfalls that are usually learned only challenging and time consuming, but will likely provide by experience. the greatest payoff for pattern-based software develop- ment during the next few years.

4 Concluding Remarks  Integration with popular object-oriented methods and softwareprocess models ± Patterns help to alleviate soft- Patterns capture the static and dynamic aspects of successful ware complexity at several phases in the software lifecy- solutions to problems that commonly arise when building cle. Although patterns are not a software development software systems. If software is to become an engineering method or process, they complement existing methods discipline, these successful practices and design expertise and processes. For instance, patterns help to bridge must be documented systematically and disseminated widely. the abstractions in the analysis and architectural design Patterns are important tools for documenting these practices phases with the concrete realizations of these abstrac- and expertise, which traditionally existed primarily in the tions in the implementation and maintenance phases. In minds of expert software architects. the analysis and design phases, patterns help to guide Over thenext few years a wealth of software design knowl- developers in selecting from software architectures that edge will be captured in the form of strategic and tactical have proven to be successful. In the implementation patterns that span disciplines such as client/server program- and maintenance phases they help document the strate- ming, distributed processing, organizational design, software gic properties of software systems at a level higher than reuse, real-time systems, business and ®nancial systems, and source code and individual object models. human interface design. In addition, the following aspects of patterns will receive increased attention in the next few years: This paper just scratches the surface of activities the pat- terns community is currently engaged in. A number of books

 Integration of design patterns together with frameworks [2, 6, 7, 15] have been published (or will soon be published) ± Patterns can be viewed as abstract descriptions of on these topics. The Pattern Languages of Programming frameworks that facilitate widespread reuse of software conference [6] is an annual forum dedicated to improving architecture. Frameworks can be viewed as concrete the expression of patterns. There are also pattern work- realizations of patterns that facilitate direct reuse of de- shops at on object-oriented conferences (such as OOPSLA, sign and code. One difference between patterns and ECOOP, and USENIX COOTS). The World Wide Web URL frameworks is that patterns are described in language- http://st-www.cs.uiuc.edu/users/patterns independent manner, whereas frameworks are generally contains a comprehensive on-linereference to pattern-related implemented in a particular language. However, pat- material. terns and frameworks are highly synergistic concepts, with neither subordinate to the other. The next generation of object-oriented frameworks will explicitly embody dozens or hundreds of patterns ± and Acknowledgements patterns will be widely used to document the form and contents of frameworks [16]. Ideally, systems of pat- I would like to thank Mohamed Fayad, Jim Coplien, Adam terns and frameworks will be integrated with tools like Porter, Tim Harrison, Ehab Al-Shaer, and the anonymous on-line pattern browsers that contain hyper-text links to reviewers for improving the quality of this paper. I would also navigate quickly through multiple levels of abstraction. like to thank Paul Stephenson of Ericsson for many hours of

 Integration of design patterns to form systems of pat- discussion on design patterns and techniques for developing terns ± most literature on patterns is currently organized object-oriented communication software frameworks.

9 References

[1] D. C. Schmidt, ªReactor: An Object for Concurrent Event Demultiplexing and Event Handler Dis- patching,º in Pattern Languages of Program Design (J. O. Coplien and D. C. Schmidt, eds.), Reading, MA: Addison- Wesley, 1995. [2] E. Gamma, R. Helm, R. Johnson, and J. Vlissides, Design Patterns: Elements of Reusable Object-Oriented Software. Reading, MA: Addison-Wesley, 1994. [3] D. C. Schmidt and P. Stephenson, ªExperiences Using De- sign Patterns to Evolve System Software Across Diverse OS Platforms,º in Proceedings of the 9th European Conference on Object-Oriented Programming,(Aarhus, Denmark), ACM, August 1995. [4] D. C. Schmidt, ªA System of Reusable Design Patterns for Communication Software,º in The Theory and Practice of Object Systems (Special Issue on Patterns and Pattern Lan- guages) (S. P. Berczuk, ed.), Wiley and Sons, 1995. [5] G. Blaine, M. Boyd, and S. Crider, ªProject Spectrum: Scal- able Bandwidth for the BJC Health System,º HIMSS, Health Care Communications, pp. 71±81, 1994. [6] J. O. Coplien and D. C. Schmidt, eds., Pattern Languages of Program Design. Reading, MA: Addison-Wesley, 1995. [7] F. Buschmann, R. Meunier, H. Rohnert, P. Sommerlad, and M. Stal, Pattern-Oriented Software Architecture - A System of Patterns. Wileys and Sons, to appear 1996. [8] G. Booch, Object Oriented Analysis and Design with Ap-

plications (2 nd Edition). Redwood City, California: Ben- jamin/Cummings, 1993. [9] R. G. Lavender and D. C. Schmidt, ªActive Object: an Object Behavioral Pattern for Concurrent Programming,º in Proceed- ings of the 2nd Annual Conference on the Pattern Languages of Programs, (Monticello, Illinois), pp. 1±7, September 1995. [10] M. A. Linton and P. R. Calder, ªThe Design and Implemen- tation of InterViews,º in Proceedings of the USENIX C++ Workshop, November 1987. [11] D. C. Schmidt, ªAcceptor and Connector: Design Patterns for Active and Passive Establishment of Network Connections,º in Workshop on Pattern Languages of Object-Oriented Pro- grams at ECOOP '95, (Aarhus, Denmark), August 1995. [12] D. C. Schmidt and C. D. Cranor, ªHalf-Sync/Half-Async: an for Ef®cient and Well-structured Con- current I/O,º in Proceedings of the 2nd Annual Conference on the Pattern Languages of Programs, (Monticello, Illinois), pp. 1±10, September 1995. [13] J. O. Coplien, ªA Development Process Generative Pattern Language,º in Pattern Languages of Programs (J.O.Coplien and D. C. Schmidt, eds.), Reading, MA: Addison-Wesley,June 1995. [14] M. Fayad, W. Tsai, and M. Fulghum, ªTransition to Object- Oriented Software Development,º Communications of the ACM, Jan. 1996. [15] W. Pree, Design Patterns for Object-Oriented Software De- velopment. Reading, MA: Addison-Wesley, 1994. [16] R. Johnson, ªDocumenting Frameworks Using Patterns,º in OOPLSA '92, (Vancouver, British Columbia), pp. 63±76, ACM, October 1992.

10