Chapter 15. Using Domain-Specific Languages with Patterns

Domain-specific languages (DSLs) and patterns can each boost productivity, simplify how we represent solutions, and support the use of automation. With such capabilities they can improve the quality of solutions, reduce time to market, and help us to leverage skills within the organization. Fortunately, DSLs and patterns are complementary topics. There is a synergy between them that allows us to further boost productivity, quality, and how we leverage expertise beyond what can be achieved by using them in isolation. This chapter will look at patterns and guidelines that support DSLs and patterns.

In addition to looking at how we can best use patterns and DSLs together, we will also look at guidelines to use in designing and creating DSLs.

Patterns

The following patterns provide guidance on how we can use model templates to support the consumption of DSLs and how patterns and DSLs can be used together.

DSL Model Template

Context

A DSL has been created and we want others to succeed in working with the DSL.

Problem

From a user perspective, when modeling with a DSL it is unclear how to get started. Starting with a blank screen can be intimidating and disorienting. How should models be structured? What diagrams should be created? What language elements should be used together?

Forces

• Often a model can be structured in multiple valid ways. Some users might think that the template provides the only valid approach.

• Model templates need to be updated as the language and best practices evolve.

• By default, nothing realigns the model with the template. So if deviation from the template occurs, the model may need to be realigned manually.

Solution

For many, it can be quite intimidating to start a project with a blank screen. What do I need to create? Where should it be put? How do the elements relate to one another? Even in cases where we have provided the user with patterns to be used within the model, it can be confusing and intimidating to try to figure out where those patterns should be used.

To assist in creating models based on a DSL, provide a model template. A model template provides a default structure with which to get started using the elements provided by the DSL. This includes guidance on the packages to use and what goes in the packages, as well as guidance on elements that are used together, default diagrams, viewpoints/perspectives, and documentation.

A model template should be created as the DSL starts to solidify, and it can be used to test out the DSL. Some questions to ask in building the template include these:

• What are the different diagrams that the language supports?

• What are the relationships between the diagrams?

• Are there timing considerations in regard to when each of the diagrams should be created?

• Of the available language elements, which are the most common? Which are the least common?

• What are the expected user roles that will need to work in creating models using the language? What are the expected user roles that will need information from the model? How do the needs of these roles align? Differ?

• How will models feed into other work products? Are there associated model-to-model or model-to-text pattern implementations that the models will need to work with? Do they have requirements for how input models need to be structured?

Are there patterns that should be used within the models? What diagrams do they relate to? Are there any timing or ordering issues related to the use of patterns and the DSL elements?

Example

When working with Rational Software Architect (RSA) to create SOA-based solutions, you can use the Software Services Profile1 to create models of your solution. The DSL contains the elements shown in Figure 15.1. As expected, when working within the SOA domain, we see model elements such as Service, ServiceProvider, ServiceConsumer, Message, and other domain-specific terms.

Figure 15.1. Graphical view of the Software Services Profile

image

However, for the user it can be confusing to figure out when and where to use these elements. How should you structure the model? Are there recurring ways in which the elements should be used together? Are there different viewpoints/perspectives that should be supported? Looking at the elements and basic relationships is a difficult way to figure out answers to these questions. Documentation and tutorials offer some assistance, but they require us to remember the details rather than guiding us toward a solution.

Figures 15.2, 15.3, and 15.4 are views of a template providing guidance on how the model should be structured, covering the following:

Perspectives. As shown in Figure 15.2, there are three suggested perspectives to use: Collaboration, Message, and Service, marked with the «perspective» keyword.

Grouping elements. As shown in Figure 15.3, the template, via a set of Reusable Design Elements, provides guidance to the user regarding how elements should be used together. For instance, there is a set of elements that come together to create a «serviceProvider». The set will change depending on whether it is a complex service, a legacy provider, or just a simple provider.

