Integrate Modeling and Design Pattern
Learn how combining application modeling with patterns can help you automate your development process. Then delve into how aspect-oriented modeling can help you take full advantage of this approach
Technology Toolbox: UML
Part 1: The Case for Modeling and Patterns
Successful software and system modeling has been a goal of both researchers and the software-development industry.
This goal is an outgrowth of the decades-long trend toward abstracting away the hardware and getting closer to the business problem. Modeling hides more of the underlying implementation, enabling designers to focus on the problem rather than its implementation. Ideally, a successful model becomes the implementation, through transformations, code generation, or compilation that provides a means of directly executing the model of the solution.
In practice, the modeling part of that equation has been feasible for years. However, the difficulty of bridging the gap between the model and the implementation has been an innate limitation to taking full advantage of modeling. The application might be modeled, but the model gets set aside as the team codes the implementation. Many software designers believed that there was value even in building a "throw-away model" because it showed the overall design of the application and the interactions of components in a visible way. However, the cost in software and project time was often deemed not worth the effort.
The gap between modeling and implementation has narrowed significantly in recent years. Today, the question doesn't typically hinge on whether you will adopt modeling, but when and to what extent. Most developers and designers associate modeling with the well-known Unified Modeling Language (UML), but there are other options.
Patterns and modeling can be complementary. Patterns refer to recurring solutions to the problems of design and implementation. They are generalized descriptions of how to go about doing a specific task, and are typically described in combination with specific types of software scenarios.
The problem with patterns, at least from an industry and practical standpoint, is that they are even more nebulous than models. They tend to make good topics for books, presentations, and discussions, but often lack a structure and approach that make them amenable to building software tools around. It's not impossible to do, but the end result tends to be limited and more difficult to use than developers would prefer.
There is little or no automated support for pattern development and implementation. Enterprises that use patterns do so as a part of a methodology, painstakingly building pattern libraries and requiring the application of patterns during application design and development. This approach works, and enterprises that practice it report significant efficiencies using it. But the level of commitment to get started is more than many IT organizations are willing to invest.
The challenge to development teams is to define specifically how modeling can help deliver higher quality software more quickly, how to integrate patterns into the design and development process, and how to create and apply a road map that enables the team to achieve the benefits of these approaches.
Building on UML
The basis for mainstream modeling today is UML. UML, standardized by the Object Management Group (OMG) and now in version 2.0 of its life cycle, provides a comprehensive graphical language for the formal modeling of software and systems.
UML is unique in that it is a formal modeling approach. Unlike most previous modeling techniques, such as flowcharts and dataflow diagrams, UML is a true graphical language, with established syntax and unambiguous semantics. Thus, any correct UML model has only a single interpretation that, unlike text-based specifications, cannot be misunderstood.
This unique approach means that UML models can be proven to be correct and consistent. Of course, the fact they are "correct" doesn't necessarily mean they reflect the desired application accurately, but they do follow a given internal logic unfailingly. It also means that it is possible to demonstrate some certainties about application models. For example, it can be proven logically whether all parts of the model are reachable from a given path through the system. If parts are not reachable, they represent dead code in the resulting application.
These provable characteristics mean it is possible to generate code directly from UML diagrams. There are limitations in doing so, but UML provides a strong foundation for creating source code, especially more consistent and structured object-oriented code. Many vendors have provided code-generation facilities based on UML.
In this context, it's useful to compare UML diagrams to flowcharts and dataflow diagrams, which can be useful in helping to understand an application, but do not have well-defined syntax or semantics. The resulting diagrams can usually be interpreted in multiple ways, and they are not effective in getting rid of ambiguity.
The biggest disadvantage of UML is its complexity. UML 2.0 consists of a total of ten types of diagrams. Taken together, these diagram types can enable a designer to describe a system or application completely (UML is not limited to software only; you can also use it to model hardware or hardware-software interaction). But it takes a significant effort to learn these diagrams and how to apply them.
In practice, it's usually unnecessary for designers to know and apply all of the diagram types. Many rely on state, activity, and sequence diagrams to design the flow of data and logic in the application. So, a given designer might use class diagrams to create the object classes, with interfaces and methods needed to implement the data and logic flow. If they do nothing else, many designers apply use case diagrams at the beginning of a project to understand the user needs better and determine how the users intend to interact with the application to accomplish specific tasks.
Even a large language such as UML has structural limitations. These limitations stem largely from the fact that different hardware and operating platforms have different ways of doing things. It's possible to have a correct and relatively complete set of UML diagrams, yet have that application implemented in myriad ways, depending on the underlying platform.
In response to these limitations, the modeling community introduced the Model-Driven Architecture (MDA). MDA purports to bridge the gap between the model and the platform-dependent implementation by defining a series of transformations from a platform-independent model (PIM) to a platform-specific model (PSM), and from PSM to code implementation. These transformations are highly dependent on the problem domain, and can be created manually or through automation. Today, few automated transformations are available, possibly because of their highly specific nature.
For many application designers, MDA adds an additional layer of complexity on top of the already complex UML. Acceptance and use of MDA by development teams remains relatively low. A part of that usage level may be because of the lack of domain-specific transformations, and the small number of MDA tools in general. However, for the majority of developers who are just in the process of getting their arms around the concepts of UML, widespread MDA adoption remains years in the future.
Perhaps the best way to establish the use of patterns is to tie them to modeling. The model represents the design, and the pattern represents the implementation. This approach makes it easier and more straightforward to build the application, even if the UML modeling environment doesn't do general-purpose code generation.
Of course, there are also design patterns (along with several other types of patterns). It makes sense for development teams to leverage both design and implementation patterns. Design patterns can describe how a particular common component in an application is structured, while implementation patterns can provide a road map for implementing that component.
Design and implementation patterns can be delivered in higher-level modeling components and plugged into UML tools to provide prepackaged designs and functionality. This approach can further streamline the process of building models and generating the resulting applications.
In practice, automating patterns is much more difficult than straightforward code generation. Patterns are intended to be general descriptions of problems and working solutions, with example code or even pseudo-code for demonstration purposes. It's not a trivial exercise to turn such patterns into useful model or code components that you can import readily into a modeling environment. This means that fully realizing the power of patterns by plugging them into automated model construction and code generation scenarios can take much longer to develop.
Modeling and pattern use are not techniques that you can pick up and use immediately and easily. The training and cultural acclimation necessary to adopt and use these approaches effectively is significant, and many developers fail to manage this on their first attempts. Many other developers look at the effort necessary to make this work, and forego trying to combine patterns and modeling altogether.
Even so, modeling bridges the gaps between the requirements, specification, and implementation of an application. Code generation is fast and at least adequate in quality and performance when you apply it to specific parts of an application rather than the entire application. Patterns can also fill in when code generation doesn't provide a good solution.
It would be a mistake to attempt to adopt MDA immediately if you're not already practicing UML modeling or using a comparable, formal modeling approach. Rather, you should create a multiyear road map that takes you there in gradual steps.
Start with use cases at the beginning of the development process to understand user interaction with the application. Once the team is proficient in creating, understanding, and working from use cases, you can move to modeling aspects of your implementation. Plan out the application's execution path with sequence diagrams, and get used to envisioning your objects as class diagrams. After you work on one or two projects, the team will likely start thinking about design and implementation in UML. At that point, you'll be on your way to realizing the benefits of modeling.
At the same time, be sure to provide a searchable repository for patterns and encourage developers to document ways that they solve specific problems. These repositories might not prove useful immediately, but you will have begun cataloging your solutions, which will pay off down the road. After a year, have the team take a couple of days to go back and refine the items in your repository so that the items are more general in nature. With a few iterations, you have the beginnings of a patterns library.
This gradual adoption process can take a couple of years to establish good UML practices, and several more years to get to full MDA with regular pattern development and use. The end result, however, is better software, developed more quickly, which makes your investment in time and effort ultimately worth the cost.
Part 2: Try an AOM Approach
Aspect-oriented modeling (AOM) represents the next step in the use of patterns for model-driven development. Its application can improve developer productivity, as well as the quality and fidelity of the developed model and its resulting application.
Organizations can use pre-made patterns as-is, or develop them from scratch (or even something in between). Then, they can assemble a domain-specific patterns library that not only increases productivity, but adds another layer of consistency to the development process. Modeling tools that readily support patterns and provide pattern libraries can make this approach easy and efficient for all concerned.
I'll walk you through how you can put aspect-oriented modeling to use, but first let's review the circumstances that led to this approach. The use of design patterns in software programming has been a standard industry practice for many years. Developers use patterns to represent an entity's common characteristics and allow repeated application or re-creation of that entity. Developers use patterns throughout engineering disciplines, but have recently been using them to augment software modeling.
In fact, many unified modeling language (UML) modeling tools today have some kind of pattern support built in or are available as an add-on module, such as a large, user-modifiable library of classic software and systems engineering patterns that an architect or designer can access when creating a new model or modifying an existing one.
The application of patterns to modeling makes sense; there are many useful patterns that you can use to build architectural and design models of complex, distributed systems and enterprise applications. Using design patterns for model-driven development can increase the productivity of the architect, designer, and developer, much like the benefits from using patterns when programming.
Using design patterns also significantly increases the readability, understandability, and maintainability of the models themselves—especially when utilized by large, distributed design teams. There have been dozens of useful software patterns identified so far, many of which are in common use today. One of the most common is the Observer pattern, which is employed by almost every modern user-interactive software application.
Applying patterns to systems architecture is also an emerging technique. Rather than focusing on detailed algorithmic or procedural issues, patterns at the systems or enterprise-level work with high-level concepts and network structures. These kinds of patterns can assist architects in creating more understandable views of their enterprise, systems, and applications.
Copy-and-paste remains a state-of-the-art technique for implementing most patterns used in modeling tools today. That is, when a model builder recognizes that a particular diagram or system component could be addressed with a known pattern, he or she selects an appropriate pattern from a library and uses the modeling tool to apply it to the diagram. The modeling tool then might access the pattern's definition automatically and prompt the user to fill in the names for placeholder items.
In more advanced cases, the modeling tool itself can attempt to analyze the existing diagram and apply the pattern to elements already displayed or preselected by the user. These attempts at automation yield varying degrees of success, but in all cases they complicate what was once a simple model. It can be even more confusing if the tool tries to apply a copy-and-paste pattern to dynamic parts of a model, such as executable activity diagrams and state machine diagrams.
The copy-and-paste approach can work in some cases, but it falls apart when you need to apply the same pattern needs to a large number of model elements and/or diagrams (sometimes called a crosscutting pattern). Even with the previously described automation, this approach isn't rigorous enough to ensure accurate and thorough coverage. Missing a pattern or applying one inappropriately can undermine the modeled application's accuracy and efficiency.
The next major step in using patterns is borrowed from an emerging technique called aspect-oriented programming (AOP), where source code constructs are analyzed for crosscutting concerns, or common needs or edits, and matched with a set of advanced pattern-matching rules and model fragment templates. When rules are matched, their corresponding templates are applied and filled out automatically. When applied to modeling, templates can be applied recursively to make significant changes to a model, from its overall structure all the way down to individual dynamic elements like function calls or signaling.
Given that there are formal syntax specifications and rules about describing the patterns, their matching rules, and their precedence, this approach enables you to achieve a significant amount of automation and audit it with a high degree of confidence.
You can improve productivity dramatically using the right patterns and automation. For example, an architect or designer could create models for only the positive case for many parts of a system. Then, using an aspect pattern and automated application rules, the architect or designer could apply crosscutting special-case or error-case model fragments (including dynamic parts of a model) across an entire system model.
Let's compare adopting a UML-based versus aspect-oriented model approach. Assume that a communication must happen between two cooperating tasks or instances of an application (see Figure 1).
In a UML model, this communication might be expressed in a clear, simple state machine diagram that shows a message is sent and a response is expected. However, a real-world message might not arrive or not receive a response, so the architect or designer must add error checking, a timer and time-out processing, as well as error handling to the model. The result: Your once simple, easy-to-understand diagram that describes interprocess communications has become complex and difficult to understand.
The aspect-oriented model can help you overcome this challenge. Simply apply a set of rules that cover what to match (a signal send followed by a signal receive) and what to put in (a timer, wait state, timer timeout, or error-handling block). Then, modify the model automatically with the additional model data immediately before code is generated and the modifications are discarded, leaving the model in its pristine state, just as the architect or designer created it.
You can achieve further gains by applying aspect patterns across an entire model at the same time. For example, if a pattern is applied that does special timeout tests for interprocess communications, then the model and code that check for the timeout are consistent, correct, and complete in every single case where it is needed. This application also removes the burden of knowing, understanding, and applying huge libraries of patterns on the architects and designers. In many cases, designers will only use the patterns they are familiar with, even when another pattern might be more applicable, or miss some opportunities for pattern application altogether.
When using aspect-oriented modeling techniques, only a few pattern experts (at the project, system, or enterprise level) need to be intimately familiar with the different kinds of patterns and their use. Application designers and developers can then work with simplified models, building the positive cases quickly, and allowing the aspect processing to add the repetitive details.