Domain-Driven Design: The Repository


Part 2: Domain-Driven Design: Data Access Strategies

The Ubiquitous Language

The ubiquitous language is the foundation of Domain-driven design. The concept is simple, developers and domain experts share a common language that both understand. This language is set in business terminology, not technical terminology. This ubiquitous language allows the technical team become part of the business.

The Repository

Repositories play an important part in DDD, they speak the language of the domain and act as mediators between the domain and data mapping layers. They provide a common language to all team members by translating technical terminology into business terminology.

In a nutshell, a Repository:

  • Is not a data access layer
  • Provides a higher level of data manipulation
  • Is persistence ignorance
  • Is a collection of aggregate roots
  • Offers a mechanism to manage entities

Data Access Objects

In the absence of an ORM framework, the Data Access Object (DAO) handles the impedance mismatch that a relational database has with object-oriented techniques. In DDD, you inject Repositories, not DAO’s in domain entities. For example, imagine you have an entity named User that needs to access the database to retrieve the User details:

class User
{
    private $id;
    private $name;

    public function __construct(UserDao $dao, $id)
    {
        $row = $dao->find($id);
        $this->setId($row['id']);
        $this->setName($row['name']);
    }

    public function setId($id) {}
    public function getId() {}
    public function setName($name) {}
    public function getName() {}
}

The User DAO class will look something like this:

interface UserDao
{
    public function fetchRow($id);
}

class UserDatabaseDaoImpl implements UserDao
{
    public function fetchRow($id)
    {
        ...
        $query = $db->select();
        $query->from('user');
        $query->where('id = ?', $id);
        return $db->fetchRow($query);
    }
}

$dao = new UserDatabaseDaoImpl();
$user = new User($dao, 1);
$userId = $user->getId();

But, what about separation of concerns? DAO’s are related to persistence, and persistence is infrastructure, not domain. The main problem with the example above is that we have lots of different concerns polluting the domain. According to DDD, an object should be distilled until nothing remains that does not relate to its meaning or support its role in interactions. And that’s exactly the problem the Repository pattern tries to solve.

Injecting Repositories

Lets create a UserRepository class to isolate the domain object from details of the UserDatabaseDaoImpl class:

class User
{
    private $id;
    private $name;

    public function __construct(UserRepository $repository, $id)
    {
        $row = $repository->find($id);
        $this->setId($row['id']);
        $this->setName($row['name']);
    }

    public function setId($id) {}
    public function getId() {}
    public function setName($name) {}
    public function getName() {}
}

It’s the responsibility of the UserRepository to work with all necessary DAO’s and provide all data access services to the domain model in the language which the domain understands.

interface UserRepository
{
    public function find($id);
}

class UserRepositoryImpl implements UserRepository
{
    private $databaseDao;

    public function setDatabaseDao(UserDao $dao) {}
    public function getDatabaseDao() {}

    public function find($id)
    {
        return $this->getDatabaseDao()->find($id);

    }
}

$userRepository = new UserRepositoryImpl();
$userRepository->setDatabaseDao(new UserDatabaseDaoImpl());

$user = new User($userRepository, 1);
$userId = $user->getId();
$userName = $user->getName();

The main difference between the Repository and the DAO is that the DAO is at a lower level of abstraction and doesn’t speak the ubiquitous language of the domain.

So, what’s next?

The process of creating an entity is complex, because an entity always has relationship with other objects in your domain model. When creating an entity, we have to initialize its relationships as well. Therefore, it’s a good practice to delegate this task to another object.

We’ve seen how to write a persistence-ignorant domain model. Next, I’ll explain how to automate the creation and injection of dependencies.

Part 4: Domain-Driven Design: Sample Application


