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.

I often see model classes with properties like this:

public IList<Note> Notes { get; set; }
public bool HasNotes { get; set; }

Where the list is initialized lazy, but the boolean property is loaded directly. This has the benefit, that only the count is loaded, when the collection is not needed, but the caveat is that the value for the boolean property is always calculated.

This made me think and I came up with a solution like this:

public IList<Note> Notes { get; set; }
public bool HasNotes
{
  get
  {
    if (Notes != null) return Notes.Any();
    else // calculate (e.g. sql exists)
  }
}

This way the calculation would only happen if the collection is not loaded.

Would this be a good approach? Does there already exist different best practices unknown to me?

share|improve this question
1  
"I often see model classes with properties like this" I wonder where do you see those. –  Euphoric Jun 18 '13 at 12:23
add comment

2 Answers 2

up vote 3 down vote accepted

You can never know how users plan to use your code. In your proposal, if a caller first looks up HasNotes and only later Notes, you'll have one SQL call too many as well: first the COUNT, and then the entire SELECT to populate Notes.

If you do know that users will never call HasNotes before Notes, then your implementation make sense, but in that case, I'd suggest going all the way in that direction.

For instance, instead of trying to be smart about queries by guessing usage patterns in a model, you could make an explicit data access layer that performs exactly the right queries that are needed, and populates the model classes. The model classes are then reduced to simple data-holder classes. They might contain domain logic and validation logic and all that, but certainly no knowledge of the DB.

This is really the ORM vs DAO debate. Fowler has a nice short discussion of this debate here.

In general, I'd choose a clear approach:

  1. Try to be as automatically-smart as possible in the model classes. This is the NHibernate way. It yields an easy-to-use model layer that generates just a few queries too many. In that case, leave the smart stuff up to NHibernate and don't try to optimize your model classes prematurely.
  2. Don't even try to be smart, but leave it to the "user" to call the right methods that populate the model.

I feel that the approach you suggest is somewhere in the middle ("It's an optimization, but only if you call things this and this way"). This will confuse other developers, and yourself in a few months. Better to take a clear stance.

share|improve this answer
    
“You can never know how users plan to use your code.” That's not really true. In some cases, you know you're the only one who's going to use the code. In others, you can talk to the users about that, since they sit in the next office. –  svick Jun 18 '13 at 13:33
    
@skrebbel I guess that's a valid point. I'd clearly prefer approach 1 though. –  Philipp M Jun 19 '13 at 7:15
add comment

Would this be a good approach?

I think a better approach would be to always load HasNotes together with the rest of the entity. That way, the property is basically free (one more returned column should be much cheaper than making another SQL query for each entity).

share|improve this answer
    
It's not just another column, but an exists on another table with a join. –  Philipp M Jun 18 '13 at 14:30
    
@PhilippM I meant one more column in the returned table. And yeah, to get the value of that column, you need something like EXISTS, but that should be relatively fast due to indexes. –  svick Jun 18 '13 at 14:37
    
Then it's probably micro optimization from me, but I am just wondering if it's possible. –  Philipp M Jun 18 '13 at 14:46
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.