Chapter 13. Creating Patterns

With a design in hand, we now move forward to create the pattern. However, how do we ensure that we will successfully implement that design? What are the best practices to follow when creating a model-to-model pattern implementation? How do we write up a pattern specification? As we build the pattern, how do we ensure that we are meeting quality goals? What do we do to test a pattern? The patterns and guidelines in this chapter will help answer these questions.

Patterns

In this section we discuss patterns to help us create model-to-model, model-to-text, and UML pattern implementations.

Model-to-Model Pattern Implementation

Context

We plan on integrating abstraction in our design efforts while using models at each level of abstraction.

Problem

When using models at multiple levels of abstraction, how do we support the transition between the different models while following best practices? At the same time, how do we also improve quality, support governance, and optimize the skills of the team?

Forces

• We need to be able to think about and understand models at the meta level.

• We are making investments in artifacts that support the creation of interim deliverables. Our stakeholders are expecting software that meets their requirements, not pattern implementations. We need to ensure that the investment in creating these patterns is warranted and supports us in meeting the needs of the project.

Solution

A key aspect of working with model-driven development (MDD) is that we leverage models at multiple levels of abstraction. However, we also need to have support for automating how we move between these levels of abstraction. To that end, a pattern implementation that can work with an input or source model and then generate elements in an output or target model is needed. This type of pattern implementation is called a model-to-model pattern implementation, and it automates the transformation of a model at one level of abstraction to a model at another level of abstraction.

It’s important at this point to emphasize that we need a solid understanding of metamodels, both in general and the specific metamodels that we will be working with. A metamodel is a model that describes another model at one level of description higher. Another way of saying this is that a metamodel is a model that describes a modeling language. When we are building a model-to-model pattern implementation, we work at the metamodel level, with the definition of modeling languages.

Figure 13.1 provides a high-level, conceptual overview of a model-to-model pattern implementation. As seen in the diagram, we have two metamodels: an input metamodel and an output metamodel. We then create a series of mappings to define the relationship between these elements. Once we have defined the mappings, we generate the pattern implementation that is able to automate the application of the pattern.

Figure 13.1. A high-level view of the elements within a model-to-model pattern implementation

image

A metamodel foundation makes it possible to create model-to-model pattern implementations. With a metamodel in place, we are able to make rules and act upon known types, which in turn consume the elements created by the modeler.

Moving forward from the work performed in exemplar analysis, and with a design in hand, we need to keep in mind the following:

• What are the metamodels that need to be used in this pattern? Note that although Figure 13.1 shows a single metamodel at the input and output levels, multiple metamodels can be mapped to each of these levels.

• What is the mapping between the metamodel elements? Is a flow or hierarchy needed as we navigate between elements that participate in the mapping?

As we map between metamodel elements, are any additional calculations, filtering, or other special steps needed?

Example1

One way in which we can create model-to-model pattern implementations is with the model-mapping capabilities within Rational Software Architect (RSA). The model-mapping capabilities allow us to define the relationship between the metamodel elements that support two models: a source model and a target model. Based on the relationship that is defined by a set of mappings, along with a set of rules and filters, we can create a pattern implementation that will support moving between any two models. Within RSA, the main language that is used for defining metamodels is the Eclipse Modeling Framework (EMF). Even the UML metamodel that is used in RSA is defined using EMF.

In building the pattern implementation, we need to understand the EMF API and the elements that it provides. Where we go from there depends on the languages that we are using for our source and target models. If we are just using plain old UML, we will need to learn the UML metamodel. If we have extended UML by using profiles to create our own language, we need to invest additional time in learning the details of those metamodels. In cases where we have created a custom DSL with EMF, we will need to take the time to learn the specifics of those metamodels.

With RSA we can use a number of different kinds of mappings to connect model elements between the input model and the output model. The types of mappings include move, submap, custom, and inherited maps. Each pattern implementation that we create will include one or more maps, which in turn include one or more of these mappings.

