FMX anti-pattern: returning nil rather than raising an exception on an invalid state or arguments

In the Delphi RTL and VCL, a method called LoadFromFile or the like will raise an exception if the file doesn’t exist or is invalid. Similarly, if an object property getter implements a lazy-loading pattern (meaning, the value of the property will only be initialised when first needed), it will raise an exception if the situation is such that nothing valid can be loaded or initialised. This is pretty basic exception programming – when an error arises, the flow of the calling code is forcibly interupted with a clear account of what call was invalid. Imagine if (say) TBitmap.LoadFromFile didn’t raise an exception when the file name passed to it didn’t refer to a valid bitmap file – calling code could go happily on its way assuming a graphic has been loaded when it hasn’t. Likewise, what if the Items property getter for TList<T> just returned nil (or equivalent) with an out of bounds index? If T is a class type, then off-by-one errors in the calling code will end up with cryptic access violations later on that might be nowhere near where the erroneous call was actually made!

Alas, but such basic understanding of exception programming is not grasped by at least one developer on the FMX team. Repeatedly across the XE2, XE3 and now (I learn) XE4 releases, methods that an experienced Delphi programmer would expect to raise an exception when nothing valid can be returned do not. As soon as one case is fixed – e.g., the TFmxObject.Children property getter was done so in XE3, albeit implicitly – another one or two are added, and frankly, it needs to stop now. The latest cases I learn are the HScrollBar and VScrollBar property getters on TScrollBox – done properly in XE3, the anti-pattern has however been introduced in XE4, causing ‘random’ access violations in TMemo (the FMX TMemo inherits from TScrollBox).

Delphi XE4 pricing

It’s not exactly a ‘leak’ given it comes from an official promo video, albeit in Russian, but anyhow, the US pricing for Delphi XE4 has come out:

Screen Shot 2013-04-18 at 22.00.44

See here (for some reason, the video couldn’t show on Firefox, my usual browser, but it ran fine in Safari). In a nutshell, the XE4 upgrade will be a ‘nominal’ $49 for XE3 Professional edition owners uninterested in iOS support, or $499 if they are. In contrast, the upgrade cost from XE3 for Enterprise and above will be a flat $499. Slightly disappointingly (well, in my view at least), nothing clever has been done with the Starter edition – that remains Win32 only.