Naming guidance. Figures 15.3 and 15.4 show how the template provides a set of parameterized names for the different types of model elements and diagrams. The idea is that the user of the template can copy and paste elements from this package and use them elsewhere in the model. Each of the reusable elements has a parameterized name indicated with ${} characters. Typically the name is composed of a static portion and a dynamic portion, enabling the user to create a meaningful name that follows convention.

Figure 15.2. An overview of a model template for use with modeling SOA solutions

image

Figure 15.3. A view of the diagrams provided by the SOA model template

image

Figure 15.4. A view of the structural elements provided by the SOA model template

image

Related Patterns and Guidelines

Integrated Patterns and DSLs*

Integrated Patterns and DSLs

Context

When building a software solution, we need to simplify the development effort with the goals of boosting productivity, increasing quality, and improving governance of the effort. The members of the team have varying skill levels and areas of expertise in both the business and technical domains.

Problem

How can we provide the team with an environment that assists them in building solutions specific to the domain? More specifically, how can we raise the level of abstraction and have the team focus on the problems to be solved while preventing them from getting lost in the details of the development languages? And how can they do so in a way that leverages proven best practices?

Forces

• Languages that are specific to a domain, as the name suggests, are specific to a certain situation. This limits the transferability of skills because the domain is narrower. With a narrower domain we find that there is less availability of training, documentation, support, and skilled people. In contrast, a generic language and associated tooling are easily transferable and widely supported (tooling, education, books, etc.).

• Time is needed to find exemplars and best practices before patterns can be created for use with the DSL.

• Tooling to support the language needs to be created. The amount of investment will vary depending on the capabilities of the underlying platform and the complexity of the domain.

Solution

Use a DSL—a language that captures information for a specific problem domain—and patterns in combination so that we can work at a level closer to the solution space, while also leveraging best practices in the form of patterns. Such a language can be graphical or textual. The key point is that it is targeted to a specific area and is not meant to be used generally across a range of problem spaces. This is in contrast to a general-purpose language, which is used to solve problems across many domains.

As discussed with regard to the Simple Solution Space pattern (Chapter 10), we aim to boost productivity and improve quality and governance by simplifying the working environment. One way to accomplish this simplification is to get closer to the problem space by focusing on the domain. The domain could be related to technology or business, but typically we are trying to solve the problems of the business, and it benefits us to be able to think in those terms. This allows us to more easily discuss the solution with our business counterparts, confirm requirements, and build a solution that meets their needs.

As shown in Figure 15.5, there is an overlapping relationship between a domain, a DSL, and patterns. The DSL is entirely contained within the domain, whereas patterns partially overlap. Patterns provide us with support in the domain but also assist us as we make the transition from a domain into other domains such as a technology-specifc representation.

Figure 15.5. Abstract view of the relationship between a domain, patterns, and a DSL

image

When we look at general-purpose tools, we find that they present a number of challenges. That a general-purpose tool can apply to any situation is both its greatest strength and greatest weakness. Having general-purpose tools allows us to find many resources that can help us solve problems. Support for general-purpose tooling is widely available via training and documentation, and it is relatively easy to find skilled practitioners. However, generality is also a weakness, because the tooling is not targeted at any specific situation. We need to understand how to map between general concepts and the needs and demands of our problem space. So now not only do we need to figure out the solution, but we also need to figure out how to map between concepts in the problem space and the generic concepts we have available in our tooling.

As seen in Figure 15.6, there are a number of ways in which DSLs and patterns support and work with one another. Let’s take a more detailed look at each of the interconnections:

Guide model structure. Regardless of the language that we use in creating a model, our goals are always the same. We want to leverage best practices in capturing a representation of the solution. We can use patterns and DSLs to help us achieve these goals. The DSL narrows the solution space and can also provide rules, constraints, and validations to help specify the solution. An associated model template can provide guidance on how to create the model. However, we can take things even further by using patterns. One or more patterns can be used within a model to guide us in constructing portions of the model.

Simplify user model. A user model provides input into a pattern. However, we want to make the use of the pattern, and in turn the creation of the user model, as simple as possible. To do so, we can use a DSL that provides us with a narrow solution space, a set of constraints and rules, and support for validating the correctness of the user model. In combination, these elements make it easier for a Pattern User to create a correct user model.