• The move mapping is quite simple. We’re telling the transformation that we want to copy the information from the source element to the target element. This does require compatibility between the two elements; they must have similar types and one-to-one multiplicity.

• If the types of the elements differ, or they do not have one-to-one multiplicity, we have to use one of the other mapping types, either custom or submap. Submap is an indication that we are going to provide more details via another map (and set of mappings). The other map usually takes us a step deeper into the input object so that we can see the elements within that object. Then within the submap we can create mappings between the subelements with elements in the target model. A custom mapping provides us with a less constrained environment to work in; we use code to work with the API and detail the mapping.

• Within each of the mappings we have options to introduce some snippets of code to customize how the mapping will work. Regardless of the mapping that is used, the goal is to minimize the amount of code used. We want to leverage the drag-and-drop interface to specify the mappings and then use the tooling to generate the transformation code.

Figure 13.2 provides an overview of the specialized editor that is used for creating model-to-model pattern implementations in RSA. For each of the models used in the pattern implementation, we are provided with a view of the underlying metamodel so we can see an input metamodel and an output metamodel. For each metamodel there exist one or more elements. Each element can have a set of properties (essentially these are subelements). As we build the pattern implementation, we create one or more mappings between elements in the input metamodel and elements in the output metamodel. After we create the complete set of mappings, the tooling generates the code necessary to support the pattern implementation.

Figure 13.2. An example of the model-mapping capabilities within Rational Software Architect

image

Related Patterns and Guidelines

Exemplar Analysis (Chapter 12), Integrated Patterns and DSLs (Chapter 15), Model-to-Text Pattern Implementation*, Pattern Implementation (Chapter 12)

Model-to-Text Pattern Implementation

Context

The project will result in the creation of many text-based artifacts, including code, scripts, and configuration files.

Problem

When creating a solution, we use models as part of our design efforts. However, how can we transition from representations in models to text-based artifacts while following best practices? And how can we do so while improving productivity, increasing the quality of the solution, supporting governance, and optimizing the skills within the organization?

Forces

• We need to consider how the input model will be created, managed, and surfaced to the user. Working with an XML file is sufficient for testing but is not a good choice to roll out to a team for general use.

• In iterative projects we need to think about what will happen when the pattern implementation is reapplied.

Solution

Create model-to-text pattern implementations, which take a model as input and then generate a set of text-based artifacts. These text-based artifacts can include code, documentation, scripts, configuration files, and so on.

Typically a template-based approach is used to support the creation of a model-to-text pattern implementation. A template is used to represent the artifact that is to be generated. Within the template we will find a combination of static text and code or script that allows us to dynamically alter the text that is generated, leveraging user-provided content.

In creating the template, we usually start with a file provided by the exemplar. The exemplar project may have multiple instances of a file that plays a single role in the solution. For instance, if our exemplar is for generating JavaBeans, we will often see that an exemplar has more than one Bean in the project. We do not create a template for each Bean. Although there are multiple files, there is only one Bean role. As we create our template, we usually select a single instance of the Bean that is most representative of what we need to generate. If necessary, we can augment the content of the file by borrowing from the other files as needed to ensure that we account for the full range of output possibilities.

In parallel to the effort associated with the templates, we need to create an input model. The input model defines the metamodel that will constrain the information that is accepted by the pattern. In this metamodel we define the entities, their relationships, and their properties. When Pattern Users work with the pattern, the information that they provide will need to adhere to the structure defined by the metamodel.

When the pattern is applied, the input model is “merged” with the templates; that is, each template evaluates the input model using the code or script in the template. Information is retrieved from the input model and combined with the static portion of the template, and then a new file is created.

Building on the design work that has been done in exemplar analysis, we can keep the following in mind as we start to create model-to-text pattern implementations:

• Ensure that the team working on the pattern implementation includes both a Pattern Author/SME role and a Pattern Implementation Author. These roles need to work together to build the pattern.

• What should the input model be? What is the relationship between the entities? What attributes need to be captured? What attributes can be calculated?

