Tuesday 30 March 2010

The Delphi Overflow Doc Wiki Initiative

A couple of days ago, I was reading Jim Mckeeth’s blog post about setting up a Delphi documentation wiki. Now while I admire Jim’s drive and determination about anything Delphi, and I like his idea, there’s one sentence I don’t agree with.

”At first I was thinking Embarcadero could hire a tech writer to copy edit the content from the questions into the Wiki, but that is just passing the buck.”

Any why shouldn’t Embarcadero properly document their own product? They are the ones making money from Delphi, aren’t they? I’m all for community input, but that shouldn’t let Embarcadero shirk their responsibilities. I guess Jim, like many others has just given up ever getting decent documentation, and taken matters into his own hands.

Hand’s up those who have given up on the F1 key when working in the Delphi IDE?

Sunday 21 March 2010

Silverlight back from the dead.

Microsoft have probably just saved Silverlight. Their recent announcement of the Windows Phone 7 Series, and more importantly the development platform for that phone (Silverlight of course) means Silverlight is important now. I was always pretty sure WPF would become the defacto standard for desktop applications (and what with Visual Studio now being written in WPF, perhaps it will), but I couldn’t quite see a compelling reason behind Silverlight. Now there is one!

Have Embarcadero backed the wrong horse (again…)? They’re targeting the MAC with their next compiler. Probably because they think that is where the future is. Perhaps the future is with Seattle and not Cupertino!

They have Delphi Prism of course, and you can develop for Windows Phone using that. Having said that, no one has ever answered my question? Why should I use Delphi Prism and not C#? Now before I get a 1000 comments telling me that Pascal is easier to read than C#, I just want to say I agree. I love Prism! I wish I could use it every day. It’s awesome. Can I praise it anymore? I need a reason to use it though. One I can go to my boss with. I’d like to be able to go to him and say, “you know that project we were about to develop in C# (the one we decided to NOT use Delphi native Win32 for!), well I think we should use Delphi Prism because….”

If anyone can complete that sentence for me, I’d love to be able to use it. I wish Microsoft had approached Remobjects and partnered with them rather than Embarcadero. The only way my boss would agree to Delphi Prism would be if it sat along side C# and VB.NET in the default install of Visual Studio. That wouldn’t guarantee anything, but I’m sure the added exposure would garner quite a few new followers.

Saturday 6 March 2010

More Attributes

Just got a comment from Mason Wheeler, that he prefers to use attributes to indicate a property to NOT serialise , rather than those properties to serialise. I quite like this idea, as it’s true that if you have quite a few properties to serialise, your class may get rather messy. My only problem with this is that the property name must then be the same as the column name. I guess not a major problem, but still. In a perfect world, you’d have two types of attributes. Those which came before properties, methods or fields and those which came after. Those which came before would work just like the class visibility sections. i.e. they apply to all properties, methods and fields until the next attribute, or section. Those attributes that came after a property, method or field, apply to that item only. thus I could write something like this.

public
[Persist]
property Id : Int64;[Key][ColName(
'Id')];
property FirstName : string read fname;[ColName(
'Name')];
property Surname : string read fSurname;
property Address : string read fAddress;
public
property FullName : string;
//not persisted


I’m not sure how difficult that would have been to parse.

Attributes

Last time, I demonstrated how I would like to decorate my class using attributes to declare the table and column names I eventually will use to persist the class. Here are the the declarations of the two attributes I used.
PersistentClassAttribute = class sealed(TCustomAttribute)
strict private
fTableName : string;
public
constructor Create(
const aTableName : string);
property TableName : string read fTableName;
end;


PersistentPropertyAttribute = class sealed(TCustomAttribute)
strict private
fColumnName : string;
fKey : Boolean;
public
constructor Create(
const aColumnName : string; aKey : Boolean = False);
property ColumnName : string read fColumnName;
property Key : Boolean read fKey;
end;


Both fairly simple. The important things to not is that both inherit from TCustomAttribute, and their constructors dictate the way I will use them. I’m not going to bother showing the implementation of either of these classes. Both are very similar, in that the parameters passed to the constructors are stored in the corresponding private fields.