Automate model consumption. Ideally, a model should be used for communication, design, and generation. A DSL alone can certainly address the first two aspects: communication and design. However, pattern implementations play a key role in assisting us in working with a DSL and generating aspects of our solution. When we look at generating output from a model, we find that we can generate a higher percentage of the solution when we narrow the domain space. As we narrow that space, we are able to make more assumptions and leverage rules and constraints to help us in mapping elements from a modeling representation to output elements.

Figure 15.6. Patterns and DSLs leverage and support one another.

image

In summary, use patterns and DSLs in combination. Together they enable us to boost productivity and improve quality and governance by guiding us in structuring our models, simplifying the creation of user models, and automating model consumption. And although DSLs and patterns can be used in isolation, higher value is achieved by using them together.

Example

In Chapter 5 we see the Oslec team create the Subsystem Façade profile to be used with the Subsystem Façade pattern. They use a name specific to the pattern, as for now the goal is to use the DSL specifically with this pattern. If, at a later time, they determine that there is wider applicability for the DSL, they can consider a new name or enhancements as needed.

Related Patterns and Guidelines

Pattern Implementation (Chapter 12), Simple Solution Space (Chapter 10)

Guidelines

These guidelines focus on advice for how to design and create DSLs.

Create a DSL

Summary

How do we take a design as input and create a DSL? Typically we build an implementation of the DSL using either a specialized language creation framework or a general-purpose language that has extension capabilities.

Introduction

We have determined that a DSL is needed because generic modeling languages do not meet the needs of our situation. We’ve already invested time in creating a design for the DSL. How do we use that design to create a DSL? Considerations to keep in mind include these:

• As the underlying platform evolves, we will likely have to update the DSL and its supporting elements.

• As the target domain changes, we will likely have to update the DSL and its supporting elements.

Explanation

By formalizing the language, in terms of specification as well as implementation, we support our PBE efforts. By putting the DSL into tooling, we further automate our design efforts and provide users with familiar domain terms and concepts in their design environment. Automation of model consumption is not possible with an informal language.

To create the DSL in tooling we use a framework to help build the implementation. We either use a specialized language creation framework or a general-purpose language that has extension capabilities.

We have a number of choices in building tooling support for DSLs. To keep things simple, we’ll look at two examples, one from a specialized language creation framework and another from a general-purpose language that has extension capabilities. When working with Eclipse, the Eclipse Modeling Framework (EMF) fills the role of language creation framework, and UML fills the role of a general-purpose language that has extension capabilities.

UML is a general-purpose modeling language and can be used to model any type of software solution. However, because it is general-purpose, we end up using constructs and language elements that are generic; they are not specialized for any specific domain. Even as a general-purpose language, though, its supporting specification is lengthy. To be targeted and specific to many domains, the language would be unwieldy and no one would be able to use it. To address this issue, the creators of the language supplied it with an extension mechanism, known as Profiles, which allows the language to be customized and made specific to a domain.

EMF is an interesting language in that its domain is related to creating other languages. With respect to Eclipse-based tools, the UML2 API is actually built using EMF.

When looking at these two options, there are a number of considerations to keep in mind:

Freedom versus reuse. When choosing between UML and EMF, we need to weigh the trade-offs between how much freedom is provided by the framework and how much preexisting content and support we can reuse. If we choose freedom, via EMF, we will essentially be starting from scratch. If we choose reuse, via UML, we become constrained in our implementation. With UML we also have to take time to simplify the user experience. Ideally, our tooling is able to hide diagrams and model elements that are not relevant to our domain.

Simplicity. When using UML, the extension mechanism is simple and much of the work can be done without writing any code. In addition, many preexisting facilities are available to work with UML-based languages and support merging, creating subunits, and team model use. EMF is a more involved effort and takes longer to implement.

