Table of Contents

Pattern: Design Internals

Information explaining in detail how a framework was designed and implemented can be of great value for potential users willing to get a better understanding in order to reuse it in more advanced ways.

Problem

Framework instantiation for a particular application often requires customizing hot spots in a way planned by framework designers. Typical instantiations can be often achieved simply by plugging in concrete classes selected from an existing library that customize the hot spots to the needs of the application at hands, also known as black-box reuse. Other instantiations can be achieved by extending framework abstract classes in a way planned by framework designers. The instantiation requires matching of interfaces and behaviors, and the writing of code to implement new behaviors, also known as white-box reuse.

Not all instantiations of a framework are simple to achieve, but they can’t be all documented exhaustively and in enough detail, especially those more advanced customizations, or those not initially planned by framework developers.

To cover these advanced instantiations, and also other kinds of reuse, such as flexing, composing, evolving or mining a framework, it is thus important to provide framework users with detailed information about how a framework and its flexibility was designed and implemented.

How to help framework users on quickly grasping the design and implementation of a framework to support them on achieving customizations not typical, advanced, or not specifically documented?

Forces

Different Purposes. In addition to the framework purpose and usage instructions, the framework documentation must also provide information to help framework users on understanding the underlying principles and the basic architecture of the framework so that they can develop not only trivial and planned but also advanced applications that are conformant to the framework.

Balancing Prescriptive and Descriptive information. Although programmers can use a framework without completely understanding how it works, such as when following a set of instructions, a framework is much more useful for those who understand it in detail. To be effective, the documentation must achieve a perfect balance between the level of detail of the instructions provided to guide the usage of the framework, and the level of detail and focus used to communicate how the framework works, i.e. its design internals.

Minimizing design information complexity. To communicate complex software designs is challenging. Frameworks derive their flexibility and reusability from the use (and abuse) of interfaces and abstract classes, which, together with polymorphic methods, significantly complicate the understanding of the run-time architecture. The design information to communicate can include not only the different classes of the framework, but also the strategic roles and collaborations of their instances, and rules and constraints, such as cardinality of framework objects, creation and destruction of static and dynamic framework objects, instantiation order, synchronization and performance issues.

Solution

Provide concise but detailed information about the design internals of the framework by describing the framework hot-spots at a meta-level using meta-patterns, and by describing the roles of framework participants using design patterns and design pattern instantiations.

Design pattern instances. Searching, selecting and applying design patterns are the necessary steps of the cognitive process for assigning the roles defined in a pattern, to concrete classes, responsibilities, methods and attributes of the concrete design. This process is generally called pattern instantiation.

Documenting pattern instances is important because it will help other developers on better understanding the resulting concrete classes, attributes and methods, and the underneath design decisions. This provides a level of abstraction higher than the class level, highlighting the commonalities of the system and thus promoting the understandability, conciseness and consistency of the documentation. At the same time, the documentation of pattern instances will help the designer instantiating a pattern, to certify that she is taking the right decision. In general, this results in better communication within the development team and consequently on less bugs.

To more formally document a pattern instance we must describe the design context, justify the selection of the pattern, explain how the pattern’s roles, operations and associations are mapped to the concrete design classes, and to state the benefits and liabilities of instantiating the pattern, eventually in comparison with other alternatives.

Design patterns. A pattern names, abstracts, and identifies the key aspects of a design structure commonly used to solve a recurrent problem. Succinctly, a pattern is a generic solution to a recurring problem in a given context. The description of a pattern explains the problem and its context, suggests a generic solution, and discusses the consequences of adopting that solution. The solution describes the objects and classes that participate in the design, their responsibilities and collaborations. The concepts of pattern and pattern language were introduced in the software community by the influence of the Christopher Alexander's work, an architect who wrote extensively on patterns found in the architecture of houses, buildings and communities. Patterns help to abstract the design process and to reduce the complexity of software because patterns specify abstractions at a higher level than single classes and objects. This higher-level is usually referred as the pattern level.

A design pattern is thus a specialization of the pattern concept for the domain of software design. Design patterns capture expert solutions to recurring design problems. As design patterns provide an abstraction above the level of classes and objects, they are suggested as a natural way for documenting frameworks: to describe the purpose of the framework, the rationale behind design decisions, and to teach them to their potential users.

