Improving Code Quality - Episode 66: Firm but Still Anxious
Key point
Validation should be completed at the time of object creation or update, not at the time of use.
Details
The Rational class represents a fraction with an Int numerator and a UInt denominator, and in toIrreducible() it finds the greatest common divisor using the Euclidean algorithm to reduce it to an irreducible fraction. However, if you check whether the denominator is 0U inside every method each time, the validation code ends up scattered all over the place as features like plus and minus are added.
So the key is to block invalid state at the point of object creation. If you have a factory function of() that doesn't create an instance and instead returns null when the denominator is 0, then every object created afterward can be assumed to be in a valid state by default.
On the other hand, blocking it with require(denominator != 0U) inside the constructor's init leaves the burden of remembering to check it directly at every call site. This approach doesn't prevent missed validation even when the code compiles, so methods that expose failure through the type—like nullable type or Optional / Option / Maybe—are safer.
In summary, value validation should be performed at the time of object creation or state change, and where possible, failure should be enforced through the return value or type so that the caller must handle it.
This summary was generated automatically by AI. Check the original for the author's claims and context. Copyright belongs to the original author.
Our guide explains how the AI works. Report summary errors, attribution issues, or removal requests via Contact.