Showing posts with label Delphi 2010. Show all posts
Showing posts with label Delphi 2010. Show all posts

Saturday, 6 March 2010

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.

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?

Thursday, 10 September 2009

Customer Care

I was browsing Delphi tagged questions in stackoverflow yesterday, when I encountered this question. It’s all about generics in Delphi 2009. Whether they are actually usable. Here are a few clips from the answers :

 

I'm using generics extensively in Delphi 2009, and I can say it's not easy as you are often required to work around an ICE

All this trouble seems to be gone in Delphi 2010

Bottom line: if you want to use them, upgrade to 2010.

 

I have also personally mentioned before that the IDE just doesn’t seem to recognise the existence of generics (try any refactoring or code completion). So basically what we are saying is that if you bought Delphi 2009, and you want to use generics in any meaningful way, you need to fork out more money and get Delphi 2010.

Does anyone else find that disturbing? Let me give you a comparison. Let’s say you have just bought a Dell laptop. It cost about the same as Delphi 2009. The (fictional) Dell Longitude 2009. Among it’s many features, is built-in wifi. When you got the laptop, wifi kind of worked, but the laptop didn’t really recognise it had wifi, and you had to do a lot of manual stuff to get it working. When you did get it working, you noticed in some circumstances, it just refused to work, and in others it only kind of works. You complained to Dell, and they released update 2 and update 3 (some kind of bios update), which made things a lot better, and you were kind of happy. Less than a year later, Dell release the Longitude 2010. It looks like they’re not going to fix the existing wifi problems in the Longitude 2009, but if you have a 2009, they’ll give you a special price on a brand new 2010.

Would you buy Dell again? Would you not expect Dell to fix your Longitude 2009? And if they can’t or won’t, don’t you expect a refund?

I’m not singling out Embarcadero here, it is apparently industry practice. What other industry could get away with it though?

What worries me is that I have to go to my boss and ask to upgrade to Delphi 2010. I am lucky, that I work for a company that has no problems in giving us the latest tools, whatever the cost. And in the grand scheme of things, to even a small company, the price of Delphi is insignificant. However, my boss will definitely ask the question, What does Delphi 2010 give us? I can wax lyrical about increased IDE productivity, and improved RTTI, but at some point I’ll have to add the line. Well, we had a few problems with generics in D2009, but it’s all been sorted out in D2010. What kind of confidence does a line like that instil?

Monday, 17 August 2009

Now I’m excited!

I’ve just read about attributes and RTTI in Delphi 2010. As someone who has used RTTI extensively and looked at reflection in .NET enviously, I can say I’m really looking forward to playing with the new RTTI model.

As for attributes, I’m sure a whole new array of interesting ways of doing certain things is going to be possible. There are currently lots of tools and frameworks which use RTTI to do certain things. Up until now, one of the main drawbacks to this was you could only work on published properties and methods.

One example that comes to mind is a small tool supplied with a third party component that prepares Delphi components and classes for use in a scripting solution. This tool works great, and parses classes to produce the boiler plate code needed for setting up the runtime environment for scripting. Unfortunately, it can only work on published properties and methods. If you want to expose any public properties, you have to do it manually.

These kind of things excite me more than IDE enhancements or ribbon controls. Having said that, I hope the IDE keeps up with these new compiler innovations. Does code completion still work with custom attributes for example?

Wednesday, 12 August 2009

Productivity versus Excitement

Many of the commentators in my two recent posts pointed out that the IDE additions and fixes in the forthcoming Delphi 2010 will increase productivity. I have no doubt about that. There’s one in particular I can see saving me quite a bit of time, and that’s the uses units. I use that little tool all the time, and could never understand why it automatically always put the unit in the implementation’s uses clause by default. Why can’t I choose? Well apparently now I can.

One particular comment went on to say that compiler changes, the thing I said might just excite me, could in fact decrease productivity. It takes time to learn new stuff, and if you are spending more time learning, than actually doing things, then you’d not getting things done.

That got me thinking about the Microsoft world, and how it seems that you hardly have started looking at one new technology, before it’s superseded by another. You’ve just about got your head around Winforms, and they spring WPF on you, then you jump on to that bandwagon, and suddenly it’s Silverlight out of the browser that’s the new in thing. Oh wait a minute, WPF and Silverlight doesn’t seem to be doing so good, perhaps we should stick with Winforms. Same on the web development side of things. You start with ASP.NET, get comfortable with ViewState and postbacks, and bam, they bring out ASP.NET MVC and tell you to forget all that (Actually they say they’re keeping both, so you need to decide which is for you). To make things worse, they offer you Silverlight as well. It’s the same wherever you look. Linq to SQL? Well apparently Microsoft now prefer Entity Framework. Well they did. I’m not quite sure anymore.

So yeah, all these new innovations to the language and new technologies do have an effect on your productivity, especially if you are trying them all out. The thing is, it’s human nature to want something new and shiny. Look at mobile phones. Most people use their mobile phones for making and receiving calls and that’s it. Oh, they might try a few of the new features when they first get the phone. Maybe take the occasional photo with their phone, but for the most part, they just make calls. So why do they change their phone every 6 months or so? The phone they had 5 years ago still works great for making those calls. The phone manufactures know it’s human nature to always want the new model. So they oblige and keep churning them out.

Microsoft also know that they can’t just rest on what they’ve got. They’ve got to keep their audience excited. Keep throwing as much new exciting stuff as is possible to keep them coming back for more. So while I agree, I’m as productive as a Microsoft developer who is using C# and Visual Studio, I admit I do go green with envy when that get some new toy!

Monday, 10 August 2009

Delphi Love

I was rather surprised at the comments to my last post. Some were pretty heated. Delphi developers are extremely protective of their baby, but I knew that already. I didn’t actually think my post was that provocative, but perhaps it was.

A good number commented that what has been released so far is only the tip of the iceberg, and that beta testers were not allowed to reveal more yet. That’s all well and good, but I can only comment on what I have seen. When more is revealed, I no doubt will add further comments.

Actually, I never said 2010 sucks. I just said that I’m not that excited yet. I didn’t say others wouldn’t be excited. I just said that I, personally, in my humble opinion, need more than IDE changes to get my blood stirring.

Each release of Delphi Prism excites me for example. They seem to be forever adding little goodies to the compiler. Perhaps it’s easier to do with the .NET platform?

Saturday, 8 August 2009

Delphi 2010

I know I’m supposed to get excited and all that, but I’m not. Improvements to the IDE, no matter how useful or needed just don’t do it for me. I guess it’s analogous to an accountant getting excited at improvements to his favourite calculator. (although I guess accountancy is so boring that a few new buttons on a calculator might just warm an accountant’s cockles!)

I get excited at real innovation. Improvements to the language for example. Ability to do things with my preferred language that’s either impossible or difficult to do with any other language. Innovation to the underlying Compiler etc etc

I guess I’ll have to wait until Delphi 2011 comes out.