Clipcode-GoF-DSL and the One-To-One Mapping Anti-Pattern

Last week Eamon O’Tuathail of Clipcode released a Domain Specific Language (DSL) for some of the Gang of Four design patterns using theMicrosoft DSL Tools for Visual Studio 2005.

It is indeed a very remarkable proof of concept and although the implementation is still pretty rough, it represents a valuable model for discussion and learning.

Eamon is very active (particularly) within the Irish community and he is a regular speaker at the Irish .Net Developer Alliance (INDA) events where I often see him.
I briefly talked to him last night as we both were present at the excellent Roy Osherove’s talk on agile development and unit testing best practices.
Eamon told me that he only spent a couple of days developing it; this is something I consider rather impressive given the premature stage of the supporting tools currently available (I bet that his superb documentation took him more time to develop ;-)).

The DSL designer currently allows setup and code generation for five patterns:

  • Abstract Factory
  • Builder
  • Factory Method
  • Prototype
  • Singleton

Overall, I liked the organization of the code templates in the debug solution, as they are neatly located in a common folder and are referenced only through the ClipcodeEngineTransform.ReportTemplate file which acts as a template controller for all the instantiated designers.

Besides some understandable limitations of both the language and the underlying platform (i.e. the DSL Tools) that will be undoubtedly addressed in future releases, my main interest (and point of concern) lies in the level of abstraction of the model.

Using the language to generate code that realizes a pattern is pretty straightforward as the designer diligently constrains allowable classes and connections.
However, my worry is that, in order to realize a pattern, you need to select every single participant (class/object) from the toolbox and manually connect it to the permitted collaborator(s). As a consequence, you end up creating a diagram that matches quite closely the classic UML representation of each pattern. But do we really need to visualize the structure of a pattern?

As my exploration of the Domain-Specific Modeling (DSM) world progresses, I’m more and more obsessed by the idea that if we want to create the biggest ROI, it is essential to push our models towards a level of abstraction that is significantly higher than the level at which code statements and classes are written.
In other words, a one-to-one mapping between a class created in a diagram and a class generated in code does not generally save enough time and I would dare to consider it an anti-pattern.

A symptom is that the toolbox is generally filled with lots of different elements even if the main concepts (in this case the GoF patterns) are more coarse grained.

So here is a challenge that anyone interested can take. In order to realize an abstract factory, I should need to drag only one class on the designer (e.g. AbstractClassRealization) and setup its participants (AbstractFactory, ConcreteFactory, AbstractProduct, ConcreteProduct) using compartments only. Is it possible? I guess so. I will try soon anyways.

By the way, if you think about it, a GoF pattern is still at a pretty low level of abstraction. In fact, it is the very essence of an OO pattern to address recurring cross-domain concerns. So a “real” DSL may still be built on top of it and possibly provide an even higher return of investment for your organization.

Claudio Perrone

My passion is to develop the critical thinking skills of people and help them bring the best of their work to the world. Lean & Agile management consultant, startup strategist, award-winning speaker and entrepreneur. Creative force behind A3 Thinker and PopcornFlow.