Now we’ve got our attributes set up, and our class has been duly decorated. How do we access that information? Well, you’ll notice that the class which we wish to persist inherits from TPersistable. This class will take care of getting the information we need from the attributes. Let’s start with the class map information.



We’ll create a class procedure on TPersistable to load our classmap.





var
ctx : TRttiContext;
t : TRttiType;
p : TRttiProperty;
a : TCustomAttribute;
begin
ctx :
= TRttiContext.Create;
t :
= ctx.GetType(Self);
for a in t.GetAttributes do
if a is PersistentClassAttribute then
begin
fTableName :
= PersistentClassAttribute(a).TableName;
Break;
end;




Anyone who has seen any code associated with the new RTTI functionality will be familiar with this code. We use the RTTIContext to get to the class information. We iterate over all the attributes on the class until we get to the PersistentClassAttribute. We could do this every time we needed the class map information, but we’re going to do this once, and then cache the information. The next step would be to get the list of properties which we want to persist. We’ll add a few more lines to the procedure above.



class procedure TPersistable.LoadClassmap;
var
ctx : TRttiContext;
t : TRttiType;
p : TRttiProperty;
a : TCustomAttribute;
Prop : IPropertyMap;
begin
ctx :
= TRttiContext.Create;
t :
= ctx.GetType(Self);
for a in t.GetAttributes do
if a is PersistentClassAttribute then
begin
fTableName :
= PersistentClassAttribute(a).TableName;
Break;
end;

for p in t.GetProperties do
for a in p.GetAttributes do
if (a is PersistentPropertyAttribute) then
begin
if not fPropertyList.ContainsKey(UpperCase(PersistentPropertyAttribute(a).ColumnName)) then
begin
Prop :
= TPropertyMap.Create(PersistentPropertyAttribute(a).ColumnName, P.PropertyType.TypeKind);
fPropertyList.Add(UpperCase(Prop.ColumnName), Prop);
end;
end;
end;


We’re doing exactly the same thing as before, except this time we’re iterating over the properties of the class, and checking the attributes of each property. If that attribute happens to be out PersistentAttributeProperty, we create a TPropertyMap class and add it to our list of properties. Once this class procedure has been executed, we now have a cache of information about our class and how we should go about persisting it. we could add a few class functions to help us access that information.



 class function PropertyMap(const aName : string) : IPropertyMap;
class
function TableName : string;
...
...
class
function TPersistable.PropertyMap(const aName: string): IPropertyMap;
begin
fPropertyList.TryGetValue(UpperCase(aName), Result);
end;
...
...
class
function TPersistable.TableName: String;
begin
Result :
= fTableName;
end;



We’re still a long way from persisting our objects, but we now have all the information we need. When I do implement the actual persistence, I’ll make sure it is extremely easy to change from persisting to SQL Server or to a simple XML file.

On ORMs

I’ve always had a soft spot for ORMs (Object Relational Mappers). Whilst opinion is divided on their use, I just love them. I’ve actually written a few, because I’ve never found exactly the right one for me. Currently in the Delphi world, there are a few open source ones, and some commercial ones, but all seem to have been started pre Delphi 2010. Which means they don’t support Attributes and the new RTTI. When I first saw Attributes in Delphi 2010, I thought ORM immediately. All the ORMs I’ve used or written (in Delphi at least) store their mapping information separate to the actual class that needs to be stored. One I used, stored the information in an XML file, which was read, and parsed on start up to produce a class map. So I thought, how would I do it with Attributes.

  [PersistentClass('TestObject')]
TTestObject
= class(TPersistable)
strict private
fName : string;
function GetName: string;
procedure SetName(const Value: string);
public
[PersistentProperty(
'IdCol', True)]
property Id;
[PersistentProperty(
'NameColumn')]
property Name : string read GetName write SetName;
end;