Does $499 (I shan’t guess the exchange rate for outside the US) fulfil the promise of iOS support being a ‘low cost add-on’ for XE3 Professional owners? Probably not, and while I’d prefer it lower, I’m not sure it’s particularly expensive for the market either:

  • RemObjects are currently running a ‘limited offer’ promotion for getting Oxygene for Windows, OS X, iOS and Android for $499. While this is more platforms than Delphi, at least for now, you’re only getting a vaguely Delphi-like language – ignoring the lack of a shared visual component library (which RemObjects are no doubt quite sincere in dismissing the very idea of), there’s no shared RTL either, at least at the level of Delphi’s, let alone .NET’s.
  • Xamarin sell their eponymous Mono-based tools for $299 per platform for ‘indie’ developers, and $999 per platform per seat for ‘business’ customers. Since only the ‘business’ (or beyond that, ‘enterprise’) edition comes with Visual Studio integration, if you want that, you’re looking at $2,697.30 (!) for all supported platforms (this includes a multiplatform discount). On the other hand, unlike Oxygene, you are buying a commercial licence for not just a language (C# in Xamarin’s case – and a very fine language it is too), but an extensive RTL (i.e., their implementation of the .NET BCL) and a dedicated IDE, which Xamarin ships alongside (or in the case of the ‘indie’ edition, instead of) its VS integration.

Of course, beyond pricing, there is the quality issue to consider too. Put briefly, it’s all very well promising the moon, but if you end up delivering a trip to a boggy field instead, the original promise will backfire. Time will tell…

[PS - I'd forgotten about Software Assurance when I wrote this post (silly!). I've no idea how that will be handled. Pure speculation, but maybe XE3 Professional users on SA will get iOS support, but with higher renewal charges kicking in if they want to keep it for later releases...?]

[PPS - Joylon Smith has posted further comments on his blog (link). As there's no point in fragmenting the discussion, please feel free to comment there, or the thread I started on Embarcadero's Delphi Non-Technical forum (link), rather than here.]

Review: Getting Started with Lazarus IDE by Roderick Person

Recently I came across a new Lazarus book, Getting Started with Lazarus IDE, by Roderick Person (that’s not a typo by the way – there is no definite article in the title). This is a small book (only a hundred pages) put out by Packt, a small publisher with a growing catalogue. While you can purchase just the ebook, I bought the printed/ebook package from the Packt website, which still only cost £15.

The book is presented as being for Delphi programmers interested in Lazarus in the first instance, and any other developers used to RAD environments in the second. As such, it begins by walking through how to install Lazarus on Linux, Windows, OS X and FreeBSD. Following this, the next thirty-five pages or so (up until half way) are taken up by a quick tour of the IDE itself, brief descriptions of the core components of the Lazarus Component Library (LCL), discussions of how to create ‘hello world’ console and GUI applications, an overview of the Lazarus debugger, and an introduction to the IDE’s rename refactoring.

While nicely written, I found this section a little uneven – words are spent on introducing the Object Inspector, for instance, when this is something that works identically to the Delphi version. Conversely, the Project Inspector – Lazarus’s substitute for what on the face of it is Delphi’s rather more fully featured Project Manager – is not mentioned at all, despite actually appearing in a screenshot.

As an aside, while this is no reflection on the author, I did find Person’s description of how to create a Lazarus console application remarkable given how much code was needed simply to output ‘Hello World’. While good ol’

program HelloWorld;

begin
  WriteLn('Hello world');
end.

is still possible, the IDE defaults to bringing in a rather overwrought console application framework. This leads Person having to devote six pages to walking though how to write a console-based ‘Hello World’ followed by less than two for the GUI version!

Once the book gets to half way, chapter 4 tackles the topic of how to convert a Delphi/VCL application to Lazarus and the LCL. I found this chapter very well pitched, with many useful tips presented. Following it, chapter 5 provides an introduction to Lazarus custom component writing. I confess I came out of this being slightly amazed at how the Lazarus team have managed to keep their photocopiers working even when it comes to core parts of Delphi’s Open Tools API! The final two chapters of the book then provide a valuable overview of the Lazarus Documentation Editor (LazDE), followed by a somewhat less obviously useful account of rebuilding the Lazarus IDE to use the GDK+ widgetset on Windows rather than native Win32 controls.

Overall, I found the book easy to read, and with two very solid chapters (4 and 6). At other times I found it a little inconsistent in its focus however – in particular, while the best chapters were clearly aimed towards the book’s stated primary audience, namely Delphi developers, others seemed to assume very little prior Delphi knowledge. Because of that, parts of the book can cover things that most experienced Delphi developers will know off of the back of their hands. A related issue is that the author doesn’t appear to have used any modern version of Delphi. For example, when first presenting the Lazarus IDE, a comment is made about how similar it looks to the Delphi IDE – which is true, but only if you are using Delphi 7 or earlier. Likewise, mention is made when discusing 64 bit compatibility that the PtrInt/PtrUInt types should be used instead of Integer when you need to typecast from a pointer to an integer or vice versa. While that’s good advice in itself, Person doesn’t seem to be aware that Delphi defines NativeInt/NativeUInt types for the same purpose, and has done so for quite a few versions now.

Nonetheless, this shouldn’t detract from the fact that when the book maintains a clear focus, it presents its material well. Also, while it is small, it is also cheap, so if you’re interested in Lazarus, check it out.

I’m speechless

Back last July, I blogged about terrible example code posted by Stephen Ball, an Embarcadero ‘Product Evangelist’. Ultimately, the critique of Ball’s code was really just a lead-off for pointing out how the same anti-pattern used had appeared prominently in the FMX source too. Happily, XE3 RTM saw most of that removed (though not all of it). However, for reasons I don’t understand, Ball has now proudly turned his blog post into a YouTube video:

Honestly, view it and weep. I expect his defence will be ‘but I’m only illustrating class helpers’, but if so, that would be dubious given he’s already been warned the example makes him look foolish [on his original post, the automated pingback from my blog was accepted, but my actual comment - 'I’ve just posted a critical (but friendly) commentary here' - never got past the moderation queue. His reply implied he still read it though]. Moreover, it’s perfectly possible to demonstrate class helpers without writing rubbish – check out the relevant page on Lachlan Gemmell’s TIndex for examples. (*)

That said, the class helper anti-example wasn’t the first time Ball had put out poor code – if you want something just as bad, check out his ‘white paper’ on packaging a FMX form into a DLL or dylib, which was also something he originally put out in the XE2 timeframe and has now recently re-promoted. The example used in it is an image file picker, which is fair enough, but here’s how he writes his exports:

  function SelectPicture(AFolder : PChar): PChar; cdecl;
  var
    ResultStr : string;
    Temp: PWideChar;
  begin
    ResultStr := '';
    try
      ResultStr := TfrmImages.SelectPicture(AFolder);
    finally
      Result := StrAlloc(Length(ResultStr));
      Temp := Addr(ResultStr[1]);
      StrCopy(Result,Temp);
    end;
  end;

  procedure DisposePicture(SelectPictureResult : PChar); cdecl;
  begin
    StrDispose(SelectPictureResult);
  end;

If that doesn’t embody the mentality of ‘It compiles, so ship it!’, I don’t know what does.

(*) PS – the David Glassborow articles linked to on the TIndex are now found here and here – I’ve posted the corrections to the TIndex blog, so hopefully the links might even be fixed by the time you read this post.

PPS – eh?

Annoying FireMonkey buglet/oversight of the week

My personal FireMonkey buglet/oversight of the week is this: setting a TTextControl descendant’s Text property inside its constructor doesn’t do anything. For those who don’t know, TTextControl is the base class for things like TLabel, TListBoxItem and TExpander in FMX. Create custom descendants of these, then, and the following sort of code will not work:

type
  TMyExpander = class(TExpander)
  public
    constructor Create(const AOwner: TComponent;
      const AText: string); reintroduce;
  end;

constructor TMyExpander.Create(const AOwner: TComponent;
   const AText: string);
begin
  inherited Create(AOwner);
  Text := AText;
end;

The reason is quite simple: TTextControl sets a flag in Create that prevents changes to the Text property doing anything until that flag is reset in an override of AfterConstruction. In true ‘FM squared’ fashion, the code is nevertheless convoluted enough to give you RSI from having to press F7 so much in trying to track this down. Argh!!!!