Friday, September 4, 2009

What happened to version 13?

During the RAD Studio 2010 field test and now out in the Delphi non-tech newsgroups, there had been a lot of discussion, speculation and even some angst about the mysterious lack of version 13. Chill folks. The story is simple with no real conspiracies involved. In fact, the only conspiracy involved was that we knew from the outset that it would spark discussion and conspiracies.

After each product release there is a period of time where the internal developer builds overlap with the released product and the next release. This can cause confusion among the team and phantom errors if a developer build were to ever meet up with a released build. To limit this overlap, we try and bump the version number as early in the next release cycle as possible. The scene went like this:

Rewind to September 24th of 2008. I’m sitting at my desk reading emails, writing emails, surfing the interwebs, waiting for a build to complete, etc… There’s a knock on the door frame of my office (my door is always open). I turn around and Dave Wilhelm is standing there.

“I’m about ready bump the version number.”

“So the next version would be, uh, 13, right?”, I said with a pondering look.

“Yep. And, yes, that’s an interesting number”, Dave said with a wry smirk. A mischievous smile appeared on my face. Dave chuckled. Then he added, “I think we have two choices here. We can defiantly embrace it, or just skip it. What does our release schedule look like next year?”

“Why?”

“If we were to release in October, having a version 13 would be clearly embracing that whole mystique. You know, Halloween, black cats, zombies, ghouls, yadda yadda…”

I chuckled. “That could be a whole sub theme of the release! However, it looks like we’re slated to release about the same time next year. So that won’t work. We should just skip it. I don’t think there is a Friday the 13th around that time either.”

“I’ll ask a few folks on the team if they have any strong opinions one way or another.”

“Yep. Just like many buildings don’t have a floor 13 and go from floor 12 to 14. It will also be a fun trivia question down the road. Besides, I can see the community going into wild, random speculation and conspiracies as to why did they skip 13.”, I said with a slight smirk and a muted chuckle.

“Exactly. I also understand it is mostly a western superstition. It will certainly be fun to watch all the newsgroups get spun up.”

“Well, we live in the west. We are the ones checking in the changes. So I guess we get to decide.”, I commented defiantly.

“Yep. I’ll check with a few folks and get back to you.”, Dave said as he walked off.

About an hour later, there was another knock on my door. Dave was back.

“The comments among the team ranged from, ‘I don’t care one way or another’ to ‘Sure, go ahead and skip 13’”

“Then it’s decided. Bump it to 14, and check it in. Let the wild, random speculation begin. Explaining this conversation in a blog post will also be fun.”

We both let out a slight chortle and then proceeded to get on with our day.

There you have it. It was a largely unilateral decision. Nothing was ever mentioned about it until fairly deep into the field-test cycle and now after the release it seems to have gotten a decent amount of attention. Psych!

Thursday, September 3, 2009

Class Constructors. Popping the hood.

My last post introduced class constructors and destructors, a new language feature in Delphi 2010. I mainly covered what they were and what kinds of things they’re good for. In this post I’ll cover some of how they’re implemented. I’m sure the question on everyone’s mind is when and how they’re invoked? If you were patient enough to read my entire post, I provided a hint as to the inner workings. The rule for when they run is simple:

    • All eligible class constructors and class destructors are invoked in sequence with unit initialization and finalization, respectively.
    • If a given class constructor or destructor is eligible to be invoked (ie. it was linked into your application), it will run immediately before the initialization section for the unit in which the class is implemented. The class destructors will be invoked immediately after the finalization section for the unit in which the class is implemented.
    • Class constructors in a given unit are generally invoked in the same order of declaration, except in cases described below. Class destructors are invoked in reverse order from the class constructors.
    • For an ancestor class declared in the same unit, its class constructor will be invoked before the descendant class constructor and the class destructor is invoked after the descendant class destructor.
    • If the implementation of given class constructor references another class in the same unit with a class constructor, the referenced class’ class constructor will be invoked before the current class’ class constructor. If the references are cyclic (ie. they reference each other in their class constructors), then they are invoked in reverse order of declaration. This means that there can be cases where a class constructor can reference an “unconstructed” class.
    • Ancestor classes from external units used in the interface section are guaranteed to already have their class constructors run prior to any class constructors on descendant classes within the current unit.
    • Unit cycles can break down the deterministic nature of the above rules in the same manner as unit initialization and finalization. However, for a given unit, it is guaranteed that all the class constructors declared within in it will have already run immediately before the initialization section runs. Congruent to this rule is that it is guaranteed that all the class destructors will run immediately after the finalization section.
    • Dynamically loaded packages, using LoadPackage. Because there is no way to know exactly which classes are going to be used, just like there is no way to know which units are going to be used, all class constructors and destructors along with all unit initialization and finalizations are invoked according to the above rules.