• Which files in the exemplar should serve as templates?

• What aspects of the template need to be customized to support dynamicity? How does this relate to the input model?

Example

One way in which we can build model-to-text pattern implementations is through the use of JET,2 which is available in Eclipse-based products. JET has been a boon in creating model-to-text pattern implementations because it enables us to quickly create pattern implementations that are easy to use, powerful, and generate a significant amount of content for our project. This is in contrast to UML pattern implementations, where there is more effort involved in the development and a more limited scope. A UML pattern implementation has value, but when we are looking at where and when to make an investment, JET-based patterns are a better place to start.

Figure 13.3 provides a high-level view of the way that JET works. JET follows a Model-View-Controller3 pattern. The model in this case is the input model—the information that the Pattern User provides. The input model is typically provided as XML or as an EMF-based model. The control and view aspects of the pattern are both filled by templates. In the case of the control role, usually a small set of templates is used to control the execution of the pattern. The control template is aware of the input model, the calculations for information needed by other templates, and the other templates that participate in the pattern. The view templates are representations of the elements that need to be generated. They contain a combination of static text along with XPath code that allows for adding dynamicity.

Figure 13.3. A high-level view of the components within a JET-based transformation

image

So how do we build a model-to-text pattern implementation? If we follow through on looking at JET as an example, the answer depends on the product that we are using. Eclipse as a stand-alone product provides only the JET runtime and basic text editors. If we use RSA, there are specialized editors that can be used. Let’s take a closer look at what we can do with the specialized editors in RSA.

Within RSA, we find that we build on exemplar analysis with a set of steps and tooling known as Exemplar Authoring:

• Launch the JET wizard and specify the scope of the exemplar projects. These are the exemplars that will be used as the basis for building the pattern implementation. The Pattern Author/SME and the Pattern Implementation Author will figure out the artifacts that belong in the exemplar. One or more Eclipse projects will serve as the basis of the exemplar.

• As shown in Figure 13.4, once we have settled on the scope of the exemplar, we focus on the input schema and associated output actions. The input schema is used to define the elements, attributes, and calculations that work with data associated with the pattern. The output actions handle tasks such as creating required projects and files.

Figure 13.4. Exemplar authoring in action in creating a JET-based model-to-text pattern implementation

image

• Once we have settled on the input schema and output actions, we turn our focus to the templates associated with the pattern. For each type of artifact that we need to create, there is one associated template. Within the template there is a combination of static and dynamic elements. The static elements are those things that remain the same each and every time we apply the pattern. The dynamic elements will change based on the input model provided by the Pattern User. With JET, we use XPath to access and manipulate information from the input model.

At this point, however, we will only have created a pattern implementation that accepts a text-based input model. We can write XML files by hand, but that doesn’t seem to fit the goal of boosting productivity. One approach we could take is to build a wizard or form in Eclipse to capture the input model.

Another option is a visual model using UML or a DSL. If we go down this path, we can connect the visual model to JET using model mapping. To do so, we use our DSL/UML as the metamodel for the input model in the mapping, and we use the JET input model as the output model for the model mapping.4

Related Patterns and Guidelines

Exemplar Analysis (Chapter 12), Model-to-Model Pattern Implementation*, Pattern Creation Lifecycle (Chapter 12), Pattern Implementation (Chapter 12), UML Pattern Implementation*

UML Pattern Implementation

Context

We are working with UML to architect and design our PBE solutions. We need to incorporate best practices in our efforts.

Problem

When using patterns within a UML model, we run into a number of challenges. How do we accelerate the application of patterns and ensure that they are applied correctly and consistently?

Forces

• Code can be generated from the model using a code generator or other pattern implementations, but they need to be able to interpret the results of the UML pattern implementation.

• Communication is supported by recording pattern instances in the model.

• Although we are using best practices in creating the solution, the impact is limited by the narrow scope of UML pattern implementations.

Solution

