N00B. Not Fully Grasping Root, Child, and Parent: Specific Example

N00B. Not Fully Grasping Root, Child, and Parent: Specific Example

Old forum URL: forums.lhotka.net/forums/t/5369.aspx


eulerthegrape posted on Tuesday, September 09, 2008

Hi,

I have read Expert C#2005 and an enormous amount of these forum pages and have hit a wall in understanding the relationship between child and parent and child objects and root stereotypes.  I'm working on the design of one section of an application and can't get the relationships straight.

The use cases are:
- The user wishes to maintain a list of companies
- These companies can be edited
- Each company has a single address (but this may change). 
- A company can be selected from a list elsewhere in the application

I have the following business objects:
Address
Company - Editable Child Object
Companies - Editable Root List
CompanyList - Name / Value Pair?

The relationship between Companies and Company is analogous to the Roles -> Roles relationship in PTracker, right?

Currently, the companies' addresses are found in a Company Table in my database.  The simplest solution seems to be to eliminate the address class altogether but Rocky (in another thread) suggested Address being a direct child object of Company (Address may have existed in another Table, I cannot remember).  Does this mean Address is a grandchild of Companies?  Does this complicate data access?

I understand many will say eliminate the address class for expediency but if a case arises where I need to create a direct child object I will be in the same situation so I really want to work through my understanding and solve this without getting rid of the Address object.

Along the same lines, if I have name / value pairs for states and countries in Address, do these becomes great granchildren?

I am confused at this point and may be making things worse by over thinking...

Somewhat off topic, I wanted Address to format data for presentation, i.e. Company Name (Carriage Return), Address1 (CR), Address2 (CR), etc.  Is this different behavior and thus a different class and possibly not business related and belonging in the UI?  Should I create a AddressFormatter object in my forms folder that takes a company object validates and formats.  That kind of sounds the most reasonable.

Thank you so much in advance from a humbled electrical engineer temporarily turned programmer,

Euler

JoeFallon1 replied on Tuesday, September 09, 2008

Euler - shouldn't you be doing Mathematics, not programming? <g>

Let's see if this helps at all.

A Root is a BO that inherits from your BusinessBase class (which inherits from Rocky's CSLA BusinessBase class.) There is no call in the constructor for MarkAsChild.

The Root BO can *contain* other BOs.

If a Root contains a BO then the contained BO can be considered a Child. The Root is responsible for fetching the data for itself and the contained child. It pass the data reader to the child after it is done fetching its own data. So the child BO has MarkAsChild in its constructor. This means the child can't perform direct data access - it always relies on its Parent to do it for it.

So the prime example of this structure is an Order. The Order BO contains a collection of OrderLines which contains a bunch of OrderLine objects.

The Order is the root BO. The OrderLines is and Editable Child Collection (ECC) and is a child of the Order BO. Each OrderLine in the collection is also a child. But their Parent is the ECC, not the Order. This has been a point of confusion for many people for a long time. Many times they want their OrderLine to have access to some data in the root Order BO and they want to use Parent to get to it, but the Parent is the ECC. I think Rocky finally gave up and supports using Pranet all the way up the chain until you get to the Root. So you should be able to get to it now if you really want to. It is not normally a good idea for a child to know about its Parent. The Parent should know about its children though.

The Root BO can contain other BOs which are not Marked as Children. I use a pattern called the Use Case Controller which is a Root BO that contains all the other BOs required to support a given use case (which could translate to a given screen in your app). So if your screen needs to present a lot of data, the Root BO or UCC object is responsible for creating itself and then fetching all the other BOs and exposing them to the UI as ReadOnly Properties. This means the UI can set values in these BOs but now create a whole ne BO and replace the one your UCC fetched.

The UCC is now responsible for saving all the data in the right order too. It can pass around a manual transaction object in the Context so you can save BO1 and then BO2 and do a rollback if needed.

The UCC can also fetch some NVLs which are used on the screen to let the user select from cbos.

I tend to have smaller BOs which are like Entities (look a lot like the DB table) and then I compose them inside a UCC so they work together nicely. The UCC can also have its own rules that cross over more than one contained BO. It can see down the graph as far as needed too so it can evaluate collections if it has to. (The collection or its immediate parent should evaluate itself though in most cases.)

HTH

Joe

PS - for the off topic question -

The Address class contains a lot of data and has many Properties. Just add 1 more Property like ToString or MyAddressInANiceFormat or ... and use the internal data to compose a single big string like you describe.

 

eulerthegrape replied on Tuesday, September 09, 2008

Thank you Joe for your quick response.

Mathematics by day coding by night kind of situation.  Why do I always find myself working for companies that require a multi-hat disposition? Ah, to be at a large company with a clearly stated role.  It's my fault, we don't have any programmers on staff and I said, 'I took data structures in college!'  This piece of the program is part of a larger, I'll say, instrumentation control program, which is pertinent to what is, theoretically, my job function :-)

The grand children concept is not pertinent to my issue, right?

So Company is the Root BO and Companies would be an editable child collection of Company that holds something like CompanyItems?  That kind of rocks my world.  I thought Rocky said the opposite in his Role, Roles, RoleList paradigm.

Now when we say the root is responsible for fetching all the data we are talking in relation to the user, right?  The user cannot interact with a child object to access data but the child's parent can request returned data from the child, which in turn needs to access the database?

So in case of the form holding companies loading data:
----------------
In Form
_companies = Companies.GetCompanies();
----------------
In Companies
public static Companies GetCompanies()
{
     return DataPortal.Fetch<Companies>();
}

private void DataPortal_Fetch()
{
     RaiseListChangedEvents = false;
     using (SqlConnection cn = new SqlConnection(Database.CasasConnection))
     {
          cn.Open();
          using (SqlCommand cm = cn.CreateCommand())
          {
          cm.CommandType = CommandType.StoredProcedure;
          cm.CommandText = "getCompanies";

                    using (SafeDataReader dr = new SafeDataReader(cm.ExecuteReader()))
                        while (dr.Read())
                            this.Add(Company.GetCompany(dr));
                }
            }
            RaiseListChangedEvents = true;
        }
}
----------------
In Company
private Address _address;

