Before talking the final point in the network design mindset, ,act, I wanted to answer an excellent question from the comments from the last post in this series: what is surface?
The concept of interaction surfaces is difficult to grasp primarily because it covers such a wide array of ideas. Let me try to clarify by giving a specific example. Assume you have a single function that—
- Accepts two numbers as input
- Adds them
- Multiplies the resulting sum by 100
- Returns the result
This single function can be considered a subsystem in some larger system. Now assume you break this single function into two functions, one of which does the addition, and the other of which does the multiplication. You’ve created two simpler functions (each one only does one thing), but you’ve created an interaction surface between the two functions—you’ve created two interacting subsystems within the system where there only used to be one. This is a really simple example, I know, but consider a few more that might help.
- The routing information carried in OSPF is split up into external routes being carried in BGP, and internal routes being carried in OSPF. You’ve gone from one system with more state to two systems with less state, but you’ve created an interaction surface between the two protocols—they must now work together to build a complete forwarding table.
- A single set of hosts with different access policies are split onto multiple virtual topologies on the same physical network. You’ve simplified the amount of state in filtering, but you’ve created an interaction surface between the two virtual topologies, between the two topologies and the control plane, and you’ve exposed new shared risk groups where a single physical failure can cause multiple logical ones. Hence you’ve traded state in one control plane for interaction surfaces between multiple control planes.
Even two routers communicating within a single control plane can be considered an interaction surface. This breadth of definition is what makes it so very difficult to define what an interaction surface is. To understand how interaction surfaces cause technical debt, I want to point you to a recent paper on machine learning and technical debt.
In this paper, we focus on the system-level interaction between machine learning code and larger systems as an area where hidden technical debt may rapidly accumulate. At a system-level, a machine learning model may subtly erode abstraction boundaries. It may be tempting to re-use input signals in ways that create unintended tight coupling of otherwise disjoint systems. Machine learning packages may often be treated as black boxes, resulting in large masses of “glue code” or calibration layers that can lock in assumptions. Changes in the external world may make models or input signals change behavior in unintended ways, ratcheting up maintenance cost and the burden of any debt. Even monitoring that the system as a whole is operating as intended may be difficult without careful design.
Most systems are designed for a specific “world,” or set of circumstances at a specific point in time. As this “world” changes (over time), subsystems are sheared off and replaced, requirements are changed for each individual subsystem, and external interfaces the original designer counted on are changed and/or replaced to meet updated requirements.
Interaction surfaces aren’t a bad thing; they help us divide and conquer in any given problem space, from modeling to implementation. At the same time, interaction surfaces are all to easy to introduce without thought—hence their deep connection to technical debt.
Next time, I’ll (hopefully) finish this series on the design mindset.