Sunday, February 8, 2009

Executable Design

When I first “noticed” architecture, I found it pretty much irrelevant.  At that time, designers generally talked rather than drew, or they drew flowcharts. Design documents were either 1000-page tomes or they didn’t exist at all. The architect with whom I worked generated block diagrams at such a high level they weren’t useful to me at all, or worse, they were misleading, because the actual system didn’t match the architecture in anything but name.

At some point, I finally started saying “architecture must be executable.” At the time, I meant that a designer/developer should be able to take an architectural description, code to it, and though it would be a skeleton, it should execute.  It should be possible to mock all the key system functions using nothing but the architectural description.

If feel the same way about design: if you can’t use the design as an actual blueprint, it isn’t a design–it’s a concept.  Concepts are good, but they must be refined into architecture and designs.  That’s what designers and architects get paid to do.  It’s hard work.  It’s boring sometimes. And it’s very very difficult to do well, which is why there are so few good designers, and even fewer architects.

I'm trained as a nuclear engineer, and I worked in power plants as such for 15 years before moving to software development full-time. Power engineers would laugh at what usually passes for a software design.  When you design a building, you aren’t done until you can predict the construction cost and schedule to within 5%.  Same thing goes for an engine, or a CD player, or chemical dye. In other industries, you’re working with real materials, which cost a lot, and whole teams of people, who also cost a lot.  You can’t do most of the work yourself, so you must explain exactly what you want done.

The same thing is true of large software projects (agile ones included--I'll get to that in future postings).

As software developers, designers, and architects, we have a huge advantage over engineers: our cost of implementation is very low. As a result, sometimes it really is cheaper just to throw code at the wall and see what sticks.  In medium and large projects, though, it is seldom the case that this approach will work more than occasionally. As a result, we build design documents.  Designers and architects make UML descriptions (hey!  we have our own design language!) and associated text, which we then hand to developers to turn into code.

Which is incredibly wasteful (and now I’m getting to the point).

UML is a succinct, precise way to specify a design.  Why do we have to translate it into code to get it to execute?  Wouldn’t it be a great test of a design if you could run it before you lobbed it at developers to flesh out?  I’m not talking about code generation here; I’m talking about directly executing the design components to see how they work together.

The model-driven architecture (MDA) folks are running down that idea.  I’m not sure I like where they’re going with it, though. I do not think it’s a good idea to turn designs into complete applications. Designs are abstractions, and the whole point of that abstraction, and the ability to separate architecture, design, and development, is to allow people to think at different levels of detail, so they have the capacity to grok the whole application.  Divide and conquer. I do think, though, that recoding the design from UML into some other language is wasteful. Wouldn’t it be a lot more productive to give developers an executing design and let them flesh out the details in their language of choice?

The rise of virtual machines–Java and .NET specifically, but I’m sure there are others–makes me think we can build executable designs, and code to them rather than recoding them. I’m currently working on “how”. I’d like to know what you think of the idea.


  1. "Wouldn’t it be a lot more productive to give developers an executing design and let them flesh out the details in their language of choice?"

    What would the executing design itself provide?

  2. The first question is really a succinct description of what I'm talking about (which, by the way, makes a good argument for .NET). I believe the executing design should constrain the full implementation, and should provide any functionality that the (partially) coded application does not.

    I also believe it's essential that the design abstraction not be lost. That's where I depart from the model-driven architecture people; when a model gets so detailed you can't grok it, it's code, not a model.