User education. UML is a widely known and supported language. If we build our DSL using UML, we are able to leverage this supporting infrastructure and draw upon a large pool of talent that is already familiar with the base of our DSL. In the case of an EMF-based language, we have fewer constraints in our implementation; however, the more we deviate from standard languages, the less likely we are to find individuals who have relevant experience.

Related Patterns and Guidelines

Design a DSL*, Integrated Patterns and DSLs*, Simple Solution Space (Chapter 10)

Design a DSL

Summary

How do we design a consumable and high-quality DSL? When building a DSL, we need to use a meet-in-the-middle approach that accounts for language scope, granularity, semantic completeness, user friendliness, and tool friendliness.

Introduction

We have determined that a DSL is needed because generic modeling languages do not meet our needs. How do we design a consumable and high-quality DSL? Keep in mind:

• We must understand the other assets that we have available, or could have available, to help us in creating a useful and productive work environment. These could include, but are not limited to, patterns, model templates, UI customization, documentation, and wizards.

• We should use both high- and low-fidelity approaches to representing the solutions we are creating. Low-fidelity approaches can be used to quickly and inexpensively determine whether solutions will work with the expected consumers of the resulting deliverables.

Explanation

When designing a consumable and high-quality DSL, some key considerations to keep in mind include the following:

• Is the language easy to understand?

• Is it complete?

• Does it avoid redundancies?

• Does it avoid asking the user to provide information that could be calculated?

• Does the language limit the number of elements that are used?

• Do the language and associated modeling environment guide the user to successful use of the language?

To design a DSL that meets such requirements we need to consider the right aspects and use the right approaches. First let’s take a look at some of the aspects that we need to consider:

Scope. As we look at the elements that form the basis of our language, we want to ensure that the language has the right scope. We don’t want too many elements, but only those elements that are truly needed for our practitioners to successfully use the DSL.

Granularity. We want to ensure not only that we have a full vocabulary, but also that the elements have the correct granularity. Are we putting the correct level of detail in the model and its elements, and then using assumptions, rules, and configuration options to capture other details as appropriate?

Semantic completeness. Do the language elements selected allow us to describe solutions in the problem space? Are all the elements in the language useful and purposeful? Do all of the arrangements and uses of elements make sense?

User friendliness. The language needs to be user-friendly. Those who work with the solution need to be able to understand and work with the language.

Tool friendliness. We also need to look at how we can implement the language in tooling. As we look at the design, are there aspects of the language that would be difficult to implement in tooling? Are there ways in which we could alter the design to make it easier to put into tooling? Are there aspects of the tooling that we can leverage to help simplify the use of the language? For instance, can the tooling platform assist in creating palettes? Hide unnecessary views, diagrams, and elements, especially those not related to the DSL?

Implementation considerations. As part of the design we also need to consider how the design will be realized in an implementation. The tooling and language that we use to realize the design will have an impact on the choices that we make as part of the design. Two common approaches to building the DSL are to use a specialized language creation framework (for example, EMF) or a general-purpose language that has extension capabilities (for example, UML).

With these aspects in mind, let’s take a look at the approaches we can use to design a DSL:

Meet in the middle. Use a meet-in-the-middle approach that combines aspects of top-down and bottom-up design.

From a top-down point of view, we are looking at things from the perspective of the domain and the end user. What is the vocabulary of the domain? What are the key concepts? How do they relate? What skills do the users of the language possess? Do rules and best practices exist in the domain? Some details may be captured in documentation, but others may exist only as tribal knowledge. We can also look at other languages for ideas about what is needed in our new language. In particular, what elements and diagrams exist in other languages?

From a bottom-up point of view, we are looking at things from the perspective of how we are going to consume the language and use it to generate other aspects of the solution. Are there patterns that need the DSL support? What do the patterns expect for their input models? How does this reconcile with the details that are emerging from the top-down perspective? We end up with a balancing act where we need to be aware of the elements at the lower level of abstraction, but we also don’t want to overly influence the language in the DSL, which is supposed to be at a higher level of abstraction.

