Domain Model vs Data Model (Part II)

Now that I’ve gotten everything working (from a technical point of view), and have come to some understanding on TDD and DDD, I have some resevations on how appropiate some things are for my current project. Please go over the code and comment below, the make your own comments and suggestions.

To make this easier, I am going to show you things in incomplete psuedo-code form. In addition, I’ll be going through things, step by step, the way I did when I though about them.

My original LinqToSql Category entity looked like this:


Category
{
public int Id { get; set; }
public int Sequence { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public bool Moderated { get; set; }
public bool Enabled { get; set; }
public bool Visible { get; set; }
public EntitySet<Forum> Forums { get; }
}

The first thing I did was rework it for NHibernate:


Category : Entity
{
public virtual int Sequence { get; protected set; }
public virtual Title { get; protected set; }
public virtual string Description { get; protected set; }
public virtual bool Moderated { get; protected set; }
public virtual bool Enabled { get; protected set; }
public virtual bool Visible { get; protected set; }
public virtual IEnumerable<Forum> Forums { get; }
}

The next thing I needed to do was create methods to alter the values, in a domain driven fashion:


Category : Entity
{
public virtual int Sequence { get; protected set; }
public virtual Title { get; protected set; }
public virtual string Description { get; protected set; }
public virtual bool Moderated { get; protected set; }
public virtual bool Enabled { get; protected set; }
public virtual bool Visible { get; protected set; }
public virtual IEnumerable<Forum> Forums { get; }
 
public virtual void SetSequence(IPrincipal user, int sequence) {}
public virtual void SetTitle(IPrincipal user, string title) {}
public virtual void SetDescription(IPrincipal user, string description) {}
public virtual void SetModerated(IPrincipal user, bool moderated) {}
public virtual void SetEnabled(IPrincipal user, bool enabled) {}
public virtual void SetVisible(IPrincipal user, bool visible) {}
 
public virtual void AddForum(IPrincipal user, Forum forum) {}
public virtual void MoveForum(IPrincipal user, Forum forum, Category category) {}
public virtual void RemoveForum(IPrincipal user, Forum forum) {}
 
public virtual bool ContainsForum(Forum forum) {}
public virtual Forum FindForum(int id) {}
public virtual Forum FindForum(string title) {}
}

Hm…ok, so it still looks a little weak eh? The method name “SetEnabled” doesn’t really tell the coder what enabling the category actually does. So just looking at that one element, I tried:


Category : Entity
{
 
// formerly Enabled
public virtual bool NewContentAllowed { get; protected set; }
 
public virtual void AllowNewContent(IPrincipal user) {}
public virtual void DoNotAllowNewContent(IPrincipal user) {}
 
}

Well that reads a lot better, so I recoded the whole entity along those lines. It looked good, and I went on merily recoding thing. Everything was fine until I got to the UI. They way the entity was now setup, things seem to lend themselves more towards single transactions at a time:


public ActionResult AllowNewContent(int categoryId)
{
 
// let HandleError handle any exceptions thrown by entity or repository
 
if (ModelState.IsValid)
{
Category entity = categoryRepository.SelectById(categoryId);
entity.AllowNewContent(User);
return RedirectToAction("Manager");
} 
else
return View(model);
 
}

This isn’t exactly how my system works though. In the list of categories on the Manage view, I only include actions for edit and remove. The remove view simply prompts the user to confirm before removing, and the edit view has all editable fields on it (including the unique key, title). While I could still handle all these thing in a single Edit action, I now have to test the model variables before setting something:


if (model.AllowNewContent)
entity.AllowNewContent(User);
else
entity.DoNotAllowNewContent(User);

Now, I don’t know about you, but I think that’s just butt-ugly. It would be much cleaner to revert back to something like:


entity.SetAllowNewContent(User, model.AllowNewContent);

What are you opinions? Which is the correct approach, and have I missed a scenario?


An additional option just came to mind:


 
private bool allowsNewContent;
public bool AllowsNewContent() { return allowsNewContent; }
public void AllowsNewContent(bool value) { allowsNewContent = value; }
 

…continue please…