Create a UML pattern implementation, that is, a pattern implementation that is specialized for use within UML models. Rather than looking at ways in which we can move between levels of abstraction, we use UML pattern implementations within a model to ensure that we are structuring the elements within the model according to best practices. As can be expected, since we are working within a UML model, the input and output for the pattern are UML elements.

Building on the design work that has been done in exemplar analysis, we can keep the following in mind as we start to create UML pattern implementations:

• What are the roles involved in the pattern?

• What UML elements (metamodel elements) should map to those roles?

• What diagrams should the pattern work with?

• What happens as instances of UML elements are bound to the roles that participate in the pattern? Are there any dependencies between elements? What happens when elements are unbound?

• Should the pattern leverage other patterns, either as parameters or encapsulated within the pattern?

• What assumptions can be made about the pattern? What information is truly needed as input? What can be derived? What can be assumed?

• What information is needed above and beyond what is captured in UML? Are there existing profiles that can be used?

Example

For example, using products such as Rational Software Architect, we can create UML pattern implementations. In the case of RSA, a UML pattern implementation is built as an Eclipse plug-in. It is primarily built to work with structural elements such as class diagrams. When building the pattern, there is a wizard that will walk us through the creation of the structure of the pattern (i.e., the roles, rules, and dependencies). Once the wizard has generated the skeleton of the pattern, it is up to us to code the behavior of the pattern using the available APIs from Eclipse, Rational Modeling Platform APIs, and other related APIs such as UML2 API and EMF.5

Figure 13.5 shows a UML pattern implementation for the application of a Session Façade. As shown in the image, the Pattern User is able to bind elements to the pattern instance, which then updates the model elements.

Figure 13.5. An example of a UML pattern implementation within Rational Software Architect

image

This perspective is different from what we work with as we create the pattern. However, to create a UML pattern implementation we need to be familiar with the representation and the elements associated with a finished UML pattern implementation. The behavior of binding roles to the pattern instance plays a key role in how we define pattern behavior.

Figure 13.6 depicts the key classes and relationships of the elements involved as we create a UML pattern implementation; in this case we’ll take a look at the Master-Detail pattern that was introduced in Chapter 2. Starting at the top of the diagram, we see that there is a PatternLibrary class. Each UML pattern implementation that we create within RSA belongs to a pattern library, which is just a collection of related patterns. We specify the name of the library and which patterns belong to the library. The concept of a pattern library is important in helping with the consumability of UML pattern implementations. It allows the Pattern Implementation Author to group related patterns together to simplify how a Pattern User finds and works with patterns.

Figure 13.6. An overview of the elements that constitute the Master-Detail pattern

image

Moving to the next-lower level of elements in the diagram, we see an Activator class and a MasterDetail class. The Activator class is found in all plug-in projects and is used by Eclipse as it launches a plug-in. We do not have to add any code to this class. The MasterDetail class is the high-level representation of our pattern. There is one such pattern class for each pattern in the pattern library.

At the third layer of the diagram we see three classes: ListScreen, SearchScreen, and DetailsScreen. These classes map directly to the parameters associated with the pattern. We end up performing most of our coding effort in these classes. The code we write will go into methods associated with the actions related to the Pattern User binding and unbinding parameters to the pattern instance. The code that we add to these expand() methods is limited by the UML2 API, RSA API, and our imagination. Typically we add code to these methods to update the model, updating existing elements or working with new elements.

The final layer of elements in the diagram, ListScreen_DetailsScreenDependency and SearchScreen_ListScreenDependency, represent situations where we recognize that there are dependencies between some of the pattern parameters. In such situations we want to perform actions on the model based on Pattern User activity related to a set of dependent parameters.

Related Patterns and Guidelines

Exemplar Analysis (Chapter 12), Model-to-Model Pattern Implementation*, Model-to-Text Pattern Implementation*, Pattern Implementation (Chapter 12), Pattern Implementation Extensibility (Chapter 12)

Guidelines

