8

Let's say I'm having a domain-model and I want to read and save it from any persistence layer - right now it might be a json file but in the future it could be xml or a database (which might also change in its type).

To generate the domain-model from the persistence layer, I've got an implementation of a simple Interface which, let's say, contains of a getAll() and saveAll() method. If I want to switch to another type of persistence I can then simply change the implementation of the interface. However, inside the implementation I'll use completely different solutions to read and store the data so I'll have to use different objects from other libraries to deal with the data.

Let's say I use a Json serializer in the first implementation, I'll then instantiate the instance of that serializer in my implementation directly. This will then lead to my implementation directly depending on that serializer, I can never give it another one. But this wouldn't be possible anyway, because there's no universal interface for serializers (or whatever kind of persistence). So if I want a to use a different serializer, the only thing I can do is write a completely new implementation instead of just passing in another one from the outside.

So is it okay to hard code dependencies in this case? Or is there a better option?

4

With reference to my answer to a recent question, the key here is to separate your persistence layer interfaces from any implementation of the persistence layer, using the stairway pattern.

The dependency on the Json serializer then becomes an implementation detail of the Json persistence package. The rest of the application need know nothing about it, nor suffer the burden of that dependency as it only accesses the persistence package via the interfaces, which are in another package.

If you then add a database persistence package, it simply implements those interfaces and its eg ORM dependencies are hidden away too as an implementation detail.

2

You cannot remove all dependencies from your code; eventually you have to depend on something, otherwise you're just going to end up with one giant god-object that does everything itself.

As a general rule, you want each class to depend on objects that will be more stable than themselves; and you want unstable relationships to use dependency injection to allow for easier testing and more flexibility.

How likely is it that the JSON serializer will change? Is it more or less stable than the code you're writing?

If it's likely that you're going to replace the serializer more than once with a different implementation, then perhaps you can create a proxy or a wrapper object around the serializer itself. That way, you can control the interface that you have with the serializer, and only depend on an external library in one place.

That said, I personally haven't yet found a reason to replace a JSON serializer (with a different serializer), so I wouldn't worry too much about having a direct dependency on it. A serializer is pretty much always going to have a more stable interface than anything in my own applications, and the methods that I need from it are so simple and few that there's not really a reason for them to change.

It sounds like you aren't worried specifically about the serializer itself changing however - from what you described, you're worried about outside requirements changing to a totally different persistence system - in which case, your persistence layer implementation is going to get completely rewritten anyway, and using dependency injection or a proxy isn't going to help you.

As long as the interface between your persistence layer and your domain models stays the same, and you are mocking that persistence layer when you unit test your domain models, I see no problem with depending on a specific interface of a JSON library. That dependency is cheap to test, and the JSON library itself is unlikely to change.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.