LEGOs seem to be a favorite analogy for people bemoaning the state of software development today. “If only it would be as simple as putting Legos together” is a common enough statement, along with various proposals to make software that is Lego-like. Sometime, I wonder if people making these statements have actually tried to build anything non-trivial from Lego recently. Here, I will look a bit closer at the Lego-programming analogy. There is indeed quite a lot to it, but it is not all about child-level simplicity. I think there are some good lessons that can be learnt from analogizing Lego and programming.
The naïve attractive idea of Lego is, I think, is that “any piece can be combined with any other piece”. Technically, this is mostly true in my experience, but with a significant number of exceptions that might surprise someone who does not have kids of Lego age. Even if we ignore the modern Technic beams which are really a separate system with its own logic, there are many pieces in Lego that can only be attached to certain other types of pieces due their geometries (such as this).
Still – the basic unit of interface is almost universal, the Lego stud. There is the first lesson to be drawn from Lego – design for connection from the start. The reason all the pieces fit is that they all use the stud, and the reason that they all use the stud is a conscious explicit design from the very start. It is not something that was retrofitted into an existing set of random blocks – Lego pieces were designed starting with the stud and its geometry, and then designed so that each new piece uses the same-size stud and the same geometrical logic. For software, the lesson is clear: if you want Lego-style assembly, you need to start with very strong standard interfaces and build the software for these interfaces. You cannot really hope to componentized and “Legoize” an existing body of code. The connectivity is more important than functionality.
So, any two Lego pieces are easy to fit together. However, that does not mean that it is easy to build something that works in an interesting way or looks like what you had in mind. Indeed, if you look at the way modern Lego kits are designed, it is amazing how many smart solutions are employed to attach pieces at various angles.
The helicopter shown on the left is a typical modern lego design: plenty of pieces that fit at 90 degrees to the vertical, a far cry from the old-style design shown on the right. The sophistication of the design and the great variety of pieces needed is much greater for the helicopter. I think what mostly people want out of their software is more like the helicopter than the tree.
The basic composition of pieces is easy – but advanced construction is a skilled job. Your average seven-year-old will not be able to design the kits they buy, even though it is easy to follow the instructions and build them. Ease of assembly does not necessarily mean ease of actual design. If you have something particular in mind, phrasing it into Lego bricks can take a long time and a lot of trial and error. That trial and error is certainly usually quick and easy, but it never replaces some planning and forethought so that you do not have to tear down an entire building because you forgot to put some crucial part in the middle of a now-finished wall…
There is the second lesson: even for a software system where we can build like Legos, I would not expect to see regular users create superb software for sophisticated work – that would still be a rare skill. Ease of construction removes some of the accidental difficulties of software construction, but it still leaves the essential problems to be solved.
Another Lego lesson is that to build something that truly works (or looks like something real), you need rich palette of pieces. In theory, you could away with just the simplest old square pieces and basically build a 3D model by using voxels like most of the older models you find in Legoland. But that requires both very large models and very fiddly work, and honestly is not something within the reach of most users. Using tens of thousands of pieces is time-consuming, even when they are Legos.
Thus, modern Lego is awash in special-purpose pieces. To get an idea, look at the list of pieces introduced each year at Brickset. 1000s of new pieces every year. They still follow the Lego system, but it is not just square bricks anymore. Look at the piano on the left: the little microphone and the glass are a special pieces (following the size rules of the Lego minifig hands). To build the rest of it, existing parts are reused, but it is built from 11 different types of bricks, only 5 of which are used more than once (see instructions).
Sometimes when you really need something special, you just have to craft it with no heed given to the idea of composability and flexibility. Like the Lego bicycle seen on the right, which are basically three pieces: frame, and two wheels (front light and helmet are optional). Makes for a perfect model of a bike, but will not help you build anything else.
In summary, the third lesson seems to be that in order to compensate for a rigid way to connect things, it seems you need to introduce an incredible host of special-purpose components to do just that particular thing that cannot be done from heavy standard bricks.
An attractive property of Lego that might or might not be desirable in software is that even in a finished model, you have plenty of places where you can attach new things. Unless you carefully cover all studs with little flat plates, anyone can add things to the model in almost any place. Indeed, extensibility has been a common theme for long-term successful software: by allowing users to extend and build on the basic software, the power and staying power of the software is typically greatly extended. Look at tools like Emacs, gdb, good old Microsoft Word, or Eclipse: by having ways for users (and OEMs and integrators and VARs and consultants) to hook in their own scripts and extensions, you get a software ecosystem that keeps users coming back. Trying to keep users out with a shiny polished surface where things just slide off tend to result in shorter-lived software.
Finally, I have to recount a story from many years ago, when I was studying in Germany. My professor in software engineering made a remark that RAD (rapid application development) tools where like building with Lego Duplo: you quickly get something built, but you do not have much control over how it looks. I agree. You can build big things very quickly with Duplos, but they do require a lot of imagination to interpret the creation. Like the rocket on the right. Took no time at all to build, and it is very large compared to regular Lego (see minifig mechanic to get the scale).
So, to conclude, I think the Lego analogy has much going for it. But it is not “anyone can build anything”. The lessons I think that can be drawn from Lego for software designers:
- Design for modularity and connectivity from the very start
- Force all modules to be connectable, even if that contorts the shape of the module a little (global goals override local optimizations)
- Ease of assembly does not make design and architecture go away
- Sophisticated software design will still be a skill
- Expect to see many special-purpose modules created to solve very particular tasks
- Expect modularity to show through in the end product – it will not look quite the same as something monolithic
- Allow extensions throughout the life of a piece of software – embrace user extensibility