A Flaw with DDD?

I just got stumped on another DDD issue. Maybe I missunderstand things, and if so, I hope one of you has a solution.

The problem arises around a value object. In my aggergates, I pass in a user object (an entity, not the built-in security class) to all operations. Here’s are two examples:

using System;
using System.Collections.Generic;
namespace Venue.Entities
{
    using Venue.Resources;
    public partial class Category
    {
        public IEnumerable<Forum> Fourms
        {
            get { return forums; }
        }
        protected Category() { }
        public Category(string title)
        {
            Title = title;
        }
        public void AddForum(User user, Forum forum)
        {
            if (!user.Group.CanAddForums) throw new Exception(Locale.user_is_not_authorized);
            forums.Add(forum);
        }
        public void DeleteForum(User user, Forum forum)
        {
            if (!user.Group.CanDeleteForums) throw new Exception(Locale.user_is_not_authorized);
            forums.Remove(forum);
        }
    }
}
using System.Collections.Generic;
namespace Venue.Entities
{
    
    public partial class Forum
    {
        public IEnumerable<Mask> Masks
        {
            get { return masks; }
        }
        public IEnumerable<Moderator> Moderators
        {
            get { return moderators; }
        }
        public IEnumerable<Thread> Threads
        {
            get { return threads; }
        }
        public Forum() { }
        public Forum(Category category, string title)
        {
            Category = category;
            Title = title;
        }
        public void MoveTo(User user, Category category)
        {
            if (Category != null) Category.DeleteForum(user, this);
            Category = category;
            Category.AddForum(user, this);
        }
    }
}

As you can see, these entities validate themselves. When I get to a simple value object, with no relationships to any other object, things go a little wonky. Here’s the partial for that class:

using System;
using System.Collections.Generic;
namespace Venue.Entities
{
    using Venue.Resources;
    public partial class Code
    {
        protected Code() { }
        public Code(string title)
        {
            Title = title;
        }
    }
}

Basically, it holds regex info for parsing posts. Anyway, the problem is this:

As there is no parent on which to add an “AddCode” method, I am left with only one option. Put that check in the service class.

Now, I don’t know about you guys, but this smells a bit to me. Shouldn’t things be designed such that all authorization be handled in the same place for consistency purposes?

If I can’t find a way to have ALL the entities and value objects self-validate like this, I have no choice but to pull it all and do it in a service layer object. This leaves things in a less than DDD state. All the accessors on the entities would be doing is simple data testing.

Or is that all it is supposed to be doing in the first place?

I am really tempted to trash it all and go back to simple Linq2Sql contexts and not even both with trying to have the entities maintain their own state.

A Value Object is something like an Address, ProductCode. Using NHibernate, we use a Component to create and manage a Value Object. The underlying data model saves the value within the same row as the entity it belongs to:

ProductId,
ProductName
ProductCode.SomeProperty
ProductCode.SomeOtherProperty

It can also be configured to use a seperate table to store Value Objects/Components and it automatically manages PKs.

We usually move the creation of Value Objects to the root entity it belongs to and expose a method for creating them entity.AddCode(“value1”, “value2”)

That doesn’t make sense with this table. No other table / entity uses it. Code isn’t part of any other record. It is merely a lookup for the ParsingService class. It has no children, and no parent, objects.

Anyway, the concern is where to put certain methods. In this case, it looks like the ONLY place possible is in the service:

CodeService.AddCode(User user, Code entity)
{
// check user settings and either add or throw ex
}

This is where I get that nagging feeling that something is wrong. The same holds true for any top level entity. If no parent object exists, some tests have to be moved to the service. In the first two example above, you see that Category has methods that manipulate Forums, taking User into consideration, but what about when adding a new Category? The only place to handle that is in the service.

Spreading methods around like that seems wrong to me.

I share some of the “trobble” of serenarules here…

Who is responsable for creating entities?

I usualy do it in a command object with the difference that the command creating entities inevitably has a call to repository.save(entity) at the end.

@Serenarules

One of the things that makes me “think twice” is when I start seeing bi-directinal relationships exposed in domain objects.
Who ownes who?

public class category
{
public void AddForum(User user, Forum forum);
}

and

public class Forum
{
public void MoveTo(User user, Category category)
}

