I frequently struggle with determing which object should be the root object in a group of related objects. As a result, I feel my object graphs and relationships end up being too large and complex and consequently not very performant. By the end of setting the class realtionships up in an application, I am usually left with 2 or 3 large graphs in a single application.
Maybe my approach is wrong, but given the object hiearchy defined below, I have made Organization the Root object. This seems like a lot of work though when, frequenlty, I just need to gain access to the features and behavior supplied by the User object. This creates the added overhead of building the entire graph every time I want to edit a single user and it cannot be the right way of doing this. Nonetheless, I have not made User a Root object because User cannot exist without an Organization. So a user does not use an Organization it is contained within them (containment vs using relationships). Right?
Am I looking at this the right way? Is there extra reading or guidleines that I could refer to when struggling with this?
Some of the most difficult challenges that my team experienced when first starting to work with CSLA is that it is a very much use-case & behavior oriented platform. This can result in what is perceived by many to be a duplication of code or objects, however, once you get your head around that it makes building your objects much easier.
Given the examples that you've given above, when you maintain a user does it need access to the organization object or does it just require maybe an organizationID to be stored as part of the database structure? The idea of having only 2 or 3 root objects I would not think is the correct design unless you have very complicated process that requires saving as a single object and even then a Unit Of Work object could handle that better. I know that the Rocky books for 3.x series had a number of good concepts on where to use root level objects, etc.
Our class model for users for our objects are as follows:
If you need to access roles directly from users, this may make your objects a bit more complex. However, where possible I try and design each UI screen around a single root level object, with assistance from other classes / helpers where it makes sense. If all I need is a single piece of information about a related object (e.g customers having a group) then I set this up as a field (GUID or INT depending on DB) not a child relationship.
Hopefully this helps a bit and I'm sure you'll get other feedback from the great community we have here.
Thank you for your feedback. I like your recommendation of designing UI Screens around Root level objects. Do you happen to know of the top of your head which eBook contained information on this subject. I am still struggling with this conept a bit and am in search of further information.
Books 5, 6, and 7 in the Using CSLA 4 series all include discussion of behavioral object design and designing the objects around user scenarios.
I don't really design the objects around the UI, as much as that the UI and objects are both designed around user scenarios or tasks. As a result they work well together because they are designed to work together to solve the same problem.
Reading your question again, I get the suspicion that you have not yet looked at the Project Tracker demo application, at least not as close as you should have!
The hierarchical structure that you present typically comes from anticipations that we often have about the UI that we want to come up with in the end... Besides displaying the relationship between different "entities", that structure is providing the user a means of navigating to the data he wants to work with. Displaying and navigation are UI features. You would use readonly objects for these purposes.
Editable object hierarchies should be restricted to data/children that MUST be persisted together. And that does not apply to all the players in your problem domain (organization, user, roles).
I suspect that the relationship between user and roles is pretty much the same as the project-resource relationship in the Project Tracker app. You have to identify the right kind of relationship that you are dealing with each time. Here it is an m:n relationship.
In the case of the organization:user relationship you might have options... If a single user can only be assigned to a single organization (1:n), then the User object would just get a required property "OrganizationId"... and the UserRoles would result in an editable child collection, just like ProjectResources in the Project Tracker app.
Looking at the Project Tracker app should get you on your way!
P.S.: You should have a closer look at the ProjectTracker.Library project, which contains the business objetcs.
Copyright (c) Marimer LLC