Skip to main content


Showing posts from November, 2021

Generating types with build-in invariant preservation using C# source generators (2 / x) : Composition to form complex types

In the last post about "Generating types with build-in invariant preservation using C# source generators" I mentioned composing instances of Validated<T> in a smart way to form complex types that in turn also perverse their invariants. This post will go more into detail on how to do that. Validated<T> captures the essence of wetter or not an instance of a type T is in a valid state or not.  Validated<T> has 2 subtypes, namely Valid<T> and Invalid<T>. You will never guess what they represent ... Ok, you did. Valid<T> indeed means that whatever the state an instance of T is in, it is in a valid state. Invalid<T>, ... well I think you get it. So how do we guarantee the instance of T is in a valid or invalid state? Well, by validating the input that leads to a state change. When programming in a functional style, which we are doing here, we don't want to let the state of an instance of T change at all after it has been created. So th

Generating types with build-in invariant preservation using C# source generators (1 / x) : Simple types

In an earlier post, I described a way for generating value types. In this post, I want to show how to take this a step further. Usually, one does not only want an alias but enforce an invariant using the type system at the same time.  So first let's recap what we mean by an invariant. Plainly put, an invariant is a condition that stays true no matter what happens. For example, let's suppose we have a value in our system that represents a quantity that must always be greater than zero. That is an invariant. Invariants pop up all over the place when modeling a domain. We want to enforce these invariants because we want to guard the integrity of our domain model. One very convenient way of guarding the integrity of values within the domain is by capturing invariants directly into the type system. Once you successfully create an instance of a type guarding the invariant, you never have to check its validity again. In addition to that, the validation logic is captured in 1 place, wh