Others and I have noticed that biz apps spend an annoying amount of code simply shuffling attributes back and forth between forms, databases, reports, etc. It is a violation of OnceAndOnlyOnce. Possible suggestions to reduce this include the use of a DataDictionary, CrudFieldObjects, and better schema reflection (dynamic transparency of schema info).
Does anyone else have suggestions? (If not, then feel free to DeleteWhenCooked after a few months.)
-- top
Languages with reflection and dynamic features provide a way out of this. In the .NET environment, for instance, "data binding" connects UI controls to field values stored in data set objects. No more shuffling - once the bindings are declared, the shuffling is done automatically when triggered by events. Using reflection, the necessary binding declarations can even be set up automatically, either in a code-generation step or dynamically at run time. Systems like Ruby on Rails use similar approaches. This is only the barest sketch of how this works; these systems are fairly complex to build and to understand, but easy to use, and I have only a passing familiarity with them so far.
-- DanMuller
One sticky point is that looping over a list of field objects or dictionary rows is often not sufficient. Often there is not a one-to-one mapping, but rather the EightyTwentyRule kicks in, such that ways must be devised to intercept and custom map the oddballs. For example, the screen may have a separate Date and Time field, but it is stored together as one column using a "date-time" column type available in some RDBMS. Thus, it seems almost easier just to copy-and-paste the lists and locally modify them rather than devise some screwy system to turn on and off various oddball exception sets or views or hybrids as needed. So far, it is not a perfected technique, so we opt for duplication instead.
I lean toward sets, but set-management GUI's are hard to build with some tools and newbies don't relate to sets very well in my experience, preferring drag-and-copy duplication, bringing us back to ugly duplication-land.
I have tried the idea of taking a DataDictionary, copying it for local needs, and then changing it for local/task-specific needs, but was not satisfied with the results. For one, you don't know if a change to the master will somehow screw up the local rework process. It is similar to the "fragile parent" problem of OO inheritance (see DeltaIsolation). I think it is just LifeIsaBigMessyGraph showing its ugly head.
But I have not entirely given up on set-theory and DataDictionary-based (DD) approaches to manage deviants. One thing that kind of works is to create alternative entries (DD rows) for the exceptions. For example, if the data-time column above needs different variations per task, then simply create different variations in the DD. Maybe use a single-letter code to switch on the needed set. Each DD row can belong to multiple letters (many-to-many tables for set management prove too bulky). Then using a little API, request the data dictionary to exclude and/or include only those with a given letter. One may have "dummy columns" that do not map directly to the database, but are filled in manually as needed using code to calculate them. The reverse may be needed upon saving, such as splitting a single screen field into multiple DB fields, or visa versa.
Another sticky point is column order. Different screens or reports may want a different order for the same fields. Either we create many-to-many tables with different orderings, or create multiple columns in the DD for different sorting sequences. Fortunately there are rarely more than 2.
Yet another technique to explore is to just use the DD for the "clean" fields, those without deviations. Deviations are handled locally as needed by coding them from scratch. However, one must still specify which DD column is being referenced, and thus we are duplicating parts of the list all over again. You can't just iterate over the DD in a simple fashion because you have to manage where to "escape" to insert or remove the deviants.
Perhaps if an IDE was designed to view, filter, and manage such deviant-filled DD's, it would be more practical.
-- top
Modern languages are weak in this area. No language supports compiler-time linked enums, but they all should. You should link a GUI control (or section of a control like a grid column) to a dataset/datatable to an enum etc. So that you can pass Employee.Address around and use intellisense and have everything enumerated. If you then go to the GUI and add a column to your grid, it should behind the scenes add it to your enum/dataset and vice versa and enforce compiler checks. How much code is wasted casting/converting/enumerating/validating columns? All of them are simply linked tuples. You should be able to enforce that database col names = gui col names = enum value names without any code.
One has to be careful. Sometimes a UI behavior that is fine in one context is not in another. A one-size-fits all UI behavior can be problematic. A slider may be fine on a form, but not in a data-entry grid, for example. One needs an easy way to override the default per situation if/when needed. Again, the EightyTwentyRule is rampant in biz apps (unless you can convince the boss that the software tool offers no choice, which is an ugly situation.) Further, it should be possible to divorce ("un-bind") a field/widget from a DB if/when needed without much trouble. Thus, I don't like overemphasis on DB binding. --top
I also often hear that all these layers converting db table data to some "business object" graph and then further convert it to some "front end bean" should be unnecessary and just creates work without giving anything in return. Those people propose to use only one data model throughout and let some OR-mapping and frontend framework "do the work". But I think that this is seeing only the 80 of the EightyTwentyRule cited above.
If you have a simple (really simple) business and can force the DB schema to match your frontend, then and only then this may be the most efficient way. But the EssentialComplexity of any larger business will quickly force you to handle the odd-balls mentioned above. And one single special field in every second screen or some extra layer of indirection here or there will quickly lead to extraordinary hoops to either patch your framework and add lots of annotations or configuration to map this or twist your data model such that it no longer a useful data model.
The trick is not to avoid the conversion from db to object to frontend but instead to use it for good and make it as smooth as possible e.g. by introducing automatisms for converting the 80% or by adding a DSL for it or by allowing to skip the conversion in trivial cases (but don't forget to refactor them when the time comes).