Presenter Logic || Domain Service Logic || Repository Logic?

Obviously the answer to the titular question is yes.

I have recently found myself questioning whether the logic I am coding belongs in a domain service or in the presenter. I actually found the same logic in the presenter residing the base repository. Something definitely smells wrong, almost like the putrid smell of death, lol, nah just a DRY smell and a hint of mixed responsibility odor. The presenter was calling the Repository directly which was kinda of an indicator, but it is valid to do so, depending on the scenario.

The application that I am currently working in is a web application. That being said, I feel it is valid to consider the web limitations part of the current domain, not just a concern of the presentation. If we need to move to a windows app or something else, it will take a lot of refactoring, so why not just view the web’s issues as part of what affects the domain. Besides, is the purpose of the domain to be abstract enough to support multiple platforms or to dimish complexity? Anyway, that’s another discussion altogether, and I’m digressing.

Here’s the skinny, that’s a valid colloquialism isn’t it. I found string to integer conversion happening in two different places. Once in the presenter, grabbing a string Id from the view, converting it, calling an overloaded GetById method from the repository or throwing an exception if the Id was invalid. The overloaded GetById method was in the base repository, it either accepted a string Id or integer Id, if the string Id was invalid it was throwing an exception. Yikes, this is scary, and to think I was the one that coded all this, frightening, I know. I am recovering so don’t you worry yourself. Now to the current code (all code below is pseudo code, simplified for example purposes):

Code to be Refactored:

Presenter

public virtual void InitializeView()
{
if(TreatmentIdIsValid())
LoadTreatment();
else
throw new ApplicationException(string.Format("A Record of Waste cannot be completed because of the invalid treatment id: {0}", View.TreatmentId));
}

private bool TreatmentIdIsValid()
{
int validTreatmentId;

bool treatmentIdIsValid = int.TryParse(View.TreatmentId, out validTreatmentId);

if(treatmentIdIsValid)
CurrentTreatmentId = id;

return treatmentIdIsValid;
}

protected virtual void LoadTreatment()
{
try
{
CurrentTreatment = Repository<ITreatmentRepository>.GetById(CurrentTreatmentId);
}
catch
{
throw new ApplicationException("Could not retrieve the specified treatment");
}
}

Base Repository

public virtual Entity GetById(string id)
{
int parsedId;

if (!int.TryParse(id, out parsedId))
throw new ApplicationException("Could not convert the given id: " + id + " into an integer");

return GetById(parsedId);
}

public virtual Entity GetById(int id)
{
return Session.Get<Entity>(id);
}

I think that there is no place for logic in the repository it should be left to the domain service. You could even argue that this functionality is common and can be moved to a domain utility. For ease I am going to move it to a domain service. Now, lettuce see the refactoring to the code above:

Refactored Code:

Presenter

public virtual void InitializeView()
{
LoadTreatment();
}

protected virtual void LoadTreatment()
{
CurrentTreatment = RecordOfWasteService.GetParentTreatmentById(CurrentTreatmentId);
}

Domain Service

public virtual Treatment GetParentTreatmentById(string id)
{
int validTreatmentId;

if (!int.TryParse(id, out validTreatmentId))
throw new ApplicationException("Could not convert the given treatment id: " + id + " into an integer");

return GetParentTreatmentById(validTreatmentId);
}

protected virtual Treatment GetParentTreatmentById(int treatmentId)
{
try
{
CurrentTreatment = Repository<ITreatmentRepository>.GetById(treatmentId);
}
catch
{
throw new ApplicationException("Could not retrieve the specified treatment");
}
}

Base Repository

public virtual Entity GetById(int id)
{
return Session.Get<Entity>(id);
}

Alrighty then, we got any logic out of the repository, I’m feeling better already, my face has gone from grimace to grin, and no not the McDonlad’s character Grimace. Super serial, a la Al Gore about ManBearPig, what was Grimace, was he what you turn in to if you only eat McDonalds and nothing else?

The responsibility of the repository should be to read and write to persistence/web services/messages etc. The string validation logic is in the domain service, I may pull it out to a base service or utility service. Our presenter is so much simpler now, and not worried about logic that it shouldn’t have to worry about. Hmm, the cleanliness is delightful. There is no more duplication of logic in the presenter and repository, w00t! Now let me know your thoughts, comments, opinions etc. of dissent or agreement, it will help me and hopefully others learn and grow. I’m off to watch the some Teenage Mutant Ninja Turtle original series, wow, I’m a nerd.

Related Articles:

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

About Sean Biefeld

Hello all, my name is Sean Biefeld. I graduated from Baylor University with a BBA in Management Information Systems. I am currently working for McLane Advanced Technologies . The opinions expressed by me, however accurate they may be, are not necessarily those of my employer. I have been a developing software professionally since 2004. My primary development focus is on HTML, CSS, JavaScript and C#. I dabble in a little PHP and Ruby. This blog is a forum for me to post my experiences, ideas, rants, and thoughts as I traverse the mountain of life.
This entry was posted in C#, Domain Driven Design, Domain Service, Presenter, Repository, View. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • thalvor

    Why is the repositorymethod called GetById, and the domainservice GetParentTreatmentById? i mean: why “Parent” ? i would have misunderstood what i really got from the service i was the one to use it..

  • zihotki

    First of all you should avoid usage of this construction:

    catch
    {
    throw new ApplicationException(“Could not retrieve the specified treatment”);
    }
    instead use :

    catch (Exception ex)
    {
    throw new ApplicationException(“Could not retrieve the specified treatment”, ex);
    }
    This will help to keep real exception via InnerException property and you’ll be able see full stack trace of this real exception.
    As I see you are using NHibernate in your app. But I really can’t understand why are you decide to write own implementation of the repository. There are many good implementations of this pattern for NHibernate. And they are free for use. Why not to take one of them and just extend with necessary methods in derived classes?

  • http://www.lostechies.com/members/seanbiefeld/default.aspx Sean Biefeld

    @thalvor
    Sorry I did not provide very much context as I did not feel it would benefit the topic at hand. The GetById is in a base generic repository that take an entity type param. The name is left generic for that reason. As for the GetParentTreatmentById it is named that way because I am dealing with pain treatments from a bag of infusion. When the bag is near its end the nurses must record the waste, however much was left in the bag. This is dealing with that record of waste. The code in the post is pseudo code for example purposes.

    @zihotki
    Thank you for the astute observation, but the code in the post is pseudo code. What we actually do is log the inner exception and re-throw our own more user friendly exception. All logging code was left out to make the example easier to read. As for our own implementation of the repository pattern was just a team decision because we wanted the flexibility of our own.