Skip to content

GeeCON Prague 2018: Michael Nygard

Communitygeecon conference52 minOpen on YouTube ↗

Coverage of GeeCON Prague 2018: Michael Nygard from the conference program.

Summary

Michael Nygard explores coupling in software systems and strategies for deliberate decoupling to improve system maintainability and flexibility. He opens with a metaphor contrasting well-organized modular structures (buckyballs) with tensegrity structures that hold themselves together through tension and compression. Software systems often evolve from modular buckyballs into tensegrity-like blobs where moving one piece affects distant, seemingly unrelated parts—a consequence of uncontrolled coupling spreading throughout the codebase.

Nygard defines five types of coupling: operational coupling (runtime dependencies preventing execution without the provider), development coupling (requiring coordinated code changes), semantic coupling (shared concepts requiring synchronized changes across systems), functional coupling (shared implementation requiring parallel modifications), and incidental coupling (unnecessary dependencies). He illustrates these through real-world examples: email systems with SMTP and Exchange (strong semantic and operational coupling, weak development coupling due to protocol standardization); direct database access (strong operational, development, and semantic coupling); REST interfaces (moderately reduced operational coupling, improved failover transparency); and message-oriented architectures (weak operational and development coupling, though strong semantic coupling remains).

Nygard warns of two significant pitfalls. 'Semantic polymers' occur when concepts spread throughout an enterprise as shared data feeds, making any individual concept difficult to change—illustrated by a retail system where SKU concepts required organization-wide modifications when introducing price points. 'Long arrows' represent interfaces that appear simple in architecture diagrams but actually involve many sequential steps, accumulating the worst performance and availability characteristics of each component rather than the best.

The primary solution framework comes from David Parnas's 1972 paper on system decomposition. Parnas demonstrates how restructuring the same system with information-hiding (later termed decision-hiding) interfaces can encapsulate specific concerns—character encoding, memory management, storage mechanisms—allowing changes to localize to single modules. This approach introduces more components but paradoxically increases simplicity through reduced coupling. Nygard emphasizes orthogonality and separation of concerns: decisions about different system aspects should be independent, with each module hiding decisions behind clean interfaces.

A key insight is that composability—the ability to flexibly combine components—is inversely proportional to the number of distinct interfaces and data types. Modern microservices often increase coupling by creating unique APIs and data types for each service, whereas standardizing on fewer interfaces and data types improves composability and reduces coupling across all dimensions.

Nygard recommends: explicitly identify which coupling types matter most for specific systems; prefer libraries over services to avoid trading recurring runtime costs for development efficiency; standardize on fewer interfaces and data types across services; use all available structural tools (modules, components, abstractions); and always make decisions explicit rather than implicit. Coupling is necessary to accomplish coordinated effects, but uncontrolled diffusion makes systems brittle and expensive to modify.

Related talks