Every programming language has its way of performing tasks, its style. For example most Java developers follow the language’s style of creating classes to represent the relevant concepts and entities in a system and perform tasks by passing messages (calling methods).

The Java style works fine with almost all objects you could need to implement a system, from business world’s to JVM concepts like Classloaders. For example you could deal with Strings by using only basic object-oriented syntax like the snippet below:

final String WHITESPACE = new String(new char[] { ' ' });
String firstName = new String(new char[] { 'J', 'o', 'h', 'n' });
String secondName = new String(new char[] { 'D', 'o', 'e' });
StringBuffer buffer = new StringBuffer(firstName.length() + secondName.length() + WHITESPACE.length());
buffer.append(firstName);
buffer.append(WHITESPACE);
buffer.append(secondName);
String fullName= buffer.toString();

Strings are objects in Java and are fully supported by the language’s object-oriented syntax. Nevertheless like almost all mainstream languages Java has syntactic sugar to deal with Strings, its class is the one that uses operator overloading, the + operator is used only to sum two numbers or concatenate Strings, you can’t overload it in any other ways.

So the code above could be rewritten as this:

String firstName = "John";
String secondName = "Doe";
String fullName = firstName + " " + secondName;

If Java has a fairly effective syntax that could handle Strings just like it does with any other object why would such an exception to the main rule be needed? Because just like everywhere else there’s no ‘no one-size-fits-all’ here.

It is hard to think of a real world Java application that doesn’t have lots of Strings all over. Generally we have to perform lots of concatenations with Strings and our programs are full of text constants. To make these operations easier and more pleasant to the developer the language defines special syntax to deal with those objects.

The same thing can be done in almost all domains. As said above we would generally follow the language style while developing software, in Java we will use objects, get/set syntax, java.util.Iterators, interfaces, etc. Some times, however it would be better if we break this style to handle some concept.

When to Break Language Style?

A common system will deal with lots of concepts, from the Fundamental Domain (Integers, Strings, I/O…) to the actual Application Domain (the code you will write only for this application). For almost all of those the language generic syntax will be enough to write quality products with decent clarity expressed on its code.

Sometimes, however, the only way you can make clear the domain you’re dealing with is breaking the style, just like the String example above. It is hard to give generic ways of finding good candidates to be implemented breaking the language style but some guidelines could be:

  • Something that would require lots of lines to do a simple thing by the standard way
  • A complex domain
  • Something that won’t need to follow the style to get benefits (like having get/set methods to be handled by Java containers, frameworks or the like)

It’s easy to make confusion between adapting a language to better express a domain and adding syntax sugar. Syntax sugar is something provided by the language (the core language itself or an API) to make developer’s life easier. Syntactic sugar is generally not committed to clearness of intent, for example in scripting languages like PERL you have lots of obscure shortcuts and implicit knowledge that can avoid lots of work but it doesn’t provide clarity on what you are dealing with, the domain your code maps.

Ways of Doing It

There are several ways a language can be modified to allow code to express clear intent. Let’s visit some of them.

Fluent Interfaces

You use a Fluent Interface when you don’t follow the language style in order to get the intent of your code more clear to the developer. The Fluent Interface style of programming was documented by Martin Fowler. I think the whole concept can be reduced to a single sentence from his text:

The API is primarily designed to be readable and to flow.

Martin Fowler, Fluent Interface

When you design an API to be fluent you use old and simple techniques like method chaining to build code that looks like well-formed sentences. People use to misunderstand this as just a new new for the chaining technique but I think they’re different. For example Hibernate’s Criteria API has method chaining:

List cats = sess.createCriteria(Cat.class)
    .add( Restrictions.like("name", "Fritz%") )
    .add( Restrictions.between("weight", minWeight, maxWeight) )
    .list();

What makes writing those query objects much more pleasant that the standard Java style but are not committed witht eh definition of a logical flow, it is much more a syntactic sugar that helps on productivity.

A Criteria Fluent Interface could look like:

List cats = list(Cat.class).with("name", like("Fritz%") ).and().with("weight", between(minWeight, maxWeight));

Which is a lot more far from what is good object-oriented code but is clearer. While using a Fluent Interface you use those chaining to make your interface more Humane.

Eric Evans’ Time & Money library is a classic example of this style:

//(...)So as you read the tests, instead of seeing
Calendar calendar = Calendar.getInstance();
calendar.setTimeZone(TimeZone.getTimeZone("Universal");
calendar.set(Calendar.DATE, 5);
calendar.set(Calendar.MONTH, 3 - 1);
calendar.set(Calendar.YEAR, 2004);
Date march5_2004 = calendar.getTime();
//(...)you will see
TimePoint march5_2003 = TimePoint.atMidnightGMT(2004, 03, 5);

Internal Domain-Specific Languages

When you define a Fluent Interface you are still using the underlying language, you just break its style to get more clarity on your intent. There is another form of adopting a language called Internal Domain-Specific Languages. Internal DSLs define new languages based on a host one. You’re not just creating a clearer way to perform a simple task like calling several methods in a single line but defining constructs that allow programmers to write code using your little language.

To implement new languages hosted in statically typed languages such as Java you will probably use method chaining again. Let’s consider the language created by JMock.

allowing (bank).withdraw(with(any(Money.class)));
    will(throwException(new WithdrawalLimitReachedException());

allowing (bank).withdraw(Money.ZERO);
    will(throwException(new IllegalArgumentException("you cannot withdraw nothing!");

JMock’s DSL defines a way to program mock objects that will be used in test cases. That language was created to perform this action, you shouldn’t use it as a general programming language.

There is a thin line between a Fluent Interface and an Internal DSL. I think the main difference is that by using an Internal DSL you will be tied to a domain and your language “keywords” and style will be deeply related to that domain. Also you will be defining a little language to be used while programming at this domain. Internal DSLs also will be rarely inlined into plain host language code. Fluent Interfaces have no worries about defining languages, being tied to a domain or anything, it’s just a matter of breaking language style to get more clarity on what you are doing.

In the examples above while using Fluent Interfaces you changed the way you call methods in objects but you still use objects to map business concepts and still follow the same message-passing collaborative style of writing programs. When you use a DSL you don’t need to be concerned about things like that. It doesn’t matter if the throwException method returns an object, if it is static or anything, these are concerns that you have when you’re writing programs in Java and by using JMock’s language your are not using Java anymore.

Why not?

Keeping the language style while developing is generally a good practice, it makes easier for other developers to understand what your code do and allow use to use every tool your platform provides.

When you give up on the language style to create your own you have to be aware that it’s not because something seems clear to you that it will se to everyone, the new styles you create must be widely understandable by everyone working with that code.

Also frameworks and tools often rely on naming and syntactic conventions to do their job. In Java some frameworks will work only in classes that follow the get/set naming convention for methods, for example.

Modifying language style in general programming is a rare situation. Generally this will be done while developing a library or framework and not application logic itself. Neertheless modifying a language to create an Internal DSL is getting pretty common these days.

History

  • 10/18/2007 - First Draft