// Should I expose Address Properties with explicit properties in Company?
// private _addres1
// public string Address1
// { get { return _address.address1;}}

internal static  Company GetCompany(Csla.Data.SafeDataReader dr)
{
     return new Company(dr);
}

private Company(Csla.Data.SafeDataReader dr)
{
     MarkAsChild();
     Fetch(dr);
}

private void Fetch(Csla.Data.SafeDataReader dr)
{
     _id = dr.GetInt16("id");
     _name = dr.GetString("name");
     _address = Address.GetAddress(dr);
     dr.GetBytes("lastChanged", 0, _timestamp, 0, 8);
     MarkOld();
}
-----------------
In Address

internal static  Address GetAddress(Csla.Data.SafeDataReader dr)
{
     return new Address(dr);
}

private Address(Csla.Data.SafeDataReader dr)
{
     MarkAsChild();
     Fetch(dr);
}

private void Fetch(Csla.Data.SafeDataReader dr)
{
     _address1 = dr.GetString("address1");
     _address2 = dr.GetString("address2");
     _state = dr.GetString("state");
     _country = dr.GetString("country");
     _zipCode = dr.GetString("zipCode");
     MarkOld();
}
---------------

Will this work?  Do I need a separate procedure to recall the address?  If I do then I would need to know who the parent is.

Thanks again,
Euler

JoeFallon1 replied on Tuesday, September 09, 2008

You did not explain the screen so it is not possible to evalute the code.

In the first post you said you want to use this: Companies - Editable Root List

I have never used one of those in almost 5 years. There is only 1 screen where it makes sense to use that and that is a Windows Grid. An ERL is a special kind of list which takes Root BOs and stores them in the list (so no MarkAsChild in the constructor). Then as you edit each row of the grid and move off it the root BO is saved immediately.

You also wrote:

The use cases are:
- The user wishes to maintain a list of companies
- These companies can be edited
- Each company has a single address (but this may change). 
- A company can be selected from a list elsewhere in the application

The UI I would create for this is:

1. A Search screen with various criteria that the user can fill in. (Company Starts With {xyz}, State Starts With {NY}, etc.)

2. Once they enter their criteria, I do a database search and return a Result screen with a ReadOnly grid on it. So this is a ROC with contain Info items. The grid displays key info, like Company Name, State, etc. The last column of the grid is an Action column. There is a column of buttons there to Select the company to Edit.

3. When they click a button, the CompanyID is stored and the user is directed to the Edit screen which uses the CompanyID to fetch the Root Comapny BO for editing. This screen could have a grid for multiple addresses as a child portion of the window. (Master Detail relationship.)

HTH

Joe

 

 

 


 

eulerthegrape replied on Tuesday, September 09, 2008

Hey Joe,

Ok, I think I understand the confusion as the use case "These companies can be edited" is somewhat vague and lends itself to different UI conventions.

Being new to CSLA, I'm basing a lot of my work on PTracker where Rocky often uses datagridviews.  Since the company edit functionality is administrative, I thought this control would make sense but I do see the value of an editable list with a per item edit form.  I think this is where I got confused by your root object being the Company while I was thinking of Companies as the Root.

I must have accidentally implied that I wanted to work with an Editable Root List because my understanding from reading Rocky's response to people was that this is an undesirable stereotype.  With your UI construction I see there only being one child which makes things simpler in my head but what happens if we do have an editable datagridview?  Is this much more complicated?

