One of the most common pattern we use on our day to day is converting objects from one type of object to another. The reasons for that are varied; one reason is to distinguish between external and internal implementations, another reason would be to enrich incoming data with additional information or to filter out some aspects of the data before sending it over to the the user.
There are several approaches to achieve this conversion between objects:
1. The Naïve Approach
Add your converter code to the object explicitly
2. The fat belly syndrome
When we want to convert between objects, the best way is to refactor the logic out of the class, allowing us to test it separately but still use it on several classes. A typical implementation would look like this:
The converter itself can be implemented as a plain class, for example:
What I don’t like about these tests is that all of the code flows through the conversion logic and in the end you are comparing the result returned by some of the mocks. If for example one of the mock expectation of the converters doesn’t exactly compare the input object and a programmer will not match the input object and use the any operator, rendering the test moot.
3. The Lizard’s Tail
Another option is to use with Scala is the ability to inherit multiple traits and supply the converter code with traits. Allowing us to mix and match these converters.
A typical implementation would look like this:
4. The Ostrich way
Scala allows us to hide the problem and use implicit conversions. This approach allows us to actually hide the problem. An implementation would now look like this:
A good use case in which implicit conversions works is when we want to convert between object that has the same functionality and purpose. A good example for those is to convert between Scala lists and Java lists, both are basically the same and we do not want to litter our code in all of the places where we convert between those two.
To summarize the issues we encountered:
Long and unused list of junk traits or junk classes in the constructor
Traits that doesn’t represent the true purpose of the class
Code that hides its true flow
To solve all of these, Scala has created a good pattern with the usage of implicit classes. To write conversion code we can do something like this:
Note that the converter code is tested elsewhere.
This approach allows us to write more readable test on other spots of the code. For example, in our e2e tests we reduce the number of objects we define:
Related Posts Using Specs² macro matchers for fun and profit
Introducing Accord: a sane validation library for Scala