Object Design Question

Object Design Question

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


Bonio posted on Saturday, July 08, 2006

I have an Inventory object that encapsulates all the behaviours relevant e.g. add stock; calculate average cost etc. Other than a readonly list, users will never directly interact with this object, rather it is used by other objects such as Customer Orders; Stock Adjustment; Stock Take etc.

Question is, should the Inventory Object be a child object or an editable root object. The actions on the Inventory table in the DB will need to be in the same transaction as the calling object (for example when the Customer Order Object records an order, the Inventory object needs to reduce stock).

This has stumped me for the moment Confused [*-)]

Thanks in advance

Bonio

Michael Hildner replied on Saturday, July 08, 2006

Hello Bonio,

Sounds like you want to use the same business object for two different reasons. It might be better to have two business objects - one for the read-only list and another for the editable one.

I had a similar question here http://forums.lhotka.net/forums/thread/1658.aspx . There's some good information in that thread.

Mike

Bonio replied on Saturday, July 08, 2006

Hi Mike

Thanks for the reply.

Thinking about the use case, the Inventory object needs to sometimes take commands from other objects whilst on one occaision at least it needs to be directly accessible (for stock adjustments). Am looking at the Switchable object template and thinking this may be the solution.

Thanks again,

 

Bonio

Michael Hildner replied on Saturday, July 08, 2006

Hello Bonio,

Take a look at that thread. In particular, the first response to my initial question.

"As soon as you say "sometimes I may want to..." you are almost certainly describing a different use case."

I used to think that one database table = one business object. That's not the case. It's perfectly acceptable to have multiple business objects that act on different tables in different ways.

Regards,

Mike

Bonio replied on Saturday, July 08, 2006

Having studied the use case a bit more carefully, the Inventory object will need to be used both in a Child situation (when performing stock actions for Customer Orders etc) and also as an Editable Root Object (for example when a stock adjustment needs to be performed). So, I think an switchable object might be the best solution.

Yours, ever confused...

Bonio

Bonio replied on Sunday, July 09, 2006

A further thought on this question:

In Rocky's book he uses the Assigment class to aide collaboration between two other classes. My issue is this: I have an Inventory class that contains methods etc that need to be accessed by other classes (such as order entry etc). I currently have the Inventory class configured as an editable root object as I need some of this functionality.

Being a noob to all this, my question is can I instantiate a editable root object [ERO] within the context of another ERO? For example, could I instantiate the Inventory class within the Order Entry class, use some of its methods to update average costs, stock levels etc and then re-use the object to support the Goods Receiving class or the Return to Vendor class [transactionally as well]?

Apologies if I am labouring the point, but this is really stressing me at the mo Dog [&]

Thanks in advance

 

Bonio

lukky replied on Sunday, July 09, 2006

Hi Bonio,

I understand your confusion.

In Rocky's book (Expert C# 2005 BO, p. 50), there's a little piece of information that really helped me understand one of the basic proinciples behind CSLA.

Here Rocky describes a Customer class and an Invoice class, and brings up the point that an Invoice might need Customer data. He says that a "naive solution would be to have the Invoice object make use of the Customer object".

The prefered solution is to have the Invoice directly access the customer data.

Hope this helps.

 

Bonio replied on Sunday, July 09, 2006

Thanks for the reply Lukky.

 

Surely though, if I cannot get business objects to co-operate with each other, it will mean having to duplicate the same piece of code across multiple objects e.g. the same logic for calculating average cost will have to be reproduced in 5 or 6 objects - surely this isn't logical?Confused [*-)]

Thanks

 

Bonio

ajj3085 replied on Monday, July 10, 2006

Bonio,

Not at all.  You can have a third, internal class, which the two public classes collaborate with so that they share the same rules.

Tom Cooley replied on Monday, July 10, 2006

Bonio:

Thanks for the reply Lukky.

 

Surely though, if I cannot get business objects to co-operate with each other, it will mean having to duplicate the same piece of code across multiple objects e.g. the same logic for calculating average cost will have to be reproduced in 5 or 6 objects - surely this isn't logical?Confused [*-)]

