What’s true of every bug found in the field? … It passed the type checker [and it] passed all of the tests. - Rich Hickey
All bugs pass the type checker and all of the tests. More importantly all bugs represent a guarantee that was intended to be present, but for some reason it wasn’t.
Perhaps you intended to display the first name of a person but firstName was mistyped as firstname and undefined was displayed instead.
Perhaps you intended the user experience of all data entry forms to be the same. Users should see validation errors as they tab through each form. However, on one particular form validation only occurs on form submission.
You intended for there to be some guarantee with the application’s behavior, but somehow that guarantee was broken. That invariant was not upheld.
What is an invariant?
An invariant is a rule, or condition, that can be relied upon to be true during the execution of the program. Another way of describing that is:
An invariant is a logical guarantee about the application.
Invariants can be very low level. They can be represented by basic types, or the fact that you might want certain data to be immutable.
Invariants can also represent more abstract concepts. For example, they can represent the asynchronous life cycle of data, or they can represent the user experience of certain user-facing components.
What is Invariant Driven Development (IDD)?
Invariants are an important concept in software development and are commonly seen in other development approaches, such as Domain Driven Design (DDD). In this post, I’m going to speak to a related approach and refer to it as Invariant Driven Development.
Invariant Driven Development is an approach to software development that promotes invariance to a first class concern. It has three steps:
- Identify the desired invariants
- Enforce those invariants
- Refactor if necessary
At first glance this looks somewhat similar to TDD, but we’ll see the two approaches part ways shortly.