---
title: "Discussion on \"Make illegal states unrepresentable, until you have to explain them\" | Hashnode"
description: "Discussion on \"Make illegal states unrepresentable, until you have to explain them\". How to decide which constraints belong in your types and which belong in your validator."
url: "https://hashnode.com/posts/make-illegal-states-unrepresentable-until-you-have-to-explain-them/6a94628a3807e45a5040f84d"
---

[Feed](https://hashnode.com/feed) /

Discussion

# [Make illegal states unrepresentable, until you have to explain them](https://underdroid.hashnode.dev/make-illegal-states-unrepresentable-until-you-have-to-explain-them?utm_source=hashnode&utm_medium=feed)

How to decide which constraints belong in your types and which belong in your validator.

Aug 30 · 9 min read · underdroid.hashnode.dev  
Read the article

-   [#kotlin](https://hashnode.com/tag/kotlin)
-   [#software-architecture](https://hashnode.com/tag/software-architecture)
-   [#clean-code](https://hashnode.com/tag/clean-code)
-   [#programming-blogs](https://hashnode.com/tag/programming-blogs)
-   [#software-engineering](https://hashnode.com/tag/software-engineering)
-   [#backend](https://hashnode.com/tag/backend)
-   [#software-development](https://hashnode.com/tag/software-development)

## Written by

[Tom Horvat](https://hashnode.com/@tom-horvat)

@tom-horvat · Seattle, USA

  
[View profile](https://hashnode.com/@tom-horvat)

Android musings

## Responses 2

Markdown supported · ⌘↵ to post

[Adam Lewis](https://hashnode.com/@nark3d)

[Sep 2](https://hashnode.com/posts/make-illegal-states-unrepresentable-until-you-have-to-explain-them/6a94628a3807e45a5040f84d/comment/6a97f1c265e5d96ebb622ba6)

I've hit the same requirement on anything a non-developer edits, where a validator that stops at the first fault gets exactly the reception you'd expect. The rule I'd add to the split is about its own discipline: you note that nothing downstream of validate() runs on an Invalid result, and that constraint lives in prose rather than in the types, so it's the one a later change breaks first. If it can be a lint rule or an architectural test it holds, in my experience a written convention alone doesn't. I argue the stricter version of the type-level side here, with less room than you allow for the reportable case: [https://prickles.org/tenet/domain-driven-types/T1](https://prickles.org/tenet/domain-driven-types/T1)

[Tom Horvat](https://hashnode.com/@tom-horvat)

[Sep 3](https://hashnode.com/posts/make-illegal-states-unrepresentable-until-you-have-to-explain-them/6a94628a3807e45a5040f84d/comment/6a998b752df9cf7e979aa86e)

I agree, and the follow up article I am writing will show the exact point you are making about enforcing it with architecture tests. In my experience, lint rules are somewhat weaker than actual tests that break in CI or even a pre-commit rule. Tests break builds and if the codebase owner/contributor is disciplined enough to maintain them, this to me is the stronger option of the two.
