What are the chances I drop one of these small sticks while setting up? Maybe I am just clumsy, but in my experience so far, chances are about 1 in 5. I am often out in a remote area to fly my drone, so when I get the controller out, I am mindful to remove and attach the control sticks while standing over a flat, wide surface. That way, if I accidentally drop one, it is unlikely to roll away or fall into a crack. I rarely drop one, but this practice ensures no unexpected failures.
I see this as a case of the engineering maxim: “Hope for the best, but plan for the worst.”
Planning for the worst means anticipating abnormal and faulty behavior. Such planning is a hallmark of good engineering and is at the heart of safety-critical engineering. While it is relatively easy for me to anticipate the abnormal case of dropping a control stick, many of the systems we engineer are massively complex. Then it is not trivial to enumerate all the ways things can go sideways. As an example, let’s look at modern software.
Modern software is complex
To quantify how big modern software has gotten, I will use the traditional measure – in units of Apollos. That is, if the US 1960s spacecraft had around 30,000 Source Lines of Code (SLOC), then how many “Apollos” is a modern piece of software? The Operating System (OS) on your device (whether a smartphone or laptop) is in the 10s of millions of lines of code, or over 500 Apollos.
Consider the Linux kernel. It has surpassed 40M SLOC. Where does all that code go? The Pareto Principle states that roughly 80% of consequences or effects result from only 20% of the causes. Likewise in many software programs. Only a small portion of that OS code is exercised regularly. Much of it is rarely used, and on any specific machine, much of it may never be used.
You can see in the Sankey diagram that the lion’s share of the Linux kernel goes to drivers. Many of these drivers are only needed on a select few target machines. (Kind of like in typical church congregations where 20% of the people do 80% of the work!)
On the one hand, this uneven distribution means that the open source community can focus on ensuring the quality of that central core of the kernel. On the other hand, this means some bugs may lurk in the less used (and thus less examined) code. Whether they are software bugs or design miscalculations, subtle errors can be difficult to detect even with thorough testing, especially when the flaw only presents in unusual corner cases. The behavior of complex engineering systems can be very difficult to predict comprehensively. Even when the individual components are simple, the sum of the parts can exhibit unforeseen emergent behavior.
Beyond the Blueprint: The Secret Life of Complex Systems
Our designs often do not behave exactly as we intend. Abnormal behavior that we do not foresee can lead to unanticipated consequences that cause harm. This lack of foresight can be traced back to two fundamental characteristics of our human identity: we are finite and fallen.
Finite
Engineers who design technology (such as the Linux kernel) and people who use technology (all of us) are finite. Humans are finite – not as a result of the fall into sin – but from the very beginning. God created us; we are creatures.
God intended the human characteristic of finitude. We are engineered with this inherent design characteristic. Although made in the image of God, we do not share God’s infinite qualities of omniscience and omnipotence. We thus do not have perfect foresight and cannot anticipate all consequences for our designs. Our brains have a limited capacity.
Even when we augment our thinking by working with teams of naturally intelligent people using tools like artificial intelligence, our collective capacity for foresight is still finite.
Because every creature, and indeed all of creation is finite, certain trade-offs were necessary even in the beginning, before the fall. Even in the garden of Eden, the design of a bridge would require choosing the right materials, trading off load capacity with total length, and so forth. That finite nature of our materials holds true today: trade-offs are a natural part of the design process.
Fallen
Both the engineers designing technology and the people using it are fallen. Humans are corrupted by sin, and all creation with us. Sin taints our thinking and our desires, and thus it taints our engineering design. Sin taints the thinking and desire of the users of technology.
God did not intend this human characteristic of fallenness. However, when the first humans sinned, although not God’s plan, he provided a new redemptive plan to address the flaw we introduced.
Until the final restoration, sin taints creation – though it is often hard to separate out the characteristics of creation that are finite from those that are fallen. To act as Christ’s redemptive agents in this world today, we require the discernment that comes from the Holy Spirit so that we can identify the original creational good and work to root out the corruption of sin.
There are many virtues we could bring to bear in designing technology that properly recognizes both these characteristics. As an example, let’s consider the virtue of humility and see how it undergirds one particular avionics technology.
Case Study: Avionics Partitioning
A new avionics standard was published in late 1996. In that year I was an Assistant Professor of Engineering at Calvin College (now University). I wanted to keep my teaching fresh and relevant, so I pursued engineering consulting work during the summers. That particular summer I landed a part-time position at Smiths Aerospace in Grand Rapids. One of my tasks was evaluating the proposed international standard, ARINC 653. Little did I know then that I would continue working with this standard for much of my career. Thirty years later, just before my retirement, I have had the privilege to co-chair the ARINC 653 standards committee.
The ARINC 653 standard was first published in the fall of 1996, but my manager back then at Smiths had an early draft of the standard for consideration over that prior summer. I was part of a three-person team that he asked to evaluate the proposed standard. It would be used on a new powerful centralized avionics computing system. The new approach would consolidate numerous legacy federated computing systems into a single Integrated Modular Avionics (IMA) platform. Since each federated system was a separate box in the aircraft with its own power supply, enclosure, and connectors, this consolidation would substantially reduce the Size, Weight, and Power (SWaP) needed to execute all the software on a modern aircraft.
The substantial reductions in SWaP provided by IMA increase the range of the aircraft while reducing its cost. The drawback is that software previously segregated on physically separate computers is now integrated on one. This raises the possibility of unanticipated interactions between independent functions. The ARINC 653 standard, coupled with another standard, DO-297, describes how to continue segregating independent functionality using robust partitioning.
System engineers map each independent software program to a partition. The partition is allocated a certain portion of the resources. The resources are provided by the computing platform, but shared among multiple partitions. This sharing can be done in one of two ways: time partitioning or space partitioning.
Time partitioning gives a partition exclusive access to a resource but only periodically. Think of a teacher who gets to use a classroom for a 9am class, but gives it up at 10am. Likewise, the partition gets to use a processor core for the first 10ms of every 100ms, but gives it up for the rest.
Space partitioning gives the partition continuous (rather than scheduled) access to a resource – but not the whole resource, only a portion of it. Think of a student who gets one locker out of a bank of lockers, but has exclusive access to that one locker whenever they want. Likewise, the partition gets to use certain pages of memory that contain its data, which no other partition may read or modify.
Partitioning as Design Humility
By partitioning all shared computing resources in time and/or space, we can have high confidence that one partition cannot influence the intended behavior of another partition. Avoiding unintended interactions and reducing the chance of unanticipated changes in behavior is important for safety-critical systems like avionics.
Partitioning demonstrates humility in our design. As an engineer of any stripe, but especially a Christian engineer, I ought not put undue confidence in my own ability to comprehend complex systems and foresee all the ways things could turn out.
Partitioning is a way to recognize my finite nature. By segregating each independent function, I can now simplify my analysis by restricting myself to thinking about that function alone – knowing that the other functions cannot impede or alter the function I am examining. I might not be able to wrap my finite mind around 50 complex software programs all combined into one monolith, but I have a fair chance at comprehending each one individually. Partitioning allows me to divide and conquer.
Partitioning is also a way to recognize the fallen nature of humanity. A negligent or malicious design of one function is now isolated in a partition so that it cannot harm the operation of other partitions.
Conclusion
If you are an engineer, whether designing software, automobiles, bridges, or some other technology, consider humility not only as a personal virtue, but one that can become part of your work as well. Humbly consider all the ways you yourself could be biased against seeing a flaw. Humbly consider all the negligent and malicious ways a user could abuse the product beyond its intended use. Designing technology in humility makes it safer for all. If our systems are too big for any one mind to hold, is it arrogant to build them without partitioning (or equivalent)?


No comments:
Post a Comment