inherit ? contain ?? behavior-centric ????? - One more time ....

inherit ? contain ?? behavior-centric ????? - One more time ....

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


tsaltd posted on Monday, September 03, 2007

Greetings all ...

I'm doing another iteration of a domain model in C# -- a part of which has an object model of:

1.0.0.0 Actor
            1.1.0 Individual
                     1.1.1 Employee
                     1.1.2  Contact

            1.2.0 Organization
                     1.2.1  Internal Organization
                     1.2.2 External Organization
                               1.2.2.1  Vendor
                               1.2.2.2  Customer

I've implemented something similar using CSLA and found the Forum theread on

to be quite helpful.

Yet I'm concerned that I am still stuck in a data-centric design view.

I just dont feel confident that I "get" the behavior-centric thing and certainly don't see how I might be able to avoid creating too much complexity by using containment instead of inheritance.

I've browsed GOF concepts and other best practices guides and still don't feel confident that I have wrapped my head around a convincing alternative design.

What I'd really like to see ( if indeed there is a "better practice alternative" to my hierarchical inheritance tree ) is some views on re-factoring my Actor object graf that takes advantage of containment and behavior-centric design.

Any pointers to literature that focuses on these issues will be a big help ... but of course, I'm hoping that this note will trigger a stimulating discussion.

Thanks again,

Steve

 

juddaman replied on Monday, September 03, 2007

Hi Steve

I'll have a go at helping you, though I'm no expert or anything so you may want to do some more reading around. I thought I had a good understand of OO before I came across CSLA, it really through the spanner in the works. I think I've got my head around the problem now, basically in framework level code there is lots of behaviour going on so inheritance is common place this does not translate into business applications. Meaning many BO don't deal with much behaviour, well not really ballsy behaviour like you find at lower levels. Remember you should inherit behaviour not data. Any behaviour you do want to “pass on”, particularly in the business layer is probably better provided to multiple objects by means of composition. Anyway that’s just random background thought on how I’m getting to grips with CSLA, Use-Case driven and SRP.

 

Moving on to the problem at hand, I think you desperately need to take a step back to use-case level. When you laying out your object I’m presuming your suggesting Employee inherit Individual which inherits Actor?

 

1.0.0.0 Actor
            1.1.0 Individual
                     1.1.1 Employee
                     1.1.2  Contact

I think you need to ask yourself (and the objects), why? Is there shared behavior, is more probably just shared data? Be honest with yourself here! It took me a while to convince myself about this on occasion.

If they are just sharing data break them up so Employee and Contact are there own root BOs. Lets say somewhere in your system you need a list of individuals and there phone numbers, so at this point you might be thinking, well if I’d sub-classed Individual I could just take my objects and regardless of there actual type get there Name and Number as that data are properties of the Individual class. However you can do this, you just need to prepared to make the BO to match you use-case. Your use-case being provide user with a list of individuals names and numbers.. blah blah.. So at this point you’d need to think do any of my BOs (currently Employee and Contact) provide me with this info, the answer being no. Employee maintains a single Employee and Contact and single Contact. So you need a need object say IndividualInfo which has the properties Name and Number. Make a list say, IndividualsList which is a list of these IndivudalInfo objects. So now you have the object set to meet the use-case. Simply get the data from the various database tables (or other data store) and put it in the info objects.

I’m yet to find any specific literature that would demonstrate such concepts as multiple Customer objects for different use-cases for instance. However the Applying UML and patterns book by Craig Larmen is an excellent overview of OO techniques. The two cases studies in the book are not forms-over-data style apps though. There is a point of sale system and a monopoly game both of these are rich in behavior so you have to take a step back and remember that they are different types of systems to what most people develop most the time.

Sorry it’s a bit rambley, I just through a few ideas down; if anything catches your interest and you want me to be clearer on something let me know.

 

George.

tsaltd replied on Monday, September 03, 2007

Thanks, George ... I'm just starting to process your feedback ... here are my initial reactions / conclusions

