Type Systems and Domain Driven Development

Some days ago I read this tweet from @sendoaportuondo saying that creating a class for the mail field, the phone field, etc was crazy. I quickly asked who said that and he pointed me to Domain Driven Development.

After reading a little about that methodology I just agreed with it. It was a little crazy, I’m sure that there are reasons behind it but for me it seems just another crazy discipline in our field. It’s not the first time that I argued against all this dogmas that we follow without questioning, just because it’s well designed, even if at the end in the majority of cases it just results on having too many layers of complexity.

For this reason this post may seem a little hypocrite but here I go.

After working again with functional programing, after many years, and the powerful type system that the Swift compiler provides us I’ve connected the dots.

If you create types for everything, then you are using the compiler and it’s type system to its fullest potential, and you can ensure that your program is correct just by compiling it. It’s like having unit test automatically written by the compiler!

Let me give you an easy example. Imagine that you have this class Person and the sendMailTo function:

I’m using here a struct, so we are seeing already some Swift coolness, but bare with me, this is just a type. In the initialiser we validate that the mail is valid and if not we fail the initialisation.

In some other place in our code we have a function that sends an email:

If the object is created successfully, we can send the mail because we know that it’s valid. But then in another place of your program you have a mail that came from who knows where:

let mail =// this came from the hell...sendMailTo(mail, text: "Nobody will receive this mail”)

Now, you cannot be sure that this will work because you don't know if the email is valid or not. Of course, you can validate it in the sendMailTo function, or create a Validator that you can reuse (because you want to reuse everything right?). Anyway you will have to write a bunch of Unit Tests to make sure that your App doesn’t crash on the the face of your boss.

But let’s try to do what DDD says. Take a look at this other approach for creating the same class Person:

But now look at what happens with the mail that came from somewhere else::

let mail = "this is not an email"
sendMailTo(mail, text: "hi!") // 'String' is not convertible to 'Mail'

Here we go! String is not convertible to Mail. Compile time error. Even in Swift this is a little verbose, but if you look at pure functional languages basically your code is just a bunch of types interacting, so it just a simple as that.