When a Date Drives you Nuts

It’s been several years since I used datasets for anything other than quickly displaying the results of a SQL Query or Proc.  Recently I have been reminded why I dislike the TDataSet based RAD development approach so much.

If you’ve ever done a DBX conversion you would know that DBX maps datetime database columns to TSQLTimeStampFields instead of TDateTimeFields.  If your datasets use persistent TFields, which is typically the case so developers can make use of TField events to provide formatting, and validation, then you’re in for a treat!  All the persistent TFields have to be removed so new ones can be generated at design-time using DBX to ensure the right field types are used.  Of course you don’t want to remove any additional TField descendants created at design-time that are not in the dataset, so it might be necessary to go through each one to determine if the TField originates from the underlying dataset (using FieldKind may not be enough).

Once you’ve finished re-mapping all the TFields, you have to re-connect all the event handlers.  Hopefully, the original developers actually centralized all the database related code into datamodules, or you will be going through every form in the entire project.  Even re-connecting all the dataset TField handlers in the datamodules may be a treat if handlers were not shared across TFields of the same type.  For instance, if you use the OnSetText, OnGetText events to provide standard date formatting for TDateTimeFields using edit masks for input with a different format for displaying the date, you have to reconnect numerous handlers to each persistent TField event and the only way to tell if you have it right is GUI testing.  If you don’t get it right you will see errors from TField.SetAsString() with no idea what field is causing the exception.  The easiest way to actually find out is to put a breakpoint on the method, enable Debug DCUs, and generate the error through the UI.

In an application using domain objects with the MGM pattern for presentation, all the TField handlers would be replaced with mediators that perform the translation between the UI presentation layer and the database layer.  If you need to enhance the application to work with a variety of date formats, for instance, instead of locking it down to the corporate standard format which I see most often when using TField events, the enhancement would only involve a change in one place (the mediator).  It’s a much DRYer approach.  While using TField events doesn’t necessitate multiple handlers for the same purpose (one per TField type instance), not many developers think about consolidating such code across the application, and the result is a maintenance nightmare, especially if you ever think about changing the database layer.

Avoid vendor lock-in, even if you’re not thinking about changing your database, consider using an ORM, or even database application layer interfaces such as hcOPF’s IhcQuery and IhcStoredProc so changing your database layer doesn’t result in sleepless nights.  One “proposed” EULA change could have you swapping a database layer in a hurry ;-)

Leave a Reply