At it’s simplest, I have one attribute for the class, and another for each property I wish to persist. The PersistentClassAttribute, takes the table name, whilst the PersistentPropertyAttribute takes the column name and whether the column is a primary key. What I’m hoping for is if I try and save an object of type TTestObject I get the following SQL for my relational database.




INSERT INTO TestObject(IdCol, NameColumn) VALUES(2, 'Steve')



And if I try and load and object, by writing MyObject.Load(2), I’ll get SQL similar to the following.



SELECT IdCol, NameColumn FROM TestObject WHERE Id=2


Next time I’ll demonstrate how I use those attributes to create a class map

Friday 22 January 2010

The Ribbon Control Update

A little update to my previous post. Most of the problems I have encountered can easily be fixed by viewing the form as text, and then going back to the visual form. It’s almost usable. Still a pity though.

The Ribbon Control

Now I’m not a major fan of Microsoft’s ribbon control, and our clients have for the most part stuck with Windows XP, and Office 2003, so there has been no real call for it in our applications. However, with the advent of Windows 7, we are getting more and more calls for our application to look more like a Windows 7 and more specifically an Office 2007+ application.

To that end I have been experimenting with the ribbon control in Delphi 2010. And my am I frustrated. This is the buggiest component I have ever used out of the (Delphi) box. I add ribbon groups that disappear (I have found a workaround, by opening the form as a text file and back to form again) Icons initially appeared non-transparent, then started working. Sometimes actions would not have a caption. I’d delete the group, re-add the action, and the caption magically appears. It just seems so fragile. Has anyone actually managed to get anything but a hello world application, using a ribbon control, to actually work. and more importantly, not go nuts in the process.

This is why I protest so loudly at the Delphi pricing. Delphi 2009, touted the ribbon control and generics as two of it’s major plus points. Generics were barely useable until update 3, and then abandoned in Delphi 2009, with new fixes going in Delphi 2010. The ribbon control, I assume, was just as bad in Delphi 2009 as it is in Delphi 2010, if not worse.

Stop releasing new versions every 5 minutes, and fix the outstanding problems. Why should I have to get Delphi 2010 to fix the generics I paid for in Delphi 2009? Why should I now have to find a third-party ribbon control to fix what I paid for in Delphi 2010?

Thursday 21 January 2010

Upgrading to Delphi 2010

While the next major release of the application I work on will no doubt be written in C# (unless we get a 64-bit Delphi, then I have something to argue my case with), for the short-term, we will continue using Delphi. To that end, I like to keep up with the latest version (not always sure that’s a good idea, but anyway) so we recently got a copy of Delphi 2010 to see how easy the upgrade would be.

Not so long ago, I moved from Delphi 2006 to Delphi 2009, so I thought this upgrade would be a walk in the park. There should be no breaking changes. I would need to change a few defines, but that’s about it. And initially that was the case. In no time at all, I had upgraded our third-party components, made the necessary changes to include the new compiler version (more about that in a later post perhaps), and I had the whole thing building in no time. I ran it and disaster. Well it seemed like a disaster. All the fonts of all the menus, both the main menu and all popups were both the wrong font, very large (some the size of the monitor) and skewed. I checked the components in question, and yes the font property was basically garbage. I checked the DFM file, and everything was correct.

Now I have to add that we use some old DevExpress components for our menus. We never upgraded them as they did a complete rewrite of their grid component at the same time, and we had too much invested in the old one. Anyway, we have faithfully updated the source as and when needed. The unicode changes were perhaps the biggest challenge, but not too difficult. Now this! What was wrong?

Something was changing the font. I delved into the source for the components, and zeroed in on the following few lines.

var
NonClientMetrics: TNonClientMetrics;
begin
NonClientMetrics.cbSize :
= SizeOf(TNonClientMetrics);
SystemParametersInfo(SPI_GETNONCLIENTMETRICS,
0, @NonClientMetrics, 0);
Font.Handle :
= CreateFontIndirect(NonClientMetrics.lfMenuFont);
...


