Results 1 to 6 of 6

Thread: DDD and aggregate roots

  1. #1

    Thread Starter
    Hyperactive Member
    Join Date
    Jan 2010
    Posts
    259

    DDD and aggregate roots

    So I am working on understanding DDD better and there is the concept of aggregate roots. What I am trying to understand is at what point is it ok to modify the child "relationships"?

    EG (Simple example at that):

    Code:
    public class User
    {
       public string Id { get; private set; }
       public string Name { get; set; }
       public string Username {get; set;}
       public List<string> RoleIds {get; private set; }
    
       //......
    
       public bool AddUserToRole(Role role)
       {
          RoleIds.Add(role.Id);
          //Save updated user and role relationship to the database
       }
    }
    
    
    
    public class Role
    {
       public string Id { get;  private set; }
       public string Name { get; set; }
       public string Description { get; set; }
    }
    With the above example, is how I have adding the role to the user correct? Since you have to use the method of the aggregate root in order to add the role to the user and not accessing the child aggregate directly.

  2. #2
    Smooth Moperator techgnome's Avatar
    Join Date
    May 2002
    Posts
    34,532

    Re: DDD and aggregate roots

    well, normally... at least in the occasions where I've dealt with roles and users... I've never added roles to users... but rather the other way around... add a user to a role. The role isn't a property of the user... the user is a property of the role... it could be a matter of semantics... but in every case where I've dealt with things like this, that is how it's been.

    So I'd have an AddUser method in the Role class.... that would then add the user to the list of users maintained by the role internally...

    -tg
    * I don't respond to private (PM) requests for help. It's not conducive to the general learning of others.*
    * I also don't respond to friend requests. Save a few bits and don't bother. I'll just end up rejecting anyways.*
    * How to get EFFECTIVE help: The Hitchhiker's Guide to Getting Help at VBF - Removing eels from your hovercraft *
    * How to Use Parameters * Create Disconnected ADO Recordset Clones * Set your VB6 ActiveX Compatibility * Get rid of those pesky VB Line Numbers * I swear I saved my data, where'd it run off to??? *

  3. #3

    Thread Starter
    Hyperactive Member
    Join Date
    Jan 2010
    Posts
    259

    Re: DDD and aggregate roots

    Yes, I also thought of that and had some hesitation to it but, for this example, I am really looking at if using a method of the aggregate root (assume User is in this case) is the proper way to alter the underlying collection it is maintaining is correct.

    My current understanding of using user.RoleIds.Add("1231"); would be considered a violation as you as circumventing the aggregate root to make changes to its child aggregate. This could also circumvent any possible business rules and the like. Would I be correct in this assumption?

  4. #4
    Smooth Moperator techgnome's Avatar
    Join Date
    May 2002
    Posts
    34,532

    Re: DDD and aggregate roots

    Ok... now the question is a little clearer.... yes using User.RollIds.Add is bad ... which is why RoleIds should be private... for starters... then you have a read-only property that returns the collection (so you can iterate through it)....

    so what you end up with is something like this:
    Code:
        public class User
        {
            public string Id { get; private set; }
            public string Name { get; set; }
            public string Username { get; set; }
            private List<string> RoleIds;
    
            public List<string> Roles
            {
                get { return RoleIds; }
            }
    
            //......
    
            public void AddUserToRole(Role role)
            {
                RoleIds.Add(role.Id);
                //Save updated user and role relationship to the database
            }
        }
    Now the list of roles cannot be accessed directly... preventing direct edits to the collection... BUT... that just means you cannot do user.Roles.Add ... but you can still do user.Roles(0) = ""; so it doesn't affect the items in the colleciton, just the collection accessor itself.

    -tg
    * I don't respond to private (PM) requests for help. It's not conducive to the general learning of others.*
    * I also don't respond to friend requests. Save a few bits and don't bother. I'll just end up rejecting anyways.*
    * How to get EFFECTIVE help: The Hitchhiker's Guide to Getting Help at VBF - Removing eels from your hovercraft *
    * How to Use Parameters * Create Disconnected ADO Recordset Clones * Set your VB6 ActiveX Compatibility * Get rid of those pesky VB Line Numbers * I swear I saved my data, where'd it run off to??? *

  5. #5

    Thread Starter
    Hyperactive Member
    Join Date
    Jan 2010
    Posts
    259

    Re: DDD and aggregate roots

    To your first point, that is already accomplished with

    Code:
    public List<string> RoleIds { get; private set; }
    It makes the set method internal to the class. BUT, your way gives me the notion that the get method should return a copy of the RoleIds instead of it actually returning the reference to the collection? EG RoleIds.ToList();...yea yea it is expensive, but perhaps a better way to make sure no changes are made to the underlying collection?

  6. #6
    Super Moderator FunkyDexter's Avatar
    Join Date
    Apr 2005
    Location
    An obscure body in the SK system. The inhabitants call it Earth
    Posts
    7,900

    Re: DDD and aggregate roots

    I think this is really an OO issue rather than a DDD one and you're absolutely correct.

    Strictly speaking, if you want to expose the collection outside of the class you should expose a copy rather than the original (or a reference to it) because the class should be the only thing fiddling with it's private members. That said, for efficiency we'll often expose the reference and just assume that they won't be fiddled with outside of the class. If you're application has to be extremely performant you should probably stick with the reference, if not then a copy is a much better aproach. Nobody likes having their privates fiddled with (unless the fiddler is a Freind).

    For that reason I personally dislike the 2010 syntax for properties. It muddies the line between the private and the public parts. I still prefer a proper private member and then a separate public property controlling access to it. It may be more verbose but it's clearer.

    By the way, AddUserToRole should probably just be called AddRole. You're in the User class so mentioning the User in a method name is redundant, every method a class has should involve doing something to itself. And, yes, that does reveal me as an utter pedant but I do find that a strict naming convention for methods helps me think in the right way to keep their purpose nice and tight. If I ever spot a method that isn't either <verb> or <verb><noun> I start to question whether it's doing too much.
    The best argument against democracy is a five minute conversation with the average voter - Winston Churchill

    Hadoop actually sounds more like the way they greet each other in Yorkshire - Inferrd

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width