a blog about things that I've been thinking hard about

Puzzle-Oriented Versus Meaning-Oriented Programming

3 September, 2006
"i got it to work" versus "you can read it"

Most real-world programming is like solving a puzzle.

But some programmers see writing programs as a way of expressing meaning.

Puzzle-Oriented Programming

In puzzle-oriented programming, the program to be written is a puzzle to be solved. There is a specification to be satisfied, and there is a pre-selected development platform which is to be used to implement the specification. The puzzle is to write the source code which can be compiled and executed for that platform and which then runs as specified by the specification.

If the set of possible programs that you can write to satisfy a specification is constrained by the choice of development platform, then writing the program is like searching for the program needle in the haystack of possible programs that can be written on that platform.

The search may be a hard search, but it's easy to know when it's finished, because there is a running application (I'm ignoring minor details like the fact that testing can never completely verify the satisfaction of a specification).

Certain people have a personality that makes them enjoy doing puzzles, and these people make good puzzle-oriented programmers.

Meaning-Oriented Programming

In meaning-oriented programming, the programmer thinks about how they want to implement the specification, and about the meaning of the code that they are going to write, and how they want to write that meaning so that the code is easy to understand.

The meaning-oriented programmer wants to start writing the program before making any choice of development platform. Of course if you write code unconstrained by the existence of a pre-selected development platform, then the code you write is likely to only run on a development platform which doesn't yet exist.

This process of meaning-oriented application development is much more intuitive than that of puzzle-oriented application development, but there is no magic moment of "finding" the solution, because there is no direct feedback that comes from a running application. (Although feedback does eventually happen, as I will explain.)

The Real World

Practical programming always reduces to puzzle-oriented programming. There is a specification which represents business requirements, the application that implements it has to be finished by some particular date, and usually someone somewhere has already decided which development platform must be used to develop the application.

Good puzzle-oriented programmers are the "hired guns" of the software development industry, and they get paid good rates, especially if they know all the tricky stuff you have to know to get the most out of some particular development platform.

The Fantasy World

The meaning-oriented programmer lives in a fantasy world. They write code which almost certainly cannot be executed, because the process of writing the code is not constrained by any pre-determined choice of development platform.

Because meaning-oriented programmers write fantasy code which doesn't run, it's difficult to justify paying them anything. However, they might find refuge in an academic environment, or in the research department of a large IT company which has surplus funds to spend on research which doesn't produce anything immediately useful.

One symptom of a meaning-oriented programmer is an obsessive fascination with impractical high-level programming languages such as Ruby, Lisp, OCAML, Erlang and Haskell. These languages are "high-level" because they allow the expression of meaning in more natural ways, or at least that is part of what they promise.

The irrelevance of these programming languages to most real-world business application development is discussed in some detail in a recent article by Joel Spolsky. There are various reasons why these languages are impractical, but the main reason is that hardly anyone is using them (yet), so they lack reliable infrastructure, which means it is too risky to use them for anything important (which explains why hardly anyone is using them).

Source Code Complexity

One of the symptoms of puzzle-oriented programming is source code complexity. By "complexity" I don't mean how complicated it is; rather I am referring to the more technical computer science kind of "complexity", i.e. big O notation. Meaning-oriented source code should always be O(N), where N is the size of the specification. Puzzle-oriented source code can be quadratic O(N2), cubic O(N3) or, in some cases, exponential, i.e. O(2N). For example, there might be a procedure with 10 parameters and 1024 statements in the procedure body (or there might even be 1024 separate procedure definitions).

This feature of non-linear complexity can be found in ordinary puzzles. For example, the number of moves to solve the Tower(s) of Hanoi puzzle with N discs is O(2N).

Advantages of Meaning-Oriented Programming

Given the obvious disadvantage of meaning-oriented application code – that it doesn't even run – why would anyone want to hire a meaning-oriented developer?

There is one major reason why, which is that meaning-oriented developers write better source code. Their source code is "better", because it is more readable, it looks prettier, it's never longer than it needs to be, and it's more maintainable when specifications change (because the relationship between the specifications and the code is much more straightforward).

Shifting the Puzzle

As I already said, all running code that does something is the solution of a puzzle. If meaning-oriented programming is to be at all useful, the code does eventually have to run. So meaning-oriented programming doesn't really eliminate the puzzle, but it does shift it, and in particular it transforms it into a meta-puzzle. The original puzzle was how to write a program to satisfy the business specification on a particular platform. The transformed puzzle is how to write a program which executes the language which the meaning-oriented programmer invented in order to write their meaning-oriented source code. It's a "meta-puzzle", because the specific has been lifted to the abstract.

Meta-Programming Languages for Meta-Puzzle-Oriented Programming

A commitment to meaning-oriented programming is usually a commitment to meta-programming, because meaning-oriented programming requires making up a language as you go along, and making up new languages and implementing them quickly is what meta-programming is mostly about.

There are two major approaches to meta-programming:

I think it's safe to say that the ideal meta-programming environment doesn't yet exist. Meta-programming in Ruby is sometimes a bit of a hack. Lisp is good for programming Lisp, but the end result is always in Lisp, which isn't everyone's favourite syntax. And even with the advent of more user-friendly parser-development systems, like ANTLR, writing and implementing a brand new language is still a lot of work. JetBrain's Meta Programming System is one attempt to deal with this problem.

I could also mention XML. Or not, as the case may be.

Rubik's Cube

Puzzle-Oriented Solution

The puzzle-oriented approach to Rubik's cube is to do it like it is meant to be done, as a puzzle. Understanding the theory behind Rubik's cube can involve studying group theory and the concept of anti-commutators.

Meaning-Oriented Solution

The meaning-oriented approach to solving Rubik's cube is to think about the specification: to produce a cube where each side is of one colour. A "fantasy world" solution might go as follows:

The solution of the "meta-puzzle", of how to implement this fantasy solution, is to go down to the hardware store, and buy a paintbrush and six cans of coloured paint. The implementation of the solution steps consists of:

For anyone who has just spent two weeks figuring out how to solve Rubik's cube by rotating slices of the cube in different directions, this "paintbrush" solution seems a total cop-out. But if all you want is a cube which is coloured a single unique colour on each of six sides, then it's a much easier way to do it. And if you change your mind about what colours you want, all you have to do is get more cans of paint and repeat the process.

Meaning-Oriented Solution Version 2

The observant reader may have noticed that even the paintbrush solution is not as meaning-oriented as it could be. For example, there is still a requirement to use correct technique when dipping the paintbrush in the paint, and when brushing the paint onto the cube, to get a full even application. And there is an extra washing step required between colours.

A more meaning-oriented solution is to use spray-cans instead of a brush. To make one side of the cube red, just pick up the red paint can, point it at the chosen side, and spray. Very little technique required, and no extra washing step either.

Does This Mean There Are No More Puzzles?

If a software development shop adopts meaning-orientation as a software methodology, this implies that they are giving priority to writing application source code that directly reflects the meaning of what the application is intended to do. This might be seen as threatening unemployment for the puzzle-oriented programmer (especially if they are unable or unwilling to upgrade themselves to become "meta-puzzle-oriented").

However, some of the "puzzles" of software development are of a more essential nature, and not just borne of the adoption of a development platform that doesn't want to let you do the thing that you want to do. For example, problems like how to search large quantities of data efficiently, or how to do garbage collection without suspending program execution. These sorts of puzzles are essential puzzles that require clever solutions from determined puzzle solvers.

Conclusion

If you are a frustrated meaning-oriented programmer, and you haven't managed to get a job in an ivory-tower research institution, then the world of paid programming jobs is going to be depressingly puzzle-oriented for the forseeable future.

But the persistence of interest in those "fringe" high-level programming languages, i.e. Ruby, Lisp, OCAML, Erlang and Haskell (not to mention Python, which apparently counts as half-way practical, at least according to Joel Spolsky) suggests that the suppressed urge to indulge in meaning-oriented programming won't go away. The day may come when even those in "management" realise the importance of it. ("What do you mean? I should judge my developers by how well I can read their source code? Isn't reading source code the developer's job?") And some time in the distant future, it might even become something that you can put on your CV.

Vote for or comment on this article on Reddit or Hacker News ...