Archive for October, 2011

hcOPF Object Bindings

Saturday, October 22nd, 2011

Binding an object graph poses a few challenges.  Namely that an object may have children including lists, and if a parent object is refreshed, the child lists may have a different number of items and each item is a different object instance.

hcOPF uses an MGM pattern supporting design-time bindings.  The core component in this mechanism is the ThcUIObjectBinder.  At design-time the developer populates a collection of ThcUIBindingItems that specify the MediatorClass, and the bound Control.  Additional properties may be specified that are dependant on the class of the mediator, such as the attribute name if the mediator is a ThcAttributeMediator descendant.

At run-time, when the ThcUIObjectBinder has been streamed in from the DFM, it’s Loaded method gets called.  The binder checks that all bindings are correct by calling the Mediator’s IsValid method.  If one or more bindings are invalid, an error message will be displayed and the program terminated.  This prevents scenarios like in typical Delphi apps where a field name changes and nothing shows up in the db-aware controls.  No error is raised, so the developer has no idea that the form is not working as expected unless they happen to notice the absence of display item.

Immediately after the Mediator’s Loaded method, the Initialize method is called.  While this method is not currently used in hcOPF I felt it might be of some valid for initializing controls using values from the database, and that is why it takes a FactoryPool argument.

The Mediator’s Bind method is then called.  This method is used by ThcObjectLists and descendants who bind to their controls using a complex mechanism.  Simple attribute binding is accomplished by pairing the control to the attribute in the mediator which is accomplished by the streaming system, followed by setting the mediator’s Subject and calling Mediator.Bind() which is done by the ThcUIObjectBinder.

Now that I’ve spent a great deal of time on Object Binding, EMB has introduced LiveBindings.  After I get some time to evaluate that technology I might add support to hcOPF for LiveBindings.  Time to listen to the CodeRage presentations…

Shakespeare was Wrong? (Warning May be Offensive)

Friday, October 21st, 2011

What is in a name?  Apparently quite a bit, even for an open source ORM framework.  In a global world it appears Shakespeare’s words no longer ring quite as true.  Perhaps I should have googled hcOPF before now because I might have considered a different name, because hcOPF is already known as something a little different ;-)

I hope it’s my acronym that Delphi Developers think of first…

TcxEdit Validation

Friday, October 21st, 2011

If you assign the Min and Max Value properties of a TcxEdit descendant, the control will call the OnValidate event handler indicating there is no error, but a subsequent attempt to convert the displayvalue into the target datatype and check if the result is within the range specified will result in an exception being raised. If you’re using something like Eurekalog or MadExcept to trap all unhandled exceptions this can be a major pain in the derrier.

There are only two ways I’ve found to deal with this issue:

1) Tell MadExcept or Eurekalog not to process this exception type

2) Do not define the Min and Max values in the control. Instead let the hcOPF validator deal with this, and I populate the OnValidate event with the following code to prevent an earlier exception from being raised (this code is for a cxDateTimeEdit):

if Error then
begin
  MessageDlg('The Date Entered is not Valid!',mtWarning,[mbOk],0);
  DisplayValue := DateTimeToStr(Now);  //reset the display to a valid value
  dtpBirthDate.SetFocus;
  Error := False;  //don't raise an exception since we've handled the error
end;

How Can Rendering a project Uncompilable be ‘As Designed’?

Wednesday, October 19th, 2011

I’m sure everyone out there has found themselves modifying the DPR source at some point to add some conditional logic for a clean shutdown for instance if a user cancels out of a Login form, or to add conditional directives to account for differences in the Delphi compiler or VCL.

This happened to me most recently when upgrading from Delphi 2007 to Delphi 2010.  The unit generated from the WSDL of a Web Service I am calling changed with DXE so I added an {$IFDEF} to control which unit was compiled.  Then I added a new unit to my project, and suddenly, DXE would no longer compile my project.  It seems it re-wrote the uses list, overwriting my {$IFDEF} block and was trying to use the D2007 version of the web service code.  This kind of thing has been a problem for as long as I remember, which is back to D7 at least, so I submitted a bug report hoping this might finally be fixed.  Instead, the ticket (96783) was closed with ‘As Designed’.

I’ll admit, I’m a simple country boy who after living in the city for 20 years is still a bit naive.  I consider Delphi to be a testament to good design and for the most part implementation.  It’s longevity in an ever changing IT world is a testament to this IMHO.  I have a hard time imagining Anders Hejlsberg and the other original team members thinking to themselves that it was okay to wipe out developer written code and make a Delphi project uncompilable.  If this was the only example I could provide it wouldn’t be as concerning, but there is also QC #99381 which at least didn’t get dismissed with ‘As Designed’. Can someone explain this to a naive country boy?