Archive for June 20th, 2007

Every now and then, I start thinking about domain-specific languages and about how it would be really nice if we could have a relevant domain-specific language for each piece of code that we needed to write. Recently, I realised that if we ensure that we “code at the right level” then we can go a long way to achieving it.

An example of coding at the right level: If you were performing a database query, you would either specify the database query as SQL (or another query language possibly) and issue the query, or you would ask your object-relational mapping layer to do it for you. Either way, you are only dealing with querying the database rather than worrying about opening a network socket to the database server, sending the query across the wire in the correct format, marshalling the results, etc, because these operations are at a much lower level and you’ll have a library or database driver to do them for you. Likewise, you wouldn’t decide in the same method which web page to direct the user to next, because that is a much higher level. This is an example of an operation that would happen in a method of a typical DAO object and any non-DAO operations are clearly out of scope.

The same is relevant in other situations. Let’s say we have a web application and have split it up into these layers: web layer (e.g. a Spring MVC Controller or a Struts Action), business delegate layer and DAO layer. In the web layer, all we are concerned with is getting the relevant data from the request, passing it to the relevant business delegate and then forwarding to the correct page depending on the result of the delegate call. At no point should we be worried about performing any business operations ourselves, and certainly at no point should we be concerned about interacting directly with the database. As such, if we had a simple domain-specific web controller language, we could code displaying a product’s information as something like this:

get productId from request
if productId missing then display error 500 page
get productData for productId
if successful then display product page with productData
if permission denied then display error 403 page
if not found then display error 404 page

Which is a fairly typical web request pattern. To convert this into Java, we would get something like this (I had to fight with Wordpress a bit to get it to format):

String productId = request.getParameter("productId");
if (productId == null)
{
..redirect(ERROR_500);
}
else
{
..try
..{
....Product product = productLoadDelegate.loadForProductId(productId);
....request.setAttribute("product", product);
....redirect(PRODUCT_PAGE);
..}
..catch (NotFoundException e) { redirect(ERROR_404); }
..catch (PermissionDeniedException e) { redirect(ERROR_403); }
}

We’ve got a bit more syntax here than in our domain-specific language above, but all the concepts are the same. Nowhere are we dealing with database connections. Nowhere are we worrying about network sockets. Nowhere are we worrying about where our product data is stored.

If we can follow the principle of treating each class or method as a domain-specific area and program in Java or our language of choice as if it was a domain-specific language, then our code is much neater and more maintainable. It’s a game to play to enforce separation of concerns.

I’ll probably come back to this at some point when I’ve thought about it a bit more.