Someone explain the reason for multiple BO's for the same entity to me.

Someone explain the reason for multiple BO's for the same entity to me.

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


Telarian posted on Wednesday, October 17, 2007

This is the big point upon which I think I get confused when it comes to "behavior centric" thinking and design. Correct me if I'm wrong, the impression I've been getting from the forum on this subject, is that I should basically create multiple BO's to represent the same conceptual entity, based on the context in which I'm using it. So in other words, I should have one BO for "employee" if I'm using it in the context of maintaining the employee's information. Another BO for "employee" if I'm using it in the context of assigning that employee to say an "order". Yet another BO for "employee" if I'm using it in the context of calculating the employee's commission on a sale. Etc, etc, etc.

Is that accurate? It seems so strange. I know that reuse is not the primary goal. I think I've gotten that drilled home sufficiently. Still it seems like there are so many things that have to be done again and again for each "employee"esque BO that could have been done together if we just used one "employee" BO that was adapted to work in each situation. I suppose that "adapted to work in each situation" bit is the point eh? It all just seems so counter intuitive and counter to what I've been taught. From database to normal discussions of OO concepts where it's the "employee" and "order" objects that are always discussed. Not the "OrderEmployee" object.

Am I getting it? Am I just crazy?


JonM replied on Wednesday, October 17, 2007

The amount of "duplicates" you create really depends on your use cases.  In your example I would create an editable Employee business object that lets me load edit and validate and save a single employee.  Then I would write a read-only Employee list business collection and a read-only Employee business object.  The read-only version would only include the fields that I want to view in the list box or a datagrid when searching or choosing the employee from a list.  The read-only is a light-weight version that loads faster, is read-only, and contains no validation logic (unlike the editable version).  

JoeFallon1 replied on Wednesday, October 17, 2007

I agree with Jon.

I would assign the EmployeeID to an Order not an employee BO.

My ROC might have a contained class of Info objects which are ReadOnly.

I might also have a stand alone ReadOnly Employee object - for displaying Employee data instead of editing it.

I might have an NVL of EmpID and Name too.

But I probaly would have a single Editable Root Employee BO which is used for editing an employee record. And I might tweak it to do special things for a given employee like you suggested. (Maybe I am too data centric too!)

Joe

 

Brad replied on Wednesday, October 17, 2007

Telarian:

Am I getting it? Am I just crazy? ... It all just seems so counter intuitive and counter to what I've been taught.


I struggled with this point for months when I began using CSLA. We’ve been drilled for years to promote re-use. This concept, unfortunately, comes at the cost of coupling. We tend to have an object and just “add some small responsibility here” and then “add something small there” – we end up with objects that tightly coupled and unmaintainable. Rocky’s framework encourages us to design our business objects in a way that clearly separates object responsibilities.

Telarian:

This is the big point upon which I think I get confused when it comes to "behavior centric" thinking and design. Correct me if I'm wrong, the impression I've been getting from the forum on this subject, is that I should basically create multiple BO's to represent the same conceptual entity, based on the context in which I'm using it.


You are correct in your deductions. In theory, you could have n business objects which access data from table A. n is a scary number, because I immediately think unlimited. However, I’ve found in practice that usually you will have no more than 3 or 4 business objects that access table A. I’ve found that you start reusing objects based on behaviour, rather than data – and this has helped tremendously in my application designs. With code generation, even this amount of objects can be simple to create and maintain.

That said, this framework isn’t a maintenance silver bullet. It can, however, shift the maintenance burden to a more explicit area. And that to me is a Good Thing™.

I’m not sure at what time everything “clicked” for me, but now I’m finally at peace with the idea of creating multiple objects which are based from the one database entity. I continually look for areas where reuse of behaviour is appropriate. I also look for refactoring opportunities for objects which retrieve their data from the same table – if there are common methods between business objects, get them out into either static methods or base classes.

Good luck – I found this issue to be the hardest mental leap while using the framework… and the hardest to explain to co-workers.

ajj3085 replied on Thursday, October 18, 2007

The problem is that each 'adaptation' you create for that one new or changed use case has a very high potential to break ALL the other existing use cases.

This makes doing the change that much more difficult, because instead of testing that one use case, you must now retest them all.  Even after the testing, there may be bugs you missed, and you've broken the application in multiple places.

webjedi replied on Thursday, October 18, 2007

I dunno if this thought helps or hinders...but if you want to make the analogy of BO's to something you are already familiar with, think of BO's like stored procedures...you wouldn't make a single stored procedure for each table with tons of CASE statements to control your logic.  You'd have n stored procedures touching the same tables for different purposes.

