DSLs in Boo : Combining domain-driven design and DSLs

8/22/2012 5:28:35 PM
Domain-driven design (DDD) is an approach to software design that’s based on the premise that the primary focus should be on the domain and the domain logic (as opposed to focusing on technological concerns) and that complex domain designs should be based on a model.

If you aren’t familiar with DDD, you may want to skip this section, because it focuses specifically on the use of DSLs in DDD applications.

1. Language-oriented programming in DDD

The reason for using language-oriented programming is that humans are good at expressing ideas using a spoken language. While spoken language is generally very imprecise, people usually settle on a set of terms and phrases that have specific meanings in a particular context.

Ubiquitous language and DSLs

Ubiquitous language is a term used in DDD to describe the way we talk about the software. The ubiquitous language is a spoken language that’s structured around the domain model and is used by all members of the team when talking about the domain.

A ubiquitous language isn’t a DSL, and a DSL isn’t a ubiquitous language. A ubiquitous language is used to make communication clearer. Terms from the ubiquitous language are then used in the code of the system.

A DSL, on the other hand, can be seen as taking the ubiquitous language and turning it into an executable language. A DSL isn’t always about a business domain, but when it is, and when you’re practicing DDD, it’s almost certain that your DSL will reflect the ubiquitous language closely.

In short, the ubiquitous language is the language of communication inside a team, whereas a DSL is a way to express intent. The two can (and hopefully will) be merged in many scenarios.

In some fields, the domain terms are very explicit. In a Sarbanes-Oxley tracking system, the domain terms are defined in the law itself. In many fields, some of the terms are well defined (such as in accounting) but other terms are often more loosely defined and can vary in different businesses or even different departments. The term customer is probably the quintessential example of a loosely defined term. I once sat in a meeting with two department heads, watching them fight for 3 hours over how the system would define a customer, without any satisfactory result.

When you’re building software, you usually need to talk to the domain experts. They can help clarify what the domain terms are, and from there you can build the ubiquitous language that you’ll use in the project.

Once you have the ubiquitous language, you can start looking at what you want to express in the DSL, and how you can use the ubiquitous language to express that. 

2. Applying a DSL in a DDD application

It seems natural, when thinking about DSLs, to add DDD to the mix, doesn’t it?

Figure 1 shows a set of DSLs in a domain-driven application. In most applications, you’ll have a set of DSLs, each of them targeted at one specific goal. You’ll also usually have a DSL facade of some kind that will translate the code-driven API to a more language-oriented API.

Figure 1. DSLs used in a DDD context

There are quite a few domains where DDD doesn’t make sense. In fact, most of the DSLs that I use daily aren’t tied to a DDD implementation. They’re technical DSLs, used for such things as templating, configuration, ETL (extract, transform, and load), and so on.

Technical DSLs rarely require a full-fledged domain model or a ubiquitous language because the model used is usually implicit in the assumptions that we have as software developers. A templating DSL doesn’t need anything beyond text-processing instructions, for example. A configuration DSL needs little beyond knowing what it configures.