in my feeling I would “delete” the category.AddForum and all the references it has to forums since category is only a “name” (title).

cheers,
rui

That was a partial class. There are other fields. =)

What you’re saying though is I shouldn’t have a back reference to Category in Forum at all? I see a problem with that.

Most people would agree that if you use a reference, you omit the fk field (this is how NH works by the way). Now, if we also remove the reference, there is no way for a service method to know what category it belongs to, assuming that method is handed a forum object and needs to manipulate it.

So we need either the CategoryID or the Category as a property.

ForumService.ProcessMove(Forum forum, int cid)
{
Category c = categoryRepository.Get(cid);
forum.MoveTo(c);
}

Now, forum needs to be able to tell who it’s current owner is so it can notify them that they are leaving. If there is no back reference, it can’t.

If we do the inverse…

CategoryService.MoveForum(Category s, Category d, forum f)
{
s.RemoveForum(f);
d.AddForum(f);
}

There is still a problem. If there is no back reference, NH doesn’t know what value to assign to CategoryId when it’s actually saved.

I see no other way to do this.

In any case, think of it this way:

If asked who his father is, my son can point right at me.
If I am asked who my children are, I can point to each of them.

I see no real issue with bi-directional relationships. It’s when your code relies on them, that you run in to problem. I tend to limit any lines of code to one “dot” if at all possible.

In our case category.Forum is public as an IEnumerable, so it’s read only. no problem. forum.Category is also read only. Except by the persistence engine. Due to proxying, it can set things correctly. Again, this is what we want eh?

since category only “had” one field (that partial thing tricked me) I toke it for a “value”…

You know. Something occurred to me a few minutes ago. Since NHibernate can map to private fields as well, I did a small experiment. I rewrote my Category class like this (now using FluentNHibernate and is no longer a partial):

public class Category
{
#region Mapped Fields
private virtual int _id = 0;
private virtual int _sequence = 0;
private virtual string _title = string.Empty;
private virtual string _description = string.Empty;
private virtual bool _enabled = false;
private virtual bool _visible = false;
#endregion
}

I then collapsed the region so you couldn’t see it:

public class Category
{
#region Mapped …
}

I then altered the mapping to suit. Guess what. It still worked. You just couldn’t get to any of the properties to examine things (via code) while looping through a result set. But if I asked the repository for the category titled “Foo”, that’s what I got (as evidenced by the property inspector). This got me to thinking. If NHibernate can work with these objects when all the properties are private, who is to say I need to expose any of them at all?

Perhaps I’ve been approaching this whole thing completely wrong

Quote possibly, I should leave these fields private, and add only the supporting methods the entity needs. Exposing fields for get only, if I eventually see a need.

public class Category
{
#region Mapped …

public virtual void Disable() { _enabled = false; }
public virtual void Enable() { _enabled = true; }
public virtual void Hide() { _visible = false; }
public virtual void Show() { _visible = true; }

}

These methods are more descriptive of what is actually happening.

category.Disable()

looks a lot better than

category.Enabled = false;

Now that was rather simplistic, without any real logic or error checking, but you get the idea. I am just not sure my application has any real logic other than the db constraints, and some simple user auth stuff. There are no complex proocesses like customer.PlaceOrder(order), which is a lot more involved than simply adding the order to an ilist<order>.

It may very well be that my app isn’t suited for domain driven design?

I guess the key is to find a middle ground… :stuck_out_tongue:

category.Enable() / category.Disable() feels better than category.Enabled = false; ie category has control over the field.

Does “private virtual” compile? its doesn´t make sence! does hibernate complain if its just private?

also… partials is something that I never realy cared about… I see it has a “tool support” language feature.

Heh, no. That was a cut and paste from the clipboard, from before I tried compiling and testing it. It shouldn’t have the virtual keyword.

As for the partial, that was back when I was testing EF. I just added what the designer didn’t.

Anyway, I’ve thought a lot about this since I made that last post. I think I am headed in the right direction finally. Consider the following:

public class Post
{
#region Private Fields…

public virtual void MarkForReview(string reason)
{
_markedForReview = true;
_reasonForReview = reason;
}

}

That’s a TON better than setting two public fields, and it reads better too. One can tell what the heck it’s supposed to be doing.