Design comments

Design comments

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


ajj3085 posted on Thursday, July 27, 2006

Hi,

Just want to see what people though..

I have an Order / Quote / Invoice.  The part I'd like some feedback on regards the line items.  Here's what I have.

LineItems : BLB contains LineItem objects
LineItem : BB
SubLineItems : BLB; a line item has a collection of sub items
SubLineItem:  BB, looks like a LineItem, but doesn't have a collection of items.

The user creates LineItems (or SubItems) by selecting a Product, which copies price description and a few other details into the line item.  The reason is that once the user has a line item, they can do whatever they want to it (which I personally find odd, but they say they need that functionality).  Users can 'group' line items (which would created SubLineItem objects based on the LineItems, and creaet a new LineItem to contain the sub items.

I also need LineItem objects which are just notes, so I think I need SmartDouble, SmartInt, etc for 'empty' values.  Finally, I need SubTotal and Discount as a line item; I think these (including Note) would be subclasses of LineItem.  SubTotal addes the total for everything 'above' it and discount only works on SubTotals (so it must always follow a subtotal).

Does this make sense?

Thanks
Andy

vicky_iit replied on Thursday, July 27, 2006

Hi Andy,

If I am correct at understanding the logic, I want to ask: why is Subtotal and Discount sub classes of LineItem? If subtotal "adds the total for everything above it", then this does not mean that "everything above it hierarchically" (or in base class terms). I think Subtotal just needs to know what LineItems in needs to sum up, it should not matter whther these LineItems are its super classes or subs.

I might ve misunderstood yr logic but let me knw yr thgts.

Vivek

ajj3085 replied on Thursday, July 27, 2006

Because they have different behavior than standard line items.  By everything above it, I mean 'everything whose position in the collection is higher.'  One thing I forgot to mention is that LineItems are orderable by the user.  So subtotal and discount apply to those items the user put 'above' them on the grid.

vicky_iit replied on Friday, July 28, 2006

Hi Andy,

What is confusing me is that if SubTotal has diff behaviour than LI, then why not use composition instead of inheritance?

since SubTotal works on LI, why do we need to subclass it? Simple composition works better. Let me know if I make sense.

Thanks

Vivek

ajj3085 replied on Friday, July 28, 2006

Well, the main problem is that the subtotal is a LineItem in and of itself; that is it can be deleted, and it may be adding the prices of more than one line item.  If I'm missing something, let me know, but for it to be a distinct item and an of itself, I think it needs to be a sub class.

Maybe my reasoning is weak, but the grid will only be working with LineItems, not the subclasses, so the ripple effect doesn't come into play.  Of course if I'm wrong about this, please say so!

Thanks
Andy

vicky_iit replied on Friday, July 28, 2006

Andy,

What I think is that inheritance or subclassing should not depend on GUI behaviour but instead should be based on business requirements (during the object model creation phase). It seems like you decided SubTotal to be a sub class of LineItem coz it is "shown as a part of LineItems" graphically. I can sense why you felt like that but I dont think its right. Logically, if I haven't seen the GUI, I would have a tough time comprehending the "inheritance" relationship b/w LI and SubTotal class.

Let SubTotal be a different class which pertains to some business use case which calculates total of LineItems "contained in it" or some other relationship which you can define as you know the logic best.

May be others can also share their thoughts on this.

Thanks

Vivek

ajj3085 replied on Tuesday, August 01, 2006

The more I've been thinking, I don't think that SubTotal should subclass LineItem, but rather implement an ILineItem interface. 

I wasn't thinking that SubTotal 'contain' other line items... just loop over the list and get totals for things sequencially before it.

I hear what you're saying about the UI not influencing the BO design, but at the end of the day, the UI needs to be able to display the objects in the way the user expects, and if the design I come up with can't do that with the UI controls I have, well that's a problem. 

I have the Infragistics grid now (I very much doubt the requirements could be met with the standard DataGridView), so whatever solution I come up with needs to be displayable in that grid.

Thanks for the feedback so far.
Andy

RockfordLhotka replied on Tuesday, August 01, 2006

Another, broader, thing to consider is seperation of UI and business logic.

Your object model should implement the business logic. In many cases it can do this in a way that allows you to build a UI directly on top of the objects.

However, there are cases (it seems quite common actually) where the UI has some display requirement that has nothing really to do with business logic. Sorting, filtering, special ordering of items, etc.

It is my view that these special UI requirements should be handled by objects in the UI layer, which are seperate from the objects in the business layer. In other words, the business layer should do its job, and you should have UI objects that reform the data for display, if that's the requirement.

I haven't read this thread in detail, so I might miss the point, but you have a set of line items, and then you want to display a subtotal line in the middle of them or at the end of them.

Obviously the subtotal itself is a business layer concept, but the business layer merely becomes overly complicated if you try to hold the subtotal objects in the same collection as the actual line items.

So what you might consider, is creating a UI helper collection that merges the line items and subtotal items into a single view.

This is why I am quite excited about LINQ btw. Not because I think LINQ will be so useful inside business objects, but because I think it may provide a really easy way to do this type of reshaping-of-data-for-the-UI.

But today you'd do this by inheriting from BindingList<T> and having your constructor accept the line item list and the subtotal list, and then having your custom collection put them in the right order. This keeps your business layer simple, and gives your UI the view it requires.

ajj3085 replied on Tuesday, August 01, 2006

RockfordLhotka:
So what you might consider, is creating a UI helper collection that merges the line items and subtotal items into a single view.


Hmm, I hadn't thought about that.  It sounds like a good suggestion to investigate.  I'm glad I haven't started implementing anything yet.

ajj3085 replied on Thursday, August 03, 2006

I've thought about it, and wasn't sure I could get the subtotals working in a seperate collection and having a view 'glue' everything together.  It seemed like it would be pretty complex to keep track of things as the line items were moved to different orders.  I ditched the inheritence idea, because it felt like I'd be override the default behavior for everything but the standard simple line item.. so I went to an interface instead.  I've attached the class diagram to this post.. here's my reasoning.  Any feedback would be greatly appreciated! (Its times like this I wish I wasn't the ONLY developer here.. but I'm hoping you guys won't mind helping me out!)