Thanks

 

Bonio



Bonio,

While I agree with Andy's suggestion, here are a few other options for you to consider.

It sounds like some of the actions you describe might be good candidates for the Command pattern. CSLA provides a CommandBase for this. That would allow static methods to invoke the commands to say, ReduceInventoryOnHand when an order is placed.

Some of your other methods may also be implemented as static for doing things like calculations provided there is not a need for instance data to perform the calculations. This essentially becomes akin to Andy's third class suggestion.

Finally, you questioned whether or not one EditableRoot can instantiate another. Sure, if EditableRoot A has an instance member that is the primary key of EditableRoot B, then creating a method called GetEditableRootB from within Editable Root A (and C and D, etc) is acceptable. This causes a bit more of a dependency between the classes but that dependency is often already there anyway. It just depends on your use cases.

Tom

Bonio replied on Monday, July 10, 2006

Thanks for the info Tom.

I have gone with the CommandBase idea. Basically I need to update the Inventory table from more than one object and it looks like the CommandBase is ideal.

Thanks

Bonio

Tom Cooley replied on Tuesday, July 11, 2006

Bonio

Glad to hear the suggestion may be of help. I suspect though that it is only one piece of the solution. The concept of Inventory in an application such as your is very pervasive and likely to take many forms. Part of normalizing the behavior is to move away from the monolithic single class that models all behaviors of something like Inventory. Generally, an object should have one responsibility (but perhaps many properties and methods to fulfill that responsibility) so you will likely have multiple classes that handle the different responsibilities of managing Inventory. Some will be EditableRoots, others children or lists. The CommandBase derived object(s) can handle some of this as well. Rocky generally warns against using the switchable objects. While there are valid use cases for such an object, the tendancy towards them generally means you are trying to make an object handle too many responsibilities.

Good Luck
Tom

ajj3085 replied on Tuesday, July 11, 2006

I'd have to agree with Tom.  There probably are a few classes which are needed and those classes have as part of their responsibility the updating of inventory.  Hopefully in a few months I'll be able to offer more insight, as I'm going to be building an application which tracks inventory as well.

Tom, nice to see another Vermonter on the forums.

Andy

Bonio replied on Tuesday, July 11, 2006

Hi Tom

Thanks for the advice.

Actually the only behaviour I wanted to put in the CommandBase was the acutal writing to the the
Inventory table - it did not make sense to reproduce the ADO.Net code in every object that needs to write to the Inventory table.

With the CommandBase object, each Editable Object that needs to write to the Inventory can collaborate with it. Due to ongoing changes to the DB structure, this will save me a lot of time.

I am new to OO design and CSLA.Net, but is seems a backward step to have to reproduce the ado.net code for each BO. I am only using the CommandBase object for Inserts/Updates - each BO will read the data themselves.

Am I missing something re the CSLA concept??

Thanks for your help

Bonio

lukky replied on Monday, July 10, 2006

Bonio:

Surely though, if I cannot get business objects to co-operate with each other, it will mean having to duplicate the same piece of code across multiple objects e.g. the same logic for calculating average cost will have to be reproduced in 5 or 6 objects - surely this isn't logical?Confused [*-)]

The whole point is precisely to normalize behavior in such a way that it is implemented only once in your application. In your case, the fact that you need that behavior in 5 or 6 places clearly indicates that you need to normalize it.

Tom and ajj's suggestion are different way to achieve this normalization. Just like Rocky's example (Assignement class), you need to figure out the comon behavior, and pull it out from these classes.

I have myself re-read chapter 6 today, and the more I read about this behavior normalization, the more I like it.

Regards

Bonio replied on Monday, July 10, 2006

I do need to normalize the behaviour - all I wanted to do was to update the Inventory table when a sale or goods receive or adjustment was necessary. I think Tom's solution of using the CommandBase may be ideal for this.

Bonio

Copyright (c) Marimer LLC