Friday, August 11, 2006

Dedicated to Den Mothers Everywhere

In My entry on The Unusual Suspects, I introduced you to the players in our little drama.  In this entry I want to design out loud and provide more detail on the “den mother” class, also known as the Address class.  Let me re-cap the design elements that we are going to use in this particular approach:

  • The Address class which acts as a container for all of the other related classes and also provides any functionality that is related to the address as a whole.
  • A set of Data classes that hold the values of the address lines, city, state, zip code, etc.  We could refer to these as cab value classes for Attribute classes or Column classes.  I’m not happy with any of these names but I like even less using “hey, you” to refer to them.
  • A set of Rule classes that define the rules are applied to the individual values for attributes and to the Address class as a whole.
  • Various collection and control classes that are necessary but are incidental to the main theme of the design approach.

This entry focuses on the Address class.  I will focus on the other objects in later entries.

The Address class is the interface that the client programs see and interact with.  This class has to provide the following functionality:

  • Provide the means to get and set the individual Data values of the address.
  • Keep track of whether the contents of the Address have changed.
  • Initiate validation of the Address.
  • Provide the means to get the error status of each individual Data value within the address.
  • Initiate saving the contents of the Address to a permanent data store.
  • Initiate retrieval of the contents of the Address from a permanent data store.

Getters and Setters.  We have some design choices to make with respect to getting and setting the individual values within the Address.  At one extreme we could provide a façade that mapped methods on the Address class to the underlying Data classes.  The client would access the individual Data values using conventional properties.  At the other extreme we could provide a named collection of these Data classes.  In this case the client would access the individual Data values using a notation somewhat like this:

myAddress.Data(“ZipCode”).AsString = “12345”

In general, as the programmer writing the client code, I would favor the more strongly-typed façade approach.  That does mean that we have to generate a lot of mind-numbing code that passes the requests through to the underlying Data classes.  That might give me pause if I were generating all this code by hand.  Even if I were using zero-cost Chia pets to do the actual coding (the ultimate in labor arbitrage), I still would be concerned by the possibility of errors creeping into the logic.  If I were, on the other hand, using code generation to produce this code, I would be much less concerned.  Since I am a strong advocate of code generation, let’s assume that we’re going to use the façade approach and every attribute will have a strongly typed getter and setter method to support client access to the individual data values.  In all cases I would also add the more generic references to support dynamic construction of web pages and window forms.

The “Dirty” Indicator.  The nature of the problem we are trying to solve dictates that we keep track of whether the data in the address class has changed.  We have to make a choice at this point as to where the logic to keep track of this should reside.  One choice is to place this logic in each of the Data classes.  The advantage of doing this is that each Data class can distinguish between An apparent change and a real change.  For example, a Data class that handled 32–bit integers could easily determine that the following string values are all equivalent: “0”, “00”, and “000”; storing these three values in succession would not represent a change to the underlying data.  Although we track the dirty status on a Data value by Data value basis, what we’re interested in is the overall state of the Address as a whole.  The question is how do we determine the dirty status of the Address as a whole.  We could include logic in the Address class to run through the collection of Data values to determine if any of them were dirty.  All it would take is a single vote to be dirty and the Address as a whole would be dirty.  This is very simple code to write but it does have the potential to disadvantage of burning a lot of cycles each time we have to determine if the Address class is dirty.  We could also allow each of the Data classes to raise an event that would be handled by the Address class to indicate that data had changed.  This is somewhat more complex code but would probably have a slight performance edge over the polling approach above.  Another approach that is similar to the event mechanism is to allow each of the Data classes to be aware of its containing class and to invoke a “make dirty” method on the parent class. 

One other factor to consider is whether or not the “dirtiness” of an individual Data class can ever transition from “dirty” to “clean”; that is, can a Data class become “clean” again if the original value were to be stored back into the Data class.  One approach to the “dirtiness” issue is to store the original value along with the current value.  When the two values differ, the data class is dirty.  When the two values are the same, the data class is clean.  The event driven mechanisms tend to “latch” the dirtiness indicator; once dirty, always dirty.  The polling approach does permit a particular Data class to go from clean to dirty and then back to clean again.

Initiating Validation.  The next question to look at is when to initiate validation.  At one extreme we could initiate validation every time any change was made to the contents of a Data class.  The other extreme would be to only validate upon an explicit request from the client programming.  The choice that we would make in this case depends a lot on how much the client needs immediate feedback.  I have written code as part of a Windows form application (more than once) that validated the contents of a Data class linked to a text box each and every time that the user typed a character into the text box.  This provided immediate feedback to the user and allow the user interface to indicate validity or invalidity through the use of a variety of graphical user-interface elements such as changing the background color of the text box.  This approach can, however, chew up a lot of cycles but if the personal computer is sitting idle, this is probably not that serious a problem. 

All of the analysis that we did with respect to the “Dirty” indicator also apply to validity.  We need to be able to determine the validity of each individual Data class as well as the validity of the overall Address class.  I would approach the interaction between the Address and Data classes in the same manner, although I might not use exactly the same mechanism for both sets of interaction.

Saving and Retrieving.  I do not have a whole lot to say about these two topics in this entry.  I have read a wide variety of different views on whether or not classes should know how to save themselves to the database or whether they should be totally ignorant of the mechanisms of saving and retrieving.  I have done it both ways several times and both work depending upon the specific circumstances of the application.  Right now, I’m of the opinion (although it is not a very strongly held opinion) that the saving and retrieving logic should be largely outside of the domain classes such as address.  This is a very large and involved topic that deserves much more than a single paragraph.


Post a Comment

Links to this post:

Create a Link

<< Home