2

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?

1
  • 1
    "I often see model classes with properties like this" I wonder where do you see those.
    – Euphoric
    Commented Jun 18, 2013 at 12:23

2 Answers 2

3

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.

2
  • “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
    Commented Jun 18, 2013 at 13:33
  • @skrebbel I guess that's a valid point. I'd clearly prefer approach 1 though.
    – Philipp M
    Commented Jun 19, 2013 at 7:15
0

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).

3
  • It's not just another column, but an exists on another table with a join.
    – Philipp M
    Commented Jun 18, 2013 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
    Commented Jun 18, 2013 at 14:37
  • Then it's probably micro optimization from me, but I am just wondering if it's possible.
    – Philipp M
    Commented Jun 18, 2013 at 14:46

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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