Does Lazy Loading via Properties Violate Domain Driven Design Principles?

Some comments to a recent post on Jeremy Miller’s blog raised the question of whether NHibernate’s lazy loading capabilities violate Domain Driven Design.  While that conversation was centered around bypassing repositories for access data, which is not true since your aggregate roots are your repository source.  But there is another aspect that was not discussed.


Evans discusses that client code does not need to know about the repository implementation, but developers do.1


Let’s look at a simple example, suppose you have an Order object with a list of LineItems as a property. The source code is deceptively simple.



   1: Order order = orderRepository.GetById(1);
   2: foreach(LineItems item in order.LineItems)
   3: {
   4:     //do something fancy here
   5: }

Using NHibernate’s lazy loading, the LineItems property on an Order instance will not be populated until it is first called.  When it is accessed, a database call will be made to populate the LineItems collection.  The first time I saw this, I was floored.  “That is sooo cool”, Then I started thinking about it.  That lazy load call could be very expensive and if the person maintaining the code after I’m gone doesn’t know that the property accessor results in a potentially expensive database call, how can they make the proper decision on when that collection should be used?


This functionality obviously satisfies Evans first clause, but to me it violates the second part.  Developer’s need to know when expensive operations occurs, and hiding that operation behind a property accessor obscures that possibility. Now it has been argued that the real problem is that the property syntax is the real problem2. And I can agree with that, however the cat is out of the bag on that one.


The title of this blog post is a question to the community.  What are your thoughts? Do you think that using a getter method better describes to the developer that something more than an instance variable is being accessed?  Or are you okay with the property syntax?


 


1.  Evans, Domain Driven Design, p. 154


2.  Richter, CLR via C#, p.217

