storageIn one of my most recent projects, I decided to design and build the application according to the principles of Domain Driven Design. One of the guidelines promoted by Domain Driven Design is the way the interface of the Repository is designed. This changed the way I look at both the design and the location of the Repository interface. It’s all gain, no pain.

 

Most of the applications I encounter in my work as Software Architect apply more or less the same layering. The well-known layers in an application are the web layer, application layer, persistence layer and domain layer. This layering provides some boundaries for different types of logic to keep an application maintainable in the long term. Typically, layers are placed in different modules (each with their own jar file) inside a project. However, for smaller projects it would suffice to just place each layer in its own package structure.

typical-application-layering

Almost all applications I encounter have implemented a layering as shown in the image on the left. The arrows show the direction of the dependency of each module on the others.

As you can see, the Application Layer has a dependency on the Persistence layer. The need for that dependency comes from the fact that the persistence layer contains the Repository. Both the interface (since it is good practice to develop against interfaces) and its implementation. With my recent study of the Domain Driven Design principles, I gained the insight that it doesn’t really make a lot of sense to put the interface next (or near) to its implementation.

But why would you even bother to create an interface for the Repository at all? Well, there are a few good reasons (and probably some bad ones too) to do so. One of them is that it allows easy mocking and stubbing for tests. Another is that it allows you to replace or modify the implementation without the risk of breaking interaction (as long as the interface is maintained).

However, replacing the persistence layer with another one isn’t as easy as it seems when it contains the interface. To be able to do so, you must copy the interface into the new persistence layer implementation. And as any good developers knows, when you’re copying stuff, take your hands off the keyboard, and think for a second. You’re probably doing something wrong.

Quite recently, I had a small discussion with someone who said: “How often do you expect to change the implementation of your persistence layer?”. I didn’t really have an answer back then, but right now I am spending time on exactly that in one of my projects. And you’ll have to trust me on this: correctly designing the interface is well worth the trouble. Even if you only have to change the persistence implementation once every 100 projects. Furthermore, another project I recently started actually requires the ability to “plug in” different implementations of the persistence layer (no, not at runtime, it doesn’t have to be OSGi, unfortunately).

better-application-layeringInspired by the DDD sample application, I decided to place the interface in the Domain Layer. By doing this, there was no longer a need to have a (compile time) dependency from the Application layer to the Persistence layer. On paper that looks a bit cleaner.  But we don’t design applications to look good on paper.

A good repository interface, as described by Martin Fowler and Eric Evans, gives it’s client the perception of an in-memory repository. In fact, it should hide any implementation choices you make about how and where data is really stored. And if you want to be able to replace persistence layers, that’s exactly what you need.

If you place the interface next to an implementation, you’re tempted to just use your IDE to extract an interface from your implementation. Chances are that your interface “leaks” information of your implementation choices. Instead, try to force yourself to design the interface first and develop an implementation that conforms to that interface later. This will help you achieve the “in-memory” perception.

A colleague of mine asked me why I chose to put the interface in the domain layer (see Separated Interface Pattern), and not the application layer, which is most likely to need the interface and call its implementation.I had three reasons.

First, the interface is described based on a small selection of domain entities. This gives the interface high coupling with these domain objects. High coupled classes are good candidates to share a package. In fact, you repository interface probably doesn’t require any import statements at all.

Secondly, it is probable that more than one service, perhaps located in different packages or modules, need to use the same repository. In that case, which package is most suitable to put the implementation in? Choosing even another package will result in lots of inter-package dependencies that aren’t really necessary. Unnecessary package dependencies decrease the ability to refactor your application .

And thirdly, the repositories provide access to your “aggregate roots”. If you have an aggregate root named, for example, “Order” and call your repository “OrderRepository”, your IDE will sort these classes in such a way, that you can easily find the most important entities in a blink of an eye.

Well, I hope this can help you in your projects as it could have helped me in the past. If you have any questions or concerns, don’t hesitate to leave a comment.

