Ever since I read the Domain Driven Design book by Eric Evans I have been wondering a bit about the Repository pattern. Especially the part where a domain object can communicate with a repository. In most Java systems today you will have Hibernate with lazy loading which enables you to think in domain objects, but there might be some situations where you can’t do that. That’s when you need to think about the Repository pattern and how to use it. Reasons for using it might be:
- Large collections, you need to filter before loading for current operation
- External data, it is only available through calling a webservice etc. meaning Hibernate won’t handle the lazy loading for you
So basically you will need to do this in most systems some time, how do you solve this? I had a discussion about this with Johannes a while back, and we didn’t really reach a conclusion. There are several ways to handle this and they all have their benefits and problems. Terminology and some more ideas borrowed from Ben Hutchinson in this post.
The domain has no notion about repositories, but navigate through properties in the domain. This can be achieved through:
- Always passing enough data into methods so the object can make it’s decisions. This can bloat the signature and be a bit of a hassle, but probably the way to go with least magic.
- AOP on the methods that retrieve the data. This enables you to have just plain Java for tests, but enable a different retrieval at runtime. Complicates the understanding and testing of the system, but eases unit testing.
- Events in your persistence layer. When Hibernate loads up an object for you it could inject the external object. Sort of light weight AOP, but not something I think I would do.
The domain knows that it must retrieve information through a service/repository and calls it when it’s needs the information. It can be achieved through:
- Passing the service/repository in with the method call. Again bloats the methods, but is explicit.
- Using a Locator to get the service/repository. The dreaded ServiceLocator from Java EE is back! 😉 But it might have a worse reputation than it deserves. A Locator that checks the ThreadLocal and knows how to retrieve the repository is quite flexible even in Tests. Not very expressive on how and where the information can be found.
- Passing the context in the method calls. Just about the same as passing the service/repository, just another level of indirection that I don’t like.
- Injecting the repository/service into the object before execution. Somewhat like a middle ground between the Locator and passing it in as an argument.
It’s like everything else in computer science, you need to decide what works best in your project. I do however prefer the Independent Domain with passing in the required data in the method. I guess the reason for this is the uttrely horrible code I have seen before where domain and repositories/services are mixed together. A lot of programmers will tend to create integration tests when faced with testing domains that has dependencies to repositories. In many cases that means loading your Spring context waaaay too often, or mocking the repository. And neither are really good unit tests, as well as beeing harder to maintain. I hate mocking even though I have to do it often. I just try to avoid it if I can by designing logic that is independent of infrastructure.
- Christian Bauer on Repository: http://in.relation.to/Bloggers/RepositoryPatternVsTransparentPersistence
- Data Mapper pattern: http://www.martinfowler.com/eaaCatalog/dataMapper.html