Object design question

Object design question

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

Cosmin posted on Monday, November 24, 2008


I've got a sales order that is associated with a customer and an address of that customer.
I tried to design the sales order this way:

In the DP Insert and Update I get the customerid and addressid from the Customer and DeliveryAddress objects. I don't feel this is right as I serialize the RO objects back to the server. On the Customer/Address setters I could copy the IDs to the private fields and mark the ROBs  as NonSerialized.
Also, if I don't expose the CustomerID and AddressID then the databinding doesn't work smoothly as I need to do some bindings manually in code. I also have to make sure the Address for the order comes from customer.Addresses.

How would you design it? Do you expose both IDs and ROBs?

triplea replied on Monday, November 24, 2008

If Customer and DeliveryAddress are ROB (I assume you mean Read Only Business ...) then why do you have setters (in which case these should be BB)? Are you actualy inserting the customer and delivery address when saving your sales order or where these already persisted in your database and you just populated them for display purposes?

Cosmin replied on Monday, November 24, 2008

The setters are there to be able to change the address for example in case you need to. If you have a setter doesn't really mean you can change the value. You can change the Address reference that the Customer holds not the address itself. I use them not for display purposes only but because they give me a good way to model the business.

salesOrder = SalesOrder.NewSalesOrder()
c = Customer.GetCustomer(123)
salesOreder.Customer = c
salesOrder.DeliveryAddress = c.Addresses(0) //actually here I set whatever user choses

later on

salesOrder.DeliveryAddress = salesOrder.Customer.Addresses(1) //or whatever user wants

To be sure I get only selected customer's addresses in my delivery address I have a custom business rule.

Not sure if there is a simpler way. I feel that by following this design I'll have headaches in the UI.

ajj3085 replied on Monday, November 24, 2008

Ya, I think you will have headaches.

What I would do is have a SalesOrderDeliveryAddress class, and use that as the type for DeliveryAddress.  You shouldn't be able to set this property in the UI, it's read only.

You can then implement a method, SetAddress on that type which accepts a CustomerAddress instance, and copies it's values into it's own. 

I've gone down this route, and this seems to be the best solution.

Cosmin replied on Monday, November 24, 2008

SetAddress seems ok. I think I'm going to go that route either.
What do you do inside SetAddress()? Do you store the address object in a field or just grab its id and use that?

ajj3085 replied on Monday, November 24, 2008

It depends on what you're doing.  If you want the address linked, I would copy all the fields (just so the UI can display them) and also the address id of the instance passed to SetAddress.  In my case, we don't want that to be the case so I create a new row in the address table, because I need to keep the address at the time the order was created, not the most current one.

Cosmin replied on Monday, November 24, 2008

ajj thanks for your input. much appreciated.

SonOfPirate replied on Tuesday, November 25, 2008

I have run into this situation many times in cases where customers have multiple addresses that you can select from when entering a Sales Order.  Typical fields are Bill To and Ship To, for instance.

I usually have a separate BO, CustomerAddressList, that contains CustomerAddress objects and is used to display the list of available addresses to select from in the UI.  As you mention, the actual address itself is read-only in this context.  However, my SalesOrder business object has BillTo and ShipTo properties which are of the CustomerAddress type.  This works just great.

Part of the reason for this comes from the realization that a reference to the address is not sufficient when we persist the SalesOrder to the data store.  If the customer's address changes later, is should NOT be reflected in old sales orders.  They MUST reflect the address at the time the order was completed.  As a result, I have structured my business objects to satsify the required UI behavior.

When I persist the SalesOrder object, it writes out the various properties of each CustomerAddress object to the appropriate columns in the database, such as BillToAddress, BillToCity, ShipToState and so on.  Granted this decreases normalization in the db, but given the business case where we need accurate history for our sales order, it is appropriate as each sales order record is now a snapshot of the data at the time the sales order was created/completed.

Now, if the customer's address changes, the original SalesOrder will still reflect the original values when retrieved.

NOTE: I have come across a use case where there is value in updating the address data when the customer's address changes.  This has only been the case when the sales order has yet to be completed and I use the sales order's state to determine what records must be updated.  This is handled when the address changes by retrieving all CustomerOpenSalesOrders (BO) for that customer and resetting the appropriate address property then saving the COSO object.

Hope that helps.


ajj3085 replied on Tuesday, November 25, 2008

Sounds just like what I've implemented, except I keep the address in the address table and simply create a new record tied to the order.  I also have a way to refresh the address on the order, so it has to always keep a link to the original address to copy the data again.  Also... uses wanted to be able to send changes on the order address back to the original contact address... so I have a method to do that as well..

It was a PITA to get it working...but now that it's in place it seems to work pretty well.

Copyright (c) Marimer LLC