Archive for October, 2012

Developers are not to be Trusted

Tuesday, October 30th, 2012

Has anyone noticed that the Developer Edition of Interbase requires a regular restart?  I have a little invoicing program that I use on a daily basis, and the back end is IB.  I have an unlimited user license of an earlier version of IB, but I chose to install the latest version  of the Developer Edition of Interbase so I could evaluate it while working on hcOPF, and my invoicing program which used to be a demo project for hcOPF.

One would think that a Developer Edition of a product would be free of such annoying licensing restrictions because the better experience that a developer has with a product, the more likely they are to recommend it’s use in a production environment.  It’s also harder to develop when you’re constantly re-starting your machine. You don’t see such restrictions with MS SQL Server Express, and it has much better market penetration than Interbase.

One would almost think with the proposed EULA change, and the increased copy protection, that the revenue from Delphi is in decline, but in light of the Interbase re-start restriction, perhaps it’s just EMBT doesn’t trust it’s customers, or doesn’t trust developers in general, and makes it’s customers ‘bear the brunt’ of this distrust.

Apple no longer sells DRM music, and there are various other companies who have stopped using or reduced their anti-piracy efforts because it impeded their existing customers, and the public spoke out against such restrictions (remember the Sony Rootkit debacle?).  I hope EMBT changes their position on this issue soon.  For now, I am going to switch the back end of my invoicing program to SQLExpress.  One of the great things about an ORM is it doesn’t lock you into a a specific vendor’s database, and there are plenty of choices out there for databases these days!

hcOPF ReadOnly Object Attributes

Monday, October 29th, 2012

For those of you looking at upgrading to XE2 for live bindings, or XE3 to get visual live bindings I thought I would mention that hcOPF supports object binding with earlier versions of Delphi (D7 and up).  Not only that, but you’re not reliant on a black box expression engine.  Bindings in hcOPF are written in Delphi and debuggable in Delphi.  In fact, it’s quite easy to write your own mediators to support any non data aware control you want to use and best of all, since hcOPF is open source, you can modify it to suit your own needs, and there are no undocumented ’secrets’.

hcOPF automatically handles ReadOnly attributes ‘out of the box’, by assuming that the domain object is the source of the truth.  That means if an attribute on the domain object is readonly, then the mediator informs the UI control that it should also be readonly.  There are some situations though, where this is not desirable.  For instance, if you want to display some boolean values on a form when a client is selected, but in order to edit the client information, the user needs to go into the client profile form, you don’t want users inadvertently changing client information by clicking on the checkboxes.  In this scenario you can toggle the AutomaticReadOnly property of the mediator (assuming it’s implemented) to False.   AutomaticReadOnly is normally True by default, and means that the mediator will ensure the UI control mirrors the domain object’s ReadOnly attribute, or will behave as if the attribute is ReadOnly if the object itself is marked as ReadOnly.  By changing AutomaticReadOnly to False, you can control the UI control’s ReadOnly behaviour yourself.  In the example given, the checkboxes would be disabled.

I recently added a new ReadOnly field variable to ThcAttribute since I ran into a scenario where I wanted to use AutomaticReadOnly but wanted to make certain object attributes ReadOnly.  Since the ThcAttribute.ReadOnly property is determined by its MetaData, changing it for one attribute in one object instance effectively changed it for that attribute in all object instances.  Adding the ReadOnly field variable and initializing it from the attribute definition (ThcAttributeDef) effectively solved this issue.

Comparing Apples to Oranges? (Apple vs. M$)

Friday, October 26th, 2012

I used an Apple II/IIe in school briefly before I bought my first PC. Since then, I’ve used almost every generation of Windows (skipped Me & Vista).  I’ve also played with numerous Linux distributions, using both Gnome and KDE. A couple years ago I bought my first Mac so I could learn how to write applications for the growing iPhone and Mac platforms.

My experience to date with OS/X is that it is quite stable. I’ve had as many issues with OS/X through about 4 versions as I’ve had with Windows XP and Windows 7 during that time. That’s not to say I haven’t had any issues though. I had some file corruption that caused instability, lockups, and crashes where the Mac says you need to power off the machine. Even Apple’s own iWork software crashed after updating it. I’ve also had problems upgrading my iOS, to the point where I temporarily bricked my iPhone, and lots of errors trying to Sync the iPhone with iTunes requiring a uninstall/reinstall to rectify.