32 responses to “Domain-Driven Design: The Repository”

  1. User depends on the interface not the implementation. Both UserRepositoryInterface and UserDaoInterface speak exactly the same domain language. Your example does not demonstrate why both are needed when the former acts just as a proxy to the later. You could just rename dao to repository and be done with it.

    Then again repositories are usually meant to be injected into services rather than the entities themselves.

  2. > Your example does not demonstrate why both are needed when the former acts just as a proxy to the later.

    This post explains in detail the problem the Repository tries to solve. The Repository is much more than just a Facade.

    > You could just rename dao to repository and be done with it.

    No, in DDD you can’t. DAO’s are related to infrastructure, not domain. And repositories are not part of the data access layer.

  3. Hello,

    Please add your site at Sweebs.com is a place where other people can find you among the best sites on the internet!
    Its just started and we are collecting the best found on the net! We will be delighted to have you in the sweebs listings.

    Regards
    Kris

  4. > This post explains in detail the problem the Repository tries to solve.

    Yet fails to be convincing. As I said.

    1. Both interfaces speak the same language exactly. The only thing that differs is the name.

    2. User depends on the interface *not* the implementation. You could move the implementation of dao to the repository without affecting the dependent entity or disturbing the business/technical language/terminology (whatever).

    > The Repository is *much* more than just a Facade.

    Emphasis mine :) I don’t mean to sound like a smartass, but it really is just that.

  5. You are not looking at the problem from a DDD point of view.

    > User depends on the interface *not* the implementation.

    That’s why the Repository exposes a DDD-compliant API (interface).

    > Both interfaces speak the same language exactly

    How’s that? They don’t. Eric explains this in more detail here http://tinyurl.com/ykv4tf

  6. Although a Repository and a DAO look similar, they are different. Here are the main differences:

    * Repository provides a higher level of data manipulation
    * Repository is persistence ignorance
    * Repository is a collection of aggregate roots
    * Repository offers a mechanism to manage entities
    * Repository speaks the domain language
    * Repository is part of the domain model
    * Repository exposes a DDD-compliant API

    So, it’s much more than a Facade, and cannot be renamed and moved to the infrastructure layer. Hope that helps.

  7. Nice to see some posts on ddd with php.

    Some thoughts I had when reading the comments. I agree that repositories are part of the infrastructure but I would rather see as Dimitris said that they are injected to a service instead of the entity itself. I usually have the interface of the repository in my domain and the implementation outside together with other infrastructure classes. Then you could inject the interface and switch to whatever implementation you like later on.

    Using this approach you dont have to worry about having to proxy to a dao you could simply use the dao implementation as your repository implementation because it fulfills your need.

  8. Hi Johan, thanks for sharing your thoughts on this.

    > I agree that repositories are part of the infrastructure

    Err, domain? :)

    > injected to a service instead of the entity itself.

    Yes, sure. You can inject them in services and/or entities.

    > Using this approach you dont have to worry about having to proxy

    The repository is more than just a Proxy and a Facade. Facade hides complexity, Proxy handles access and Repository does both, plus, manages entities (aggregates).

    > use the dao implementation as your repository

    Hmm, in DDD, DAO’s don’t manage aggregates and are not PI.

    Feel free to provide some examples here:
    http://fedecarg.codepad.org/

    Thanks

  9. “1. Both interfaces speak the same language exactly. The only thing that differs is the name.”

    Yeah, this part is where I’m getting lost. A bit more example code would probably help. And some code behind the creation of the $db as well.

  10. It’s absolutely great to see a DDD example in PHP for a change. I’ve always liked the concept of DDD, but never have I seen an actual implementation of it in PHP (apart from my own code).

    I’m really looking forward to the rest of the series. Thanks!

  11. Nice article Federico, the use of a repository provides a nice mechanism to bridge the areas of domain and persistence. I would suggest that if some omnipotent being judges that a repository is nothing more than a facade it still serves the intended purpose well.

  12. * Repository provides a higher level of data manipulation
    * Repository is persistence ignorance
    * Repository is a collection of aggregate roots
    * Repository offers a mechanism to manage entities
    * Repository speaks the domain language
    * Repository is part of the domain model
    * Repository exposes a DDD-compliant API

    this definition is so concise and awesome!

  13. Frederico,
    I had a question regarding proper placement of data access objects when multiple data sources are present and needed. I wanted to confirm my own conclusion.

    Lets say the full user data can only be pulled by querying 2 data sources. One is a DB and one is a read only web service. So for example lets say the web service request is for only one piece of information for a user and the rest is pulled from the DB.

    Is it as simple (and proper) as having the repository handle the delegation to the 2 DAO objects or is there a better way?

  14. Thanks for all these articles on DDD Federico. One question though: why do you inject the repository into the User Entity? Since the Repo is in charge of managing all the Users, the Entities themselves should not need to be aware of the Repo. At least, they dont if I assume you do all access to them through the Repo.

  15. To avoid polluting the domain. The UserRepository class isolates the domain object from details of the UserDaoDb class and provides all data access services to the domain model in the language which the domain understands.

  16. Well yes, I agree with the UserRepository isolating the Domain object from the DAO, but if you exchange the DAOs for Repositories you just trade a database centric domain for a repository centric domain. Ok, that’s a huge advantage already, but your Entities are still not agnostic and they know how to manage themselves (see User::getData) instead of being managed through the Repository. So instead of ActiveRecord, you get ActiveEntity (kind of). I see the benefit of Lazy Loading in User::getData, but you could separate the repository access strategies through AOP or an event driven approach. But then again, Fowler injects the Repository too, so I guess there is no definite approach and it boils down to personal preference. Thanks again.

  17. Hi!

    You write:
    A Repository “…Is a collection of aggregate roots”

    The most important, if not ONLY responsibility of a Repository: to retreive an AggregateRoot.
    Most repositories do need only one method, find().
    Almost any other of the often-seen methods are another context or just plain reporting.

    Also perhaps you should take a look on the concept Bounded Context in DDD, then you would realize that there is almost never an Entity “User”, but objects that play a role in a given context. One time a User isn’t existing yet, or is a RegisteredMember or a Visitor. And users don’t appear out of nothing, so who calls new User()…?

    Cheers!

  18. Hi Don,

    Not really. The repository is also responsible for talking in aggregate roots.

    Reference:

    http://dddstepbystep.com/wikis/ddd/blogged-the-repository-pattern.aspx

    > One time a User isn’t existing yet, but objects that play a role in a given context

    User is part of the negotiated language the development team uses with the domain experts. User, in this case, is something that we, developers and domain experts, understand to mean the same thing. It’ s my job then to reflect my understanding of the domain using classes, attributes, relationships and collaboration behaviour.

    > you should take a look on the concept Bounded Context

    Bounded Context has nothing to do with Repositories and the example provided in this post. The team members define the context within which a model applies.

  19. Hi Federico!

    > Not really. The repository is also responsible for talking in aggregate roots.

    But what does that mean, “talking”?
    As the (known) article also, and only, states, it is responsible for persisting the whole AR. But that’s only one opinion and some other DDD gurus like Greg Young, tell us:
    [A repo…] provides the domain collection semantics to a set of aggregate root objects.

    Also some tend to say that it’s not the responsibility of the repository to persist anything. Because Repos are the abstraction of objects in memory. Therefore they do live always and don’t have to be persisted. In languages like PHP you’d have a problem with that, though.

    The main question is:
    If domains should be persistence ignorant, why they would need to have a repository that persists anything?

    > User is part of the negotiated language the development team uses with the domain experts.

    Really?
    In a webpage scenarion, a “User” may be an Admin, a newly registered site visitor, someone who buys something in your shop, a writer of articles, an anonymous visitor.
    There is not ONE user, there are many people (or machines) that play some roles in a given context.
    The refinement of the UL in the domain is one of the main things we as developers have to pull out of the domain experts knowledge.
    And in fact that’s not your job but the DE’s one. In a new project you don’t know which roles may exist but you ask all the experts what kind of people (and what roles) they have or expect to see in their business.

    Before I knew DDD I also had, like so many others coming from a “data-based” background, a giant User class. Playing all roles and having behaviours of every possible context it could play.
    But that was before DDD ;-)

    > Bounded Context has nothing to do with Repositories

    People in different divisions may have a completely different look at things.

    A domain with only one BC has its set of repositories while another app with many BCs may have completely other ones. But both are working with the same data.

    BCs are like single applications inside another. Therefore they have other needs and another view at all the things inside a domain. And for retreiving objects needed for one context we need other instruments than for another.

    The accounting BC may want to look for outstanding invoices. Therefore they need a repo like ReceivableAccountsRepository.

    The customer service desk may want to find registered users and their visiting history on the site.
    They need a i.e. MemberRepository.

    In both cases an Entity like Member could be involved but not always as an AR but as an Entity inside another AR.

    ARs and almost any other “pattern” of DDD are just logical concepts, not structural ones.

  20. Hi Don,

    The class User was only used as an example. Feel free to rename it to whatever you think reflects better your understanding of the domain, or define a new class based on the context within which this model applies :)

  21. Hi,

    Interesting. However i have some questions.

    Let say, we have an user which can have photos albums.
    We would have an User object with an albums attribute.

    Now, we want to add an album to the user albums collection.

    How can we do that with this approach ?

    Creating the Album object and then invoke a addAlbumToUser(Model_User user, Model_Album album) from the userRepository ?

    or invoke directly a addAlbumToUser(Model_User, title) from the userRepository which will create the Album object ?

    or simply add behavior to the Model_User class like a method createAlbum() which will create an album object and add it to the user album collection ?

    I admit, i have some difficulties to choose a way :D

    It seems objects have not so much behavior, but Repository have.

    (sorry for my frenchy english)

    Thanks,
    Cya, Benjamin.

  22. Why is there a getid method which uses a repository to het the identity? I don’t understand this. If I great a new entity than it won’t have an id until I save it via the repository.

  23. Good point Onno, but keep in mind that this is just an example. I refactored the code to avoid future confusion. Thanks.

  24. A repository is supposed to construct the entity or delegate construction to a factory object or method. Why does the User have to have any knowledge about loading itself from some data source?

    And if you need a lazy loading entity, create a virtual proxy class that implements the same interface as the concrete class — then the Repository or Factory or whatever only has to know about this method of data obtainment and the entity is none the wiser.

Leave a comment