Microsoft Guidance Automation Package (GAT) and Domain Specific Language Toolkit (DSL)
are two key technologies, recently released by Microsoft, which allow architects and developers
to author and package guidance and domain specific languages.
GAT and DSL offer considerable value when used on a separate basis, and even more when used together.
And, given that Victor Aprea (Clarius Consulting) and I have been working on GAT/DSL integration for some time,
we decided to publish a paper about it.
So, here they are few GAT / DSL integration scenarios…
Providing DSL users with context / guidance
Every Domain Specific Language is designed and implemented based on the requirements
of the domain it is intended to model. When that language is used as part of the development
process of a given solution however, the solution’s context may affect the way that language
is used and how its artifacts are consumed.
For starters, DSL users will need to know whether there are only specific places in the solution
structure where DSL instances should be created/stored. And, it’s the task of the guidance provided
with the solution template to support and enforce these solution’s well-formed-ness rules.
Again, it must be noted that this knowledge may not be available to the DSL author.
Imagine a business analyst is using a Business Process DSL while developing a solution
within Visual Studio. That analyst may not have the necessary information and skills to determine
where to put the Business Process model files inside the solution, or how to process them.
In fact, that knowledge belongs much more likely to the solution developer.
Additionally, for each artifact that can be created using a certain DSL, developers will need to know
what the artifact lifecycle is, in the context of a solution development process in which that DSL is used.
In fact, the DSL toolkit support a very basic lifecycle –i.e. create, save (possibly delete),
apply report templates - for DSL model files.
The designer of a specific solution may want to change and extend that lifecycle significantly.
For example, certain pre-conditions -verifiable at solution/project/file level in the solution- may need to
be validated before a DSL instance of a certain type may be created. Or, as we will see more in details
later on, the use of one language may be affected by and/or dependent by other DSLs used in the same solution.
In a way similar problems need to be solved for all the artifacts in a solution. For example,
solutions developers need to address same problems for source code files or even binaries.
However, usage scenarios for programming languages are much more predictable, because better known,
than a generic DSL. Similarly, DSLs virtually span through many level of abstraction and their scope can
be very different from one another. That makes providing the necessary guidance to enable the DSL
artifact life cycle very important.
As part of that guidance, DSL users will also need to be educated on which procedures or commands
can be applied to language instances, and which artifacts will be created – if any – when these commands are applied.
For example, a designer of a solution may have created various transformations that
–depending on the solution’s state – may be applied to instances of a certain DSL.
So, commands to launch these transformations may appear - within a context sensitive menu -
when the developer selects certain DSL model files, or model elements or even a DSL design surface..
Indeed, GAT can be very effectively used to provide DSL users with necessary guidance about how
to use a certain language and to embed into a solution the necessary support for the specific lifecycle
on DLS’ instances, model elements, etc...
Using GAT to extend consumption of DSL artifacts
Using DSL Toolkit, a DSL author can define transformations on DSL instances in order to create various artifacts.
An example of a transformation can be the compilation of instances of a custom application
architecture language into programming modules containing classes implementing the applications
or patterns defined by that architecture.
In order to define a transformation, a DSL author uses the DSL debugging environment,
which is natively provided by the DSL toolkit when a new DSL language solution is created,
and that provides start up transformation templates.
To make transformations available to language users, templates need to be copied
inside the solution or project where the instances of that language are created.
Solution developers can select a transformation template and apply it to the language instance,
just asking the development environment to apply the template.
When launched, a transformation may load one or more models of one or various DSLs
to get its input data. However, the artifact generated must be directed to a single file. This last fact,
depending on the particular development scenarios, may be perceived as a significant limitation
on use and adoption of DSL.
On the other hand, GAT can be used to overcome this evident limitation.
In fact, GAT recipes make it easier to invoke transformation templates from within code.
And, the recipe writer can more freely determine where to direct the output of the transformation,
if one or more artifact are generated as results of the application of that transformation.
For example, a recipe can be written which repeatedly applies a text template to the same model,
perhaps using different model elements each time and generating different artifacts, one per model element.
Interestingly enough, the transformations developed by the DSL author within the DSL toolkit debugging
environment can be brought – almost with no changes – into the GAT package containing the solution guidance.
In this way, a solution developer can also apply different transformations to the same model element
or have a single transformation that applies to various model elements even of different languages.
By using additional libraries (for example Clarius has started developing one) you can have your T4 templates
accept both, GAX recipe arguments and T4 model files, giving you a powerful combination in terms
of the code you can write in the template.
DSL cross language integration
As mentioned in our introduction, DSLs are generally relatively small, highly focused languages used
to model and solve certain -clearly identifiable- problems that various developer roles may have
to tackle as part of the software development lifecycle.
The limited scope of a DSL should not be perceived as a negative factor though.
Actually, the smallest the scope the greatest is the language potential effectiveness in solving problems
that belong to that scope, and supporting the specific needs of roles who are supposed to be the primary
stakeholders for the area of concern/abstraction level (viewpoint) that is associated with that scope.
Nevertheless, in many cases, architects and developers need to be able to navigate through various viewpoints,
i.e. through different areas concerns and across various abstraction levels. Other times, they need to be able
to transform artifacts created while designing and developing a certain viewpoint, into other artifacts
belonging to a different viewpoint.
Navigation across viewpoints and transformation of related artifacts imposes new requirements on DSL design,
especially in terms of integration among them. Perhaps the most important is the ability to refer to model elements
of one language from a different one (more specifically from the latter’s model elements or properties)
For example, let’s assume modeling of Business Message Types and Business Entities in developing
a SOA application has been done using two different DSL. While using the Business Message Types DSL,
the message designer may need to refer to instances of business entities, specified using the other language,
in order to specify the payload for the message.
The current release of DSL toolkit does not support any integration across different DSLs. More specifically,
it’s not natively possible to refer from the model elements or properties in a language to those modeled
and instantiated in another one.
However, that level of integration can be programmatically obtained. In fact, a DSL integration service
can be designed to allow DSL author/users to browse through model elements defined in different languages
and to establish the necessary cross language references. Additionally, one need to develop custom property
editors that will extend the DSL user interface to activate the integration service, and allow DSL users to actually
instantiate cross language references.
While GAT does not provide any native mechanism to support DSL cross language integration,
once the integration service is available GAT recipe patterns can be used to package the necessary
integration capabilities in a way that makes it easier for the solution developer to use.
We have developed a DSL Integration Service that we are now testing with the preliminary bits of the version of
DSL Toolkit that will be released later on august. We will make these bits available to the community at large for test.
DSL constraint checking across languages
Using the DSL toolkit, a DSL author can specify as many validity checking and constraints as necessary,
within a single DSL. All she/he needs to do is to define extension to the classes implementing certain modeling
elements, following the guidelines offered by the validity checking framework provided with the DSL toolkit.
Checking the validity of the constraints on the model instances can be activated on demand or
when particular events, like file save, happen.
However, for the very same reasons why one may need to integrate different DSLs, validity checking may
need to be extended to span across multiple languages.
For example, a DSL may define a model element named Business Process, which refers to
Business Rules that have been defined in a different language. Of course, for the model to be valid
– as a whole – instances of the Business Process in the first language have to refer to Business Rules
that exist in the second, i.e. have been instantiated using the Business Rules DSL. In this case, the solution
developer can use cross DSL integration to make sure models created are valid by design, instead
of having to check it afterwards.
So? what do you think?
Are we missing something important?
What would be other integration scenarios?
Mauro Regio
Architect | Microsoft Corp.