Some weeks ago, I read a tweet that contained this picture, and someone said, "That's why Value Types are helpful!" After that, I remembered a few situations that happened a few years ago, and I decided to write about it.
I've seen a lot of validation code that was quite crazy. Most of the time, there were methods with parameters like Doubles, BigDecimals, or Strings followed by lots of business validations at the beginning of each method. These business validations were scattered around the whole codebase, and most of the time, it was copy-pasted. These contain technical bits like null checks and business validations. Situations like these are really suboptimal for several reasons.
So, today, we're going to go into why you should know and use the concept of Value Types, even if you don't do Domain Driven Design.
Why Is That Bad?
First, code doesn't reflect the business domain. Some of these methods' parameters depend on each other, and the validation check, in combination with those parameters, form a business rule that is really badly placed in terms of maintainable software. Why? Because the software offers the functionality the Product Owner wants it to have, but it will become very hard to find a specific business rule in the codebase because you can't search for specific nouns. I have dealt with this situation more than once. I had to grasp the whole codebase because it was not clear where to find this business rule and which class or method is responsible for that.
On the other hand, the semantics are unclear. When using a String, instead of a Value Type, as method parameter, it's much easier to use methods the wrong way, which results in bugs. Imagine a method with two parameters of type String. The person who implemented this method knows the responsibilities of each parameter because he implemented this method and knows its internals. Other developers who just want to use this method don't know anything about the internals. They just know the method name and the parameters, and they could be unobservant and pass the first String in the second parameter and the second in the first. The code would even compile, even though it's completely wrong from a business point of view! In a best-case scenario, the bug would be detected by a test. Otherwise, it could appear at runtime on your local runtime, or even worse: in production. When replacing the Strings with meaningful Value Types, you can't just switch both parameters without getting compile errors because they are not of the same type. You (as the developer using this method) can't use the method the wrong way and bring your application to an irregular state.
How to Improve It?
To improve this, you simply can implement an immutable class whose constructor contains this method parameter. Within this constructor, you can perform all the validation checks you did in the whole codebase before. This increases the maintainability of your software.
In the past, I often heard people saying, "But I don't want to create additional classes for just a few lines of code!" Yes, it is an additional class, but this class protects you from passing bad parameters in a method when using Value Types instead of Strings as parameters, for example.
In addition to that, bugs will be detected at compile time. Value Types could save you a lot of money because you can fix the bug early in development and not in production.
Value Objects are very powerful when it comes to the maintainability of software (even if you don't use Domain Driven Design in your projects). By using Value Objects, your code becomes easier to understand and thus easier to maintain for others. It will be easier for other developers to find the business rules the Product Owner is talking about without grasping the whole codebase and searching for usages of different method parameters.
I hope you enjoyed this and learned something new. If you like it, leave a comment. If not leave one as well!