Validatable: it may come from a library, be generated, or have its rules in another
module. validation<T> { } writes the rules of a type from outside it, and returns a Validation<T> that
checks any value of that type.
Address.kt
this, so ::street is its property and country its value, exactly as
inside a Validatable. The constraints are the same, and so is the result.
Validating a value
Validation<T> takes the value to check:
The zip code is not checked here:
postalCode knows the formats of 72 countries by their alpha-2 code, and USA is not
one of them, so it has nothing to compare against.
Validating a property with these rules
A property of that type is checked withvalid(rules), and its violations are nested under the property:
Delivery.kt
One value, once
When you have a single value and do not need to reuse the rules,validatable(value) { } pairs the value with its
rules and returns a Validatable, with all four ways to run it:
Rules as an extension
The block thatValidatable uses, validation { }, also works in an extension, which is another way to keep the rules
of a foreign class next to your code. The extension is then passed to valid as a function reference:
Which one to pick
The class is yours and its rules never change
The class is yours and its rules never change
Implement
Validatable. The rules travel with the class, and valid() needs no
argument.The class is not yours, or it has more than one set of rules
The class is not yours, or it has more than one set of rules
Write a
Validation<T> with validation<T> { }, one per set of rules, such as addressForShipping and
addressForBilling, and pass the one you need to valid(...).The rules depend on who is asking
The rules depend on who is asking
Implement
ContextualValidatable<C>: the caller passes the context, such as the logged-in
customer.