Encapsulating  CRUD/ DataPortal functions in an inheritance chain of business objects ... that really cool pattern of passing the command object  from the Organization and Individual up to the Actor  --  base.insert(cm)  --- to populate parameters before excecuting the DoInsertUpdate function in the Organization orIndividual 

... That's not really an appropriate use of inheritance???

Better to contain an instances of :

and

 

I'm puzzling over how I can follow that containment pattern and keep the number of database command executions to a minimum.

I see the value in creating a separate "IndividualInfo"  object for the phone and address attributes for … Individuals and Organizations

I'm starting to come around ... What would really be helpful is to see an example of where the type of inheritance that am so attached to and am trying to unlearn IS actually a "best practice" .... ie: the use cases where inheritance is actually "behavior-centric" and is a better choice than containment.

If I could understand that, then I would have more to go on in terms of what to look for in analyzing when Inheritance is the "best practice" and when it is better to go with containment.

Is this art ? engineering ?? religion ?????

Thanks,

Steve

 

 

juddaman replied on Tuesday, September 04, 2007

Hi

In this case I'm not even suggesting you should contain Actor and Individual in Employee and Contact. Rather Employee should have all the"data" it needs. So basically this involves cutting and pasting all your properties from Actor and Individual into Employee and Contact. Any shared behavouir such as custom validation methods etc can be put into another object, like what Rocky did with the Assignment class in the project managment system described in the book. Thats just my opinion of how you should go anyway. There is no hard fast rule at the end of the day.. if it works it works kind of thing. In general I'd say you shouldn't find yourself inherting your own BO's. Though you may find your self creating inhertience structures with your none BOs, your behavouir class's etc. Then using these via client-supplier in yours BOs. Does this help?

George

tsaltd replied on Tuesday, September 04, 2007

I'm going to need more convincing before I consider implementing re-use via cutting and pasting, George .... The Actor Class is actually part of 3 or 4 other entities, and I have other Business Objects that share data and behavior ( CRUD / Data Portal ).

Maybe I don't understand the downside of placing references in Roots to Editable Child ... I got some inspiration from Rocky in this post:

http://forums.lhotka.net/forums/post/12714.aspx

You can have an editable root directly contain an editable child, that is fine. The property in the editable root that allows access to the child should be a read-only property, because you don't want the UI to change that reference, only gain access to the child object.

The idea of containment (or aggregation) is at the core of object-oriented design. Objects contain other objects all the time, this is not a bad thing. In fact, it is a way to express important relationships between objects.

In most cases this is not a form of tight coupling. The root object is aware of its child, but probably won't interact with it very much. The child object may be entirely unaware of its parent.

 

Again, a major objective of my posting here is to understand when it is ( if ever )  a "good practice" to create sub-classes for the types of entities that are modeled as sub-classes in a relational DB design

.. ie:

 Person

Employee

Hourly Employee

Exempt Employee 

More thoughts ???

Steve

RockfordLhotka replied on Tuesday, September 04, 2007

I think one key element of understanding all this is the following:

Properties are not behavior. Reuse of properties (and thus fields) is not a priority.

Using inheritance to "reuse" properties and fields is counter-productive. It results in more complexity and coupling (fragility) costs than can be offset by any benefits of reuse.

This leads to the second big concept:

Reuse is not the goal. Maintainability is the goal.

Reuse can decrease maintainabiltiy if it results in coupling. Coupling is the big danger, and inheritance is (almost) always a form of tight coupling. Thus inheritance should generally be avoided. Which leads to the maxim:

Favor composition over inheritance.

But actual composition can have some serious downsides in terms of performance, especially when it comes to data access. At least if you view composition as the use of multiple object instances working in a coordinated manner.

However, if composition becomes combination - at least of properties/fields - then you avoid the performance issues. And now we're to the point where you would have separate objects for HourlyEmployee and ExemptEmployee, even though they share some properties/fields.

The key, imo, is that you don't want to replicate behavior (methods). Replicating properties/fields doesn't matter - they can be code-genned or created with snippets. There's little to no variation in a property - they are just stamped out like widgets.

But methods are unqiue. Most methods actually do something interesting (unlike properties), and so you only want to write and maintain a method exactly once. This leads to

