Design suggestions

Design suggestions

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


ajj3085 posted on Tuesday, August 28, 2007

Hi,

Finally my users have begun testing my quoting module in their sales application, and I'm getting lots of good feedback.

One wishitem in particular is this:  my application allows multiple price lists, and when product line items are added they must all be of the same price list.  Changing the price list used for the quote will currently clear the line items.  The obvious functionality they want is to have the line items update with the prices from the newly selected list.

I'm trying to think of a good, clean way to do this.  Currently I have different line items, some of which have prices, some of which do not.  The changing of a price list will only affect some of the line item types.  I'm struggling trying to figure out where to put this funcationality.

Should it be the responsibility of the line item to get its own price from the database?  Is it another objects  responsibility?  My current thinking is to add a method to the line item types affected so that they can reload their own prices, but I'm not sure if this violates SRP. 

Any thoughts?

Thanks
Andy

RockfordLhotka replied on Tuesday, August 28, 2007

If I understand, the Quote knows that there's a new PriceList. I'd suggest first that the Quote provide this new PriceList to the LineItems collection, which in turn provides it to each LineItem - as a notification basically.

Then I'd suggest that there's a PriceCalculator object (logically anyway) that accepts a LineItem and PriceList, and which recalculates the price (if appropriate). That way your LineItem-type checking goes there, as does any calculations. The result is a new price.

If data access is required during that process, it would be encapsulated in PriceCalculator, which might use a command object or RO object to get the new price.

This way LineItem stays simple, but is responsible for triggering the generation of a possible new price.

stefan replied on Wednesday, August 29, 2007

Two things that come to my mind when reading this:
I would then try to minimize database-access by retrieving all the prices that are needed for the entire LineItems collection at once. Maybe there is something called a QuotePriceManager that would  retrieve and temporarily store the required prices. The PriceCalculator would use the prices provided by the QuotePriceManager.
Maybe this sounds a bit complicated (Thinking as I type...) - then think of a PriceCalculator object that accepts  a whole LineItems collection instead and a PriceList and does the work for the entire quote.
I think this is it.

The second thing was to keep in mind the undo mechanism:
Undoing the PriceList change in the quote must also trigger the undo for the prices in the LineItems collection. So, assuming the PriceList change in the Quote is happening inside a public property, the PriceCalculator object would also have to call the public price-setter-property of each LineItem.
But that's basic anyway...

Hope this is of some help

Stefan

ajj3085 replied on Wednesday, August 29, 2007

Thank you both for your responses.  This sounds like the best way to go.

Things are somewhat simplier because there's no calculations necessary, just need to replace the current unit price with a new one.  Also I do cache price lists in memory, so I can simply use that and not really worry about data access (and if data is required, another class can get all the info I need).

I'll get on this right away.

Bowman74 replied on Wednesday, August 29, 2007

When dealing with a process that spans multiple disparate business objects like this, my first worry is always coupling.  What I would usually do in this situation is create a process object (ChangeQuotePricelist or something like that) that handles changing the price list on a quote.  This object now serves as a mediator for this special business process, it handles the interaction between the separate quote/line item and price list/price object hierarchies.  If you need a process that updates multiple objects and saves them, then I inherit from CommandBase so I can ensure that they happen within the same transaction.

Personally I would avoid having the quote/line items fetching and using the price list/price objects directly.  It will work but if you put this type of coupling everywhere in your app, as it grows and changes you are going to have a tougher time maintaining it.  Don't get me wrong, coupling needs to happen somewhere.  But the mediator pattern was created to make the pain of it as low as possible.  Personally I use process objects quite a bit for this exact reason and have been very happy for doing so.

Thanks,

Kevin

Copyright (c) Marimer LLC