Sunday 1:10 p.m.–1:40 p.m.

Deliver Your Software In An Envelope

Augie Fackler, Nathaniel Manista

Audience level:
Best Practices & Patterns


Guaranteed behavior makes software modules useful. Software guarantees are commonly incomplete with good reason: promises that are narrow and few are most easily kept across wide ranges of platforms and long times. We define the space of a module’s allowed behavior to be its “behavioral envelope” and show that thinking and speaking in terms of envelopes eases maintenance and makes APIs delightful.


Every piece of software delivers a combination of supported behavior (“what must be”) and incidental behavior (“what happens to be”). Good software differentiates between the two. Great software uses every tool and technique available to describe the two and the difference between them to ease the work of clients, authors, and maintainers. The full behavior that a software module provides can be associated with a single exact point in the space of all possible behaviors. The behavior that that module guarantees is, for software modules of any significant size or complexity, specified less than completely, and thus can be associated with a continuum of points in the space of all possible software behaviors. We define a software module’s behavioral envelope as this continuum of allowed behaviors. Acknowledging the role that documentation and type systems play in shaping and describing a module’s behavioral envelope, we focus the bulk of our talk on how software testing isn’t today being used to reason about behavioral envelopes, how it could be, and why it should be. Testing code for algorithmic correctness is a great start on the path to stable, maintainable software, but it’s only a part of the battle. We introduce the idea of defining a behavioral envelope for your software via machine-executable tests. Such tests inform good API design and sustainable test architectures. Your tests become a critic of your design, and if you delay tests it can be the smell of technical debt creeping into your codebase. We conclude by expanding our ideas to rethink the craft of software engineering itself not as assembling simpler behaviors into more complex behaviors but rather joining simpler envelopes of guaranteed behavior into more complex and more powerful envelopes of supported behavior.