Created June 30, 2021
Updated June 30, 2021

Jeroen's Hierarchy of Constraints

The "lower to the metal" you enforce a constraint, the more robust it is. It also tends to be simpler to understand and maintain higher up the chain.

For a given constraint you're trying to enforce (i.e. guarantee you want to provide), start from the top and consider each option before moving on to the next level.

  1. [Make Impossible States Impossible]
  2. Provide guaranatees through API design
  3. Provide guarantees through code generation
  4. Provide guarantees through elm-review rules

For example, let's say you wanted to make sure that a custom type that can have errors must always have at least one error if it uses the error variant.

type ApplicationContext
    = Loading
    | Error ( List LoadError )
    -- ...

If you enforce that with level (4) by trying to write an elm-review rule, it will be far more complex to implement and understand the rule, and more likely to miss some cases. Instead, it's much more robust and simple to use approach (1) by changing your custom type to make impossible states impossible:

type ApplicationContext
    = Loading
    | Error ( LoadError, List LoadError )
    -- ...

Sign up to get my latest Elm posts and course notifications in your inbox.

Incremental Elm

Pure Elm content. Unsubscribe any time.