DEV Community

Make impossible states impossible - Kotlin edition

Pin-Sho Feng on March 16, 2020

Sometimes called "functional domain modelling", there are a bunch of articles and videos titled like that but I haven't found a Kotlin edition, so ...
Collapse
 
le0nidas profile image
le0nidas

That is a clever usage of interfaces!

I recently had to deal with a similar case while refactoring some legacy code.
My approach to create valid entities was achieved via factory functions. In a nutshell you can have a

fun UserName(value: String): UserName? {
    return if (value.isEmpty()) null else UserName(value)
}

which tricks the dev to think that is using a constructor but at the same time keeps everything valid and readable.

If you are interested I wrote a blog post here.

Collapse
 
psfeng profile image
Pin-Sho Feng • Edited

Interesting blog post, thanks! I like that increasingly more people are aware of this problem :)

As for the suggestion, I'd advise against doing it that way because it goes against the conventions:

  • Naming: function names should start with a lowercase letter, see here.
  • From outside it looks like a constructor and I wouldn't expect a constructor to return null.

My 2 cents.

Collapse
 
le0nidas profile image
le0nidas

Both arguments are valid. Especially the second one didn't even crossed my mind. Thank you!

Collapse
 
patroza profile image
Patrick Roza • Edited

Big fan of such (Functional) domain modelling.
What's your take on the Null vs Option vs Either?
From my perspective:

  • Null and Option have a similar semantics; they both can model the availability or absence of a value
  • Either can help you document the error cases in more detail to expose what is wrong and perhaps have decisions made based on that, or to report it back to the user.

My interest is in when to choose Null or Option. I'm facing the dilemma in Typescript; if I don't need the resolution of Either, shall I use Option or just keep it simple with Null...
That is ignoring for a moment that we also have undefined ;-)

In languages without good type support, null can be a real pain, but in Typescript and I suppose Kotlin, things are better. So I guess it just is a matter of null can make it more difficult to compose, yet easier to consume as you only need to assert, not unwrap like Option/Either.

Collapse
 
psfeng profile image
Pin-Sho Feng

I've had the exact same dilemma and for the moment my loosely-held conclusion is that Option is unnecessary in Kotlin. Perhaps if you use Arrow it provides syntax sugar with monad comprehensions but I wouldn't say that's a good enough reason to use it over built-in nullables.

The only case where I think using Option or Optional has an advantage is when your code needs to be used from Java and you want to keep null-safety. Would this apply to Typescript and Javascript?

Collapse
 
cubiclebuddha profile image
Cubicle Buddha • Edited

Great article. However, I will say if you want first party support for unions it’s likely better to use a language that has unions like TypeScript.

Collapse
 
psfeng profile image
Pin-Sho Feng

I'd say that multiple reasons need to be evaluated before choosing one language or another :)