Normalization of behavior.

The idea is that you normalize behaviors that are common across objects. To do this, at a design level you move that behavior into its own object. Related behaviors can go into the same object (a concept called cohesion).

Of course at the implementation level you may actually implement many of these behaviors as Shared/static methods and so not have real objects. But that's an implementation artifact and doesn't impact the design process.

In CSLA objects, most behavior is in the form of rule methods, and those are easily normalized (they are normally Shared/static to start with).

Other custom methods (like calculating a price, or a wage or something) are more interesting, but are typically also easily normalized.

In ProjectTracker I do this normalization into the Assignment "object". At a design level, this object contains behaviors common to ResourceAssignment and ProjectResource. At an implementation level it is a collection of Shared/static methods.

But the result is that all interesting business logic that would have been duplicated is now centralized, and the two original objects now collaborate with this Assignment object to do their work.

tsaltd replied on Tuesday, September 04, 2007

Thanx, RL ...

I think we're close to putting this to bed .... tho I must again say that the seeing the little trick of implementing inheritence in BO's by passing the command object to add parameters from a base class's InsertUpdate method using base.insert(cm) , then returning it back to the subclass to execute the command added a whole new level of excitement to my life as a developer.

 Does that make me an Elvis or an Einstein ??  Or just a hot-dogger ??????

I agree whole heartedly with what you are saying, but one thing in particular needs clarification ....

"And now we're to the point where you would have separate objects for HourlyEmployee and ExemptEmployee, even though they share some properties/fields."

What about adopting the approach where we have HourlyEmployee and ExemptEmployee objects that contain PersonInfo and EmployeeInfo Objects  ??

.... I read what you said about re-use ... but implementing this way allows:

Reuse, Maintainibility .... elegance ???  Too brittle ?????

Thanks again.

Steve

RockfordLhotka replied on Tuesday, September 04, 2007

tsaltd:

I agree whole heartedly with what you are saying, but one thing in particular needs clarification ....

"And now we're to the point where you would have separate objects for HourlyEmployee and ExemptEmployee, even though they share some properties/fields."

What about adopting the approach where we have HourlyEmployee and ExemptEmployee objects that contain PersonInfo and EmployeeInfo Objects  ??

.... I read what you said about re-use ... but implementing this way allows:

  • the HourlyEmployee to instantiate the PersonInfo and EmployeeInfo objects as EditableChildren ....
  • The same PersonInfo editable-children and EmployeeInfo BO's are used in the ExemptEmployee

    and
  • PersonInfo could be contained/reused in Contacts

This can work. It is a use of both composition and containment.

However, you'll probably find that it is awkward at the UI level. Data binding prefers to have a single, flat object in most cases. Because you'll have a two-part "flat" object data binding will have a harder time working with this model. Or more accurately, you'll have a harder time convincing data binding to work with this model.

In other words, you've achieved some potential elegance at the business layer, but you've increased the complexity at the UI layer (where complexity is more expensive).

Also, you've got a potential data access issue. You may need to hit the database twice to load an object - once for the employee stuff, once for the person stuff.

While you could combine the data access into a single, merged, query, that would result in coupling again. Adding a field to PersonInfo would require alteration to objects and/or queries used to load several other objects - while directly illustrates how coupling creates fragility.

tsaltd replied on Tuesday, September 04, 2007

OK - I'm getting "Mort"-ified .....

I'm obviously holding on to my data-centric focus ... and the value of the elegance / reusability "normalization of 'un-interesting' behavior"

I guess I should just hold my nose and go ahead and maintain multiple versions of the same code.

However ...

I am  thinking that even tho the BO design pattern that I don't want to give up on may have data access functions that get pretty funky .... the data binding issues could be "normalized" by using a wrapper ... something similar to the "facades" that are created for CSLA Web Service interfaces that would (?) and certainly could be a workaround for the databinding issue.

I don't want to beat this to death ... but there is a germ in this thread that makes me think in terms of an MVC pattern / a controller class that feeds a "flat" boundary object for data binding.

