Who are you targeting with your DSL?

I had quick DSL appropriateness argument last week for someone that was objecting about us implementing a DSL for some small part of the domain.
The argument: “Business users will never write code”.

My response: “But business users will read code”.

And to test the argument, I later emailed one of the business users with a small snippet of the DSL that we were crafting and simply said in the email: “Please check the following configurations for the client…”.

His response: “You incorrectly configured the final_costing_policy.  It should be …”

In the large, the DSLs that you create are going to be read by a larger audience than just developers.  So, like all good code, this DSL code should be highly readable, but not all of your audience needs to know it’s syntax in detail.  You create a DSL to make your life, the developer, easier.  Getting business users to understand what you are doing is part of making your life easier.  Anyway, is it not about ubiquitous language and vocabulary?  You can’t get closer to the domain than revealing data and behavior with a DSL, can you!?

Heck! We should have paid attention that day.

I’ve been doing some internal DSL coaching recently, and my coaching-partner and I have been working BDD/TDD style.  It turned out to be quite a nice experience overall.  We started with a Cucumber based feature that described the behavior of a typical DSL script and we drove it down into rpsec where we tested each little part of the script.  In the end, I achieved what I set out: the person I was coaching grokked the whole “code is data” idea behind DSLs.
Then I started thinking about what it takes to coach external DSLs.  I got really scared – parsers, generators, abstract syntax trees.  Those were things that most people wanted to forget about the day after they wrote the exam for that horrible semester course in university.  What makes it worse is that I never did that in university – I did Electronic Engineering and we spent our coding time figuring out how to do Fast Fourier Transforms on digital signals.

But when I look at the progress that is being made in language workbenches to help us create DSLs, then I reckon we should dust off those books and start paying attention again.  Some of these language workbenches still leverage a host language such as Java or C#, but the act of using a structural editor that edits the AST directly is strangely weird.  But, some refactorings are just not a problem anymore.  For example, if you are changing the node on a tree, then all the references to that node are automatically aware of it.  Compare that to a text editor where you need refactoring wizardry in the tools to make sure all references are updated neatly.

I think that language workbenches may be a great tool for coaching DSLs because the things that made your head spin during that lex and yacc week, are made a whole lot simpler.  You can focus on designing the language and walk into ASTs with less fear.  But, be warned — language design is not easy, and you still need to know about ASTs and parsers and generators.  In fact, just write a parser and a generator and it will be a learning experience that goes beyond DSLs.  Better still, do it BDD/TDD style.

The relevancy of language oriented programming is just going to continually increase.  Those previously “irrelevant” courses are important again.  Watch out, the gap just got wider.

SOA is a wicked problem

I had a really interesting discussion this morning with two bright people about their SOA journey.  They are responsible in many ways for moving their rather massive company to SOA.  So we chatted about all sorts of things and argued and disagreed and converged and disagreed again and got confused and converged again and diverged again … and then we realised 2 hours had gone by and we all had other things to do.
Driving back to my office, I was bothered by the fact that we were struggling with how to implement this thing called SOA.  And I also have a feeling that there are more SOA failures than successes in the world.  And all these contribute to experiential knowledge for the greater good of our geek community, blah, blah, blah.

But I did not have a clear cut solution, neither did they, neither does their vendor partner (for sure!), nor their management, nor anybody!

So, I am now convinced that a SOA implementation (not theory!) is a wicked problem.  Wicked problems come from social sciences to describe an extremely difficult problem to solve, even impossible because of contradictory or ever-changing factors or incomplete requirements.  Some characteristics of wicked problems include:

  • every solution is a degree of goodness (or badness) but there is no distinctly right or wrong solution
  • every solution is a one-shot solution because you don’t have room for trial and error
  • consequently, every solution attempt counts immensely … positively or negatively
  • there is no uber-test of a solution, so the proof is in the execution (my TDD blood froze about now 🙂 )
  • each problem is symptom of another problem, indefinitely, i.e. there is no stop rule.
  • stakeholders all hold different understandings of the domain
  • there is no solution, but the problem is understood only after a solution has been crafted.

And last, but not least … maybe the most telling is

  • Those that are held accountable for the consequences of the solution have no right to be wrong ! Ouch 🙂

I think that some architectural things feel like wicked problems.  Read the work of  Jeff Conklin and Robert Horn, two guys that spend a lot of time researching tools for solving social messes.

Discovering Language and Context

Last night, I attended the 43rd Cape Town SPIN meeting that turned out to be a fun, interactive exercise with John Gloor. John introduced a system of analysis which focused on modeling a domain – but not from and object oriented paradigm. It was more about “things” and “influences”. I am really doing a bad job of using the right terms, but let’s just try something out.

  1. As a group define (frame?) your problem domain (We chose “How to be a successful team”)
  2. Then individually…
    • write down as many thoughts about the domain as possible – short snippets of 3-8 words each.  The recommendation was to aim for about 70 thoughts.
    • Color code (or group) these based on some notion of similarity.
    • Give each group a name or label on a post-it
  3. Then as a group …
    • the first person sticks their post-its on the wall
    • each other person, in turn, then sticks their post-its up and aligns it with whatever else is already on the board (or creates a new spot altogether)
    • Optimize the emerging clusters and give them names
  4. Finally, put directed lines between the named clusters using the guide of “A influences B” and give the line a label as well.

