Wednesday 21 September 2011

Scala case classes and DDD value objects

I was looking for a neat way to use the Scala case class construct when implementing value objects as advertised by the domain driven design approach.

The only problem with using case classes, which come with all the convenience features like "unapply" and "copy", was that I wanted to operate on arguments before the class constructor assigns them to the immutable class members.

In case of the example below I simply wanted to trim the given postcode. Similar use cases, where I want to bring value object arguments into a particular format, pop up all the time.

The best pointer to a suitable solution was this Stackoverflow post: http://stackoverflow.com/questions/5827510/how-to-override-apply-in-a-case-class-companion

Since we cannot override the default "apply" method of case class companion objects I changed the method to be called "parse" which is not as concise as using the "apply" approach but with time I actually started to appreciate the more explicit naming.

Following code shows the way I'm currently implementing DDD value objects in Scala:


Making the case class constructor private ensures that the factory method "parse" of the companion object must be used to instantiate a new postcode object.

In addition to the version above I just recently found another way of tackling the problem.

There is a related discussion happening here:
https://issues.scala-lang.org/browse/SI-844?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel

According to the Scala specs the definition of apply is omitted if class c is abstract. Unfortunately this also prevents the compiler from generating the copy method which will have to be implemented manually.

Sample case class with companion object that sanitizes parameters before instantiating a new case class instance:

No comments:

Post a Comment