LineItems - will be a child of Order, Quote or Invoice. 

SimpleLineItem - pretty simple; a line item which allows changes to quantity, price, etc.  No changes to description though or part number.

GroupLineItem - a line item which contains other line items.  Its description, part number and quantity are user modifable, but the price is not; instead the price is calculated from its quanitity and the sum of the prices from items within the group.

GroupSubItems - holds the subitems which belong to the GroupLineItem.

GroupSubItem - will function similar to SimpleLineItem, except an additional property ShownOnPO exists.  The reason is that, depending on how the customer submits the PO, items in the group will be shown or hidden (to match the PO).  This field is set by the application user.

BundleLineItem - some products in the database are bundles of other products.  A product bundle has a distinct part number, so the description and part number on these are not editable.  The price of the bundle may be a fixed amount, or the sumation of the parts which make it up (this is set on the product).  Component items are never shown to the customer.

BundleSubItems - Container for the items which make up the bundle.

BundleSubItem - A component of the bundle; price can't be changed here either, nor can product number or description.

NoteLineItem - Part #, price, etc. cannot be entered.  Only the Description can be changed.

SubTotalLineItem - sums the price of all the line items 'above' it in the list.

DiscountLineItem - applies a discount to a subtotal line item.

This captures all the behaviors required by the users; each line item has a different set of goals it must meet.  So, am I way off base here?  Or could this be a good way to proceed?

Thanks
Andy

ajj3085 replied on Tuesday, August 01, 2006

Because subtotal operates on multiple items; if I understand comp. correctly, you'd encapsulate a LineItem as a 'server' type object, and have the sub total item delegate some if its properties or methods to the encapsulated LineItem. 

First, there can be any number of LineItems to be subtotaled.  Second, there is no property or method which I would delegate to the encapsulated line item.  Quanity, description, unit price, ext. price cannot be edited.  There then doesn't seem to be a reason to even keep the reference to the LineItem at that point.

I've not decided to directly inherit line item either, I misspoke there.  Likely, there'd be an interface ILineItem which subtotal would implement, if it really ends up not sharing anything.

Tom Cooley replied on Thursday, July 27, 2006

Andy,

First off, when I hear line items and sub-items, I think of a composite pattern. But if this only ever goes two levels deep, that might be overkill. Maybe if I understood the domain a bit better, it would be easier. Are the sub-items components of an assembly?

Instead of the SmartDouble & SmartInt, you may want to make the Note lines AND the "standard" line items derive from a common base class so the note lines won't even have a price property and such.

So, what happens if a Sub-total line is added as say, line 6? Can another standard line item (or several) be added after that followed by yet another sub-total? Or does the sub-total actually summarize all the standard line items and always appears below them?

ajj3085 replied on Tuesday, August 01, 2006

Tom,

You're sort of on target.  First, yes, there is only ever two levels (also, the DataGrid controls don't like when a collection can contain items which in turn contain that same collection.. they tend to lock up VS when you attempt your databinding.) 

The sub-items may be components of an assembly; or they could simply be a group which the sales person designated.  The functionality they want is to select a bunch of items in the collection, specify they want to 'group' them, at which point they are indented under a new line item which contains them, and the sales person can then type anything in the description. 

I thought about your approach regarding the Note items; the problem though comes back to databinding.  The grid needs to display the price and allow the sales people to update that, so a Note item which doesn't have the appropriate property would break databinding.

Finally, the subtotal can be added at line 6, and then more standard items can be added after that.  There may be several subtotal lines within the order.

To clear things up a bit, they want this portion to work like a program called QuoteWerks (there's a free demo you can download, if you're interested).


Copyright (c) Marimer LLC