Welcome to AspAdvice Sign in | Join | Help

AzamSharp

Some day I will know everything I hope that day never comes

Syndication

Tags

Navigation

The Dilemma of Responsibility

One of the things that bug me while developing a new software is the issues related with distributing the responsibility among entities and managers. Let's say that I have an Exam object which has a IList of Questions. The relationship between the two is one-to-many. The collection Questions is set to be in lazy mode. This means the collection Questions will only be fetched when required. I have an ExamManager which works with Exam entities and QuestionManager which works with Question entities.

The ExamManager class have a method GetById(int id) which returns an Exam based on the id passed. This method should return the Exam object with the Questions collection. The code is given below:

public static Exam GetById(int id)

{

Exam exam = null;

using (ISession session = sessionFactory.OpenSession())

{

exam = session.CreateCriteria(typeof(Exam))

.SetFetchMode("Questions", FetchMode.Join)

.List<Exam>()[0];

}

return exam;

}

Although the code works fine but the responsiblity is distributed. Now, the ExamManager is fetching the questions and populating the exam object. I can use the QuestionManager to get all the questions based on the exam but then exam.Questions is a readonly collection hence it cannot be assigned.

Off course, I can use a method like Populate/Insert Questions into Exam but this just does not sound right. My main concern is that should the responsibilty of fetching the questions of the exam be inside the ExamManager or should this be part of the QuestionManager?

Published Monday, September 17, 2007 1:14 PM by azamsharp

Comment Notification

If you would like to receive an email when updates are made to this post, please register here

Subscribe to this post's comments using RSS

Comments

# re: The Dilemma of Responsibility @ Tuesday, September 18, 2007 10:18 AM

You bring up a really interesting point. Ignoring your domain for just a second, what are you gaining by setting the fetch mode for the 2nd related entity? If you've defined your mapping to lazy load the related entity collection, then you shouldn't need any additional code here. I think that the concerns for loading are that of the mapping, not of the code here. Now back to your domain, Exam sounds like an aggregate root for Questions. Is that true? Do quests ever exist outside the context of a specific exam? If not, then you have an aggregate relationship and by DDD principles it should be entirely managed by the Exam object. (You would not even have a QuestionManager object) I remember having this same problem in a domain of mine a few years ago (not using NHibernate) where I wanted to load related entities from a data reader, but I wanted to encapsulate the code in the class that is supposed to load it. I ended up with a little trick that would pass the data reader to the various classes along with a prefix for the column names.. So if I pulled back a user object I'd have this in the User class: internal static User Fetch(IDataReader dr) { User u = new User(); u.FirstName = dr["FirstName"].ToString(); //load more user columns u.Address = Address.Fetch(dr, "addr_"); return u; } So here the Address object would have a fetch method that knew how to load itself from a datareader, but now we're prefixing the column names with a unique string so that we don't ever get any collisions. This is a very interesting subject indeed.

Ben Scheirman

# re: The Dilemma of Responsibility @ Tuesday, September 18, 2007 2:49 PM

Hi Ben,

Thanks for your comments. Exam is the main object which serves as the Aggregate root. Although, I can solve this problem by using lazy = false but this introduces another problem. Sometimes, when I request an Exam I just want the exam and not the Questions or Choices. If I fetch a list of exams (say 20) then it will fetch Questions from each of the Exam and Choices for each of the Question. This is just too much data when all required is only the Exam itself.

Off course, for this scenario you can always use HQL but then let's keep HQL out of this problem. I see that you are using a the DataReader approach but in my case the List<Question> in an Exam is readonly. This is mainly because I don't want the user to use the collection to add Questions to an Exam since I have a AddQuestion method in the exam object.

The recommended solution in my opinion will be to use lazy = "false" and load all the questions and choices when the exam is loaded.

azamsharp

Leave a Comment

(required) 
required 
(required) 
Enter the code you see below