Let's hear it for Garbage Collection! Hip-Hip-Ho.... whoa there Nellie!! When it comes to VCL for .NET and Garbage Collection, the more things change, the more they stay the same..
The level of source-code compatibility between the traditional VCL/Win32 and VCL/.NET is nothing short of amazing. If you witnessed the Product Address at this year's Borland Developer Conference, you would have seen a demo where the original FishFact database demo was opened in Octane (Delphi 8 for .NET), compiled and ran with 0 (zero), count them, 0(zero) code changes. Not even the uses lists needed to change (remember WinTypes, and WinProcs? ;-).
OK, so they're compatible... What does this have to do with Garbage Collection? Well... there are some myths around GC that may get you in some serious trouble. Yes, it is true that in a GC environment, you generally don't have to worry about freeing memory. However there are a lot more types of resources than simply memory. Things like file handles, GDI handles, etc... It is easy to understand that these items are out of the reach of the GC, so you have to continue to guard your code with try..finally blocks to open/close, allocate/release, etc.. What is more subtle, though, are those "resources" that don't quite "fit" the definition of an "object."
So what other kinds of "resources" out there have to be managed in a similar fashion to those more traditional notion of a resource? I use the term "resource" loosely here in order to simply highlight the correlation to what one normally thinks of as a "resource." Suppose you have a class of objects that have specific knowledge of the container in which they live. When you create an instance of one of these object classes, they are given the container and proceed to toss themselves into that container. You now have this "bag" of objects by referencing the container. You can pick each item from the bag perform some operation on them. One suich operation that is common is to "destroy" the item. Well, since this item knows about its container, it plays nice and removes itself from the container before it self-destructs.
In the GC world, a common mistake is to simply think of "destroying" an object is simply freeing its memory. So I don't have to do that in the GC world because that will be handled for me, right? Sure it will.. eventually. But it will not automatically take care of one important resource, it's container's reference. That reference needs to be cleaned up. It is not a "resource" onto which the item itself holds, but is a resource nonetheless. When you look at the declaration of the object, you won't find a reference to this resource... oh wait yes you do... It is the reference to the container itself. It is through this reference that the "resource" lives.
So if you don't "destroy" an object, how do you make it release its references? In .NET, there is a simple pattern that is followed. An object that needs to do immediate resource cleanup, should implement the IDisposable interface. It has one method called procedure Dispose; (or for you that prefer a more "curly" world void Dispose();). Now when you want to "destroy" an item in the container, you cast the item to IDisposable and call the Dispose method. In the Dispose method it just performs the nessesary steps to remove itself from the container.
Sure, you could manually remove the item from the container yourself and forgo the IDisposable riggamarole, but what if you hand the item off to someone that has no specific knowledge of the particular container instance in which the object is currently living? This is why the IDisposable pattern is important.
So let's bring all this around now to Delphi 8 for .NET and its view of the world. All this IDisposable stuff seems tedious and would require some massive changes to my code to play nicely in .NET. This is where Delphi has realized some of the benefit of arriving a little later to the party. Delphi introduces an interesting language construct called "class helpers." There could be a whole tome written about the subject of "class helpers", but suffice it to say, they have given the Delphi programmer a familiar world in which to work. All that code you have written in which you dutifully have implemented your destructors to properly clean up after yourself, release resources, and generally keep your house in order can now continue to live on..and serve a real purpose beyond simply releasing memory. Releasing memory is no longer the responsibility of the lowly Destroy destructor. It now is a cue to the Delphi compiler that you want it to implement the IDisposable pattern for you. Your object now implicitly implements IDisposable and the Dispose method maps to your Destroy destructor. It even takes care of guarding your destructor from being called more than once by implementing the pattern of setting a compiler generated instance variable to true the first time through the Destroy destructor and exits immediately on all subsequent calls. To the world outside Delphi, your objects simply appear to implement the IDisposable pattern. The really cool thing though, is that all objects that come in from outside Delphi (remember all objects in .NET descend from System.Object, which is not Delphi's System.TObject. In the CLR world, it is the other way around. Borland.Delphi.System.TObject = System.Object) "appear" to have a non-virtual method called Free (thank you class helpers). If you are a seasoned Delphi developer, you know that in order to maintain proper "exception safety" you never call the Destroy destructor directly. This is because the Free method would check to make sure Self (or this) is non-nil before calling Destroy. In .NET it continues to do this as well, but now it checks if Self implements IDisposable and then calls Dispose if it does. This is why you can call MyHashTable.Free. Through the magic of class helpers, the Free method appears to be a method of HashTable.
So now all your nicely done try...finally code continues to serve a purpose, in fact is remains critical to the proper operation of VCL code. For instance, a TComponent derivitive takes an Owner parameter in its constructor. It then proceeds to add itself to the Owner's list of Owned Components. So, when you call Free on the component, the expectation is that that component is removed from the Owner's list immediately. These semantics are now preserved.
Garbage collection certainly takes away certain programming chores, but it is not a panacea. The more you understand the environment in into which you are moving, the better you'll be able to migrate your existing code. So the upsot of all this is that you don't have to change nearly as much code as I'm sure you originally thought nor should you.
Friday, November 21, 2003
The rules have not changed...
Thursday, November 13, 2003
Up periscope...
Just a quick note here... For those two or three folks that seem to be gluttons for punishment and actually read this jumbled mess of random thoughts... I hope to be back in the blog saddle within the next few weeks. I need to make good on the promise that I'd present some of the material I had planned on preseting in my "IDE Spelunking" BorCon talk that was canceled.
Monday, November 10, 2003
Aftermath
Now that the 2003 BorCon is behind us, we are now "kickin' it up a notch" for that final drive to release. This is mainly why the blogs have been coming less frequently... that whole "work" thing keeps cutting into my blog time ;-)... Also we're at that stage where the days are sort of blending together...
It seems the rainy season here in Santa Cruz, County, CA has started in earnest. While it is sunny today, the past week was filled with dark overcast foggy skies. That certainly makes it easier to keep ones head down and concentrate on completing the release.
Wednesday, November 5, 2003
BorCon talk
I just finished my one talk I was still giving at BorCon and am now back in the office... It was a small crowd, but it always is since Open ToolsAPI stuff isn't a huge draw. I got to present some interesting things, like we plan on publishing a Delphi/C#Builder integration package to registered users and partners to allow them to move thier existing Delphi and/or C#Builder IDE plug-ins over from Delphi 7.
Stay tuned.
Friday, October 31, 2003
Avalon: Yes, the Picture's Changing
Avalon: Yes, the Picture's Changing
Here's a response that I posted to the above article:
I can see everyone rolling their eyes at the loony that is about to make this statement.
The movement of the declarative "InitializeComponents()" code to another more suitable "language" is nothing new, nor earth-shattering. Now comes the controversial part. Take a look at Borland Delphi... "Oh, I've heard of that" No, it is *not* just that "database" tool. It is a full featured, powerful object-oriented, component-based, compiled-to-native-code, development environment.
The Visual Component Library (VCL) that is included with Delphi uses a predecessor to Avalon's XAML. By using a text or binary declarative "language", the form construction is taken out of the code. This "script" is attached to the executable as a resource. It can also be easily localized by providing an alternative script.
Avalon is clearly an evolutionary step along this same path, but I would certainly *not* characterize it as "revolutionary."
Yes, I work for Borland. Yes, I'm one of the original developers that designed and built Delphi. Delphi was launched on February 14, 1995 at the Software Development West conference in silicon valley.
If you look closely, and resist the urge to revise history, you'll see that one of the primary architects behind .NET is Anders Hejlsberg... who was one of the original architects behind Delphi. Anders left Borland and helped produce J++ and WFC, then eventually C# and .NET. If you compare WinForms, WFC, nay Delphi's VCL, the similarities are... let's just say, striking.
What I find interesting and, to be honest, somewhat frustrating, are the reactions when I state that "Delphi's been doing this since 1995." I can see them rolling their eyes, as if to say, "There's another of those Delphi crackpots who thinks they actually innovated something."
In actual fact, we at Borland are extremely excited about the technologies that are coming out of Redmond.
In fact, if you happen to *be* a Delphi programmer you need to keep your eye on the "Octane" project.. and if at all possible, attend the Borland Conference in San Jose, CA starting this weekend (Nov. 1, 2003).
So I guess it *is* true that imitation is the highest form of flattery.
Allen Bauer.
Borland Software Corporation.
RAD .NET IDE Architect.
Wednesday, October 29, 2003
Editor pair highlighting
Since one of my BorCon talks has been canceled, I will begin to post some of the content that was planned here. To get things started, here's one item that applies to C#Builder (and the upcoming Delphi 8, codenamed "Octane").
Modifying which character pairs the IDE highlights:
Insert standard disclaimer concerning editing your registry, here
Open RegEdit and go to the following key:
HKCUSoftwareBorlandBDS1.0EditorSource OptionsBorland.EditOptions.XXXXPair Table
Under the above key there are string entries formatted as comma separated values, for instance the "(* *)" pair in the "Borland.EditOptions.PascalPair Table" key is represented as:
0,1,2,(*,*)
The meanings of these values are, in order:
Nestable = 0 - No, 1 - Yes, 2 - Maybe
ImpliedDir = 0 - No, 1 - Yes
CharCount = 1 or 2 only
Starting string = 1 or 2 char string
Ending string = 1 or 2 char string
So to create non-nestable, implied direction pair for, say <% and %> it would look like this:
0,1,2,<%,%>
So if you don't want to highlight the quote characters since they have no implied direction and will often highlight strangely, delete the 0,0,1,',' and 0,0,1,"," entries and those pairs won't display as match characters. Note that this will also disable the Ctrl-Q+[ and Ctrl-Q+] functionality for those characters.
Tuesday, October 28, 2003
Talks canceled
Due to product scheduling constraints, one of my BorCon talks has been cancelled. The "IDE Spelunking" talk will not take place on Tuesday, November 4 as planned. The Open Tools API talk is also in danger of being canceled as well. This stinks... I'll also not going to be able to be there very much either... Even though it is less than 30 minutes from Borland.
Sunday, October 26, 2003
Borland at this year's Microsoft PDC
Marco Russo - Borland at PDC
It seems that some folks are certainly noticing the conspicuous placement of Borland at this year's Microsoft PDC. And, since BorCon is after MS' PDC, there'll be a lot of continued buzz... You don't want to miss it.
Saturday, October 25, 2003
Managed code gotcha's...
.NET Framework Security: Using Win32 and Other Libraries (Working with C#)
Just learned a little lesson when working with managed code and P/Invoke. If you are providing a delegate as a callback to a P/Invoke'd Windows API function, make absolutely sure you hold a reference to that delegate for as long as that Windows API needs to call it... ;-) Since the CLR doesn't track references to things that travel off into the unmanaged nether-world, it will blithely garbage collect your delegate. This promptly hangs your unsuspecting API out to dry (think RegisterClass and CreateWindowEx). The absolutely insidious thing about all this is that it will work.. for a while. So take my advice, the oven is hot; wear your oven mitts...
For all the time I've spent working with managed code, COM-interop, and P/Invoke, you'd think I'd know this stuff... But then again, I'm no Don Box, ChrisAn, or Lutz Roeder, et. al.... they've had the luxury of being exposed to this for a few more years ;-) Eventually, this stuff will seep through the several inches of solid rock and touch some grey-matter someplace...
Friday, October 24, 2003
Ryan Dawson on Longhorn (in hot water...)
Ryan Dawson on Longhorn
Whoops... somebody raised a few eyebrows at MS ;-)... Ryan's previous post has been expunged and he doesn't even work for MS. I still have a cached copy though.