In the following guidelines we discuss the creation of pattern specifications, automating pattern creation, and testing patterns.

Automate Creation of Pattern Implementations

Summary

How can we reduce the amount of time it takes to build high-quality pattern implementations? Create and use pattern implementations to automate the creation of pattern implementations.

Introduction

The team has adopted PBE and is creating pattern implementations that are unique to the organization. As with other initiatives, there is pressure to produce better results, more quickly.

How can we build high-quality pattern implementations in less time? Pattern implementations can be used to automate the creation of pattern implementations. Keep in mind:

• We need to be able to apply our pattern discovery and creation skills at an even more abstract level, using them to create patterns for patterns. In cases where an organization is getting started with PBE and creating patterns, it can be quite a leap to consider patterns to automate the creation of patterns.

• As the target patterns evolve over time, the metapatterns will need to be updated as well.

Explanation

As we’ve seen with the general use of pattern implementations, they can support us in building solutions more quickly and with higher quality than if we tried to perform the same work manually. We are able to use best practices and automation to ensure that those patterns are applied consistently and quickly. We can apply the same thinking to how we build pattern implementations. We can think of these as being metapatterns, that is, patterns for patterns. We can create and use pattern implementations to automate the creation of pattern implementations.

As we become experienced and familiar with creating patterns, we may find that there are cases where we are performing repetitive steps. At this point we should be conditioned to always be on the lookout for opportunities for creating patterns. We want to look at recurring solutions and see if it makes sense to not only capture them as a pattern, but to create a pattern implementation that will assist us in creating other pattern implementations.

For example, we may decide to use Eclipse-based wizards as the front end to our model-to-text pattern implementations rather than XML or UML. Thus, for each pattern implementation we build, we would also create an associated Eclipse-based wizard. Each wizard would be its own Eclipse plug-in project—a project that would need to be aware of the model-to-text pattern implementation as well as the metamodel that is associated with the pattern. Rather than going through all of the manual steps in re-creating this best-practice solution, we can recognize it as a pattern and create a supporting pattern implementation as a way to advance our efforts in building pattern implementations.

Related Patterns and Guidelines

Determine Business Impact (Chapter 11), Pattern Implementation (Chapter 12), Pattern Opportunity (Chapter 11)

Pattern Specification

Summary

How do we define and document a pattern so that it can be understood and reused? Write a pattern specification detailing the pattern name, context, problem, forces, solution, examples, related patterns, and so forth.

Introduction

We have identified a pattern and we want to define and document it so that it can be reused. Here are some considerations to keep in mind:

• Using a standardized format for recording best practices improves communication.

• A pattern specification can be used to help support the reuse of pattern implementations.

Explanation

To successfully define and document patterns, we write pattern specifications detailing the pattern name, context, problem, forces, solution, examples, related patterns, and other information about it. Without a specification, the pattern doesn’t really exist for use and reuse. Pattern specifications can also be used in conjunction with a pattern implementation, providing further support for how, when, and where the pattern implementation should be used.

In writing the pattern specification, there are a number of things to keep in mind:

• Use a standard format. A number of formats are available for pattern specifications. We need to take the time to evaluate and select a format that works for our situation.

• Gather and incorporate feedback. Get people involved in reading and reviewing the pattern before it is “released.” Note that this process needs to be only as formal as we require it to be.

• Patterns will evolve and mature over time; no one expects a perfect pattern specification upon its initial release. Resist the urge to overengineer.

• Leverage patterns that detail how to create patterns. In addition to the patterns captured in this book, there are other patterns that can be leveraged. For instance, Figure 13.7 illustrates the Pattern Language for Pattern Writing.

Figure 13.7. A graphical view of the Pattern Language for Pattern Writing pattern

image

This figure is a reproduction of Figure 29-1 from page 531 of Martin, R. C., D. Riehle, and F. Buschmann. 1998. “Context-Setting Patterns.” In Pattern Languages of Program Design 3. Boston: Addison-Wesley. Reproduced by permission of Pearson Education.

