Skip to main content

Posts

Too Many Moving Parts

A common, if somewhat informal, observation about a large code base is that there are "too many moving parts" in it. In my experience, this is especially true for large Java systems but is probably universally true. What do we mean by ‘too many moving parts’? Simply put, there is always a significant semantic gap between a programming language and the program. The larger this gap, the more that has to be expressed in the language, as opposed to simply using it. For example, consider the problem of traversing a recursive tree structure. In Java, we can iterate over an Iterable ; structure using a loop, for example, to count elements: int count = 0; for(E el:tree) {   count++; } If the Tree class did not implement Iterable we would be forced to construct an explicit iterator (or worse, write a recursive one-off function): int count = 0; for(Iterator<E> it=tree.iterator(); it.hasNext();) {   E el = it.next();   count++; } This version illustrates what ...

Late Binding in Programming Languages

Late binding is key to enhanced productivity in programming languages. I believe that this is the single most important reason why so-called dynamic typed languages are so popular. This note is part of an ongoing ‘language design’ series which aims to look at some key aspects of programming language design. What do we mean by late binding? Simply put, a programmer should not have to say more than they mean at any particular time. To see what I mean, consider a function that computes a person's name from a first and last name. In Star, I can write this: fullName(P) is P.firstName()++P.lastName() This constitutes a complete definition of the function: there is no need to declare types; furthermore this function will work with any type that has a first and last name. Contract this with a typical well-crafted Java solution: boolean fullName(Person P){ return P.firstName()+P.lastName(); } Not so different one might argue. Except that we have had to define a type Person ; at bes...

Productivity gains are permanent, Performance losses are temporary

This is the first in a short series of notes about language design. The goal is to identify what is truly important about programming language design. It is all about productivity There are 'too many moving parts' in a typical Java program. Here is a simple straw-man example: iterating over a collection. Before Java 5, the paradigmatic way of iterating over a collection was to use a fragment like: for(Iterator it=coll.iterator();it.hasNext();){ SomeType el = (SomeType)it.next(); ... } There is a lot of 'clutter' here; but worse, there are a lot of concepts that are not really that important to the problem at hand. Compare that to the Java 5 version: for(SomeType el:coll){ ... } Here we can focus on exactly what is needed: the collection and the iteration. This kind of example can be repeated fractally up the entire stack of abstractions: not just at this micro level but also at the level of using standard JDK class libraries on through to using features such as Spr...

(Software) Architecture = Policy + Mechanism

In the early 1980's Bob Kowalski made famous an interesting equation: Program = Logic + Control. The idea of that equation was that programming was essentially a combination of logic -- i.e., what you wanted done -- with algorithm -- how you wanted it done. It is a fairly commonplace fact that any non-trivial program has a similar flavor to it: there is often a substantial amount of machinery that is used to deliver the value in the program; together with some form of policy statement/expression that governs the precise requirements for a particular execution of the program. The larger the program, the more obvious it is that there is this layering into mechanisms and policies. For example, one could argue that a word processor's mechanisms are all the pieces need to implement text editing, formatting and so on. If the word processor supports styles, especially named styles, then these styles are a simple form of policy. At larger scales, when considering networked applications...

Sub-turing complete programming languages

Here is an interesting intuition: the key to liberating software development is to use programming languages that are not, by themselves, turing-complete. That means no loops, no recursion 'in-language'. Why? Two reasons: any program that is subject to the halting problem is inherently unknowable: in general, the only way to know what a turing-complete program means is to run it. This puts very strong limitations on the combinatorics of turing-complete programs and also on the kinds of support tooling that can be provided: effectively, a debugger is about the best that you can do with any reasonable effort. On the other hand, a sub-turing language is also 'decidable'. That means it is possible to predict what it means; and paradoxically, a lot easier to provide a rich environment for it etc. etc. An interesting example of two languages on easier side of the turing fence are TeX and CSS. Both are designed for specifying the layout of text, TeX is turing complete and CSS ...

On programming languages and the Mac

Every so often I dig out my Xcode stuff and have a go at exploring developing an idea for Mac OS X. Everytime the same thing happens to me: Objective-C is such an offensive language to my sensibilities that I get diverted into doing something else. All the lessons that we have learned the hard way over the years -- the importance of strong static typing, the importance of tools for large scale programming -- seem to have fallen on deaf ears in the Objective-C community. How long did it take to get garbage collection into the language? I also feel that some features of Objective-C represent an inherent security risk (in particular categories) that would make me very nervous to develop a serious application in it. As it happens, I am currently developing a programming language for Complex Event Processing. Almost every choice that I am making in that language is the opposite to the choice made for Objective-C -- my language is strongly, statically typed; it is designed for parallel exe...

About the right tools for the job

Some time ago I was involved in a running debate about whether we should be using Ruby on Rails rather than the Java stack (junkyard?) that we were using. At the time, I did not really participate in the discussion except to note that everything seemed to be at least 5 times too difficult. I had this strong intuition that there were so many moving parts that that was the problem. The application itself was not really that hard. My assertions really ticked some of my colleagues off; for which I apologize; sort of. I guess that I come from a tradition of high-level programming languages, by high level, I would say that I would consider LISP to be a medium level language, and Prolog is slightly better. I would say that it is a pretty common theme of my career that I end up having to defend the position of using high-level tools. I have gotten a number of arguments, ranging from "it will not be efficient enough" to "how do you expect to find enough XX programmers?". I u...