Other rules about their use are:

    • You do not have to declare a class destructor if you declare a class constructor, and vice versa.
    • They cannot be virtual, dynamic or message.
    • They cannot be explicitly called.
    • They cannot have any parameters.
    • They do not have to be called Create and Destroy. (ie. Init and Fini are equally valid names).

With this implementation, it was easier to leverage the same table that the compiler creates for unit initialization and finalization. It satisfies this requirement: “Called automatically to initialize the class before the first instance is created or any static members are referenced.” Issues with cycles are also clearly warned against in VB.NET and C#: “Avoid circular references in Shared … since it is generally impossible to determine the order in which classes containing such references are loaded.”

Another benefit is that since it is running during the initialization/finalization phases, any threading implications are no different than the existing rules regarding unit initialization and finalization.

Class (, Static, or Shared) Constructors (and Destructors)

In my last post, I hinted at a new native Delphi language feature, class constructors and destructors. For those familiar with, say, C# or VB.NET, they are called a ‘static’ constructor (C#), or a ‘shared’ constructor (VB.NET). Let’s now take a closer look at them in terms of how they’re useful along with a little hint at how they’re implemented. Class constructors had been available in Delphi Prism, but until Delphi 2010, they were notably absent from native Delphi. The main reason for this was that the .NET runtime controlled and defined when a ‘static’ or ‘shared’ constructor was invoked. In native Delphi there was no defined mechanism to do the same.

From the C# documentation:

Called automatically to initialize the class before the first instance is created or any static members are referenced. The constructor cannot be called directly.

From the VB.NET documentation:

Shared constructors initialize a type's shared variables; they are run after the program begins executing, but before any references to a member of the type. A shared constructor specifies the Shared modifier, unless it is in a standard module in which case the Shared modifier is implied.

Since the .NET runtime is a garbage-collected environment, there are no references or mention of ‘class destructors’. Because native Delphi is is not garbage collected and requires explicit destruction of instances and freeing of memory, it stood to reason that for congruency, native Delphi would also have the notion of a class destructor.

First of all let’s look at the syntax:

type
EDliException = class(Exception)
private
class constructor Create;
class destructor Destroy;
end;


 


Technically, it does not matter where in the class declaration they are declared (private, public, protected, published) since, as the  documentation above states, “The constructor [destructor (added)] cannot be called directly.” So in this example, I just made them private to merely make it more clear in the source that they cannot be called. Just like the other kinds of ‘class’ methods, the body of theses methods can only access other class methods or variables. They also have no implicit “Self”, so you cannot call virtual class methods in a polymorphic manner. You can have one and only one class constructor/destructor per class type. As we’ll see in a moment, you should treat the class constructor/destructor methods in a manner similar to a unit’s initialization/finalization section. That’s it. It’s pretty simple, really.


Now let’s look at why these are useful. There were several main reasons for adding this to the language. They were:



  1. Improved encapsulation

  2. Better control over smart-linking

  3. Better language compatibility with Delphi-Prism

Improved encapsulation


How many times have you needed to initialize something related to a specific class? What if your class is using the singleton pattern and you need to create that single instance? How about registering the class with a “class-factory?” Prior to Delphi 2010, there were several options available to you, none of which were really in keeping with the OOP notion of encapsulation. You could put all the code into the initialization section of the unit in which the class lived, add a regular class method and call it explicitly, or manually integrate the init code into your application’s startup. By moving all this code into a class constructor, the mere act of “touching” the class will cause the class constructor to run in keeping with the above rules.


Better control over smart-linking


Loosely coupled with improved encapsulation is the notion that by moving any initialization code into the class constructor you have a little more control over what code is linked into your application. You can now take advantage of the fact that as long as the class type isn’t referenced referenced anywhere in your code, none of the code related to the class type is linked in, including the VMT, virtual methods, RTTI, etc.. If you had placed this init code into the initialization section of its containing unit, then at least the VMT, virtual methods and RTTI would have been linked into your application. Even though none of your code references it. The new enhanced RTTI throws an interesting wrinkle to this theory, but that will have to be covered later.


Better language compatibility with Delphi Prism


As Delphi Prism gains popularity, more people will need to maintain some of their code in a manner that they can compile with either compiler. There are still many language constructors that both compilers have that the other doesn’t, but this is a continuing effort to close that gap where it makes sense. Expect to see more work in this area, in both compilers.


In my next post, we’ll “pop the hood” (or bonnet, for our good friends across the pond) and take a peek at how they work and exactly when they are invoked. I will say that many people tend to read way, way too much into this simple statement describing when a class constructor is invoked; “Called automatically to initialize the class before the first instance is created or any static members are referenced.” The only temporal reference in that statement is “…before…”. I will leave you to consider the implications of that word, lest many of you begin to talk about “threading issues” and “code-bloat.” Class constructors and destructors are to classes as initialization and finalization are to units.