Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

Persistence ignorance is ability to retrieve/persist standard objects, where standard objects are considered as classes focused on particular business problem and thus don't contain any infrastructure-related logic. In DDD a Repository pattern is used to achieve PI.

Assuming we don't use ORM's POCO objects to model the Domain, then our Domain objects don't have to adhere to design requirements of a particular O/RM ( such as using default constructor or marking properties as virtual ). Such Domain objects would be considered Persistence Ignorant.

But if we want these Domain Objects to also support features such as lazy loading, then their properties must contain some logic which at some point would need to check whether related data was already loaded and if it wasn't, it would contact the appropriate Repository and request the related data.

Now even though these Domain Object are completely unaware of how they are being persisted and as such their Domain is completely decoupled from the underlying DAL provider, couldn't we still argue that such Domain Objects contain Infrastructure-related logic and thus still violate PI?

Thank you

share|improve this question
2  
"couldn't we still argue that such Domain Objects contain Infrastructure-related logic and thus still violate PI?" No, because "these Domain Object[s] are [still] completely unaware of how they are being persisted." –  Robert Harvey Jan 8 '13 at 19:28
1  
Then put the infrastructure-related logic in the repository; i.e. cache it. But the key word here is "persistence." An object that is "caching itself" is not persisting itself (i.e. writing it to a storage device); it is merely remembering some previous value. –  Robert Harvey Jan 8 '13 at 19:42
1  
There are always things that you need to do to your domain objects to make things work with some of the popular ORM's, whether it be virtualising your members, or decorating them with attributes. My question is what is the risk of doing that? At some stage you have to make a decision on how you are going to persist your objects and its unlikely going to change once the decision is made. So is it really that bad? If keeping your domain free of influence from ORM is important to you then maybe don't use an ORM and look at alternative persistence solutions such as NoSQL. –  stephenl Jan 8 '13 at 19:49
3  
It all comes down to practicality, not slavishly adhering to some abstract principle. I personally believe that there's no such thing as 100% persistence ignorance, since requesting an object requires some form of ID, and that ID is going to be supplied by, and dependent upon, the persistence mechanism. –  Robert Harvey Jan 8 '13 at 20:16
1  
As an aside, I don't like the term "ORM POCO". It's either an ORM-aware class, or it's a POCO. I don't see how it can be both. But, just in case there is such a thing as an "ORM POCO"... If it's truly a POCO, and it matches your domain requirements, then does it matter if it was generated by an ORM? –  Eric King Jan 8 '13 at 20:54
show 4 more comments

migrated from stackoverflow.com Jan 8 '13 at 19:30

This question came from our site for professional and enthusiast programmers.

2 Answers

up vote 4 down vote accepted

After coming across the same problem, here is the solution I implemented for it.

Domain

public class DomainObject : AggregateRootBase //implements IAggregateRoot
{
    private ChildEntity _ChildEntity = null;
    public ChildEntity ChildEntity
    {
        get
        {
            OnChildEntityRequested();
            return _ChildEntity;
        }
    }

    public event EventHandler ChildEntityRequested;
    protected void OnChildEntityRequested()
    {
        if (ChildEntityRequested != null) { ChildEntityRequested(this, new EventArgs()); }
    }

    public static void SetChildEntity(DomainObject destination, ChildEntity child)
    {
        //To set or not to set, that is the question.
        destination._ChildEntity = child;
    }
}

Repository Implementation

public class DomainObjectRepository : List<DomainObjectTracker>, IDomainObjectRepository
{
    private void Load() //Method called by constructor or other loading mechanism.
    {
        foreach (DomainObjectDataModel dodm in ORMSystem) //Iterating through each object returned from ORM.
        {
             DomainObject do = Translate(dodm); //Translate into domain object.
             do.ChildEntityRequested += new EventHandler(DomainObject_ChildEntityRequested);
             DomainObjectTracker tracker = new DomainObjectTracker(do, dodm.Key);
             base.Add(tracker);
        }
    }

    protected void DomainObject_ChildEntityRequested(object sender, EventArgs e)
    {
        DomainObject source = sender as DomainObject;
        //Here, you could check to see if it is null or stale before loading it.
        //if (source.ChildEntity == null || IsStale(source.ChildEntity))

        DomainObjectTracker tracker = base[IndexOf(source)];
        ChildEntity entity = LoadChildEntity(tracker.Key); //Load the child entity from ORM.
        DomainObject.SetChildEntity(source, entity);
    }
}

After examining my solution, you may be thinking, "Isn't calling an event infrastructure related code, it certainly doesn't relate to my domain?". While that may be true, if you think about it solely in terms of PI, then you realize that you're just offering a message from your domain saying, "Hey, I'm about to access this child entity." which allows your repository to respond with, "Hold on, if you need one (or a new one), I got it right here in my db so let me give this to you before you continue!".

There are a few caveats here. One, it means that you need an event for every child entity within an aggregate. Two, it breaks encapsulation because you are allowing a public way of setting the child entity. On the flip side, the benefits are expressive code, infrastructure implementations are easily separated from the domain, domain objects are PI, and the ORM remains encapsulated behind the repository implementation.

If someone has a better way of solving this problem, I'm all eyes!

EDIT Also, even though my answer provides a solution for PI, I agree with the commenters above. You need to evaluate if DDD is even the right answer for you because, while it makes a project easier to maintain and simplifies what would otherwise be a highly complex project, it comes at a cost (usually up-front development time and training your team to organize code properly and utilize the various patterns).

share|improve this answer
    
"You need to evaluate if DDD is even the right answer for you..." I don't know, since I've only started learning DDD yesterday, but when reading PeAAA, DDD ( from the bird's eye view of course ) made the most sense to me, while I found Table Module and Active Record explanations rather confusing. Btw - great solution, thanx –  user437291 Jan 8 '13 at 21:02
    
thank you all for your help –  user437291 Jan 8 '13 at 21:02
    
No problem and good luck! –  Aaron Hawkins Jan 8 '13 at 21:06
    
Next step would be implementing an event sourcing pattern :) –  Yves M. Apr 5 at 13:28
add comment

If you choose to not use ORM POCOs for your domain logic, fine. You also give up everything that come with them, such as lazy loading and caching, which become features that you need to account for (if you want) as part of your domain or assume they will be provided by the ORM at a lower layer.

Another challenge is the extra step to shuttle the data back and forth from the ORM POCOs to your Domain POCOs, which can be done with tools like Automapper but cause issues such as when updating an object you may need to force the ORM to retrieve it so it can be updated, depending on how the ORM is implemented.

How much are you really gaining by requiring 100% purity? Is not violating PI really so important?

share|improve this answer
    
"Is not violating PI really so important?" I just started learning DDD, but I thought to adhere to DDD at the very least ( due to among other things not violating PI ) we shouldn't use ORM POCOs to model the domain. You don't agree? –  user437291 Jan 8 '13 at 20:26
3  
Life is full of compromises. You have to choose which pill is less bitter. I've doing this decades before DDD and I tend to take every method/ology with a grain of salt. –  A----------------------- ----- Jan 8 '13 at 20:33
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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