QIAOPANG.COM · SELECTED ESSAYS (2013–2026) · 260 ESSAYSBrowse Chronologically (2013 → 2026) ↗
QiaoPang · Programmers LifeSelected Essays · Systems, Craft & Agentic Era
Timeline ↗

Boundary

Boundary

Much of what we do when building systems and designing software is, in fact, defining boundaries. Functions need clear boundaries with other functions, modules with other modules, services with other services, applications with other applications. Clear boundaries make our code logically rigorous and well organized. Inside a boundary, the interior is a black box to the outside world: all exchanges, material and immaterial, can occur only at the boundary through known interfaces; at the same time, impure data from the outside world is validated, filtered, and transformed here into pure data that fits the way the internal world operates.

In the prehistoric era of computer software, software resembled a prokaryote: utterly simple—just lines of machine code piled onto punched paper. Later, the assembly era introduced the concept of the subroutine/procedure, which further evolved into the function. A function’s boundary is its signature; a function’s signature consists of its name, input parameters and their types, and return value and its type. External callers need not understand the implementation; they execute the function’s code by calling it. Functions are like cells in an organism.

Boundary

As software grew more complex, groups of functions were organized into classes or modules to accomplish a particular functionality; from then on, the concept of scope became deeply ingrained. Some functions serve as external interfaces and are public; others perform internal work and are private. The boundary of a class or module consists of its file name, class name (module name), and public methods. Classes or modules are like tissues in an organism.

Boundary

Further up, several classes/modules aggregate to provide a particular service, forming a component. A component is often embodied as a directory (or subdirectory) with its own abstract interface (start / stop / process_message / …). A component’s boundary consists of the directory it occupies, its abstract interface, and its public classes/modules. Components are like organs in an organism.

Boundary

One thing organisms and software share is that they too reject a single point of failure. The image above shows the human kidney—a classic active-active cluster setup. One reason those who sold a kidney to buy an iPhone 4 or iPhone 6 Plus are still alive and kicking is that even if one kidney is gone, the other takes on all the traffic, keeping the circulation of bodily fluids unobstructed (though its maximum load capacity is of course reduced).

Like LEGO bricks, we can further aggregate several components to achieve a particular purpose, forming an application or subsystem. An application is embodied as a project made up of several directories. Its boundary consists of its name, the resources it uses (such as ports), and the application’s entry point (such as the main function). An application is like a system in an organism—for example, the circulatory system shown below:

Boundary

Further up, several applications form a solution that safeguards a particular business objective. A solution is like a complete organism; its boundary can be as large as a complex business blueprint or as small as a utility app on iOS. By analogy with a complete organism, when we build a solution, we must define its subsystems—which of them should be:

  • dummy system — like our respiratory system, it works rain or shine, operating automatically even while we sleep. Examples that come to mind include logging systems, monitoring systems, and error-reporting systems.
  • intelligent system — like our immune system, it responds according to external changes. Such systems are generally used in behavior-based reaction systems, such as firewalls and dynamic user classification.
  • C&C system — command and control, like our brain, issuing orders and controlling the behavior of the whole organism. The “S” in SDN, which was all the rage a few years ago, is exactly this thing.

Let us review the boundaries we have just discussed and their impact on architecture and design:

Boundary

All the boundaries discussed so far are merely those we design during development. Boundaries at runtime differ somewhat:

Boundary

As we can see, even if we organize code into components or services, the operating system—or the runtime (VM) of most software—does not provide us with a similar organizing mechanism. So even when we separate components clearly within a project, at runtime they are all mixed together. In most cases, we can only organize them ourselves based on experience. nginx, for example, uses multiple processes to delineate the control plane and data plane—a classic approach.

The Erlang VM has a good design that solves the problem of component independence at runtime, giving them clear boundaries even while running. This is its concept of an application.

Boundary

In this diagram, a process in the OS sense consists at runtime of several applications (components). Each application has its own supervision tree and its own heap, and can be started, stopped, restarted, or even upgraded independently.

MORE IN Languages & Craft

Further Reading in This Column

View all essays in “Languages & Craft” →

Time to Meet jj: Git's Next Evolutionary Step

Git has ruled version control for twenty years, but its staging area, brittle rebases, and blocking merge conflicts are becoming liabilities in the AI era. jj rebuilds the mental model from the ground up — while staying fully Git-compatible. Here's why it deserves your attention.

New Hope (2025–2026)5,588 chars · 12 min read