Archive for the ‘mapping’ tag
TDD: Testing mapping code
I’ve previously written about some of the aspects of the mapping efforts that we’ve done on recent projects and what we’ve found from our testing (or lack of) around this type of code is that somewhere along the line you are going to have to check that you’re mapping these values correctly, be it in an automated test or just by manually checking that the correct values are being sent across our integration points and into other systems.
Writing unit tests around mapping code is certainly one of the areas of testing where it feels like there isn’t that much value in doing so – after all we are just copying data from one data structure to another, what could possibly go wrong?!
While I would certainly agree that in this case we are not using the tests to drive the design of our code, I think they are still very valuable for helping us to ensure that our specific bit of mapping code is doing what we expect it to.
Let’s say we have data flowing across our application like so:

We get the data from the UI and we need it to end up being sent to the service. Along the way there are a few different places where data could get lost and from (painful) experience I’ve found that if we aren’t testing that all our data is being mapped then we will forget to map something and then we will have the fun job of debugging end to end trying to work out where it got lost.
I would certainly relax the notion of taking small steps a bit when doing this type of testing otherwise it can get immensely frustrating – maybe write the tests for a set of similar fields and then writing the mapping code rather than creating the test -> code cycle individually for each one.
These tests can end up getting quite difficult to read so an approach we’ve been trying is to setup the test data in a TestFixtureSetUp at the top of our NUnit test fixture and then creating just the assertions for similar sets of fields in each test. I think it’s working reasonably well even though maybe it goes against the convention of the way you would typically use NUnit.
We’re still got higher level tests around this code and while they’re useful they don’t help us zoom into the point of error that easily so the humble unit test still has a part to play!
Trade Offs: Some Thoughts
As we know with software development with pretty much every decision we make or technology we choose there is a trade off that goes with making this choice as compared with choosing an alternative.
I first learnt this when working with Ade a couple of years ago and while I know it to be true, I had come to believe that some practices are just non-negotiable and we should look to apply them judiciously wherever possible.
Various conversations have made me come to the realisation that not everyone believes this and that there are trade offs being made by following or not following these practices.
Domain Driven Design Ubiquitous Language
I consider this approach to writing software to be absolutely key to ensuring that the code base is easy to navigate around for newcomers and indeed to anyone who has to read the code after we have written it.
The trade off we are making here is that sometimes we will end up writing more code in designing our code around the language of the business rather than choosing a solution which may be technically easier to implement but less expressive.
To take a simple example of this in action, consider car insurance.
As a customer I would provide the insurer with details about my car, where I live and so on. This information would lead to me being provided with a Quote. Should I then decide to buy that Quote it would become a Policy. There is clearly quite an important difference between the two terms but in terms of data, maybe 75% is the same across both concepts.
If we decide to implement the language of the business in our code then we may end up creating a new object and copying a lot of data across from the old one.
The benefit we get from doing this is that the code is more expressive and describes the business process more accurately.
Interacting with other systems
My thoughts when it comes to using data from other systems is that we should look to keep interaction with the other system in one place – inside the anti corruption layer.
The benefit of doing this is that we keep control over our model and similar (but not exactly the same) concepts from other systems don’t creep into our application and lead to confusion around our domain model.
The disadvantage is that we may end up writing a lot of mapping code depending on how closely the other systems’ models are to our own. This code tends to be extremely tedious to write and difficult to test in a way that doesn’t involved re-creating most of the production code logic in our tests to create our expectations.
Object Oriented Programming
I have had the opportunity recently to work with several people who really know how to write code in this way and I’ve found it to be the most effective way to manage complexity in code that I’ve come across so far.
I’ve a long way to go before I’ve mastered OOP, but I try to follow the SOLID principles as much as possible – keeping classes small, behaviour with data and so on. – and I think it helps to make code much easier to understand and indeed change.
Now the trade off is that it is much harder to write code in this way than to just write procedural code and create anaemic objects which just have getters and setters on them. It also requires much more thinking – we have to think where to put behaviour, how to name new classes and so on.
Therefore I could easily see an argument that it’s quicker to write code procedurally than in an object oriented way. If we take this approach though we have to be prepared for the time we lose later on when it comes to trying to change the code that we were able to write so quickly before – it will probably take much longer now.
In Summary
I still believe that there is a lot of value in these approaches but it’s always good to know what alternative approach is being discarded by choosing a particular approach.
That way we can make more informed decisions.