Now this code hasn’t changed since we compiled it with Delphi 2009, so I delved into windows.pas, and found the record that TNonClientMetrics ultimately points to tagNONCLIENTMETRICSW and down at the end, the following line.



iPaddedBorderWidth: Integer; //Requires Windows Vista or Later


Aha, I’m working on Windows XP. I checked the same record in Delphi 2009, and that line was missing. So sizeof was returning 4 bytes extra in Delphi 2010 than it did in Delphi 2009. I confirmed this by trying the following



NonClientMetrics.cbSize := SizeOf(TNonClientMetrics) - SizeOf(NonClientMetrics.iPaddedBorderWidth);


Yes, everything back to normal. Obviously, the code should check for windows version and return the size accordingly, but some kind soul has done that work for me, and added a static method, sizeof, to the record. So the code becomes



NonClientMetrics.cbSize := TNonClientMetrics.SizeOf;


The sizeof static method checks windows version and adds or removes the extra 4 bytes accordingly. I hate breaking changes like these, but whose fault was it. Delphi 2010 or Microsoft?

Sunday 17 January 2010

C# Native Compiler

I was wondering the other day about all the (failed) attempts by Borland/Inprise/Borland/Codegear/Embarcadero (that list there says a lot just by itself) at diversifying their native Delphi compiler. You had Kylix (Delphi for Linux), Delphi for .NET, and C# Builder. All of them not really what you would call successful. Now they are working on a cross-platform compiler, which will be the next version of Delphi. (I still don’t get why they think this is more urgent that a 64-bit compiler)

Has anyone ever contemplated a native C# compiler? I don’t mean something that could take existing C# projects and compile them for Win32. Delphi for .NET showed that the two platforms are just too different for that to ever work in either direction. No, what I’m thinking about is a C# native compiler built on the VCL and the Delphi IDE. I think we all agree that there is a place for native development. There’s a load of C# developers out there though, who would never contemplate Delphi, but if they needed to write some native code, they would certainly look at a C# native compiler.

If that worked, it would definitely save Delphi. As long as the VCL was alive, and you had the same kind of compatibility you now have between C++ builder and Delphi, then Delphi would be back in the limelight.

Just a thought.

Friday 15 January 2010

Delphi is Dying

Don’t you just hate those Delphi is Dying blog posts? I do? We have been bombarded by messages of doom since about Delphi 4. “Delphi is dying” they scream. “No it’s not”, we counter. “It’s alive and kicking”.

The problem is, I think they finally may just be right. Now I’m a big fan of Delphi, I have been since Delphi 1 (and if you count Turbo Pascal, then a lot longer still), but if I’m beginning to despair, then what hope is there? It’s got absolutely nothing to do with what other people are saying. It’s just a feeling I get from trawling the internet every day looking for Delphi related stuff. There used to be a time when you needed something, you googled it (probably, yahooed it in those days), and you’d get tonnes of hits with sample code, downloads and documentation galore. What do you get now? Almost exclusively you get abandon-ware. Code that hasn’t been updated from Delphi 6 or 7. Half finished components with no, or poor documentation. I guess this didn’t happen over night, but up until Delphi 2009, you’d find some Delphi 5 code, compile it (in say Delphi 2006), and you’re off. Now, with the unicode changes in Delphi 2009, you invariably have to work hard to get any code to compile and work properly. Rather than moan about it, I should perhaps give back to these open source projects, and post my changes somewhere, but to be honest, a lot of the code is so half baked, that it’s just not worth it. You need to not only fix the unicode problems, but do a whole lot more to make anything worthwhile.

 

No doubt, I’ll get a few comments regarding how great Delphi 2010 is, and I won’t disagree. This post is not about how good or bad the IDE is. You can do anything with Delphi today. Sure it has some deficiencies, but what language/platform doesn’t? On the whole though, you can produce fast, compact and useful applications with Delphi. But that’s not the point. The point is that developers are abandoning it in droves. I have no scientific data to prove or disprove that statement, but I do have a feeling. It’s beginning to feel like a ghost town. I’ve just woken up, and realised everybody’s left.