Best Tool for the Job

I thought I’d start the new year not with a boring (or not so boring) retrospective. I’d also like to avoid a post conveying my best wishes, but of course, I do wish you all a happy new year.

Instead I’d like to write a short post about an old adage and it’s (mis-)use in computing:

Use the best tool for the job.

You’ll most often hear the phrase applied in discussions about programming languages, in particular when it comes to which is better or worse than another. Those discussions usually (at least when I’m listening) get more and more heated with each subgroup participating declaring that one language is better than any others because of one feature or another.

If they end, they tend to end with some veteran of language flamewars stepping in and calmly declaring that, while the discussion is fun and all, of course each language has its own merits, and should be applied to whichever jobs it’s best suited for. If you’re lucky, you won’t then get dragged into another flamewar on the best language for a given job, say web development.

But is this wise guru telling the truth, or just applying some much-needed diplomacy to the proceedings? Or maybe a bit of both?

Let’s look at things from a pseudo-mathematical perspective. If the choice of programming language is to be expressed as a function, and we apply the “best tool for the job” paradigm, the function will accept exactly one parameter: the job.

best_tool = F(job)

That’s one way of looking at the issue, of course. But it slightly obscures an aspect of the problem, too.

There is an unspoken implication to the “best tool for the job” paradigm, and that is that a language that’s well-suited to a given job will likely include language features that make certain things related to the job easy to do. An example would be that SQL makes it easy to query data columns from a table that match a certain set of criteria.

Of course the example is rather contrived, since SQL is expressly designed to do this job well. It’s a special purpose programming language, after all — or a domain specific language, if you prefer.

But the same applies to general purpose programming languages as well. If your problem absolutely requires reflecting data structures into a database1, then a language with rich introspection features is a must.

So far, so good. But what’s that got to do with anything?

Well, the existence of a language feature that makes a particular “thing to do” easier than more general purpose instructions would is a question of expressiveness. And expressiveness is not really a question of how applicable a language is to a given job, it’s a question of how applicable a language is to how people phrase problem solutions. It’s a user-centric feature, not a job-centric feature. Therefore, the function for selecting a programming language really accepts two parameters:

best_tool = F(job, user)

Any semi-experienced software engineering manager will understand this. Within reasonable limits, let the people who use the tool choose it, as they’ll choose the tool they’re most productive with. The reasonable limits here tend to be that the tool shouldn’t be too obscure, and should be well-supported (perhaps by a large, vibrant community).

I suppose I could leave this post at that, but then I wouldn’t be saying anything particularly new.

Instead, I’d like to circle back to the beginning, to the hypothetical flamewar about which programming language is best. The thing is, this argument seems to hold an unholy fascination for programmers. It might be that we all strive for perfection, for the one language to rule them all, an end to the flamewars.

Or it might be that it’s easiest to view the world through the lens of your own, specific needs, and make language choice a function of yourself alone:

best_tool = F(self)

Given that self is something of a constant, you might as well shorten this to:

best_tool = F()

This way of looking at things is interesting to me not only because a great many of the language flamewar instances revolve around the fact that one person defines F() differently from another, more than anything else.

It’s also fascinating to me because whenever I look at a new, or up-and-coming programming language, I get the feeling that the motivation behind developing it is very much the same: the author felt that their particular needs were not adequately served by other languages. Note that this isn’t a “best tool for the job” perspective; at best, it’s a “best tool for the jobs I tend to do most often” perspective.

This is somewhat baffling to me precisely because the most enduring of all programming languages — languages such as the venerable C, or it’s bastard offspring C++ — were expressly designed to be the opposite: as general purpose as possible.

That is not to say that these languages haven’t changed over the years. C++11, for example, finally made the concession that it’s quite common to iterate over all elements of a container, and introduced special syntax for that. Still, that’s a far cry from introducing domain-specific features.

Yet this notion that languages should be designed for a specific purpose prevails.

I’m dabbling with the design of a programming language. I really shouldn’t even mention it, given that I haven’t had the time to look at my design over the course of the last year; in all likelihood, this project will never see the light of day. Nevertheless, it’s dear to my heart, and occasionally I’ll discuss it with people.

In one such discussion, a friend whose opinion I value asked me “well, what is it for?”. I remember struggling to answer that question. In the end, I gave the reply that it should make meta-programming easier. In a sense, that’s true. It’s also not a very satisfying answer.

The thing is, I don’t want domain specific languages, whilst understanding their usefulness. I think they’re exactly the wrong approach to language design. And the reason I think that is simply because I’ve yet to see a domain specific language that did not, over time, include more and more general purpose syntax constructs. Worse, because the language wasn’t intended to include them, they tend to be added in rather haphazard and decidedly un-expressive ways.

What I’d like to see is the opposite approach: have a simple, general purpose programming language, that can easily be extended with domain-specific constructs of such elegant expressiveness that there is no motivation to ask for a domain-specific language, only to ruin it later by making it more general purpose again.

In other words, as each user views expressiveness slightly differently, it should be possible to express language choice simply as:

best_tool = F(user)

Now if only someone was happy to give me a grant to work full-time on at least one of those choices…

  1. Not that any problem will have that absolute requirement. []