All in all there are some good points in your post, but i also have some points that are Not very good.
1. It's still possible to create an invalid UserId because of the constructor. I find it generally better to prevent any invalid instantiation by verifying in the init and throwing. This ensures all other places are 100÷ Safe when they receive a UserId.
2. Given a private constructor, the factory could either be an extension on String, because then you can follow the established convention String.toUserId which throws and String.toUserIdOrNull which catches and returns null. Or when you don't like std class Extensions, the factory could just live in the companion and return nullable or just Result of User or respectively Result of UserId.
3. For binary cases of success or failure, it's better to use nullability, sealed results are best for multiple options of outputs.
4. Dont name the method isUserValid when it's already on class User. isValid is better, called like user.isValid() or when the class only has vals, calculate it as a property in the class body, wo that it's called user.isValid. same for UserId.
08/31/2020, 10:13 AM
1. Constructor of UserId is privatised
2. that's subjective to use case. Here instead of null i returned another bounded type.
3. I agree. While nullability is Kotlin's way of expressing, but sometimes people consider nullability as more like a side effect rather than an intended design, as people are used to using ? or !! Sealed classes tries to break the mould and make dev more awareness into the intention part. But yes, nullable also does the same thing.
4. My bad on the naming. That was anyways showing "what not to do" So I guess its fine 😅
Thanks for your opinion. Cheers!
10/01/2020, 12:39 PM
Can't seem to comment on the article, so trying here.
Wouldn't inline classes be better suited for this?