Design Patterns


Definition: Design patterns in software are (usually) short descriptions that capture practices that have proven successful in the past. They are not concrete pieces of software, but a kind of stencil applied in certain situations. They are generally not prescriptive, but suggestive, and include guidance on when their use is most appropriate and provide examples from existing systems. Their most important use is in describing the interaction of objects or systems with their environment (i.e., other objects or systems). Design patterns can occur at different levels of system design, from low-level programming to system-of-systems. At the latter level, they are most associated with interface design and coupling.

Keywords: coupling, design pattern, interface

MITRE SE Roles and Expectations: MITRE systems engineers (SEs) are expected to understand the general principles and best practices of design patterns for information technology (IT) intensive systems. They are expected to select and recommend the patterns appropriate to the application, understand the challenges and choices that arise, advise government on the applicability of design pattern choices, and understand the issues and challenges of interface design in an enterprise environment.

Background

The concept of design patterns is usually attributed to the work of the architect Christopher Alexander and was adapted to software by Kent Beck and Ward Cunningham. In 1995, the popular book Design Patterns—whose authors are often referred to as the "Gang of Four" (GOF)—established a set of patterns that are in continuous use and provided a "pattern" for describing the patterns [1]. These 23 patterns are divided into creational, structural, and behavioral categories. Many other patterns have been defined, as well as other categories, such as user interface.

As an example, one GOF pattern is the Abstract Factory, a creational pattern that presents an interface for creating new objects, without the caller knowing the specific type of object being created. This could be used to implement a different look and feel with minimal changes to the program. Other examples are the Proxy structural pattern, in which one object becomes a surrogate for another (with the same interface), often used in remote procedure calls; the Singleton pattern, in which a class allows only one instance of itself to be created, often used in managing shared resources; and the Mediator behavioral pattern, which allows loose coupling between classes by being the only class that has detailed knowledge of their methods.

Design patterns enable review and discussion of software design to take place at a higher and more abstract level than reviewing specifics of interface calls—"Should you be using a Singleton pattern here?" or "Would an Abstract Factory pattern help?"

GOF patterns have several things in common: they are defined in terms of object-oriented software, they (usually) describe the interaction of an object with its environment (e.g., other objects), and they are generally used within the internal design of a single application (i.e., a local calling environment).

Patterns can also be viewed at a broader level of design, however, and MITRE SEs are more often involved in this aspect. MITRE SEs are less likely to be involved in the development of the detailed internal workings of system components than in the review of interfaces between components or, at a higher level, between systems. This calls for a set of design patterns that focus on the manner in which connections are made across the system boundaries. Many GOF patterns will not directly apply.

Design Patterns in an Enterprise Engineering Service-Oriented Environment

When designing for a large-scale enterprise service environment, two considerations arise: (1) users may put services, interfaces, etc. together in ways that designers did not anticipate, and (2) any interface changes will affect a larger set of users. Thoughtful use of design patterns can help deal with both of these issues. A third issue with scaling to the enterprise is that a service will generally have to deal with a (currently) unknown and potentially large number of users. Design patterns are of less use in dealing directly with this issue.

In an enterprise environment, when considering system-to-system interfaces, the notion of design patterns can be broadened to encompass more general guidance on how to manage the coupling in the interface. As a general rule, loose coupling is preferred over tight coupling whenever possible. Loose coupling means that a change in the implementation of one side of the interface does not affect the implementation of the other side. For example, using a code in a field with a lookup table that must be distributed to users is not loose coupling. Also, a loosely coupled interface should not lock in specific limits that will inhibit scalability. As a simple example of this, in an interface for contact information, allowing for only one (or two) telephone numbers of 10 digits may not be sufficient. A more extensible interface might allow for an arbitrary-length list of telephone numbers of indeterminate length.

Loose coupling insulates users of an interface from changes in the implementation. For example, a well-designed interface should be able to add more parameters to the interface, while still generating and accepting messages without the new parameters. This allows for growth and innovation without stranding users of the previous version of the interface. On the flip side, though, this extension mechanism must be managed with discretion, or the number of supported interfaces that differ just in parameters can grow large, and the maintenance of these can swamp the value of backward compatibility.

Example Interface Standardization Efforts

Cursor on Target (CoT) [2] is an example of an enterprise effort to simplify a collection of interfaces and provide loose coupling. The U.S. Air Force has had a large number of tightly coupled point-to-point interfaces among many components. Gen. John P. Jumper (former Chief of Staff of the Air Force) inspired MITRE to come up with a small set of data elements that would give the majority of what most users need. MITRE studied several months' worth of messages and found that a small number of data elements were used repeatedly. CoT standardized a definition of these elements in an XML format that is easy to generate and parse. It provided for compatible extensions so that new elements could be added without disrupting existing users.

The National Information Exchange Model (NIEM) [3] is an XML-based information exchange interface. It grew out of the Global Justice XML Data Model, as a collaboration between the Department of Justice and the Department Homeland Security. It has been adopted by many states and the Department of Defense. It provides a vocabulary of information elements, from which partners can select to create messages.

Alignment with MITRE Systems Engineering Competency Model (SE CM)

