In my work on Wartime Software, I describe the methods used by small groups of smart, motivated programmers to compete with large, established groups using standard software techniques – and win. I haven’t invented those methods; I’m simply collecting, organizing and describing what such groups of software ninjas actually do.
Similarly, after observing the internal structure of many bodies of software over a long time, patterns emerge about the internal structures that yield competitive advantage, and tend to take market share. These internal structures are a kind of continuum rather than an either/or: a group that is farther along the continuum of goodness I’ve observed has a substantial competitive advantage over any group whose software is more primitive in the continuum. This pattern is so strong that you can see it play out with many companies competing over a long period of time.
The patterns are fundamentally simple, but rarely discussed among programmers or in the literature – and not taught (to my knowledge) in Computer Science departments. Using the patterns, it’s possible to rank any piece of software along three independent but conceptually related dimensions.
The dimensions are:
- The code. The not-good end of this axis is code that has a great deal of redundancy, and the good end is code that has no redundancy.
- The data. The not-good end of the axis is data that is defined and/or stored in multiple places, and the good end is data that is uniquely defined and stored.
- The meta-data. The not-good end of the axis is a software system with no meta-data, and the good end is one in which most application functionality is defined and controlled by meta-data, and can be changed by editing it with no code changes. I often think of this as the vertical dimension.
These dimensions are closely related conceptually, but in practice aren’t necessarily linked. Nonetheless, in practice, movement towards the good end of any dimension encourages and helps movement towards the good end of the others.
Why should anyone care about dimensions of software architecture goodness?
It’s an abstract idea. It’s new to many people. It’s a tough addition for managers whose heads already are chock full of barely understandable buzzwords and acronyms. Why pile on more?
Simple: investments in moving software towards the goodness end of the dimensions is HIGHLY correlated with shorter times, lower costs and lower risks of meeting the evolving needs of existing and new customers in a highly competitive market. The correlation is clearly demonstrated historically, and incremental progress yields immediate benefits in sales and business satisfaction. There is no single thing a software group can do that has greater impact on fast, low-cost and trouble-free delivery of existing and new product features to customers.
I know these are bold claims, particularly in an environment that swirls with buzzwords for software. Everything will be better once we start programming in Golang, like Google! Our teams will work better and our software will be scalable once we re-organize using micro-services! We’ve got to automate testing and move to test-driven development! We have to add Kanban to our Agile environment, and hire a certified SCRUM master! These subjects and more have passionate adherents and are widely implemented. But none of them yield the promised results, which is part of why there’s such a merry-go-round of methods becoming fashionable, only to fade quietly into obscurity or ho-hum, nothing’s changed but it’s just what we do.
Details of the Dimensions
Data
The data dimension is the most widely understood and practiced of the three. I hope everyone who can spell “relational database” is familiar with the concept of a normalized schema – the whole point of which is to assure that each piece of data is defined and stored in exactly one place. But the concept of a normalized schema applies strictly within the bounds of the DBMS itself – there is no widely used term or concept for a truly central definition of data, including inside the code.
Is having fewer, less redundant, more centralized definitions a good idea? You bet. This is largely why the RAILS framework for Ruby rapidly grew to widespread use. It had nothing to do with the design of Ruby or its object-orientation – it was all about the RAILS framework and it’s central DRY principle; DRY = “don’t repeat yourself.” The idea was/is simple: data definitions in RAILS are created in a central place – and then applied by the framework both in the DBMS schema and in the data definitions in the code to access the data. To change a data definition, you change it in the RAILS definition, and it changes it in both the database and the Ruby code.
It’s important to note that the data dimension in my definition encompasses data wherever it appears – program files, schema files, anywhere.
Code
The code redundancy dimension is much less understood and recognized for its importance. But the value of reducing code redundancy is easily understood: when you need to make a change to a program, how many places do you have to go to make the change? The answer any appropriately lazy programmer would like is “exactly one place.” The programmer finds the place, makes the change, and all is good. As you add code to a system to make it do new things, often you end up repeating or creating, perhaps inadvertently, variations on existing themes in the code. When you’re done, what’s the best thing you can do to make the next change as easy as possible? Eliminate the redundancy. That’s it! Objects, layers, components, services and the rest don’t matter. Redundancy matters.
Meta-data
The third dimension is meta-data. Having no redundancy in the meta-data dimension is important, and is often achieved by measures such multiple inheritance hierarchies and links. But the most important thing is this: to the maximum extent possible, application-specific behaviors of all kinds should be defined in meta-data rather than lines of code. Goodness in this dimension is measured by growing meta-data. Over time, decreasing code redundancy is achieved by increasing the size, extent and power of the meta-data.
This evolution directly powers business benefits for the simple reason that meta-data can be changed and augmented quickly without creating a new version of the code and without fear of introducing bugs into the code. In the end, you end up with something like Excel: the source code never needs to be touched, while supporting endless variations of spreadsheets, with no programming skills required. When you make a mistake in a spreadsheet, you may not get the result you want, but Excel doesn’t crash.
Conclusion
Wartime Software is a collection of techniques that have evolved to build software quickly, and to win in a software-fueled business. People who practice some subset of this collection of techniques often find themselves moving towards the goodness end of the software architecture dimensions as they rapidly cycle their code, since every small step along any of the three dimensions helps them move more quickly and satisfy emerging customer needs more rapidly than the competition. It’s one of the most powerful tools in the Wartime Software arsenal.
Comments