The patterns referenced in Figure 13.7, such as Single-Pass Readable, Skippable Sections, Findable Sections, Evocative Name, Terminology Tailored to Audience, and others, help us to successfully write a pattern specification. This book uses the Mandatory Elements Present pattern as the basis for pattern specifications. In following this pattern, the pattern specifications include these sections:

Pattern name: the name of the pattern, allowing others to easily reference it.

Context: the circumstances in which we would use the pattern. These circumstances place constraints on how the problem can be solved. There are times when the context is described in terms of patterns that have already been applied.

Problem: a description of the problem that the pattern will address.

Forces: the considerations that must be taken into account when applying a pattern. These considerations may at times be contradictory, so we leverage the context to help us prioritize the forces.

Solution: the solution to the problem.

A few other sections of the PBE pattern specifications are based on the Optional Elements When Helpful pattern, including these:

Example: an example of the pattern being applied.

Related patterns: a list of patterns that are in some way related to the pattern being discussed. These may include patterns that offer alternate solutions, patterns that could/should be used along with the pattern under discussion, and patterns that may solve similar problems in a more generic or more specific approach.

Some of the additional patterns used in creating the PBE Patterns include

Visible Forces pattern. Following on the Mandatory Elements Present pattern, we ensure that forces that are associated with the pattern are highly visible.

Findable Sections pattern. This pattern ensures quick and easy navigation through the sections within the pattern specification.

Relationship to Other Patterns pattern. This pattern details the relationships between patterns.

Readable References to Patterns pattern. Many pattern descriptions reference other patterns. We have used those pattern names within the write-up and have ensured that the formatting highlights the references.

(External) Pattern Thumbnail pattern. This pattern references patterns from external sources and summarizes their details. The case study in Part II also uses this pattern.

Evocative Pattern Name pattern. In a catalog of many patterns, remembering and locating them are difficult if the patterns have poor or nondescriptive names. This pattern provides guidance for robust pattern names.

In addition to using patterns to write our specifications, additional support is available in the form of specification templates. Rather than starting from scratch, we can use specification templates to give us a head start. A number of templates are available for us to use as inspiration for our own templates. These templates have been used in other books and reference websites and within many companies. If we need to, we can tweak the templates to improve the fit for our organization, but they should provide us with a high percentage of the solution that we need. In addition, the templates can be used in conjunction with the patterns discussed previously; and as we review the templates, we’ll see that they align with and have already used some of the patterns. Some of the templates to consider include the following:

GoF Pattern Specification Template. The fields in this template6 include Pattern Name, Intent, Also Known As, Motivation, Applicability, Structure, Participants, Participant Name, Collaborations, Consequences, Implementation, Sample Code and Usage, Program Listing, Known Uses, Related Patterns.

One issue that we may run into with the GoF template is that it is tailored specifically to design patterns. What if we want to capture other types of patterns? In that case we would need to either tailor the template to the type of pattern that we are using, or else look for other templates that are better suited to the type of pattern that we are detailing.

Microsoft Pattern Specification Templates.7 Microsoft has made two templates available; one template is used for architecture and design patterns, and the other template is used for implementation patterns. This highlights the fact that we can use different templates not only based on the preference of the organization, but also based on the type of pattern that we are creating. We don’t need to settle for a one-size-fits-all solution. The Architecture and Design Patterns Template includes the following fields: Pattern Name, Context, Problem, Forces, Solution, Example, Resulting Context, Aliases*, Testing Considerations*, Security Considerations*, Operational Considerations*, Known Uses*, Variants*, Related Patterns*, Acknowledgments*.

The Implementation Patterns Template includes the following fields: Pattern Name, Context, Implementation Strategy, Resulting Context, Background*, Example*, Tests*, Testing Considerations*, Security Considerations*, Operational Considerations*, Known Uses*, Variants*, Related Patterns*, Acknowledgments*.

