I was approached recently at a show by a developer who had taken over a project that I had worked on in the past. After a few pleasantries about the project domain, which to be fair is quite interesting but not for this post, we moved on to picking over the bones of the architecture. Again this was quite interesting in itself, but there was one feature of the solution that was of particular issue.
The project was a web service built using one of the popular frameworks that enable you to produce an API for the Web using the .Net Framework. It always seemed pretty straightforward to me at the time, but my friend quite rightly pointed out that you had to dig into it some way to actually get at any implementation.
This made it tough from a testing point of view because I’m sure it didn’t start out being tested from the point of view of an ideal interface. In fact I would have thought that you’d have to write three or four tests before you got to some hard implementation. Chasing all those calls through to the business layer, so that you can respond to a request with some object that you got from some data store.
“Why didn’t you provide some of this functionality on the entity itself?” the developer asked, observing that the design of the solution seemed to push all implementation into a business layer leaving a collection of DTOs that had no implementation at all. After a pause, I answered,
“I want my entities to be something, and my services to do something.”
The developer was ok with this statement but asked me to expand on it a little, so here goes.
If I had a trainee object and it had a collection of courses that it had taken. I would find it hard to represent a get training method in the context of the trainee without messing up my REST service. Instead, if I had a training service, I could have a GET method which would take a couple of identifiers, one for a trainee and one for a course. It would happily return a trainee, complete with a shiny new learning outcome. I can represent this easily on my API, as there is no implementation, just the plain old entities.
I’m not saying that this is the only way to do it, nor am I claiming that I have invented anything new. It’s just that when asked why it was as it was, the idea of entities being something, and services doing something seemed to make a case for itself.
Recently, I’ve realised how keeping to my mantra on entities, has helped me to consider the ideal interface for a service. This makes it more natural to test the software only at the boundaries i.e. the public methods on the service API. It makes it easier to stop the test suite getting brittle. I can still drive out design using tests if I really have to, but in terms of coverage and semantics, I seem to be in a happier place than I was a month ago even. I’ve certainly got a lot less top heavy test fixtures to worry about, but I’ll post more about my experiences with that another time.
I’d be really happy to hear anyone’s thoughts on this, but please go easy on me, its my first blog post. Hopefully things can only improve from here, so thanks for reading, and any feedback.