Related Articles:

    Post Footer automatically generated by Add Post Footer Plugin for wordpress.

    This entry was posted in NHibernate DDD. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
    • http://www.derickbailey.com Derick Bailey

      I think this is one of Joe’s “it depends” situations… depends on your team, their capabilities and knowledge, your specific project situations, etc.

      For me – Make it right before you make it fast… If a developer is using those line items, doesn’t this mean that the developer needs the line items at that time? If the developer does need the line items and it that part of the app is found to be a bottleneck, then you go back and decide if it’s appropriate to lazy load the line items or change how the developer is working so they don’t need the line items…

      i don’t think lazy loading violates DDD at all, either. Evans talks about the options of lazy loading or not… can’t find the page # at the moment, though.

    • jlockwood

      @John

      “That lazy load call could be very expensive…”
      It could be, but most often is not. In particular, if you have a class with a pretty deep object graph you wouldn’t want to load all that data at once if you didn’t need it. I’m currently working on an app (w/ hibernate) that can’t use lazy loading because of the architecture, this is leading to really expensive calls to the database and hurts performance.

      “…and if the person maintaining the code after I’m gone doesn’t know that the property accessor results in a potentially expensive database call, how can they make the proper decision on when that collection should be used?”
      Ah, that really leads to a deeper question. Any system abstraction takes the nitty gritty of a given implementation out of the developer’s line of sight. Think of ASP.Net and the fun we’ve had with the page cycle. If a developer really doesn’t understand how the page cycle works they can create some really annoying bugs in a web app. So, should a developer utilize a tool without knowing how it works? I’ve seen issues with lack of framework education on my current team when it comes to using both Spring and Hibernate. Since most team members don’t know what the frameworks do, they tend to write it off as magic and seldom seem to learn what’s going on under the covers.

      Heck, even classes from core libraries can introduce performance issues that the developer is not aware of. Again, as Derick said, “Make it right before you make it fast”. When a performance issue is detected, it should be tested then fixed to meet performance specifications.

      I don’t think lazy loading violates any DDD principle. The repository classes can still be used to give you an object of the type that you expect (as it should). I don’t think that DDD really addresses performance issues (though I could be mistaken…I don’t remember reading anything to the effect).

    • jcteague

      Thanks for the resposes guys. I agree with what you guys are saying. When appropriate for your aggregate, lazy loading collections is preferable. I guess I fall Richter’s camp that the property syntax makes a method look like a field and most of us assume there is very little cost involved in access a field. That’s why I think that using an actual getter method is more explicit to the developer that something more is going on when you need the LineItems.

      The section that referenced does relate to performance, but it gives an example where lazy loading should have been used. It gives an example where the entire object graph is being rehydrated. I also follow the “make it right first” approach.

      “Developers need to understand the implications of using encampsulated behavior. The does not have to mean detailed familiarity with the implementation. Well design Components can be characterized.”

    • Josh

      There’s a post by Ayende that mentions something similar to this (http://ayende.com/Blog/archive/2008/03/27/Adaptive-Domain-Models-with-Rhino-Commons.aspx)
      I think the degenerate case is
      decimal total = 0.0;
      var orders = orderRepository.GetAll();
      foreach (var order in orders)
      {
      decimal subTotal = orders.CalculateTotal();
      total += subTotal;
      }

      which effectively becomes problematic if your calculate casues the lazy load to go – for every single order.

    • http://www.elegantcode.com Jarod

      I think lazy loading is bad in this context. Since the order is the aggregate root in this scenario, it should load the required data (spans) explicitly to complete the graph (think transaction), in this case line items and maybe products. Were just getting one order right?

      IMO, the example above w/lazy loading is a smell the developer is using the wrong aggregate/repository for the job. If the developer doesn’t need the line items at the time, it is likely they are really dealing with a different aggregate, such as Customer.Orders, where the customer repository would not load line items.

      This would become very apparent once you begin to distribute data accross bounded contexts, whether its messages or crud/sync.

    • jcteague

      @Jarod
      I knew that example was going to come back and bite me :)

      I agree with you, it is a poor example and I knew it as I was writing it. Please look beyond the specific example and think about how we use Properties to lazy load. Do you think we are hiding important information from developers by lazy loading a Property?

    • http://devlicio.us/blogs/sergio_pereira/ Sergio Pereira

      I think replacing the property with a getter is not the answer. That would cause the reverse problem of developers thinking twice or building unnecessary caches to save the result of the method call even when lazy loading is Off. One way or the other the problem will always be that the data access choice made in the mapper will always be obscured by the business object member. I’d say that maybe we are worrying too much about DDD purity.

    • Kerry

      I think lazy loading properties in general is a bad practice, if only from the standpoint of reducing transparency in your code. It doesn’t take any more code to call a repository or other getter to load your collections, and the simple act of doing so ensures that the developer has some awareness of the data operations.

      Another consideration is true separation of concerns – if the business rules surrounding the loading of the property change, there is no indication to the consumer of this at all. Even if the property is lazy-loaded by calling an appropriate repository method, the existing code is still impacted with no indication to the developer that a change has been made.

    • jcteague

      @Sergio

      That’s a very good point. It’s always important to remember we don’t live in a perfect world and using property behavior may be an acceptable tradeof.

      Thanks

    • http://www.elegantcode.com Jarod

      @jcteague

      I think your example is great and fits the subject of the post well. Yes, I do think that lazy loading violates DDD concepts. Another principle to consider here is Command-Query-Seperation. (I think?)

      IMO, when I hit a repository, I want all the data for that aggregate. I want to be explicit with my query, I want to know exactly what I send to my db and when. If its too much data to get, then I say the aggregate is too big, or I am using the wrong one in context.

      I agree with Kerry here, I see LL more and more as bad practice. (There may be some limited scenarios where it is useful)

      Lazy loading can be a curse. As with your statement, I used to think it was ‘sooo cool’, but have since changed my mind. This mainly from working with distributed domains, and in pre-ddd days, working with teams who abuse lazy loading, just walking a graph sending endless queries to the db causing nasty perf issues… its, well, Lazy!

    • http://www.flux88.com Ben Scheirman

      I think the answer is exactly what you said… if it’s a potentially expensive operation, don’t put it on a property… instead put it no a method.

      While I agree that some things should be very explicit, having persistence concerns leak into your model (AHEM entity framework) is a bad idea.

    • jcteague

      @

      That’s a great perspective. Not every fetch / db call are created equal. Use your judgment and design appropriately.

      Thanks

    • http://colinjack.blogspot.com/ Colin Jack

      Good discussion and I agree with those who think that lazy loading doesn’t violate DDD principles.

      As far as getting the data you need when you need, Udi Dahan had some interesting ideas regarding fetching strategies. Never tried that approach, we just use eager fetching queries when we need them, but you might want to give it a look.

      Would an approach where we could explicitly say to a repository, at a high (as in DDD driven) level, give me this aggregate along with these associated aggregates be better?

      @Jarod
      Totally agree with your point, when you load an aggregate you *should* get the whole thing. I tend to view lazy loading as more useful between aggregate roots though.

    • t_moriarty

      Maybe a better example would be:

      order.LineItems.Count;

      Obviously, it would be quicker to just get count(*) from the db if the list is not yet loaded.