Balance. We need to balance these characteristics. We can’t have a language that is focused on user friendliness to the exclusion of being tool-friendly. We cannot have a solution that focuses on scope to the exclusion of granularity and semantic completeness.

Sketching. Do not rush into implementation and use of tooling in the design of the language. As we begin our design efforts, we can take advantage of simple tools such as pen and paper or whiteboards to sketch out the language. What are the elements within the language? What properties are associated with the elements? What are the relationships between the elements? Once we feel that we have a good start in describing the language, we can begin to create draft storyboards for some of the use cases associated with the domain we are attempting to model. How well does the language help us to describe the solution? We may also want to include experts from the domain in these sessions to help us in both the design and use of the language.

Storyboards. Work with users and discuss different scenarios where the language will be used. Then use storyboards to detail the solution using the language. Will the language allow us to describe solutions? Are our users able to create storyboards successfully with the current design? What feedback do they have? How can we incorporate this feedback into our design?

Model. Create a model to visualize the language elements, their properties, and their relationships. This can help to further refine the language and also serve to communicate details of the language to those implementing aspects of the tooling and related patterns.

Review existing languages. Last, but not least, we can take time to look at other existing languages, whether it’s UML or an existing DSL. As we examine the existing artifact, we can give thought to how that language serves the needs of its audience.

Related Patterns and Guidelines

Create a DSL*, Integrated Patterns and DSLs*, Simple Solution Space (Chapter 10)

Meaningful Icons in a DSL

Summary

How do we make the DSL more intuitive, user-friendly, and easy to work with? Use meaningful and easy-to-understand icons to provide visual cues to those using the DSL.

Introduction

We have determined that a DSL is needed because generic modeling languages do not meet the needs of our situation. We’ve already invested time in creating a design for the DSL and are working on the implementation of the DSL.

It can be difficult to understand what certain aspects of a DSL are intended to mean. For example, generic lines, boxes, and shapes do not convey enough information and guidance to the user of the language. We want to ensure that communication with the DSL is as straightforward as possible. What can we do to make the DSL easier to work with? Considerations to keep in mind include these:

• We need to be able to produce or procure a set of icons that are meaningful within the domain.

• Graphical representations can be open to multiple interpretations. Consultation with the expected user base is essential to ensure that they interpret the icons as anticipated.

Explanation

We should use meaningful and easy-to-understand icons to provide visual cues to those using the DSL. Just using a generic box leaves the user guessing and leads to misinterpretation. With training, the user will learn the meaning of such elements, but the burden of remembering the meaning is on the user.

Instead, we work to use useful and meaningful icons within the DSL for each of the graphical elements within the language. The icons should be related to the domain and clearly communicate the meaning of the language element.

As shown in Figure 15.7, when working with RSA to create SOA-based solutions, we can use the Software Services Profile. In contrast, Figure 15.82 provides an overview of the language using just lines and boxes. The lack of meaningful icons makes the language much less intuitive.

Figure 15.7. Graphical overview of the UML Profile for Software Services using meaningful icons

image

Figure 15.8. Graphical overview of the UML Profile for Software Services with only lines and boxes

image

Copyright IBM developerWorks, www.ibm.com/developerworks. Reused with permission.

Related Patterns and Guidelines

Create a DSL*, Design a DSL*

Summary

Using DSLs and patterns together allows us to boost productivity, quality, and how we leverage expertise beyond what can be achieved by using them in isolation. However, it is not as simple as just saying, “Use DSLs and patterns.” We need to give thought to how they should be used together and how we can design and implement a quality DSL, one that works well with patterns. In addition, we can look at how to drive consumability via the use of model templates and meaningful icons.

In Chapter 1 we discussed the importance of creativity and the freedom to be creative. As we create a set of DSLs and patterns that work together, we are indeed placing constraints on how the team will build the solution. However, we have not eliminated creativity or the freedom to create. Rather, we have moved the target to channel creativity into areas of higher value. We need to be creative in figuring out the DSLs and patterns that will be used to deliver a solution.

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

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