So you think you’re domain-driven?

In a project I am currently involved with, a core part of the system involves a couple of fairly complicated (at least to me :)) computations involving time, power, energy, fuel, volumes etc.

At first, we just implemented the computations “as specified”, i.e. we went ahead and did stuff like this:

to calculate how many MHhs a given device can deliver. This is just an example, we have a lot of this stuff going on, and this will be a major extensibility point in the system in the future.

I don’t know about you, but I got a tiny headache every time I looked at code like this, part from trying to understand what was going on, part because I knew errors could hide in there forever.

To remedy my headache (and the other team members’ headaches), we started migrating all that funky double stuff to some types, that do a better job at representing – i.e. Power for power, Energy for energy, and so on!

All of them, of course, as proper immutable value types (even though we use classes for that).

And then we utilized C#’s ability to supply operator overloading on all our domain types, allowing stuff like this to happen:

where currentProduction is an instance of Power and remainingRuntime is a TimeSpan. And whoever gets the Energy that comes out of this, will never have to doubt whether its Whs, KWhs, or MWhs – it’s just pure energy!

Now, this may seem like a small change, but it has already proven to have huge ramifications for the way we implement our computations:

  1. There is no such thing as multiplying two powers by accident, or subtracting two values that cannot be subtracted and still make sense, etc.
  2. We have no errors due to wrong factors, e.g. like KWs mistakenly being treated as MWs
  3. We have gained a cleaner, more intuitive core API, which is just friggin’ sweet!

In retrospective, I have done so much clumsy work in the past that could have been avoided by introducing proper value types for core domain concepts, like e.g. money, percentages, probabilities, etc.

I usually call myself “pretty domain-driven”, but now I realize that there’s an entire aspect of being just that, that I have overseen.

Do you think you’re domain-driven?