Since one of the goals behind CSLA is to make to business objects UI agnostic would it be prudent to have a way to edit both Companies and Company?  But then, unadvisably, Company is sometimes a root and sometimes a child.

Thanks,
Euler

JoeFallon1 replied on Wednesday, September 10, 2008

One of the key ideas is that you build BOs for each use case - without regard to re-using them in different cases! Many people shudder over that idea but once you wrap you head around it you find that things are simpler to maintain. A given BO has only 1 function. I admit I do not always follow that rule and there is some twisted code inside some of my BOs to support extra cases - but I regret some of that and would change things to keep it simpler if I could go back.

I don't run PT and am not familiar with the examples. I don't do Winforms either. As I said, I never built a ERL and have no plans to.

But your last statement is not true:  "But then, unadvisably, Company is sometimes a root and sometimes a child."

Recall that an ERL list is Root List which contains Root objects! So in that example Company is never a child. It is always a root. Sometimes used on its own and sometimes used as part of a grid where it saves itself when you move off the row.

BTW - a BO can be a root and a child. That is called a Switchable object. It just combines both sets of templates and calls MarkAsChild when appropriate. It has been said that if you want to use a Switchable object then something is probably wrong with your object model.

Joe

 

 

eulerthegrape replied on Wednesday, September 10, 2008

Thank you Joe, you have been extremely helpful in making CSLA much clearer.

I guess this is a more than one way flay a bear scenario.

It seems like I have two clear design choices.  The first solution is to create an ERL that contains Company root objects.  I would then bind this collection to a datagridview control and perform edits directly in the datagridview.  The other solution is to create a datagridview or listview control and bind to a read only list or name / value pair.  Then have a separate editing form to edit the company.

In the second solution I would have to create a read only list but I'm going to have to do this anway for another use-case, as I originally explained.  One solution does seem much more web-centric.

I was under the really dumb assumption that ERLs was a huge no-no but re-reading Rocky's book I see now that his Roles class is, in fact, an ERL and their are lots of posts regarding them in this forum.  But also in re-reading the forum, it does seem that many around these part discourage the use of ERLs or have disdain for them.

I guess I'll pose the question to the gallery:
What is your preferred design solution?

ajj3085 replied on Thursday, September 11, 2008

eulerthegrape:
I was under the really dumb assumption that ERLs was a huge no-no but re-reading Rocky's book I see now that his Roles class is, in fact, an ERL and their are lots of posts regarding them in this forum.  But also in re-reading the forum, it does seem that many around these part discourage the use of ERLs or have disdain for them.


Um, that's probably the wrong attitude to show toward the ERLB.  The words around may be strong, but it's perfectly valid to use.  But, it's designed to be used in a very limited scenerio:  by a Windows Forms (or WPF, I would assume) application, where changes to each row are to be committed independately to the database as the user leaves the row.  So even though each row is in the same grid, they really exist in their own independant universe. 

So if that's what your use case calls for, then by all means use an ERLB.  But if you're doing something else, it probably doesn't fit.  This is the trap that most fall into; they assume ERLB should be used for most lists, and BLB is some kind of exception, when the relaity is the opposite.

eulerthegrape:
I guess I'll pose the question to the gallery:
What is your preferred design solution?


It sounds like no matter what you'll want a readonly list of companies.  For display, to select a company maybe, etc.  So there are two classes (ROLB and ROB subclasses).

Now, you're going to need a way to edit a company.  No matter what you'll be editing one company at a time (that is, you're going to be changed within a single transaction only one at a time).  So you'll definately need a Company which is a BB subclass.

So the only question is this:  do your uses expect to see the entire list, and be able to change multiple companies at once?  If yes, should the changes be batched or not?

If the changes should be batched, your Company class should be a child and containined within a BLB subclass.  You'll Save the list of companies all at once.  All changes go, or none do. 

If your users want to "save" each company as they click off the row, then your Company class should be a root and contained in an ERLB.

Finally, if editing a company is too complicated to be done in a single row of some kind of grid control, you'll probably want a seperate form.  In this case, there's no need for a BLB or ERLB class.

HTH
Andy

Wbmstrmjb replied on Tuesday, September 16, 2008

Wouldn't the following scenario lend itself to an ERL?  Just want to make sure I understand it correctly:

A list of invoices that you would like to "approve" or some other function, it's just an example. 

It would be a list of root objects (invoices) that you need to do something with.  Wouldn't that be an ERL?

ajj3085 replied on Tuesday, September 16, 2008

Only if each approval should be recorded immediately as the data is committed in the Winforms grid you're using.  So the user selects approve, clicks to the next row on the grid and the approval is recorded at that point.

If the list of approvals must go as a batch, or if it needs to wait for a Save button click, for example, the no, ERLB would not be appropriate.

Copyright (c) Marimer LLC