Bruce MacIsaac Leverage patterns to solve problems and to capture and communicate solutions. ProblemBroad experience is a quality in short supply, and even experts should not be inventing new solutions if there are proven solutions that work. Patterns offer "distilled experience" with the following benefits:
This practice describes how to use patterns to solve problems and capture and communicate solutions. BackgroundLet's start with a few key definitions. Pattern: A General DefinitionBefore giving a definition, let's start with a simple example. "Divide and conquer" is a time-honored strategy in war, government, and computing science. The strategy can be described as follows:
Figure 6.2. Divide and Conquer.A pattern, such as "divide and conquer," applies to many different situations.
This simple example demonstrates the defining characteristics of a pattern:
Benefits of PatternsWhether developing a new system or integrating or upgrading an existing system, basic problems recur that have already been solved. When the solution is distilled and captured as a pattern, it can be reused, which saves time. But more important, using proven solutions reduces risk and so increases the likelihood of success.
Patterns are also useful as a means to understand and document existing systems. Like an archaeologist, you can excavate the patterns used by the original software designers and use patterns to document that architecture. Learning standard patterns provides developers with a rich vocabulary for communicating design alternatives and offers a toolkit full of proven solutions that can be applied as needed. Developers thus become more effective and efficient. One caution: overuse of patterns can complicate a design. It is generally best to apply new patterns in their simplest form until you have gained experience.[2]
Software Design PatternsSoftware design patterns are patterns that solve software design problems. In addition to providing a name and description, design patterns can often be enhanced by diagrams. Figure 6.3 shows an example of the "Proxy" design pattern,[3] expressed in UML.[4]
Figure 6.3. Structure of the "Proxy" Design Pattern.The client uses an interface. Both the Proxy and RealSubject implement that interface, but the Proxy just redirects calls to the RealSubject.
Figure 6.4 shows the behavior (how invoking the proxy results in a delegated call to the RealSubject). Figure 6.4. Behavior of the Proxy Pattern.Calls to the proxy are redirected to a class that provides the real implementation.
Note the following characteristics of the notation used in this pattern:
Software Architecture PatternsA software architecture pattern is a design pattern that has a wide impact on the overall system. Because of the wide range of problems encountered in software development, architecture patterns (and more generally design patterns) are typically organized into categories of the problems they solve, such as the following:[5]
The pattern categories above closely relate to the architectural views described in RUP.[6] Considering each view and pattern category helps ensure that the key aspects of the architecture are addressed.
A reference architecture is a collection of patterns that define a basic architecture for a system. Using a reference architecture is easier than picking and choosing individual patterns, but offers less flexibility.
Applying the PracticeLearning to apply patterns is a skill that takes time and practice to cultivate. The following section provides guidance for getting started with patterns and introduces more advanced applications of patterns. Increase Your Knowledge of Relevant PatternsIt is important for developers to be familiar with key patterns relevant to their field and to use them as basic tools for solving problems and communicating solutions. The section Additional Information at the end of this practice lists some good places to start.
Use Reference ArchitecturesThere may be existing documented architectures within your organization, or in literature, that fit closely with the system that you are trying to build. A good "reference architecture" is a collection of related patterns that fit a particular business and technical context and should include examples and other artifacts to enable their use. One such set of reference architectures is IBM's Patterns for e-Business.[7] The IBM Patterns for e-Business Web site provides more than a simple list. It includes a wizard that helps you progress from identifying the business problem that you are trying to solve to choosing the specific architecture that meets your needs.
Reference architectures are a good way to start looking at patterns. The set of patterns is predefined, which saves you picking and choosing patterns yourself. Reference architectures are also less risky, since the selected patterns have been proven to work together. Identify Patterns for Cross-Cutting ConcernsSolving common problems the same way keeps an architecture consistent and understandable. Architectural patterns for structure, distribution, concurrency, persistency, and presentation generally impact multiple components of the system. Requirements to support globalization, security, redundancy, error reporting, and so on typically also affect multiple components. There are two aspects to addressing most cross-cutting concerns: (1) identifying software that provides common services (sometimes referred to as "mechanisms") and (2) describing how those mechanisms are to be used by the client software (patterns). In early analysis, these mechanisms are described textually, as a placeholder for one or more components yet to be selected or designed. Classes are mapped to mechanisms as shown in Figure 6.5. Figure 6.5. Mapping Design Elements to Analysis Mechanisms.Classes and subsystems are mapped onto the identified analysis mechanisms: the arrows indicate that the class uses the mechanism. A client class often uses several mechanisms.
As analysis and design proceed, analysis mechanisms, such as "persistency," are narrowed to specific design mechanisms, such as "relational database persistency" and patterns of use. This relationship is then further refined to specific implementations such as "Cloudscape database," and patterns of use can be demonstrated with working examples. As the system evolves, you may find similar code appearing in several places, or different code being used to solve similar problems. Such discoveries frequently signal a need to define and refactor to a common pattern.
Document Patterns Used in Your ProjectArchitectural patterns are solutions to key technical challenges, many of which have systemwide implications. If there are no guiding systemwide patterns, developers may come up with different solutions to similar problems, causing additional effort and unnecessary complexity. Consciously applying patterns throughout the system generally leads to more consistency and simplicity.
To ensure that the architecture doesn't degrade, architectural patterns need to be documented and enforced. Enforcement here simply means that the architecture should not be allowed to degrade through sloppiness; developers and reviewers should defend standard patterns and avoid deviations whenever possible. The simplest way to do this is to create good examples early in the project for others to follow. Using UML to Document PatternsAn intermediate application of patterns is to use UML to document the patterns in your software, as shown in the previous "Proxy" example. UML provides a rich standard visual notation for capturing both structure and behavior. The advantages of UML are further discussed in Practice 18: Model Key Perspectives. Your main goal should be to document the problem and to describe when the pattern applies and when it does not apply. Diagrams, UML or otherwise, can help you create compact and precise descriptions.
Automated Pattern ApplicationTools[8] are available that not only document patterns using UML but can also apply and enforce patterns in a model. As an example, you might decide to apply the "Proxy" pattern (described earlier) to a particular client and subject class. A wizard can automate applying the patterngenerating the interface and proxy class from the subject class, revising the original client to invoke the proxy, and generating calls from the proxy to the real-subject class.
Note that since patterns are not generally complete solutions, but rather characteristics of solutions, only some patterns can be automated. The best approach is to identify excessive repetition in your designs or your implementations and use automated patterns as a tool to simplify your work.
Other MethodsTraditional waterfall development details all the design before implementing and testing. Patterns can be incorporated in this approach, but waterfall development does not provide the opportunity to validate these patterns on a small amount of code before they are used broadly. Patterns are a key part of the Unified Process's focus on architecture. Patterns are validated by implementing and testing examples before they are widely implemented, allowing the patterns to be improved without impacting a lot of the design and code.
Early implementation of patterns is consistent with XP's principle of "incremental design," which states that "design done close to when it is used is more efficient."[9] However, the Unified Process explicitly recommends looking for key patterns and implementing them. XP doesn't have this same architecture focus; rather, patterns and consistency emerge through continuous refactoring.
RUP encourages automated application of patterns and reuse of patterns to increase productivity, although this is an advanced application of RUP. XP doesn't discuss this topic explicitly, but XP's value of simplicity and principle of "baby steps" remind teams to be cautious about doing too much too soon. Levels of AdoptionThis practice can be adopted at different levels:
Related Practices
Additional InformationInformation in the Unified ProcessOpenUP/Basic covers the basics of applying patterns and reference architectures. RUP and RUP plug-ins elaborate on these basics. For example, the J2EE plug-in to RUP describes important J2EE design patterns, while the Service-Oriented plug-in describes patterns that apply to service-oriented architectures. Additional ReadingThe following classic work popularized design patterns:
There are many books on patterns. The following address patterns of architectural scope:
For guidance on improving existing code with patterns, see the following:
For guidance on applying patterns and UML in the context of an overall software development process, see the following:
|