This blog post was originally posted on my blogpost blog at this URL, and was later migrated to this place. There may be some comments at the original URL.
Ruby standard library has a nice little utility named OpenStruct which gives you objects on which you can dynamically add and remove fields. .NET framework added a similar class named ExpandoObject in its version 4.5.
With version 2.10, Scala has the necessary machinery required to support this kind of utility, so I went ahead and wrote it!
This utility supports the standard features supported by Ruby’s
OpenStruct and .NET’s
ExpandoObject, but also supports a couple more features in addition:
- You can define an
OpenStructwith an underlying object. All field accesses and method invocations are first delegated to this object. If the field/method is not found in the underlying object, the map backing this
OpenStructwill be consulted.
- You can optionally have the results of field updates and method invocations wrapped in an
OpenStruct. This lets you chain dynamic field accesses and method calls nicely. This however is not set as default due to some issues.
Lessons learned in this project:
- TDD can be pretty awesome for some tasks. It gives you a clear idea of what you’re building and dictates your design choices in such a way that they result in looser coupling and better testability. The extra time spent writing test specifications, at least in this project, paid off well.
- I can’t get myself to like the Scala reflection library. It’s tedious, unintuitive, verbose, bug-ridden, and thread-unsafe. The last bit caused several surprises during test execution, which went away when I added a
sequentialflag in my Specs2 specifications. I think it’s a wonder that I was able to get Scala reflection work for me at all.
- Scala’s local
breakare implemented using exceptions. This can lead to strange surprises when using them in blocks that catch exceptions. Watch out for such situations.
traits with smart constructors (read: factories in companion objects) are in general preferable to classes.
The project is hosted here. Any kind of feedback and contributions are welcome.