The fields with an asterisk are optional elements. The template uses the Optional Elements When Helpful pattern. In this way we keep the number of fields to only those that are important to the pattern and those using the patterns. If an optional field/element is not needed, it is excluded from the pattern specification.

We can see from this list that although there are some variations, there is overlap, with some elements appearing consistently across the templates.

When selecting or creating a template, we should keep in mind that some fields should be captured as metadata in an asset repository, rather than just within the pattern specification itself. For instance, the author of the pattern, when the pattern was last updated, contact information, and similar details, while important, should be provided only where needed to avoid cluttering the specification.

Participating in a pattern writers’ workshop8 can be helpful in creating pattern specifications. In such a workshop, peers read and evaluate each other’s patterns and then provide suggestions for how to improve them. Although some workshops are held formally in a conference-like setting, we can use the same approach within our organization as a way to validate and improve the quality of our own patterns.

There’s even a set of patterns associated with the writers’ workshop. These patterns include Safe Setting, Authors Are Experts, Workshop Comprises Authors, Community of Trust, Moderator Guides the Workshop, Sitting in a Circle, Authors Circle, Reading Just Before Reviewing, Author Reads the Work, Fly on the Wall, Volunteer Summarizes the Work, Positive Feedback First, Suggestions for Improvement, Author Asks for Clarification, Thank the Author, Selective Changes, Clearing the Palate.9

The specifications for the PBE Patterns discussed in Chapters 10 through 16 serve as examples to support this guideline. An additional example is in Appendix D with the specification of the Subsystem Façade pattern.

Related Patterns and Guidelines

Exemplar Analysis (Chapter 12), Pattern Description (Chapter 11), Pattern Language for Pattern Writing10

Pattern Testing

Summary

How do we ensure that a pattern has sufficient quality and is consumable? The simple answer is to test the pattern.

Introduction

Quality and consumability are critical aspects of PBE. Regardless of the importance of a best practice, if the resulting pattern is not consumable or lacks quality, it will not be used. An unused pattern is a wasted investment and will lead to a failed PBE initiative. Considerations to keep in mind include these:

• Multiple roles need to come together to support the testing effort, including a Pattern Author/SME, Pattern Specification Author, Pattern Implementation Author, Asset Librarian, and Pattern Tester.

• Automating the test in the context of a pattern implementation could significantly improve the productivity and reduce the delivery time for a new pattern implementation.

Explanation

To ensure that we produce consumable and high-quality patterns we need to effectively test them. But what does it mean to test a pattern? And how do we do so effectively? Do we just reread the pattern specification? Do we check the grammar? For a pattern implementation, is it enough that the code compiles and runs?

As we get started, let’s consider the different aspects of quality that we can evaluate. First, let’s take a look at criteria that apply to both pattern specifications and pattern implementations:

• Is this truly the best practice?

• Have we accurately captured the best practice?

• Is the pattern consumable? Can a Pattern User understand and work with the pattern?

• Have we successfully provided the correct points of variability that would allow others to apply these best practices to their situation?

Here are some additional criteria specific to pattern implementations:

• Is the pattern reliable?

• Does the pattern run without error?

• Can the pattern recover from situations where invalid input is provided?

• Does it fail gracefully when it encounters an exception that it can’t handle?

• Does the pattern meet performance expectations?

• Is the pattern packaged and documented correctly to support reuse?

With these perspectives and questions in mind, it should be apparent that pattern testing represents many considerations and will impact many of the PBE roles, including Asset Librarian, Pattern Author/SME, Pattern Implementation Author, Pattern Specification Author, and Pattern Tester. All of these roles come into play as we test our patterns; each role works through the considerations that best align with his or her area(s) of specialization. The Pattern Tester is the primary participant in working through this pattern, but this role will leverage the entire set of roles in successfully testing a pattern. With this in mind, let’s take a more detailed look at how we can test patterns.

