At Infi, we started our first Scala project mid-2016. When it became clear that Scala might be one of the technologies used in the project, I jumped at the chance to be part of it. I’m always eager to learn new tech, and doing a project in a functional programming language was already near the top of my professional wishlist.
As always, when learning a new technology, I like to push the envelope to see where things start to break down. I think it's a nice way to get to know the limits of that technology. As it turns out, Scala is a powerful language, with a strong type system that lets you use many advanced concepts I won’t detail here (eg. type classes, high-level abstractions like the ones in the Typeclassopedia with the help of scalaz or Cats, generic programming with shapeless and much more).
The thing I want to discuss here is a common annoyance: mapping one type to another and the amount of boilerplate it takes to do so. How can we get rid of that silly, boring-to-write mapping code?
Here's how I tried to solve that problem in Scala.
It might be familiar: you have two unrelated composite data types that share some fields with the same name and type, and you need to map an instance of the first type to an instance of the second type. For example:
Say you want to get a Bar instance from a Foo instance. This one is simple, right?
All clear, no doubt what's happening here. But as your types get more fields, more mapping code needs to be written:
Also, when more types get added that you want to map to and from, you'll get more lines that are a variation of the last one in the code above. Yuck.
In short: the amount of mapping code you need to write depends on two things:
- The size of your data types (let's call this the quality axis)
- The number of data types (the quantity axis)
Possible solution #1: mapping code, concentrated at one place
So... In keeping things DRY, you don't want to repeat the above kind of mapping code at each location you want to get a Bar from a Foo. You might create something like the Scala equivalent of a C# extension method that keeps all the boring boilerplate code in one place, separated from Foo, Bar and other future types to map:
You probably guessed it: as the number of classes that need mapping increases, the nl.infi.thingamabob.data.mappings package will grow over time, potentially becoming a maintenance burden. There might be a better way...
But what way is that? In my next blogpost I'll explore the use of the shapeless library for a possible solution to this problem. Stay tuned!
[Stefan is a software developer at Infi]