Never design a language

It is a common occurrence in software development. Someone says: “We should design a language”. The usual context is that some part of the development requires a rich functionality set, and it appears appropriate to provide a flexible solution through a specialized language. As an example, in the development of an airline’s frequent flyer program on which I once worked the suggestion came to design a “Flyer Award Language” , with instructions appropriate for that application domain: record a trip, redeem an award, provide a statement of available miles and so on. A common term for such notations is DSL, for Domain-Specific Language.

Designing a language in such a context is almost always a bad idea (and I am not sure why I wrote “almost”). Languages are endless objects of discussion, usually on the least important aspects, which are also the most visible and those on which everyone has a strong opinion: concrete syntactic properties. People might pretend otherwise (“let’s not get bogged down on syntax, this is just one possible form”) but syntax is what the discussions will get bogged down to — keywords or symbols, this order or that order of operands, one instruction with several variants vs. several instructions… — at the expense of discussing the fundamental issues of functionality.

Worse yet, even if a language will be part of the solution it is usually just one facet to the solution. As was already explained in detail in [1], any useful functionality set will naturally be useful through several interfaces: a textual notation with concrete syntax may be one of them, but other possible ones include an API (Abstract Program Interface) for use from other software elements, a Graphical User Interface, a web user interface, yet another for web services (typically WSDL or some other XML or JSON format).

In such cases, starting with a concrete textual language is pretty silly, since it cannot yield the others directly (it would have to be parsed and further analyzed, which does not make sense). Of all the kinds of interface listed, the most fundamental one is the API: it describes the raw functionality, excluding any choice of syntax but including, thanks to contracts, elements of semantics. For example, a class AWARD in our frequent flyer application might include the feature


             redeem_for_upgrade (c: CUSTOMER; f : FLIGHT)
                                     — Upgrade c to next class of service on f.
                       require
                                    c /= holder
implies holder.allowed_substitute (c)
                                    f.permitted_for_upgrade
(Current)
                                    c.booked
( f )
                       
ensure
                                    c.class_of_service
( f ) =  old c.class_of_service ( f ) + 1

There is of course no implementation as this declaration only specifies an interface, but it says what needs to be said: to redeem the award for an upgrade, the intended customer must be either the holder of the award or an allowed substitute; the flight must be available for an upgrade with the current award (including the availability of enough miles); the intended customer must already be booked on the flight; and the upgrade will be for the next class of service.

These details are the kind of things that need to be discussed and agreed before the API is finalized. Then one can start discussing about a textual form (a DSL), a graphical interface, a web services interface. They all consist of relatively simple layers to be superimposed on a solidly defined and precisely specified basis. Once you have that basis, you can have all the fun you like arguing over everyone’s favorite forms of concrete syntax; it cannot hurt the project any more. Having these discussions early, at the expense of the more fundamental issues, is a great danger.

One of the key rules for successful software construction — as for many other ventures of course, especially in science and technology — is to distinguish the essential from the auxiliary, and consequently to devote proper attention to the essential issues while avoiding disputations of auxiliary issues. To define functionality, API is essential; language is auxiliary.

So when should you design a language? Never. Well, hardly ever.

Reference

[1] Bertrand Meyer: Introduction to the Theory of Programming Languages, Prentice Hall, 1990.

VN:F [1.9.10_1130]
Rating: 7.9/10 (18 votes cast)
VN:F [1.9.10_1130]
Rating: +8 (from 16 votes)
Never design a language, 7.9 out of 10 based on 18 ratings
Be Sociable, Share!

5 Comments

  1. thomas.beale says:

    Hi Bertrand,
    you are of course right in the general thesis that writing a ‘specialist’ language for each new kind of business requirement is not useful. The problem with your solution however is that business rules are mutable, and often change at whim, or because of legislation. Such rules can’t be encoded in software because they change so often – they have to be dynamically addable / changeable within a deployed information system. The only things that can be safely ‘in the software’ are things that are essentially invariant across the domain. Today, even the idea of a withdrawal needing to be less than the overdraft limit is not invariant – my bank’s computers decided it was ok the other day.

    A better way to support this kind of business logic is a general purpose ‘soft’ computing layer, such as the one we are now using in health based on ‘archetypes’. See for example this online model repository – http://www.openehr.org/knowledge/ . To make this work, a new language was required, but a very general one based on constraint logic – see http://www.openehr.org/wiki/pages/viewpage.action?pageId=196633

    – thomas

    VN:F [1.9.10_1130]
    Rating: 5.0/5 (1 vote cast)
    VN:F [1.9.10_1130]
    Rating: +2 (from 2 votes)
  2. sharov_am says:

    Why A in API stands for Abstract but not for Applization?

    VN:F [1.9.10_1130]
    Rating: 3.0/5 (2 votes cast)
    VN:F [1.9.10_1130]
    Rating: +1 (from 1 vote)
  3. “Application Program Interface” is indeed the old expansion of the acronym. It goes back to old IBM mainframe terminology (from the 1960s I think) and the word “application” does not make much sense anymore. That’s why I prefer to use the alternative expansion “Abstract”. I discussed this small point in my introductory programming book “Touch of Class”. Thanks for raising the point.

    VN:F [1.9.10_1130]
    Rating: 0.0/5 (0 votes cast)
    VN:F [1.9.10_1130]
    Rating: 0 (from 2 votes)
  4. bahadir_konu says:

    Hi Bertrand,
    I agree that a Domain Model should be specified and then many different ways can be made available to manage that domain model: a DSL, a GUI, an API, web service API etc.

    I don’t understand why you say “never design a language!”. A team can talk about domain specific matters by using a DSL. That may help to form an “Ubiquitous Language”. The team can later decide whether to actually implement the DSL or not. I dont say “always start with a DSL discussion”, but this is just a tool on discussions of the domain.

    It seems you mean this: Don’t get lost in the details of implementing a DSL before actually specifying the essential business rules of the domain. I agree on this. But the sentence “Never design a language!” is not leading me to this conclusion. I prefer this: “Never get lost in the details of DSL construction before understanding the business rules in detail”.

    You seem to advocate designing the API in detail before anything else. Someone from Bell Labs said: “Desiging an API is designing a language”. So, in that sense, you are also designing a language while you are desinging an API.

    Bahadır Konu
    http://kurumsalyazilim.blogspot.com/

    VN:F [1.9.10_1130]
    Rating: 5.0/5 (1 vote cast)
    VN:F [1.9.10_1130]
    Rating: +1 (from 1 vote)

Leave a Reply

You must be logged in to post a comment.