I read this blog entry on Domain Driven Design (DDD) that I thought it is both interesting and relevant to the issue I am currently dealing with when it comes to data dependencies. For those not familiar with DDD please see:
The heart of DDD is the fact that the entire system is driven by a model representing the domain, using ubiquitous language (UL) of the domain and not based on a data driven design (which nearly all IT systems adhere to). So, in DDD it is of the utmost importance to deal with data not as a value from a database, but as an object itself. The first step in doing so is building object to access the data. These are known as Data Access Objects (DAO) and they are essentially equivalent to the front end services we are looking at building to abstract DB specifics from our code base. See: http://en.wikipedia.org/wiki/Data_access_object
However, DDD goes one step further. If you simply have an abstraction layer for retrieving data, the data becomes inherently imbedded in the code and code specific dependencies arise. For example, code related to voice quality, a system developed by me for measuring call quality of our home phone customers, may have dependencies around the valid values an R-factor can have (for G.711 20 ms packetized voice the range is 0 - 93). However, what happens when the data source also supports R-factor for the older Sprint service. The range of possible values is different for POTS (0-100). So, these dependencies on the expected value and boundaries of the data become imbedded in the code base.
To mitigate against this, DDD using the notion of 'value objects' or 'data transfer objects (DTO's). See:
http://dddstepbystep.com/wikis/ddd/value-object.aspx, http://en.wikipedia.org/wiki/Data_transfer_object
Now, the interesting thing here is that DTO's are objects, they only provide an interface to access the specific data object and can have methods to provide details of the value within the object.
So for the following pseudo code:
R_factor = fetchRfactorValue(MTA_MAC);
if (R_factor <>
print "Bad quality";
} else if (R_factor <>
print "OK quality";
} else if (R_factor <= 93) {
print "Great quality";
}
You have a service to get R-factor and then place a message according to its values. However, these values are hardcoded and relative to G.711 Packetcable values. Instead in DDD you would have:
R_factor_object = fetchRfactorObject(MTA_MAC);
if (R_factor_object->value <>badQuality) {
print "Bad quality";
} else if (R_factor_object->value <>okQuality) {
print "OK quality";
} else if (R_factor_object->value <>maxValue) {
print "Great quality";
}
In the above code, an object is returned with methods that provide the value, bad quality threshold, ok quality threshold and max threshold. The backend logic set these according to the service VoIP or POTS called. If were were to add another voice product with different R-factor specs, the codebase would not need to be touched.
Interesting and powerful.