Having said that....I've been lurking on these forums and reading the book for a couple weeks now and haven't written a single line of code yet. :-)  I'm just trying to take it all in while I wait for my development environment to be completed.

 

Ryan

 

ajj3085 replied on Thursday, October 18, 2007

Funny you should mention that; I actually worked one place were we did basically that to help keep the number of procs down.  Wow, what a nightmare.

webjedi replied on Thursday, October 18, 2007

ajj3085:
Funny you should mention that; I actually worked one place were we did basically that to help keep the number of procs down.  Wow, what a nightmare.

That's just plain crazy and someone should be punished for that. :-)

 

ajj3085 replied on Thursday, October 18, 2007

Well, the good thing was it was never a shipping product, and the one that thought up the idea was able to figure out that it was a bad idea... but I spent days just writing the procs.. yuck. 

robert_m replied on Thursday, October 18, 2007

It' s not that you have to come up with a new class for every use-case your conceptual entity is involved in. So, you can have a single Employee class that does many different things, nothing wrong with that. It's relations between two or more classes that are sometimes tricky and that may justify introducing additional classes. If you model an invoice, 3 classes will do:  Invoice , InvoiceItem and an InvoiceItemList where Invoice will have a member of type InvoiceItemList. No extra classes here. This is quite simple and straightforward because classes are in simple hierarchical (parent - child) relationship, ie. invoice has items, item is a part of invoice and invoice item doesn't make much sense outside of the context of invoice it belongs to. 

But with your example, (emloyees and orders), we have a two-way relationship. We might want to list all orders for a given employee - which means your Employee class should maintain a list of Order instances. On the other hand, every order has an associated Employee, which implies our Order class should contain an Employee instance. Now we have a circular reference (Employee contains Order and Order contains Employee) which is not good from maintainence point of view - every time you change Order you implicitly change (and  probably break !) Employee and vice versa. One way out of this situation would be to introduce "intermediary" class which will have the sole responsibility of maintaining the relationships between customers and orders - an OrderEmployee class. This class would be quite simple (therefore easy to maintain) and Employee and Order classes are no longer entangled...

 

ajj3085 replied on Thursday, October 18, 2007

robert_m:
But with your example, (emloyees and orders), we have a two-way relationship. We might want to list all orders for a given employee - which means your Employee class should maintain a list of Order instances.


Actually I'm not sure your employee class would maintain such a list.  I think your Orders factory would take an employee id or Employee object which it would use to fetch such a list.  You might have a GetOrders method on your employee class... but it would just call the Orders factory method I just mentioned.  The Orders list itself would likely be readonly, as would the orders it contained.

robert_m:
On the other hand, every order has an associated Employee, which implies our Order class should contain an Employee instance. Now we have a circular reference (Employee contains Order and Order contains Employee) which is not good from maintainence point of view - every time you change Order you implicitly change (and  probably break !)


Not at all.  Your order would have an employee id property, which it would use to link back to the employee.  But it would NOT have an Employee editable class as a property.  At most, it'd have a readonly Employee object, which it would use ONLY to get the id from so that the order could save itself.

robert_m:
One way out of this situation would be to introduce "intermediary" class which will have the sole responsibility of maintaining the relationships between customers and orders - an OrderEmployee class. This class would be quite simple (therefore easy to maintain) and Employee and Order classes are no longer entangled...


I don't think you'd need a class to maintain the relationships between the two, unless you have a use case which you're changing the orders that belong to employees in some kind of batch setting.

robert_m replied on Friday, October 19, 2007

Well, I agreee with you - what you suggest will work in most situations, but it all depends on the requirements of the app you're building. Maybe employees / orders pair is not the best example, but sometimes you do bump into a situation where you have mutually dependent classes. And when you do, it usually is better to introduce another class to handle the relationship - easier to maintain.

There's a sample of something similar in ProjectTracker CSLA sample application (ProjectResource class that handles relationship between Project and Resource classes)

Anyway, the point I was trying to make is that introducing another class into your business model doesn't always increase the complexity of your code, but on the contrary it can sometimes make it simpler to handle and maintain...

ajj3085 replied on Friday, October 19, 2007

Right, it always depends.  I guess the point you were trying to make got lost as I got too caught up in the details.  Sorry.  Smile [:)]

Telarian replied on Friday, October 19, 2007

It seems a lot easier to use simple ID's in some of these objects rather than an instance of an object but isn't that breaking encapsulation?

Copyright (c) Marimer LLC