why not hold reference to Root object in the child object

why not hold reference to Root object in the child object

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


jason2000 posted on Wednesday, August 30, 2006

During my research on CSLA, I found a problem which confused me these days:
A business Object has a member field named _parent that is a reference to the Collection Object which contain it. But, during many business applications, the validation rules and authorization rules of a child object usually utilize the information of its root object rather than the collection object which containing it.
 I will take ProjectTracker as an example. I assumed that there is a validation rule such as :"if days between started date and Ended date is no more than 10 days, then the total number of resource needed should be less than 4 ". When this rule is established in the ProjectResource class, started date and ended date should be achieved from the Root Object(that's Project) while the total number can be achieved from the collection object, but it seemed that ProjectResource object doesn’t having the referrence to a Project object.
 To solve this problem, I do the following work.
 1.Firstly declare a private filed in the ProjectResource class and establish corresponding attribute and set method
        [NotUndoable()]
        [NonSerialized()]
        private Project _parent;
        public PriceSuite Parent
        {
            get { return _parent; }
        }

        internal void SetParent(Project project)
        {
            _parent = project;
        }
 2.Secondly override OnDeserialized in the Project calsss,

        protected override void  OnDeserialized(StreamingContext context)
        {
            this._resources.SetParent(this);
        }
 3.add this sencentence in  method DataPortal_Create of Projectclass to cope with locally creating project object
    protected override void DataPortal_Create(object criteria)
    {
      _id = Guid.NewGuid();
      _started.Date = DateTime.Today;
      this._resources.(this);
      ValidationRules.CheckRules();
    }
  Then in every ProjectResource object, the reference of Project object can be achieved through ((ProjectResource)this.Parent).Parent.
  I don't know whether it is a satisfied solution. Because I think ProjectResource class doesn't hold the reference of its root object in CSLA.NET architecture. Does it mean that these business rules should be implemented in the Project class. If it is,how to appropriate to implemente it?

thks

dean replied on Wednesday, August 30, 2006

There has been some discussion of this in the past - you may want to search.

The upshot is that maintaining a reference to the parent couples the behavior of the two objects too tightly. The child then has to "know" about the fields in the parent. Instead have the parent implement an interface that expresses the data you need to share. In your case it would be ResourceCount and you could have an iProject interface that implements this.

Dean

tetranz replied on Wednesday, August 30, 2006

I sometimes do something similar to what you've described Jason for the same reasons, ie, rules in my child objects depend on the state of the parent.

Rather than keep a reference to the parent in each child, I put a reference to the parent in the collection, probably expose it as internal and then use the existing parent property of BusinessBase. To get a parent property from within the child it then needs something like:

((ProjectList) this.Parent).ParentProject.MyProperty

Ross

DanEssin replied on Wednesday, August 30, 2006

I guess this is a question for Rocky. Why not provide every base object with the Parent property so we don't have to add it by hand each time we need it?

jason2000 replied on Thursday, August 31, 2006

i suppose that Rocky'original intention is to implement  rules like "if days between started date and Ended date is no more than 10 days, then the total number of resource needed should be less than 4 " in the Project Class,but i wander how to implement it appropriately and effectively.i  hope rocky could give his opinion

malloc1024 replied on Thursday, August 31, 2006

One of the basic OOP principles to keep in mind is program to an interface and not an implementation.  A child should not have a reference to its concrete parent.  A child should know as little about its parent as possible.  It is not a good idea for the child to have a reference to its parent because it becomes tightly-coupled with its parent.  This creates a rigid design and does not make your child reusable.  The most common way to solve your problem is to abstract out what your child needs into an interface or abstract class.  The parent should implement this interface and the child should only reference the parent through this interface.

jason2000 replied on Friday, September 01, 2006

malloc1024:

One of the basic OOP principles to keep in mind is program to an interface and not an implementation.  A child should not have a reference to its concrete parent.  A child should know as little about its parent as possible.  It is not a good idea for the child to have a reference to its parent because it becomes tightly-coupled with its parent.  This creates a rigid design and does not make your child reusable.  The most common way to solve your problem is to abstract out what your child needs into an interface or abstract class.  The parent should implement this interface and the child should only reference the parent through this interface.

validation rules like "if days between started date and Ended date is no more than 10 days, then the total number of  resource needed should be less than 4 " contains information from the root object Prjoect and the child Object ProjectResource,at last, i implement this in the Project Class like this:

      protected override void OnDeserialized(System.Runtime.Serialization.StreamingContext context)
      {
          _resources.ListChanged += new System.ComponentModel.ListChangedEventHandler(Resources_ListChanged);
      }
     
      and if the DataPortal_Create Method is RunLocal(),add the sentence before ValidationRules.CheckRules();     
      [RunLocal()]
      protected override void DataPortal_Create(object criteria)
      {
        _id = Guid.NewGuid();
        _started.Date = DateTime.Today;
        _resources.ListChanged += new System.ComponentModel.ListChangedEventHandler(Resources_ListChanged);
        ValidationRules.CheckRules();
      }

      then we could do complex rule validation in the method Resources_ListChanged
      void Resources_ListChanged(object sender, System.ComponentModel.ListChangedEventArgs e)
      {
          //do complex validation things;
      }

     

Copyright (c) Marimer LLC