This Post Has 5 Comments

  1. Eamon O'Tuathail

    (note: reply copied from http://forums.microsoft.com/msdn/ShowPost.aspx?PostID=64106)

    Claudio,
    Interesting comments.

    “What is the most appropriate level of abstraction for DSLs?” is a question that will be frequently asked when folks are thinking about creating DSLs. There are a variety of ways of categorising DSLs, but for now if we just look at closeness to code, we can think of DSLs in terms of high-level, medium-level and low-level.

    An example of a high-level DSL would be one for web services. I bet there is a team somewhere in Redmond working hard on a DSL for Windows Communication Foundation in Vista (which is why I did not pick that as the basis for my DSL!). We can imagine such a DSL will provide high-level constructs for designing SOAP interactions, and the generator will created many instances of CLR types for each element instance in the model. It is the perfect example of where DSLs can be immensely useful. However, because it will be high-level, an open question is how it will handle significant variability. The further you are from the code, the more important this question becomes. If the DSL user sticks to the common usage, it will work extremely well. I openly wonder, when the DSL user wants greater variability, how the high-level DSL will support that? (in my case, I would be interested in support for something like: http://www.ietf.org/internet-drafts/draft-mrose-rfc3288bis-02.txt).

    An example of a medium-level DSL would be one for custom resource managers using .NET v2’s System.Transactions. There are a couple of important design decisions about how your RM works with the kernel transaction manager and the DTC; and when the model is finished then for each element instance a few CLR types will be instantiated in the generated code.

    High-level and medium-level DSLs will be most popular, but I think low-level DSLs can sometimes deliver benefits.

    An example of a low-level DSL would be one for fundamental design patterns, such as GoF, POSA or Hohpe. Before looking at how these might be created, we should first ask are they needed at all? One viewpoint might be, just don’t bother. Since they are so low-level, code snippets might be a better idea. A while back I wrote GoF in C# http://www.clipcode.biz/stream/gof/index.html and similar implementations for other patterns/languages are available.

    In my opinion, what a low-level DSL for GoF brings to the table is:

    A) visualisation of the pattern (I am a fan of “UML as a sketch”)

    B) ability to customise the pattern before code generation and

    C) elimination of potential error conditions (the model will prevent these)

    If one is new to GoF, all this helps a lot – if one is already a GoF expert, one would probably be quicker hand-coding. In contrast, for high-level and medium-level DSLs, even if you are an expert, you will likely be more productive using the DSLs.

    When creating my GoF DSL, I considered three approaches: one-element-per-pattern, common-elements-among-patterns and one-to-one-mapping.

    One-element-per-pattern is along the lines you outline in your blog – one toolbox entry per pattern, this could be dragged onto a design surface and various properties set on it directly, and compartments within it could contains lists of participants (and their properties). For simple patterns (e.g. Singleton) this will work nicely. The problem is with the more complex patterns – such as AbstractFactory. Here we have multiple participants of different types; participants have a variety of relationships (ConcreteFactory creates ConcreteProduct, which inherits from AbstractProduct which is used by Client). If we go beyond the simple case of one of each, to a user-defined number of each with varying per-element relationships, it becomes difficult to represent this all within one element (note: compartments cannot be nested). Furthermore, we are getting no benefit from a graphical design surface (it just shows one element).

    The common-elements-among-patterns approach involves sharing elements among different patterns. Many GoF patterns have a Client, an Abstract and a Concrete and we need to ask could we represent them in the toolbox as common elements. The two problems here are that each pattern attaches different semantics to each element and that the connectors would need more intelligence built into them to decide the permissible connections (e.g. in the AbstractFactory pattern, we do not want to allow ConcreteFactory inheriting from AbstractProduct, even if we have a connector that allows Concrete inherit from Abstract). With a bit of work, maybe these problems could be overcome.

    Therefore I went with the one-to-one mapping. I am not saying the first two approaches are wrong, it is just that the one I chosen has maximum flexibility.

    I agree that the most productivity gains will be had from higher level DSLs – The big question is how to expose significant customisation while maintaining the DSL at a high-level. I reckon in certain circumstances, low-level DSLs will be useful too.

    Eamon

    P.S. One question to ponder is how best to implement composable DSLs – imagine we want an abstract factory AND a web service element; or a Singleton AND a ResourceManager.

    P.S. 2: In my GoF DSL, the icon in the toolbox that represents each element within a pattern is meant to appear in the top-right corner of the element instance box in the design surface. (We obviously need some graphical way of distinguishing model elements). In the current DSL Tools, icons in multiple design surface elements are not supported. (This is in the FAQ – which of course I did not read at first – So read the FAQ before coding).

    P.S 3: A library of prebuilt GoF models would be useful. I could imagine opening a directory, accessing a prebuilt model, and then customising. The same applies to other DSLs.

  2. Rui Quintino

    De volta ao activo 🙂 Chegaram ao fim estas fantásticas semanas de retiro “espiritual” 🙂 … De volta a casa, e sedento de novidades, aqui deixo o que me captou a atenção…

  3. Archiveloper

    Clipcode-GoF-DSL Clipcode-GoF-DSL is a domain specific language for the Gang Of Four…

  4. Steven Kelly on DSM

    Higher level of abstraction = higher ROI Claudio Perrone spots the mistake that many beginners make in starting to use DSM: building a modeling language that is at essentially the same level of abstraction as code…

  5. Chris Breisch

    This is an interesting blog entry on Clipcode-GoF-DSL and the One-To-One Mapping Anti-Pattern. To quote…

Comments are closed.