Design patterns are particularly good for documenting frameworks because they capture design experience at the micro-architecture level and capture meta- knowledge about how to incorporate flexibility. In fact, design patterns are capable of illuminating and motivating architectures, preserve design decisions made by original designers and communicate to future users, and provide a common vocabulary that improves design communication, and to help on the understanding of the dynamics of control flow.

The concepts of frameworks and patterns are closely related, but neither subordinate to the other. Frameworks are usually composed of many design patterns, but are much more complex than a single design pattern. In relation to design patterns, a framework is sometimes defined as an implementation of a collection of design patterns.

To document the design internals of a framework in relation with the patterns it implements we must first know, or recognize, the patterns in the framework design, and to match them against the many popular design patterns already documented, such as the catalogues known as GoF patterns and POSA patterns. However, more contextualized design patterns are very likely to not being yet published or documented, due to its specificity, either in terms of applicability or organization dependency. In these situations, it is required to spend the effort to mine and write the patterns considered important to explain the underlying framework design. A good source of knowledge for those willing to learn how to write patterns is, itself documented under the form of a pattern language.

Meta-patterns. Frameworks are designed to provide their flexibility at hot spots using two essential constructs: templates and hooks. The possible ways of composing template and hook classes in the hot spots of a framework were catalogued and presented under the form of a set of design patterns, which were called meta- patterns. Although meta-patterns can be used to document the roles of framework participants, the level of detail is too fine to be useful, but extremely useful to document the roles of the participants involved in a design pattern.

Examples

Design patterns are commonly used to document the global architecture of the framework. We will illustrate here with examples of how design patterns are used to document popular frameworks, such as JUnit, Swing, J2EE and .NET, and also the classical HotDraw framework.

HotDraw. The first paper that mentions the advantages of using patterns to document a framework is authored by Ralph Johnson, which presents a pattern language to document the HotDraw framework, comprising a set of patterns, one for each recurrent problem of using the framework. In that work, patterns are not only used to document the design of the framework, but also as a way of organizing the documentation, similarly as a cookbook does with the recipes (COOKBOOK AND RECIPES), where each pattern provides a format for each recipe.

JUnit. The document “A Cook’s Tour”, devoted to explain how JUnit was designed, includes a pattern-by-pattern tour to the design internals of JUnit. The figure below presents an extract from this document that shows the design patterns used in the architecture of JUnit, which describe in more detail JUnit’s internal design. In concrete, it informally enumerates the design patterns instantiated by the major abstractions of JUnit.

The following figure presents on the left another extract from this document informally explaining, using natural language, models, and fragments of source code, how the class TestCase instantiates the Template Method design pattern. On the right presents an extract from the documentation relative to the Template Method pattern that shows the structure of the solution proposed by the pattern, the participants involved and their roles, and the consequences of instantiating the pattern.

Known uses

Swing. The much more complex Swing framework instantiates many more patterns (e.g. Observer, Composite, Decorator, Visitor, etc.) but its accompanying documentation doesn’t use pattern instances as explicitly and exhaustively as we can observe in JUnit, probably due to the cost of doing it.

The figure below shows an extract from an overview of the Swing architecture, where we can learn about the foundational design principles of Swing, concretely the model- view-controller architectural pattern (MVC) and its instantiation in Swing classes.

J2EE. The patterns underlying the design of the enterprise version of Java is documented in the core J2EE patterns catalog [20], which serve as a valuable source of knowledge to learn more about how J2EE is designed and how the applications based on J2EE should be designed. the figure below shows the index of all the core J2EE patterns.

.NET. Similarly to J2EE, there is a document that presents the patterns underlying Microsoft’s .NET framework for enterprise applications. The figure below shows the documentation of the MVC pattern, which includes an example of its instantiation in .NET.

Consequences

By documenting the framework design internals, using patterns and pattern instances, namely, we provide framework users with additional knowledge that can help them better understand the underlying architecture and design principles of the framework, and therefore to enable more advanced customizations or simple but not documented customizations elsewhere in another form of documentation.

However, to document framework’s specific patterns, not published, and to document pattern instances can be hard work, if not done at the right moment by the right people.

As one of the most complex kinds of object-oriented software systems, frameworks can be hard to understand and explain, but definitely patterns are a excellent mean to do that, as they provide a good balancing between simplicity of reading and richness of the information provided.