Software Engineering as Systemic Anatomy & Pathology

Treat a running system as an organism rather than a diagram and a different set of questions becomes natural. Diagrams show structure; organisms have to stay alive โ€” they regulate themselves, they have organs with distinct jobs, and when something goes wrong in one part the symptom often shows up somewhere else entirely. This lecture maps software architecture onto anatomy deliberately, not decoratively: each anatomical layer corresponds to a real, separately-reasoned-about concern in system design, and the mapping earns its keep when it changes how you diagnose a failure.

Anatomical Mapping

graph TD Brain["๐Ÿง  Cortex
business logic, decisions"] Skeleton["๐Ÿฆด Skeleton
interfaces, ADTs, boundaries"] Autonomic["โš™๏ธ Autonomic system
GC, thread pools, circuit breakers, logging"] Limbs["๐Ÿฆพ Limbs & actuators
I/O, DB writes, network calls"] Immune["๐Ÿ›ก๏ธ Immune system
validation, types, assertions"] Brain --> Limbs Brain -.regulated by.- Autonomic Skeleton --- Brain Skeleton --- Limbs Immune -.guards.- Limbs Immune -.guards.- Brain
Anatomical layerSoftware equivalentGoverning idea
SkeletonInterfaces, abstract data types, module boundariesParnas's information-hiding criterion: modules should be decomposed around the decisions likely to change, not around the flowchart [1]
Autonomic regulationGarbage collection, thread pools, circuit breakers, loggingRuns continuously and silently; failure here doesn't crash the "mind", it degrades everything gradually โ€” the software equivalent of losing temperature regulation
Brain (cortex)High-level business logic and decision-makingWhere domain rules live; the layer everyone means when they say "the logic"
Limbs & actuatorsSide effects โ€” database writes, network calls, I/OWhere the system touches the world, and therefore where the world's failure modes (timeouts, partial writes) leak back in
Immune systemInput validation, type systems, assertion boundariesMeyer's Design by Contract: precisely-stated preconditions and postconditions as the antibodies that reject malformed input before it reaches the cortex [2]

Systemic Pathology

The reason the anatomical framing earns its keep is that it predicts where symptoms appear relative to their causes, and in living systems as in software those are often far apart. Charles Perrow's study of high-risk technologies coined "normal accidents" for exactly this shape of failure: in tightly-coupled, complex systems, small, individually-survivable faults interact through pathways nobody designed for, producing failures that are not attributable to any single broken component [3]. A thread pool quietly exhausting itself (an autonomic problem) does not announce itself as a resource error โ€” it shows up as the cortex appearing to "hang", or as actuators timing out downstream, because the layer that failed is not the layer where the pain is felt.

Nancy Leveson's systems-safety work generalises the same point into a design method: in a sufficiently complex system, treating an accident as a chain of component failures misses the accidents that arise purely from unsafe interactions between components that were each, individually, working exactly as specified [4]. This is precisely why "which component is broken?" is often the wrong first question for a systemic failure โ€” the better first question is which two correctly-functioning components are now interacting in a way nobody designed for.

Meinhard Lehman's laws of software evolution add a slower-moving version of the same pathology: a system that is used continues to be changed, or it becomes progressively less satisfactory (Lehman's first law); and unless deliberately maintained against it, a system's structure will drift toward greater disorder over successive releases (Lehman's second law, on "declining quality") [5]. Architectural decay is not a discrete event โ€” it is closer to the organism ageing, and it is detectable long before it is symptomatic if anyone is measuring coupling and complexity trends rather than only counting open bugs.

Surgical Refactoring

If the system is alive, changing its internals without killing it requires something closer to surgery than demolition: maintain the patient's vital functions (backward compatibility, uptime) throughout the procedure, change one structure at a time, and verify function is intact before closing up. Martin Fowler's definition of refactoring makes this explicit as a discipline, not just good taste: a refactoring is a behaviour-preserving transformation, verified by tests, applied in small enough steps that the system is never observably broken between steps [6]. The strangler-fig pattern โ€” routing an increasing fraction of traffic to a new implementation while the old one keeps serving the rest โ€” is the direct engineering analogue of a staged surgical replacement rather than a transplant done in one irreversible cut.

The anatomical framing also explains why some "obviously good" refactors are dangerous: replacing an autonomic component (say, swapping a circuit breaker implementation) looks lower-risk than touching the cortex, because it isn't business logic โ€” but autonomic failures are exactly the ones that present as vague, distributed symptoms elsewhere in the organism, which makes them the hardest to link back to the change that caused them. Nygard's operational patterns for production systems treat circuit breakers, bulkheads and timeouts as safety-critical infrastructure precisely because of this โ€” they fail quietly, at a distance, from wherever they were touched [7].

Practical Exercise: System Diagnostics. You are given a running application experiencing degraded performance (real or a provided fault-injected sandbox). Using only externally observable symptoms and logs โ€” no source access at first โ€” form a hypothesis about which anatomical layer is implicated: is this a logic bug in the cortex (wrong decision, right resources), or autonomic resource exhaustion in the "brainstem" (right decision, starved of resources)? Then trace the actual root cause and write up which observable signal correctly pointed at the layer, and which signal was misleading.

References

  1. Parnas, D. L. (1972). On the criteria to be used in decomposing systems into modules. Communications of the ACM, 15(12), 1053โ€“1058. https://doi.org/10.1145/361598.361623
  2. Meyer, B. (1988). Object-Oriented Software Construction. Prentice Hall.
  3. Perrow, C. (1984). Normal Accidents: Living with High-Risk Technologies. Basic Books.
  4. Leveson, N. (2011). Engineering a Safer World: Systems Thinking Applied to Safety. MIT Press.
  5. Lehman, M. M. (1980). Programs, life cycles, and laws of software evolution. Proceedings of the IEEE, 68(9), 1060โ€“1076. https://doi.org/10.1109/PROC.1980.11805
  6. Fowler, M. (1999). Refactoring: Improving the Design of Existing Code. Addison-Wesley.
  7. Nygard, M. T. (2007). Release It!: Design and Deploy Production-Ready Software. Pragmatic Bookshelf.