We never had the time to get to complete step 6.  But the really interesting angle for me was that a language for the domain was emerging.  It was not perfect, but it was a nice start.  Secondly, some of the clusters felt a lot like strategic contexts.  Sure, it was a conceptual decomposition of sorts, but it may well be a nice starting point for discovering bounded contexts.

And those influence lines felt like dependencies and interactions between contexts.  The use of the word “influence” is a really nice alternative to the traditionally naive terms like “uses”, “has”, “is like”.  It naturally focuses on behavioural interactions.

So, this simple exercise may be a nice technique for discovering language and contexts within a domain.  And it proves to me, yet again, that language is most critical.  This is not just about maintaining a lifeless glossary of terms – but the energy surrounding the vocabulary and terms need to be depicted and felt as well.  And if we combine all of this with an agile mindset, we can adjust this “language model” with each iteration and gain deeper domain understanding continuously.  Hmmm, this notion of “language model” is intriguing!

.NET Rocks! Podcast

Yesterday I had a telephonic chat with Richard Campbell and Carl Franklin from .NET Rocks! I tried to talk about modularity, but it kind of veered off into design in general and how an agile runtime is really important to being really agile.  A lot revolved around getting the domain understanding right before diving into object oriented design.  We touched on SOA, SaaS, UML, tools.  That’s a heck of a mess for less than an hour!
You can listen to the podcast here.  I think I just rambled on a lot about anything and everything and it felt like a wayward discussion to me at the time.  Have a listen and tell me what you think.  I really would like to improve myself for these kinds of events.

So, thanks a lot to the kind folk at .NET Rocks! for having me on their awesome show.  And for persisting with trying to get hold of me at the hotel in Lech, Austria.  I am deeply priviledged and humbled.  I hope I helped someone with my ramblings.

Oh, and many thanks to Jimmy Nilsson for all his help (again!).

Aural Ambiguous Assumptions

One of the nicest ways to learn or understand a new domain is to understand it’s vocabulary.  If you can have intelligent, unambiguous domain conversations using this vocabulary, then you are likely to immerse yourself in the domain quite deeply.  You see, it’s all about ubiquitous language.
But when do we start building our domain vocabulary?  Most likely when we hear domain terms for the first time in conversation.  But when we listen, we should not assume meaning.  And we should clear ambiguity by establishing the context.

I had a fun moment yesterday filled with aural ambiguous assumptions.  I was talking to a group involved in diamond trading and the one person said “… diamond sales at all our sites are …”.  Hmmm, that’s not hard to understand – site:  the place or location where diamonds are sold.

But what the person actually said was “… diamond sales at all our sights are …”.  Ooops, it turns out that the place of sale is actually the location when a cut and polished diamond is first seen by the buyer.  Ambiguous – yes,  Assumed – definitely, Contextual – absolutely.

Øredev Presentations

My presentations from Oredev are finally available.  After working through almost all the export options on Keynote, I have settled on QuickTime as the distro format.  The “flying code” in the aspects presentation worked out best with QuickTime.  Note that it’s not a continuous playback and you have to click-through each frame.

Concepts and Types

Last week, while working in a domain that was entirely new to me, I found myself using the word concept in domain conversations more often than I expected.  For example, I said something like “So, you mentioned forward exposure cover, which I understand a bit.  It seems to be about covering financial risks? Explain this concept of covering risk a bit more”. When I realised that “forward exposure cover” was a type in the domain (i.e. a class of sorts), I thought about “risk cover” again.  Is risk cover and forward exposure cover of the same type?
I like (want?) to think not.  I have spent a lot of time in recent months working with metadata and modeling of data itself.  In that time, I came across the concept of “concept”.  A concept is an abstract thing.  It cannot be manifest in anyway and is the metadata of concrete things.  It is not part of the type hierarchy but information about the type itself.  Concepts are part of an abstract general domain, perhaps not tied to any domain at all. But types are part of a specific domain.

So risk exposure is the metadata concept of the type forward exposure cover (in the domain of foreign exchange).  At the same time, risk exposure is the metadata concept of the type loss coverage (in the short term insurance domain).  Both types model vastly different things in vastly different domains but share the same purpose, i.e. have the same concept.  The concept risk exposure (in my layman’s terms) deals with danger or possibility of financial loss which holds true of loss coverage and forward exposure cover.

Subconsciously, I was looking for something that I was familiar with to understand something that was completely new.  Sometimes, finding the concept for a type may be better than finding a metaphor in our quest for gaining deeper insight.  This may be more valuable if the concept is the metadata for another type in a domain in which we already have deep(er) insight.