I certainly don't want to trade off the benefits of the CSLA data portal architecture to do this ...

Get the picture ?

Have there been discussions / Are there any examples of anything like this ??? 

The picture is getting much clearer .... very informative .. thanks.

Steve

juddaman replied on Tuesday, September 04, 2007

Hey Steve

Glad to see you are getting to grips with the method. Think the "the value of the elegance / reusability "normalization of 'un-interesting' behavior" line sums that up. :-) Though you say:

I guess I should just hold my nose and go ahead and maintain multiple versions of the same code.

Take this as an advantage as you have decoupled your objects so they can change independently.

Implementing the MVC pattern is a lot of work even with plain objects with a few properties with BOs and errors coming back and forth you'd spent a hell of a lot of time writing code that doesn't do anything interesting. Copying and pasting a few properties would be a lot quicker and more maintainable. Properties only exist to aid encapsulation without them youd only be copying a line per data item so don't worry about copying them.

Regards

George


.

juddaman replied on Tuesday, September 04, 2007

Rocky

In the post above you said:

 "if composition becomes combination - at least of properties/fields - then you avoid the performance issues."

Would you mind defining combination for me please? Are we talking about copying and pasting or something fancier maybe, making "dumb" object with all the properties that are shared in or something?

When you talk about collaborating with Assignment this is by association right?

Cheers, George.

RockfordLhotka replied on Tuesday, September 04, 2007

“Combination” is basically copy-paste J  Or better, it is code-gen of properties for both objects. The idea is to create a resulting object with the “shape” (properties) required by the use case.

 

The “dumb” object idea is problematic because you lose interactive data binding.

 

The relationship with Assignment is more collaboration than association. In implementation terms there really is no Assignment – just a bunch of shared methods. But at design time, ProjectResource and ResourceAssignment are collaborating with (or using) Assignment.

 

Rocky

 

 

From: juddaman [mailto:cslanet@lhotka.net]
Sent: Tuesday, September 04, 2007 2:27 PM
To: rocky@lhotka.net
Subject: Re: [CSLA .NET] inherit ? contain ?? behavior-centric ????? - One more time ....

 

Rocky

In the post above you said:

 "if composition becomes combination - at least of properties/fields - then you avoid the performance issues."

Would you mind defining combination for me please? Are we talking about copying and pasting or something fancier maybe, making "dumb" object with all the properties that are shared in or something?

When you talk about collaborating with Assignment this is by association right?

Cheers, George.


juddaman replied on Tuesday, September 04, 2007

Hi,

Thanks for clearing up the use of  “Combination” I can use that in future posts :-) People do get freaked out when "copy and paste is mentioned". lol. Im sure I prob did the first time thou, until I realised the time I would have saved if avoiding subclassing for the sake of properties, I've been there!

[It's interesting how the relationship (or at least naming of the relationship) changes from design to implementation.
Collaboration confused me, as at implementation time this suggest a strong whole-part relationship with X creating and instances of Y. In the Assignment case no Assignment object is ever even created. At anyalsis time the word collaborating seams to make sense though as a word not a implementation concept.] Actually I'm confusing myself.. I think the ambiguity comes from the difference between UMLs and CRCs use of the word Collaboration.At implementation level the "collaboration" doesn't even exist, like you said its just a bunch of helpers.

Regards

George

 

Tom_W replied on Friday, May 29, 2009

Apologies for resurrecting an old post, but I've been struggling with getting my head round behaviour-centric design since I started looking at CSLA and this post has helped immensely.

Rocky, is there anyway you could add a read only 'Learning CSLA Basics' forum section where posts like this could be archived for quick access?  I think it would be a really useful resource for newbies (me) and the more experienced (everyone who helps me here!) alike.

RockfordLhotka replied on Friday, May 29, 2009

What I can do (and just started) is create a list of links to forum posts that are particularly useful

http://www.lhotka.net/cslanet/faq/CslaObjectFaq.ashx

Tom_W replied on Friday, May 29, 2009

Brilliant, thanks Rocky

Copyright (c) Marimer LLC