I don’t understand the appeal of Apple’s software compared to Microsoft’s in terms of ease of use. Novice computer users claim it’s easier to use a Mac, but that hasn’t been my experience. Both have their issues, because software is complex, and issues always crop up when deploying into different environments. Apple should have less problems with deployment, since they control their own hardware, but it doesn’t always appear to be the case. Perhaps it’s because Microsoft has been supporting a myriad of devices for a long time, so they’ve figured out better ways to deal with it.

One of the things I dislike most about Apple software is the hidden functionality. In the M$ world, if you Right Click, or use the local menu keyboard key, you get a menu that shows all allowable options. With Apple, this is not so. Sometimes it’s an option click, and sometimes the local menu just doesn’t show the option at all. For instance, Safari, Apple’s flagship browser does not appear to allow for Bookmark folders within a Bookmark folder, since right clicking on a bookmark folder doesn’t provide the ‘New Folder’ option. In fact, to add a Bookmark folder you have to use the menu, and it always adds the new folder at the root level, regardless of the currently selected folder. It turns out that you can drag a bookmark folder into another bookmark folder afterwards. The help doesn’t mention anything about this, but googling showed other Mac users were baffled by this as well. If Apple was so concerned about the user experience, this kind of thing would be corrected.

Another source of annoyance is that check boxes in Reminders do not respond when you click on the label associated with the checkbox. This is standard behaviour in the Windows world, and even on Linux IIRC. Popup windows also tend to appear and block the underlying window. The window isn’t moveable, so you cannot view the context of the issue if the popup doesn’t display enough information. I constantly have this issue when spell checking in Thunderbird. Often OS/X windows don’t provide a UI hint that the window can be moved. In Windows, the mouse cursor will change or it’s known that a window with a title bar is moveable by dragging the title bar.

I’m sure with some additional time spent learning OS/X specific conventions I will come to appreciate it more, but right now, I’m of the opinion that since Windows 7 shipped that the Apple vs. Microsoft OS wars are pretty much a stalemate, and the applications they run are comparable.

hcOPF - using Attribute OnChange Events

Monday, October 22nd, 2012

Althought hcOPF implements automatic calculations via a ThcCalcObject registered with the object metadata, it’s not the most efficient implementation.  Since the framework has no idea of the attribute dependancies in the calculation, it calls the CalcObject whenever an attribute of the object changes.  Of course it avoids doing so, during mass object attribute changes, such as when initializing the object, or reading it from the objectstore.  Nevertheless, you may encounter situations in which you want to optimize the calculation, such as when you make a database call.

Just like a TField object, a ThcAttribute implements an OnChange event that can be used implement calculations.  This is a much more efficient mechanism, but unfortunately does not benefit from the framework’s knowledge about the calculation, and cannot therefore automatically avoid triggering the calculation event during object reads or other mass object changes, such as object initialization or resetting object attributes after writing them to the objectstore.  It also suffers from the disadvantage that the code for multiple calculations is spread out across different event handlers instead of being in one place.  That said, any good framework does not box you in, so hcOPF allows you to use either method.

If you use the ThcAttribute event to perform the calculation, make sure to subscribe to the event early enough in the lifecycle of the object in an overridden method.  For instance, subscribing to the event for each object processed in the ThcObjectList.Load() method may be sufficient for most cases, but if you create individual objects for consumption, you should subscribe to the event in the ThcObject.Initialize method instead (recommended).  Also, be sure to check objectstate before performing the calculation.  Avoid trying to access attributes while they’re being initialized, or populated.  IOW, make sure the ObjectState = osNone and remember to fire the event in any ThcObject.Read() or ThcObject.ReadAttribute() override.

For example here is a possible event handler:

procedure TMyself.HairColorChanged(Sender :TObject);
begin
  if (ObjectState = osNone) then
  begin
    FQuery.SQL.Text := Format('select HairColor from fnRandomHairColor(%d)',
            [GetTickCount()]);
    FQuery.Open;
    try
      HairColor.Assign(FQuery.Fields[0]);
    finally
      FQuery.Close;
    end;
  end;
end;

and in the Read() override:

procedure TMyself.Read(Source :ThcObjectStore; WithChildren :boolean = True);
begin
  inherited Read(Source,WithChildren);
  HairColor.OnChange.FireEvent(HairColor);  //Sender should always be the attribute
end;

Falling through the Cracks