Factories, Builders and Fluent Interfaces

Last week I started working on very short proof of concept with a team that I am currently coaching at a short term insurance company.  We hit a very common design decision: when do we use a factory pattern and when do we use a builder pattern.
In the problem at hand, we needed to describe an item that will appear in an insurance policy that must be covered for fire damage.  It turns out that these items are not trivial in their structure, and many things influence the premium that will paid by the policy holder for fire insurance.  So, the first bit of code (in Java) in the test looked something like this.

FireItem fireItem = new FireItem();
fireItem.setIndustry("Building Construction");
fireItem.setOccupationCode("Workshop");
// the postal/zip code for the location of the insured item
fireItem.setAreaCode(7800);
// ignore the number, we actually created a Money class
fireItem.setSumInsured(200000.00);
fireItem.setRoofing("Non-Standard");

 

After the test passed, we refactored and I sneaked in a factory method which will be used to honor default values and at the same time threw in a fluent interface (the term coined by Eric Evans and Martin Fowler.  After all, I was also quietly introducing Domain Driven Design without actually saying that).

The code looked like this.

FireItem fireItem = FireItem.create()
                      .inIndustry("Building Construction")
                      .withOccupation("Workshop")
                      .InAreaWithPostalCode(7800)
                      .forSumInsured(200000.00)
                      .havingRoofing("Non-Standard");

The FireItem class looked like this:

public class FireItem {
    String industry;
    String occupation;
    // other properties ...

   private FireItem() { }
   public static FireItem create() {
       return new FireItem();
   }
   public FireItem inIndustry(String industry) {
      this.industry = industry;
      return this;
   }
   // other chained methods follow a similar style returning "this" ...
}

Nice! Much more readable. But, we then realised that it’s easy for someone to miss one of the methods in the chain.  That will result in the item having an incomplete structure.  Not good!  

One of the things I tend to do as a coach, is to let the team I am working with, experience the problem, solution and any rewards and smells as well.  Sometimes I even throw in red herring for sake of experience ;-).  So, the third pass at refactoring was to introduce a validate() method on the item which throws an exception if everything was not in place.

try {
  FireItem fireItem = FireItem.create()
                       .inIndustry("Building Construction")
                       .withOccupation("Workshop")
                       .InAreaWithPostalCode(7800)
                       .forSumInsured(200000.00)
                       .havingRoofing("Non-Standard")
                       .validate();
} catch (FireItemException e) {
  // handle the exception
}

Now the user of this class needs to know that the validate() method must be called before they really want to use an item object.  Yuck, that’s smelly!  So, for the fourth design refactoring, I introduced a builder and moved the fluent interface to the builder, still using method chaining but introduced a build() method that did the work of the previous validate() method before returning the well structured item.  The FireItem class now needs the traditional bunch of getters and setters (rant – the framework goodies need them anyway!!)

import static insurance.FireItemBuilder.fireItem;
// ...
try {
  FireItem fireItem = fireItem().inIndustry("Building Construction")
                         .withOccupation("Workshop")
                         .InAreaWithPostalCode(7800)
                         .forSumInsured(200000)
                         .havingRoofing("Non-Standard")
                         .build();
} catch (FireItemException e) {
   // handle the exception
}

Much better!  Note the use of the static import which gives us the liberty to use the static method without specifying the class in code body.  The FireItemBuilder class looked like this.

public class FireItemBuilder {
   private final FireItem fireItem;
   private FireItemBuilder() { 
      fireItem = new FireItem();
   }
   public static FireItemBuilder fireItem() {
       return new FireItemBuilder();
   }
   public FireItemBuilder inIndustry(String industry) {
      fireItem.setIndustry(industry);
      return this;
   }
   // other chained methods follow a similar style returning "this" ...
   public FireItem build() throws FireItemBuilderException {
      validate();
      return fireItem;
   }
   private void validate() throws FireItemBuilderException {
     // do all validations on the fire item itself and throw an exception if something fails
   }
}

Sure, we can improve the bubbling of the exception from validate() to build() and we could do with a better name for validate().  And perhaps, validate() should be on the FireItem class.  But let’s stick to factories and builders and fluent interfaces.  I think these three things work nicely “together”, when used for the right purpose.

In a nutshell, factories are great for creating objects where defaults and invariants are easily honored during the simple call to the factory.  However, if the structure of the object is more complex which makes long argument lists ugly, and some form of validation is necessary  before we can use an object then a builder works beautifully.

Also, note that the fluent interface was used to improve readability and kick off a tiny little DSL for describing insurance items.

An alternative is to allow the object to have an invalid structure but you track it with an invalid state, perhaps using a state pattern.  This is not exactly what the state pattern was meant for, but it will work nonetheless.

The last time I was with this team was in August 2006, and it is really great to work with them again.  So, much more for me to learn from them.