Of course, HowBuildingsLearn inspires lessons for software design.
See also DoesAbstractionScale (and the BigBallOfMud)
HBL describes buildings as a number of layers or systems (ShearingLayers). The important point is that each layer adapts over a different timescale. #
The outermost layer, the site is the boundaries within which the building can adapt. In an ancient city like Rome, the boundary can remain fixed for 2000 years. The next layer is the structure (weight bearing columns etc). This can only be changed by rebuilding. Then come the services (water pipes, cable ducts, chimneys), then the partitions between rooms, then the decoration, then the furnishing. Each is more ephemeral and subject to revision than the last.
Should we build software this way? As an onion of systems designed to adapt at different rates. Perhaps the tools for building and revising such systems should be different in each case :
- compiled language for the structural support
- scripting language on top
- templates / GUI for the configuration and fine tuning.
This sounds pretty much like what goes on already. Foote & Yoder think this in BigBallOfMud when they say
Can we identify such layers in software?
Well, at the bottom, there are data. Things that change most quickly migrate into the data, since this is the aspect of software that is most amenable to change. Data, in turn, interact with users themselves, who produce and consume them.
Code changes more slowly than data, and is the realm of programmers, analysts and designers. In object-oriented languages, things that will change quickly are cast as black-box polymorphic components. Elements that will change less often may employ white-box inheritance.
The abstract classes and components that constitute an object-oriented framework change more slowly than the applications that are built from them. Indeed, their role is to distill what is common, and enduring, from among the applications that seeded the framework.
But I think they're wrong : Traditional layers (eg. data-model and control logic) don't correspond to shearing layers the same way.
We need to rethink the decomposition into layers. And think how layers communicate. (Radically, could we get inspiration from RodneyBrooks's behaviourally decomposed SubsumptionArchitectures, JaronLanier's PhenotropicProgramming, AspectOrientedProgramming?) The systems should certainly be connected by OneWayLinks. (See also my account of ModelViewController) Maybe it's because DecompositionByLanguageIsProbablyAModularityMistake
thinking further about this, there are several deep principles we need to understand about the structure of our software :
- the HerbSimon / modularization question : what are the natural module boundaries. How do the concepts of CohesionAndCoupling really carve up the space. When is it true that DecompositionByLanguageIsProbablyAModularityMistake?
- the StewartBrand / ShearingLayers question : how is our system sheared into layers which need to evolve at different rates. And how do we support these different rates of flexibility?
- the ChristopherAlexander StructurePreservingTransformations question. How do we turn our development process into a suitable sequence of organic transformations that produce a something with TheQualityWithoutAName (maybe ExtremeProgramming / PracticeChange)
Time for a quick table :
|| HBL || Software || Notes || More ||
|| Brick || Text || Bricks are simple modules, 8000 years old, and still a great building material. People are always saying text has had its run and we need to move towards representing programs with some other structured format. I say no. || OnWritingAndAlphabets, IntentionalProgramming, LanguageOrientedProgramming, SubText, TextPeople, SmartAscii ||
|| Vinyl cladding || CheckedExceptions || Brand offers a choice. Do you want a material which shows its age before failing, or which looks good right up to the point it fails, and often hides problems until they become too big. Exception handling can become an encouragement to trap an error and brush it under the carpet ie. guess how to handle it when you're still down in the depths of the code and don't know what you really want to do. Classic example, trap a "divide by zero" because you have to, and then return 0 because you don't know what else to do. Problem only becomes apparent much later. || FailQuicklyAndObviously, BeauSage||
CategoryDesign, CategorySoftware, CategoryComputerScience