Tuesday, October 16th, 2012

After my last post I was asked by a prominent EMBT team member why I titled the post the way I did.  I responded right away, and got a courteous “thanks for the feedback” response that also posed some additional questions.  I responded and asked a very specific and some general questions to which I have not received any reply.  That was on October 2nd.  I pinged the EMBT representative one week later on the 9th with a friendly reminder that I was waiting for a reply.  I am still waiting for a response to both my original email and the ping.

I know we’re all busy, and sometimes things fall through the cracks.  I have personally been guilty of not responding to an email because I flagged it as a todo item, and never got back to it.  That said, when I receive a follow up request, I make sure to jump on it right away and apologize for not responding sooner.  No one likes to be ignored…it doesn’t make them feel like a valued customer.  To add insult to injury, it makes people feel used when they respond to your questions, but you do not reciprocate.  The Dale Carnegie program is based on the premise that people will generally respond in kind.  I was told when I took the course that it doesn’t work with everyone, and if it doesn’t work, there is really nothing you can do about it…you just have to write it off as a lost cause.

I am the proud father of two daughters.  I teach my children that when asked a question they are to respond to the question, and that it’s not acceptible to answer a question with a question.  If they don’t respond, they are being rude and disrespectful to the person that posed the question, essentially saying to them “I got what I wanted and that’s all that matters…it’s not worth my time to respond to you”.  To say that you listen to your customers, and then ignore them is hypocrosy, something I will not accept in my life on a personal level, and try to avoid on a professional level.

I’m not sure whether the EMBT rep’s email is malfunctioning, or they have been swamped creating 31 days of XE3 videos and travelling.  I do know that this isn’t the first time I asked an EMBT rep questions, and never got a response.  Mike Rozlog said he would get answers for me about specific questions I asked during the XE2 World Tour.  I pinged him months later and never got a response.  Shortly afterwards, he left EMBT.  Is it corporate culture?  Avoidance of tougher issues?  Poor email management or ineffective delegation,  that gives a negative perception?  I’ll let you be the judge….

These are not the errors you are looking for….

Thursday, October 11th, 2012

Recently the DBA made some database changes in my current project and we started seeing a new error in the Eurekalog reports from my Delphi front-end.  The interesting thing is that the error message was actually a warning message from SQL Server 2008 R2.  The message is ‘Warning : null value was eliminated by an aggregate or other SET operation’.  The DBA had found from previous experience that ADO doesn’t always report the actual error, but a preceding message output to the console in a stored proc.

We decided to write a test stored proc and call it from Delphi, confirming his past experience.  I modfied my code to look through the ADO Error collection, and found the source of the exception.  As a result, I have modified hcOPF to provide access to the error collection via the new Errors function on the IhcStoredProc interface.  I have populated this TStringList in the event of an error with the ADO error collection messages.  The original Exception is re-raised, but now you can catch it, and access the actual source of the exception.  I have also stubbed out the DBX implementation.

An additional note about ADO; due to a sporadic bug we encountered with ADO I use the AddParameter method to create and populate stored procedure parameters through hcOPF.  The parameters must be created in the same order as they are defined in the stored procedure since ADO seems to ignore the parameter name when populating the proc parameters.  Using the stored procedure Refresh method followed by SetParamValue calls resulted in sporadic “Parameter @XXX not found” errors.  This appears to be a known issue with ADO that you can read about here.  Since making this change we have not had a single such error report.

Whats new in FM2/XE3

Tuesday, October 2nd, 2012

Unfortunately, I wasn’t able to attend the XE3 World Tour because of family committments.  As a result, I have registered to attend David I’s Lunch and Learn webinar in order to validate my decision that XE3 holds insufficient improvements to recommend an upgrade purchase.  I wonder what David I is serving up for lunch….

I also thought I would visit the What’s New in FM2 web page to investigate items I might want to ask questions about.  The first one that comes to mind is, “Why is Interbase XE3 included in whats new in FM2?”  Surely EMBT knows about programming rules such as the separation of concerns….so why is the Data Access Layer part of whats new in the Presentation or User Interface Layer?

Also, why is it FM2? I would interpret that as not version 2 of FireMonkey which incidentally uses the FMX namespace (great idea using consistent nomenclature), but FM squared! I am really looking forward to seeing the exponential improvements in FireMonkey ;)  I must have missed them when I read through the XE3 feature matrix….