But when it comes to business DSLs, we’re in a much more interesting position. Assuming that we have a CLR application (written in C#, VB.NET, or Boo) and assuming we’re writing the DSL in Boo, we have immediate and unlimited access to the domain. This means that, by default, our DSL can immediately take advantage of all the work that went into building the ubiquitous language and the domain model.

All the ideas about the domain model and ubiquitous language are directly applicable and exposed to the DSL.

Listing 1. A DSL that uses an existing DDD-based domain model
when User.IsPreferred and Order.TotalCost > 1000:
    AddDiscountPercentage  5
when User.IsNotPreferred and Order.TotalCost > 500:

Notice that we’re using both IsPreferred and IsNotPreferred—having both of them means that you get better readability. But consider the actions that are being performed when the condition specified in the when clause is matched. We aren’t modifying state, like this:

Order.TotalCost = Order.TotalCost - (Order.TotalCost * 0.05) #apply discount


That would probably work, but it’s a bad way to do it. It’s completely opaque, for one thing. The code is clear about what it does, but there is no hint about the business logic and reasoning behind it. There is a distinct difference between applying a discount for a particular sale offer and applying a discount because of a coupon, for example, and this code doesn’t explain that. It’s also probably wrong from the domain perspective, because you will almost certainly want to keep track of your discounts.

In the domain, we probably would have something like this:


That would be valid code that we could put into action as well. But in the DSL, because we already know what the applicable operations are, we can make it even more explicit by specifying the discount as an operation with a known context. This makes those operations into part of the language that we use when writing functionality with the DSL.

  •  Active Directory Domain Services 2008 : Restore Group Policy Objects and Starter GPOs
  •  Active Directory Domain Services 2008 : Comment Group Policy Objects and Starter GPOs, View, Print, and Save a Report for Group Policy Objects, Back Up Group Policy Objects and Starter GPOs
  •  Apple Society … Money x Property
  •  Active Directory Domain Services 2008 : Create a New Group Policy Object from a Starter GPO, Edit Group Policy Objects and Starter GPOs, Copy Group Policy Objects and Starter GPOs
  •  Active Directory Domain Services 2008 : Create Group Policy Objects, Delete Group Policy Objects, Create Starter GPOs, Delete Starter GPOs
  •  System Center Configuration Manager 2007 : Architecture Design Planning - Device Management Planning
  •  System Center Configuration Manager 2007 : Architecture Design Planning - Software Update Planning
  •  Programming .NET Components : Marshaling-by-Reference Activation Modes (part 2) - Server-Activated Singleton
  •  Programming .NET Components : Marshaling-by-Reference Activation Modes (part 1) - Server-Activated Single Call
  •  Programming .NET Components : Remoting - Remote Object Types
  •  Active Directory Domain Services 2008 : Seize the RID Master Role, Seize the PDC Emulator Role, Seize the Infrastructure Master Role
  •  Active Directory Domain Services 2008 : Seize the Schema Master Role, Seize the Domain Naming Master Role
  •  Synology DS212+
  •  QNAP TS-219P II Turbo NAS
  •  Netgear Readynas Duo V2
  •  Iomega Storcenter Ix2 Network Storage Cloud Edition
  •  Freecom Silverstore 2-Drive NAS 2TB
  •  IBM WebSphere Process Server 7 : Installing WID on Windows
  •  IBM WebSphere Process Server 7 : WebSphere Integration Developer overview
  •  D-LINK Sharecenter Shadow DNS-325
    Top 10
    Nikon 1 J2 With Stylish Design And Dependable Image And Video Quality
    Canon Powershot D20 - Super-Durable Waterproof Camera
    Fujifilm Finepix F800EXR – Another Excellent EXR
    Sony NEX-6 – The Best Compact Camera
    Teufel Cubycon 2 – An Excellent All-In-One For Films
    Dell S2740L - A Beautifully Crafted 27-inch IPS Monitor
    Philips 55PFL6007T With Fantastic Picture Quality
    Philips Gioco 278G4 – An Excellent 27-inch Screen
    Sony VPL-HW50ES – Sony’s Best Home Cinema Projector
    Windows Vista : Installing and Running Applications - Launching Applications
    Most View
    Bamboo Splash - Powerful Specs And Friendly Interface
    Powered By Windows (Part 2) - Toshiba Satellite U840 Series, Philips E248C3 MODA Lightframe Monitor & HP Envy Spectre 14
    MSI X79A-GD65 8D - Power without the Cost
    Canon EOS M With Wonderful Touchscreen Interface (Part 1)
    Windows Server 2003 : Building an Active Directory Structure (part 1) - The First Domain
    Personalize Your iPhone Case
    Speed ​​up browsing with a faster DNS
    Using and Configuring Public Folder Sharing
    Extending the Real-Time Communications Functionality of Exchange Server 2007 : Installing OCS 2007 (part 1)
    Google, privacy & you (Part 1)
    iPhone Application Development : Making Multivalue Choices with Pickers - Understanding Pickers
    Microsoft Surface With Windows RT - Truly A Unique Tablet
    Network Configuration & Troubleshooting (Part 1)
    Panasonic Lumix GH3 – The Fastest Touchscreen-Camera (Part 2)
    Programming Microsoft SQL Server 2005 : FOR XML Commands (part 3) - OPENXML Enhancements in SQL Server 2005
    Exchange Server 2010 : Track Exchange Performance (part 2) - Test the Performance Limitations in a Lab
    Extra Network Hardware Round-Up (Part 2) - NAS Drives, Media Center Extenders & Games Consoles
    Windows Server 2003 : Planning a Host Name Resolution Strategy - Understanding Name Resolution Requirements
    Google’s Data Liberation Front (Part 2)
    Datacolor SpyderLensCal (Part 1)