Parent Object Changes - How to handle in validation rules

Parent Object Changes - How to handle in validation rules

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


DCottle posted on Tuesday, February 10, 2009

Ok, so we have 2 different object trees, that look like this:  (these are purely theoretical...the real objects wouldn't make sense to those outside of the industry)

Teacher(BB)

   Student (BB)

 

Teacher(BB)

     Students(BLB)

         Student(BB)

 

If i had a requirement to validate a Students age against a teachers age, then i run into a problem where I do not have a consistent parent relationship in my validation method.  So, I know I could do a branch like so

   if Student.Parent is Teacher  //Teacher is parent

     'do some action

   else

      'do some other action   //Students is parent

 

I do not like branching code to handle this though...is there a better option?

RockfordLhotka replied on Tuesday, February 10, 2009

I think your object model is incorrect from the start.

A Teacher doesn't own a Student, nor does a Student own a Teacher. At least in the US it is illegal for one person to own another :)

Really, a Teacher has a collection of AssignedStudents or CurrentStudents or maybe has a Class.

And a Class is a collection of Attendee objects.

And each Attendee object represents the relationship between the Teacher and a Student.

If you read the chapter(s) in the Expert Business Objects book about object design you can get a much more complete discussion about why to do your object model like this, and a more complete example as I walk through the design of the ProjectTracker object model. ProjectTracker has exactly this M:M relationship.

DCottle replied on Tuesday, February 10, 2009

Well, I was trying to illustrate an example of the problem without getting into domain specific language.

But our real scenerio is this:

DealShortTerm (of type Deal)

   Package

 

DealLongTerm (of type Deal)

   Packages

      Package

 

And a deal can indeed be of a type that it can only have a single package, or of a different type that would allow for multiple packages.  To fulfill these requirements, we are inheriting from Deal to have a DealShortTerm, and a DealLongTerm

In both cases, I have the requirement to compare the value of Package.MDQ to Deal.MDQ to ensure that the Package.MDQ < Deal.MDQ

 

so, inside of my validation routine, I again have code similiar to before:

if target.Parent is DealShortTerm

   //compare target.MDQ < (Deal)target.Parent.MDQ

else

   //compare target.MDQ < (Deal)target.Parent.Parent.MDQ

 

Again, I am trying to avoid the ugly branching here, but I need a way to get at the Deal.MDQ property, when I do not have a consistent parent.  This is not a many to many relationship...it is truly a one to one or a one to many relationship depending on what type of deal you have.

ajj3085 replied on Tuesday, February 10, 2009

I think Rocky's answer still applies.  You're faced with this "ugly branching code."  That's a good clue your design is heading down the wrong path.  His answer still may help; it sounds like a Package is something that is defined elsewhere, and so you have a class IncludedPackages or SelectedPackage.

It also sounds like the Deal should be checking it's child (or children) to ensure that your rule is met. 

RockfordLhotka replied on Tuesday, February 10, 2009

The trick is to put the responsibility where it belongs. If your code feels awkward (and branching is awkward) then the responsibility is in the wrong location.

 

I’d consider having the Deal class define a method to do the comparison – but an abstract method.

 

Then each Deal subclass would implement that comparison method.

 

Then your code is more like this:

 

var p = target.Parent as Deal;

if (p != null)

  p.Comparevalue(…);

 

No branching – you allow the object model to naturally figure out the right course.

 

Rocky

 

 

DCottle replied on Tuesday, February 10, 2009

RockfordLhotka:

Then your code is more like this:

var p = target.Parent as Deal;

... 

 

target.Parent is not necessarily a Deal...that is the whole point of my original question.  We are re-evaluating our model now, but I really do not have high hopes of restructuring this in such a way as to solve this.  I do appreciate your time in answering though.

RockfordLhotka replied on Tuesday, February 10, 2009

Obviously I don’t know the specifics of your model.

 

The solution however, is generally the same (though there are different techniques you can use). You need to invert how you think about the problem, so the decision point of what rule implementation is executed flows naturally from the object model itself.

 

Rocky

 

skagen00 replied on Tuesday, February 10, 2009

If you are constrained to where heavily modifying your object model is not an option or if you believe (I haven't read the thread thoroughly) that your package needs to be a child of deal, one option would be to set an internal property on "IsPackageValidForDeal" on package.

You would, in your "Deal" class, respond to child events / changes in package(s)' MDQ value.

Both deal classes would look at it's own MDQ and compare it to the value of the child being changed, and change the IsPackageValidForDeal property on the child. 

A change in the MDQ on the deal would presumably have an effect too - it would need to potentially change the IsPackageValidForDeal values on the child or children. Since you'd be doing this from DealShortTerm or DealLongTerm, you'd know whether or not to do it to the child or the collection of children.

On the Package, you'd have a validation rule tied to IsPackageValidForDeal. If that value is changed to true, the validation rule passes. If the value is changed to false, the validation rule fails and you can display an error message -- that child package would be invalid.  (i.e. it's a very simple validation rule that simply uses the valid value the deal gave it).

Anyways, just another option for you...

 

malloc1024 replied on Tuesday, February 10, 2009

Normal 0 false false false MicrosoftInternetExplorer4 /* Style Definitions */ table.MsoNormalTable {mso-style-name:"Table Normal"; mso-tstyle-rowband-size:0; mso-tstyle-colband-size:0; mso-style-noshow:yes; mso-style-parent:""; mso-padding-alt:0in 5.4pt 0in 5.4pt; mso-para-margin:0in; mso-para-margin-bottom:.0001pt; mso-pagination:widow-orphan; font-size:10.0pt; font-family:"Times New Roman"; mso-ansi-language:#0400; mso-fareast-language:#0400; mso-bidi-language:#0400;}

malloc1024 replied on Tuesday, February 10, 2009

Create an interface called IMDQ that contains a MDQ property.  Implement this interface in Deal and Packages.  In Deal, return the MDQ value.  In Packages, return Parent.MDQ.  Program to the interface and you won’t need the if-else statements.  

Compare target.MDQ < (IMDQ)Parent.MDQ

FrankM replied on Wednesday, February 11, 2009

How about thinking in this way:
Which means if Package.Parent is not a Deal type, validation should always return true. Only check parent type, but doesn't care any parent type other than Deal.

Then override Package's isValid property to implement the validation rule for package list. I think it's better to separate the validation rule between the single Package and the Package group/list.

Copyright (c) Marimer LLC