A System Of Layers
The ability of the human mind to grasp and understand large, software-intensive, systems is severely constrained by the level of complexity that can be held within its boundaries at once.
One way of reasoning about a large system is to conceptually view it as a layered stack of increasingly abstract, reasonably distinct, entities.
“Each system level provides the context for the level(s) below.” – Unknown
At the top of the stack, we have the System layer: The set of interrelated capabilities and functions that capture the abstract ideas, wants, needs, and expectations for what we want the system to do for us.
The next layer down is the Architecture: the patterns of structures and behaviors of the set of interconnected elements that comprise the system. Every system has an architecture, whether it is widely known or not.
The third layer down is the Design: the patterns of structures and behaviors of the set of interconnected modules within each architectural element. Like at the system level, every architecture has a design, whether it is widely known or not.
Finally, at the bottom, where all is scrutably visible, we have the Implementation: the concrete, messy, raw materials (the source code and the hardware) which we create and mold over time to develop, build, integrate, and test, the system. In C++ implementations of a system, the source code is comprised of nested namespaces, classes, functions, and imperative statements stored on files that are compiled and linked together into a set of libraries and executable images deployed on the hardware that ultimately runs the software.
“It’s better to have a partial view of the whole than a complete view of the parts.” – Dave Snowden
When the system switch is flipped on, all the inter and intra connected layers begin an intricate shake-bake dance from which dynamic behaviors emerge to provide perceived value to (at least) some subset of its stakeholders (users, owners, builders, etc).
A System Of Systems
No system exists in a vacuum. Many four layer SADI systems are often inter-connected to provide more value to existing and newly added users. Take the Bitcoin eco-system, for example:
Many L2 systems like the Lightening and Liquid products are under development as we speak. L3 systems – who knows?
A large system can development can start unintentionally from the bottom up, intentionally from the top down, or semi-intentionally from both ends at once via an unknown, creative, iterative, schizophrenic, thinking process.
The Fused Satoshi Layers
If you read Satoshi Nakamoto’s writings, you can get some insight into the thought process he used to birth one of the potentially greatest man-made systems of all time, Bitcoin.
As Satoshi’s quote implies, instead of a neatly stacked, modular, four layer SADI system with crisply defined boundaries and interfaces, he thought about the top 3 “fused” layers for 2 years before hatching the first C++ implementation that ignited a movement intended to crush the existent, corrupt, world-wide banking system.
Other than his groundbreaking white paper, Bitcoin: A Peer-to-Peer Electronic Cash System, it is unknown if he captured/recorded any of his architectural and/or design ideas in writings and drawings like Leonardo daVinci.
Perhaps there seems to be no a-priori diagrams/notes avalailable for the world to marvel at because he kept obsessively massaging, molding, and simulating the top three SAD system layers deep inside his brilliant mind before writing/releasing the first version of the Bitcoin C++ implementation as an open source project for all to see:
Somewhat paradoxically, Satoshi also said that he wrote all the code before hatching the white paper:
So, Satoshi’s personal development process for Bitcoin seems to have been:
- Intense, iterative, simulative, thinking at the SAD layers of abstraction for over 2 years (like all brilliantly obsessed innovators do?)
- Intensive, iterative, detailed C++ coding at the Implementation level for an unknown period of time.
- Writing the white paper after the code was “done“.
Like life, system development is damn messy. Whether you start developing a system to implement a grand vision of yours rigorously from the top down, or haphazardly from the bottom up, you’re likely to get something working. However, you never know what you’re gonna git: 1) an elegant, highly maintainable code base, 2) a kludgy house of cards, or, most likely, 3) a semi-maintainable psuedo-mess in between those two extremes.
So, what’s the point of this post? Hell I don’t know. I just felt like writing it. Since I had no “grand vision” for what I wanted from this post, I started haphazardly from the bottom up and then bounced back and forth between bottom-up writing and top-down thinking until I decided it was “done“. In my day job, where I write C++ software, I always start from the top-down first (unless I’m trying trying to understand/localize/fix a bug in my or a peer’s sprawling code – which is, sadly, most of the time).
How about you? Do you start a new project with “Hello World” coding and pray for guidance from the good lord above to lead you to the promised land, or do you start rustling up and leading those billions of brain cells in your head that are just chomping at the bit to guide you to the holy grail of self-realization?
“The entire system also must have conceptual integrity, and that requires a system architect to design it all, from the top down.” – Fred Brooks
It took me approximately 20 minutes of iterative e-sketching to whip up the following figure:
During the process of construction, I experienced a slew of fragmented, half-baked, thoughts on how to present the intent and meaning of the diagram with some accompanying text. After I deemed the diagram “done“, I uploaded it to this page and reflected on it for 10 more minutes – trying to stitch the thought fragments together into some kind of coherent story that would interest you. I know the overarching theme has something to do with “matched system design“, but that’s all. I failed; and it’s time to move on.
If you’re a C++ programmer, you’ve surely written code in accordance with the RAII (Resource Acquisition Is Initialization) idiom. Inspired by the RAII acronym, BD00 presents the RAID idiom: Requirements Allocation Is Design…
In order to allocate requirements to a design, you must have a design in mind that you think satisfies those requirements. Circularly speaking, in order to create a design (like the one above), you must have a set of requirements in mind to fuel your design process. Thus, RAID == DIRA (Design Is Requirements Allocation).
In any control system design, the accuracy of its input sensors, the force of its output actuators, the ability of its controllers to decide whether the system’s goals are being met, and the responsiveness (time lag) of all three of its parts determine its performance.
However, that’s not enough. All of the control system’s sensors and actuators must be actually interfaced to the controlled system in order for the controller + controllee supra-system to have any chance at meeting the goal supplied to (or by) the controller.
Before reading any further, please contemplate this Box cutter:
Essentially, all models are wrong, but some are useful- George Box
Now, let’s start with a pair of “model” problem-system and control-system templates:
Next, let’s hypothesize a new composite system that you designed, built, and deployed to “solve a vexing socio-technical problem“. You diligently employed the dorky BD00 templates, your brain, and your positional power to form a “semi–effective” marriage between your specific problem (indicated by the blue, scoped boundary) and your specific controller (indicated by non-white components):
Although your new system may appear to be alleviating (or least containing) the problem, looks can be (and usually are) deceiving. Before you pat yourself on the back for being a “problem solver“, please contemplate these Gall-isms:
New systems generate new problems – John Gall
Systems Develop Goals Of Their Own The Instant They Come Into Being – John Gall
Intra-system Goals Come First – John Gall
Thus, according to the Gallster, the a-priori and noble “G” you designed into your fabulous controller subsystem will eventually be usurped (sooner rather than later) by the emergent “G” of the new composite system entity. Sometimes the new “G” totally obscures the original “G” so thoroughly that, given enough time, nobody can even remember what the original “G” was. D’oh!
And what might this new system “G-Spot” be? Could it be to perpetuate and maybe even exacerbate the original problem so that the new system (especially the controller subsystem) can grow and thrive? After all, if the problem gets solved, then there will be no more need for the controller subsystem. In effect, the new system would be devouring itself as it solved the problem. But wait! That can’t happen because it would be a fruitless attempt to violate this Gall-Shirky pair:
Systems Tend To Grow, And As They Grow, They Encroach – John Gall
Institutions Tend To Preserve The Problem To Which They Are The Solution – Clay Shirky
An alternative BD00 quote rip-off is:
Systems, like people, tend not to consume themselves as food.
Can you concoct another alternative rip-off quote?
Alright, before we go on, let’s first get something out of the way so that we can start from the same context. This post is not about Small Scale Development (SSD) projects. As the following figure shows, on SDD projects one can successfully write code directly from a list of requirements (with some iterative back-and-forth of course) or set of use cases or (hopefully not) both.
Now that we’ve gotten that out of the way, let’s talk about the real subject of this post: Large Scale Development (LSD <- appropriate acronym, no?) projects. On hallucinogenic LSD efforts, one or possibly two additional activities are required to secure any chance at timely success. As the next figure shows, these two activities are “System Design” and “Software Design“.
So, what’s the difference between “system design” and “software design“? Well, if you’re developing software-intensive products for a specialized business domain (e.g. avionics, radar, sonar, medical, taxes), then you’re gonna need domain experts to bridge the GOHI (Gulf Of Human Intellect) between the higher level requirements and the lower level software design…..
Most specialized domain experts don’t know enough about general software design (object-oriented, structured, functional) and most software experts don’t know enough about domain-specific design to allow for successfully skipping the system design phase/stage. But that hasn’t stopped orgs from doing this….
On the left-hand side of the diagram below, we have a static system design structure where four “workers” and their manager have their hearts set on producing a world class product. On the right, we have an alternate system design where only one worker has his/her heart set on creating a world class product. The other team members are too busy posing, competing, and jockeying for positional stature in the mind of the manager for their next upward career move. It’s not shown on the diagram, but that manager is also jousting with his peers to advance his/her career.
In orgs where the policies/procedures/incentives/rewards promote individual performance over (and at the expense of) team performance, you’ll most likely find the design structure on the right in operation. Which archetype does your system design map onto?