A good place to start is to ensure that the exemplar on which we are basing the pattern is of sufficient quality. Early in our pattern development efforts, we want to review the exemplar with the Pattern Author/SME. At a minimum, an exemplar should run. That’s a good start, but that doesn’t mean that it is a quality solution. We need to follow through with other normal quality-measuring steps: reviews, inspections, and testing. The exemplar is a key artifact in many ways; the first and most obvious way is as the basis of the pattern. The exemplar can also represent our first test case. We should be able to take the completed pattern and re-create instances of the exemplar.

Once we have a quality exemplar in place, we can move forward and take other steps to ensure the quality of the pattern. We can double-check the patterns that we followed in writing the pattern, as discussed in the Pattern Specification guideline.

Microsoft’s “Testing Software Patterns” publication proposes a five-part testing strategy,11 which includes

Literature comparison. Compare the pattern specification to other already written pattern specifications. We want to ensure that the specification is well formed and that the guidance that is provided aligns with already created patterns.

Solution comparison. Ensure that the solution, as guided by the pattern, is a good solution in comparison to solutions described by other patterns.

Solution testing. Ensure that the solution itself is of high quality. This step is close to traditional testing—we need to make sure that the solution that the pattern leads to is of high quality. Because we are building our pattern based on an exemplar, we already have a good start on this effort.

Technical writing clarity. Look at how consumable the writing is for the pattern specification and any other documentation that supports the pattern implementation. The directions associated with the pattern should be clear, and the flow through the pattern should be self-evident.

Brainstorming and proof by contradiction. Ensure that the pattern is correct and behaves gracefully when exception conditions arise.

We can also use the following Pattern Writing Checklist12 as a guide for checking the quality of a pattern. The checklist includes the following tips:

A Pattern . . .

• Describes a single kind of problem.

• Describes the context in which the problem occurs.

• Describes the solution as a constructable software entity.

• Describes design steps or rules for constructing the solution.

• Describes the forces leading to the solution.

• Describes evidence that the solution optimally resolves forces.

Describes details that are allowed to vary, and those that are not.

• Describes at least one actual instance of use.

• Describes evidence of generality across different instances.

• Describes or refers to variants and subpatterns.

• Describes or refers to other patterns that it relies upon.

• Describes or refers to other patterns that rely upon this pattern.

• Relates to other patterns with similar contexts, problems, or solutions.

Recall that pattern implementations built on the Eclipse platform are created as plug-ins. Thus, we can leverage the tooling and best practices associated with testing plug-ins. To test a plug-in we can launch an instance of Eclipse from our development instance; this is called a runtime instance of the Workbench. We can then inspect, set break points, and walk through the code.

We also need to make sure that we are managing the test effort, the results from the tests, and the versions of the patterns.

Related Patterns and Guidelines

Pattern Implementation (Chapter 12), Pattern Specification*, Pattern Version (Chapter 14), Update Existing Patterns (Chapter 11), Use an Asset Repository (Chapter 16)

Summary

We’ve looked at how we can create the two key types of patterns: pattern specifications and pattern implementations. Approaches to building a pattern implementation include UML pattern implementations, model-to-model pattern implementations, and model-to-text pattern implementations. This chapter discusses patterns for creating these types of patterns, as well as considerations to keep in mind as we do so. Model-to-text patterns provide a great way to get started in building our own pattern implementations. They are easy to learn and quick to build and can impact a significant portion of a project.

Pattern specifications are also a key part of our toolkit, helping us in detailing and communicating our patterns. A number of templates are available to help us in detailing our own pattern specifications. We want to standardize on a template for the organization as a way to simplify the authoring effort and also make the resulting patterns more consumable. Templates also can be used in conjunction with a pattern implementation, providing further support for how, when, and where the pattern implementation should be used.

Perhaps most important of all, we need to ensure that we are producing high-quality patterns. A focus on best practices in designing and then creating patterns is very important. But we still need to ensure that we understand how to test the patterns that we create. Regardless of the importance of the proven solution within the pattern, if the pattern has poor quality, it will not get used and our reuse efforts will fail.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset