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
In the prequel to this post, “Sloppy Coding“, I showed some rather trivial, small-scoped, examples of antiquated C++ coding style currently present in a hugely successful, widely deployed, open source code base. In this follow up post, I’ll do the same, but at the higher, class level scope.
Hey, I troll often, and this is what trollers do. 🙂
The Class Definition Under Assault
If you’re a young, advancing, C++ programmer, you may want to think about avoiding the bad design decisions that I rag about in the following class definition:
Where Are The Private Members?
After scanning through the class definition for the first time, the most blatantly obvious faux pax I noticed right off the bat was the “everything is public!” violation of the golden rule of encapsulation. If the intent was for CBlockHeader to be a user-defined type with no need to establish and preserve any invariant conditions, then it should have been declared as a less verbose struct .
I know, I know, that’s another nitpick. But there’s more to it than meets the eye. Notice the last three CBlockHeader class member functions are declared const. Since users can directly reach into a skinless CBlockHeader object to mutate its internal state at will, nice users can be unsafely stomped on by cheaters (Jihan Wu? 🙂 ) in between calls.
The cheater gets the 50, and the nice guy gets the goose egg.
Where Are The Initializers?
Notice that the CBlockHeader class constructor does not contain an initialization list – all initialization is performed in the constructor body via a call to SetNull().
An initialization explicitly states that initialization, rather than assignment, is done and can be more elegant and efficient (CppCoreGuidelines). It also prevents “use before set” errors. For a slight performance bump upon each CBlockHeader object instantiation and good C++ style, the struct implementation of the CBlockHeader constructor should look like this, no?
Nasty Pre-processor Hackros, Turtles All The Way Down
Ugh, I don’t even know what to say about the dangerous 1980’s C pre-processor macro bombs planted in the class definition: ADD_SERIAL_METHODS, NCONST_PTR (nested within ADD_SERIAL_METHODS) , and READWRITE. Compared to the design flaws pointed out previously, these abominations make the class uncomfortably uninhabitable for a large population of otherwise competent C++ programmers.
Bjarne Stroustrup is the creator of C++ and a long time hero of mine. He’s been passionately evolving the language (C With Classes, C++, C++98, C++11, C++14, C++17) and a leading force in the community since the 80s. Mr. Stroustrup has this to say about Hacros:
A safer, more maintainable, alternative to the current Hack-Horiffic design would be to wrap the required inline functionality in class templates and have CBlockHeader publicly extend those classes. The details are left to the aspiring student.
Ok, ok. EVERYONE on social media knows that trolls beget trolls. So, troll away at this post. Rip me to shreds. I deserve payback.
I bought into Bitcoin 2+ years ago with a full understanding that my investment could instantaneouly go to ZERO – poof! I was (and still am) hoping to kill 2 birds with one stone:
- Help give the world’s billions of “unbanked” people the opportunity to bootstrap themselves out of poverty by participating in commerce (the original Bitcoin cash use case) without any middlemen blocking their way and “feeing” them to death.
- Make money in the long term on my investment in other, less fortunate than I, people.
Before proceeding to view and interpret the following blasphemous diagram as either “right on” or a total “croc o’ conspiracy crap“, here’s my caveated stance on the devastating civil war going on in Bitcoinland:
Activating SegWit is clearly the safest technical option available to move the Bitcoin protocol forward at this point in time. Thus, the I hope it activates and the smoke clears ASAP.
The caveat is this… Based on my observation of how the strategic trajectory of the protocol regarding future on chain scaling has been subtly distorted since the worst thing to ever happen to Bitcoin occurred (the insertion of Blockstream Inc. financial influence into the development team), I hope the whole “the Bitcoin Core software development team Is An Untainted, Decentralized group” potemkin village is destroyed and this particularly toxic special interest group, Blockstream Inc., is seen for what it is – a big, centralized, banksta in clever disguise.
The way the Bitcoin protocol is evolving, it looks like more and more “regular” people are being priced out of the the L1 “trustless” blockchain and kicked upstairs onto L2 “trust-me” IOU payment service providers.