Systems engineering work with design patterns most closely aligns with the "Architecture" (Section 2.3) and "Software and Information Engineering" (Section 4.7) competencies in the MITRE SE CM [4]. In the former, design patterns can be a useful tool in discussing, visualizing, comparing, and recording architectural interface decisions. In the latter, because design patterns are now a well-established paradigm within software engineering, an understanding of the techniques and terminology is useful in facilitating communication between the customer/user and software specialist.

Best Practices and Lessons Learned

The following rules of practice can be seen as design patterns for interfaces at the enterprise level as well as at the detailed implementation level.

Avoid complexity in the interfaces. Complex interfaces typically do not scale well. The complexity is pushed out to all users, and the skill in dealing with it may vary. For example, rather than providing latitude and longitude in 10 potentially different formats, each of which has to be handled by the user, provide it in a single format instead. If an interface is too complicated, there is a greater possibility that it will be misinterpreted, or that developers will copy sub-optimal implementations of the user end. Complexity leads to errors, which can lead to poor performance that may not be correctable, and may even become security risks.

Use loosely coupled interfaces wherever possible. Loose coupling implies that a change in the implementation of one side of the interface will not affect the implementation of the other side. This allows enormous freedom on both sides to make improvements and to keep development schedules disjoint. Tight timing requirements or software version requirements may be considerations that require a reevaluation and relaxation of this practice, but this should be made explicit and documented in such cases.

Use tightly coupled interfaces only if they are necessary for performance. Tight coupling can lead to code that is buggy and fragile. An example of tight coupling is in the Link-16 interface, which, because it is a tactical link, uses a number to represent the type of an aircraft. This ties the user to a particular version of a conversion table. If the table is updated on one side, the user may be left with a meaningless number until the table is updated as well. Of course, a more expansive communication protocol could carry all information on the aircraft explicitly, but bandwidth limitations may prohibit this as an alternative.

When possible start design with loose coupling. Even in cases where tight coupling will be used, initial design can begin with loose coupling interfaces. Document why a tight coupling is being used. This is analogous to defining a logical schema in a database management system (DBMS)-independent way, but implementing it in a DBMS-dependent physical schema. This may be a useful pattern for systems of systems.

Focus on data conformity in the interfaces rather than in internal representations. In the 1990s, government organizations tried to enforce data uniformity across all applications, even to the point of specifying how data was to be represented within the application and its databases. This was never achieved. More recently, the focus is on creating common definitions for data exchange, leaving applications free to choose how to represent data internally. This has proven to be an easier goal to reach.

Recognize that differences in the representation of data result from different uses of the data. For example, consider a gun. A shooter wants to know its range, caliber, etc. A shipper wants to know its size, weight, etc. Finance wants to know its cost, estimated lifetime, etc. The same gun is naturally represented differently in different systems. Forcing all characteristics on all systems would be burdensome. However, unanticipated, innovative uses of data can be achieved through compositional patterns to create new data representations that are built on existing representations.

In the design of an interface, consider the 80/20 rule. It may be better to implement 80 percent (or so) of what most users need most of the time, especially if this can be done quickly with a simple interface. This reduces the cost and time for implementation.

Build in the ability to extend the interface. Some users will need to reach at least part of that remaining 20 percent, and in any case, interfaces have to grow and change over time. A loosely coupled interface should build in a mechanism for compatible extension, so that changes and additions can be made without affecting users who do not need the extensions.

Consider the governance of the extensible interfaces. Extension of an interface creates multiple versions/copies that must be managed. Consider the justification for and understand the impact of doing this.

Do not forget about the semantic level of understanding in the interface. It is fine for someone to be able to correctly parse your interface, but there must also be agreement on the meanings of the data elements.

Involve developers in the development of system interfaces. Those who will implement the interface should be involved in the design because they may have insight into decisions that could inhibit scalability or cause other problems.

References and Resources

  1. Gamma, E., R. Helm, R. Johnson, and J. Vlissides, 1995, Design Patterns: Elements of Reusable Object-Oriented Software, Boston, Mass. Addison-Wesley Longman.
  2. Miller, R. W. and D. G. Winkowski, June 2007, Loose Couplers as an Information Design Strategy, The MITRE Corporation.
  3. , accessed August 5, 2014. (By the way, they are looking for .)
  4. The MITRE Institute, September 1, 2007, MITRE Systems Engineering Competency Model.

Additional References and Resources

Bell, M., 2010, SOA Modeling Patterns for Service Oriented Discovery and Analysis, Hoboken, N.J., John Wiley & Sons.

Erl, T., 2009, SOA Design Patterns, New York, Prentice Hall.

Fowler, M., 2002, Patterns of Enterprise Application Architecture, Addison-Wesley.

Hohpe, G., and B. Woolf, 2003, Enterprise Integration Patterns: Designing, Building, and Deploying Messaging Solutions, Boston, Mass., Addison-Wesley Longman.

Van Welie, M., , accessed April 14, 2014.

Vora, P., 2009, Web Application Design Patterns, San Fransisco, Calif., Morgan Kaufmann Publishers.

Publications

Download the SEG

MITRE's Systems Engineering Guide

Download for EPUB
Download for Amazon Kindle
Download a PDF

Questions?
Contact the SEG Team