views:

84

answers:

4

I am working on a new domain model for an application that will have order processing for items built in (well, too keep it simple for this question anyway). I have a class "VendorItem" that represents items that can be ordered. Originally the "Order" class was going to have a list of VendorItems associated with it, but I have come across problems with it so far.

Let's say that the system has been creating orders for some time just fine. One day a user comes along and decides that a vendoritem has changed price or some other detail like packaging size. I wouldn't want the previous orders to be effected by such change.

At first wash I was going to make a "OrderLine" class that is basically a copy of the "VendorItem" class, but that just feels (smells?) wrong in the OO sense.

Is there a better way to refactor this so I don't have copies of classes and information in the domain model?

A: 

Yes, you can use "boilerplates", ok anyway the idea is you have one object Item that represents the "product" of your item, skates or whatever, then you have that object composed of some Pricing object or something, foreach order you get you assign a pricing object, so now when you change a price o r something of the sort you just assign a new price object (with different args) to your Item objects, that way you only have 1 class representing each o ne of your items and you have a price object that defines what price and characteristics that item has (to represent the attributes that could change over time). The boilerplate in this case is the Item because it sort of like a template and it never changes, and you customize is with your Price object (in the examples given)

Daniel
I disagree with this solution because then you would have pricing existing as a stand alone object (and table in you database) where as pricing is only relevant to a product. Also other information can change about a product, title, description, color etc where you update the product item and now have no idea what was prior to the update and can no longer track changes easily. Did the person buy this when the title was "Superfantastical ProductX" or when it was changed to just "ProductX"? See my answer for more detail.
Chris Marisic
A: 

In past, I've created "Variation" classes. A VendorItem contains "Variations" A variation can be a t-shirt size, or flavor of underwear. Each Variation carries it's own price, so that you can make chocolate panties more expensive than strawberry ones. OrderLine class has a reference to the Order, Variation, quantity, and price. You keep price in OrderLine so that you can change the price of the variation later without affecting auditing procedures. Then, instead of editing an existing item, you can just simply add a variation and set the old one as "InActive"

Did I tell too much of the family business?

Darthg8r
A: 

IMO you should this mostly handled by your database. That every product which you call a VendorItem has a PK along with an effective start (null not allowed) and effective end date (possibly null to handle current until discontinued) along with all the related information about the item.

In your order table you should have a CustomerID related to 0 to many order id's with the record containing a foreign key to the VendorItem that was sold at that time.

This way you can track all the changes that have ever been made to your Product Lines, and allow easy analysis of price changes, description changes etc to effects on sales easily.

Inside your code almost nothing would even change except during the ordering/viewing items process you're getting the current item from the products table.

Chris Marisic
The domain model will be persistence ignorant, so it will not be possible to design for the database.
Charlie Brown
Although... I could see this for a much smaller system like online ordering of products.
Charlie Brown
My answer is completely in line with a PI solution. You need to have the relationships between the objects as I've mentioned.
Chris Marisic
+1  A: 

I find it much easier to first describe everything you know about the items as they really exist, and not as classes. Then figure out the information hierarchy, then how to model that with classes.

For example: An item is a product you purchase from one or more Vendors, typically defined by a UPC (Universal Product Code - the registered barcode).

The vendor often has an internal id number for it as well, commonly called a Vendor Item Number (VIN).

An item can come in different sizes and colors, all with the same UPC - but different VINs possibly with different costs:

T-Shirt UPC 9055540022
VIN: 40001 - Large, White - $5.00
VIN: 40002 - Small, White - $4.00
VIN: 40003 - Large, Green - $5.00
etc.

and the costs on those items / VINs will change over time.

An order is a list of items and their cost at a given point in time, so your Order information will need to include the cost and any other changeable information about the items on the order.

So if the item UPC is at the top of your information hierarchy:

Item - 1 record per item - Descriptive info, UPC

Vendor - 1 record per vendor - Vendor info

VendorItemVin - 1 record per Vendor/Item/VIN - Vendor specific info, size/color/cost etc.

Then you can get an idea what the database tables should look like, then work out the classes.

Ron

Ron Savage
This was an informative post but this really didn't answer the OP's question on how to deal with versioning of items. You need to expire the VIN#'s in this case to handle history.
Chris Marisic
Which would then require each Item to have 1 to many VIN#s.
Chris Marisic
The current method we use in an older version now is similar to this, but we still have issues with versions. The problem we have now is users changing the "item" side of the relationship. We could lock this so they can't change it, but that is not a realistic option. Ideally we want a situation where vendor items never change and inventory items never change but we can't have that either.
Charlie Brown
Then you also would be required to have a 1 to many for Item UPCs
Chris Marisic