8 thoughts on “Designing the Repository interface

  • March 3, 2010 at 2:51 pm
    Permalink

    Hello Allard, great article. In our developmentgroup we are currently busy with a refactoring project “Design For Testability” and moving the Repository-interface out of the persistance layer and into the Domain Layer is exactly the way we go as well. Because we need to create stubbed/mocked implementations of the Repository, that do not have any dependency to our ORM-persistance store this is very defendable. What I miss though in the clear pictures is; where do you tigh everything together? That is, if you do not have a dependency from your application-layer to your persistance layer anymore than where do you buildup the implementation of the Repository that is created for persistance? Am I missing the Infrastructure layer which contains a Factory or IoC to loadup the actual repositories/services?

    • March 3, 2010 at 3:31 pm
      Permalink

      If you use the “Separated Interface Pattern”, you don’t have a dependency from Domain to Infrastructure, but the other way around. As you state, your service layer cannot choose which implementation to use. That’s where you use IoC for. When you build up your web-app, you choose which jars are included in the war file. One of these jars will contain an IoC configuration file (e.g. spring context) which is loaded and creates the repository implementation.

      All the service layer needs to know is: “at runtime, some form of repository is provided to me”. Alternatively, you can use an Abstract Factory to retrieve a repository instance. Personally, I prefer IoC.

      Hope this answers your question.

  • July 8, 2009 at 12:45 pm
    Permalink

    Hi Aleksandar,

    thanks for your comment.

    placing the interfaces in a separate JAR gives you almost all of the benefits I described in my post. However, that will likely create a jar file creating only very few classes that are, in my opinion, conceptually tightly coupled to the domain. That’s why personally, I would prefer to place it in the jar where the domain is implemented.

  • July 8, 2009 at 11:10 am
    Permalink

    Another good post as we used to from You.

    Regarding Your comment:

    However, replacing the persistence layer with another one isn’t as easy as it seems when it contains the interface. To be able to do so, you must copy the interface into the new persistence layer implementation. And as any good developers knows, when you’re copying stuff, take your hands off the keyboard, and think for a second. You’re probably doing something wrong.

    After few projects on my own in Java and using Maven, I’ve decided to separate Interface of Repository and it’s implementation. So I actually have two different JAR’s that is specified as dependency in Application Layer. As You can see there is no need to copy interface in domain layer, interface of repository can be left as it is , and when You need another implementation of repository You just write new Interfaces implementation.

    I can be more descriptive about this if You wish.

  • July 5, 2009 at 10:20 am
    Permalink

    Erik,

    It makes sense, when you think about it. Perhaps the reason that most developers do it differently is that the difference between “Domain” and “Core domain” (to use Eric Evans’ terminology) is hard to spot at first.

    Nice one as usual, Allard.

  • July 4, 2009 at 8:11 pm
    Permalink

    I had to cheer when I read that yet another colleague believes interfaces are part of the domain packages!

  • July 2, 2009 at 8:25 am
    Permalink

    Hi Taras,

    that’s a very good and valid point you make there. I would lie if switching persistence implementation was a fully transparent and non-intrusive job. Fortunately, I would say, as simple transitions would make our job boring. ;-)

    However, all persistence frameworks (ORM or other) provide the same simple set of features: store, fetch and find. How these features are used using a specific ORM tool should be hidden inside the implementation of the persistence layer. Details such as open-session-in-view (which I dislike, but that’s another discussion), caching and transactionality are usually quite nicely abstracted away by frameworks like Spring. But, I have to admit, they aleays leak through at least a little bit.

    Recently, I had to replace a JCR (Java Content Repository) with an ORM solution. Unfortunately, the persistence layer was not as nicely decoupled as it could have been (with relatively little investment at the time). The investment seemed big and useless at the time, but would have been well worth the trouble.

    Full decoupling is quite hard to achieve and would often require advanced use of things like AOP. Personally, I prefer the pragmatic solutions. If there is a quick win (like keeping the repository interface technology agnostic), I take it. If there are any leaks, make them visible and easy to replace.

    Finally, about “query by specification”, there is a very nice topic about that in Evan’s book. If you use the Abstract Factory pattern to create specification objects, it’s easy to create a basic interface that allows you to specify most commons forms of specification (equals, and, or, etc…), regardless of the actual implementation chosen.

    I hope this helps.

  • July 1, 2009 at 10:20 pm
    Permalink

    In my experience different persistence technologies come with a totally different set of paradigms. Most ORMs provide a form of “demand-based paging” – swapping relevant parts of the database into memory as lazy (on non-lazy) relationships are traversed. JDBC (through wrappers like spring, or not) and IBatis take a totally different approach. In addition, even the different ORM flavors exhibit substantial differences in a non-trivial model. Usually a mix of lazy and eager fetching (for the same relationship, depending on circumstances), approaches like open-session-in-view, differences in transactional semantics, caching, etc, make swapping a persistence layer transparently a pipe dream.

    Specific to DDD, implementing patterns like query-by-specification are wildly different (sometime non-portable) across persistence technologies.

    Any details on how you managed to pull this off?

Comments are closed.