Managing Data Change In Custom Objects

Okay, I have been putting this off for some time, but I am jumping in with both feet. I recently posted a question on NJMSDeV message board regarding proper OO design. Needless to say, the response although credible is not necessarily what I was looking for.

Let's say we create a class called Customer. We make the class smart enough to hydrate itself via the constructor which is declared as "Friend". We have another class called CustomerRoot where communication to the Data Access Layer(DAL), the Customer Object and the outside world is all managed. It is basically your driver for your line of business. Public methods in CustomerRoot provide access from the outside world but only CustomerRoot can create a new instance of the Customer Object.

For this discussion, let's say the UI calls a public method in CustomerRoot to obtain Customer data. CustomerRoot will get the data from the database via the DAL. The DAL will return a DataSet. CustomerRoot then instantiates the object passing in the data. The object hydrates itself with the data and the object is returned to the UI by CustomerRoot.

So the question I had posed was this... Is it proper OO design to track if something has changed in the Customer object via a private variable (i.e. "Dirty as Boolean") within the object? Or should it be up to the outside world to know that the content of Customer has changed and call the "Insert", "Update", "Delete" routines of CustomerRoot to manage the changes?

If Customer is to handle it's own change routine, what should the mechanism for determining the kind of change that occurred look like? Instead of a flag (Dirty) should there be a field containing an Enumerated Type?

Public Enum ChangeType
None
Insert
Update
Delete
End Enum

Let's take this one level down. What if we create a CustomerCollection class? Now should there also be a (Dirty) flag in the collection class? This would surely prevent us from unnecessarily iterating through the collection to inspect each object checking it's Dirty flag. However, it is another layer of logic that must be coded in the object. How does the collection class learn that something has changed in the objects it contains? Do the objects fire an event?

The counter argument here and the answer I received from my original post is, use the DataSet object as it does most of what I am trying to do. So why do I resist this approach? Well as my friend Don pointed out, where do you put the business logic. Sure I can use the DataSet as a data container and have my object clean up the mess after the fact, but why? Isn't one of the most significant benefits of spinning your own objects the ability to control the data and implementation of proper business rules for such data? I prefer prevention over reaction to bad data.

Parting Questions:
Why isn't there a book or posts on the web that speaks about these kinds of issues? Where are the Enterprise development Gurus? Why are the examples in the VS Help geared mainly toward bound UI controls to data objects?

--chaz

Print | posted on Monday, March 28, 2005 11:25 PM

Feedback

# re: Managing Data Change In Custom Objects

Left by Jay Glynn at 3/29/2005 8:56 AM
Gravatar First, the Customer object is responsible for determining of it needs to be updated or not. There are 2 common ways to determine change. The dirty flag is one way. This works if you just need to know something in the object changed and you don't really care which property was changed.
The other way is a little more complex, but has bigger benefits. Create a private struct that is used instead if individual private member vars to back up the properties. When you hydrate the object, you set the values of the struct, the public properties use the struct as the source for their data. When you start editing the object, make a copy of the struct. When the update method is called you can compare the structs and see what is different. The advantage is that if something changes, and then they change it back you can compare the structs and see that they are still the same. Also you can determine exactly what property was changed and only update that column instead of the complete row of data.
As far as the collection class goes, it should never have to worry about any of this. The Customer object should be responsible for adding and modifying and deleting from the database.

# re: Managing Data Change In Custom Objects

Left by Dave Gladfelter at 3/29/2005 11:19 AM
Gravatar I do more systems programming than data access, so take my comments with a grain of salt. It seems to me you have to decide what the "Customer" class is, is it just a convenient collection of fields to hold the data from the dataset? Is it the representation of the customer (both the operations on the customer and the information set that the customer represents) in programming land?

I agree in principle with Jay Glynn's idea of having the ability to discover whether the customer object has changed in a meaningful way if there is a proven need for that optomization. Don't pre-optomize, though, why pay the development and testing cost if you don't need to? Encapsulate the logic of comparing changes by having the customer class expose get/set properties for all its fields, and have one public read-only property "HasChanged" and one public method called "Update" or something that can connect to the database and make any necessary changes. In your first implementation, just use one private field to represent each property and have a private boolean that you set to true if _any_ set method is called. The "HasChanged" property simply returns this private field and the "Update" method does nothing or throws an exception if "HasChanged" is false.

If this doesn't have the performance you need, you can have two private fields for each logical data element of your customer, one representing the original value and one representing the last "Set" done to the corresponding property. You can then change the "HasChanged" property to do a property-by-property comparison to see if anything has changed and your "Update" can only change the fields that have changed.

My main philosophy here is to encapsulate complexities caused by performance considerations and to make _one_ class responsible for understanding the data transformations, retrieval, and updating necessary to keep customer information up-to-date and consistent in programming-land. If designed right, this object can be independently unit-tested and verified for added reliability.

Regards,

Dave Gladfelter

Your comment:





 

Copyright © Chip Lemmon

Design by Bartosz Brzezinski

Design by Phil Haack Based On A Design By Bartosz Brzezinski