A site devoted to discussing techniques that promote quality and ethical practices in software development.

Saturday, July 28, 2007

The debate of private field convention in .Net and Microsoft's convention

The other day over lunch a few of my mates got together to catch up. One of the topics that came up was the private member naming convention in .Net.

One of them suggested it to be prefixed by a '_' character. I then threw in a question saying something like this: "if you propose to use _, why not m_?".

My mate told me that that is Hungarian Notation and no place in the .Net. I then asked what Hungarian notation is that: why is "m_" signifying for "member var" any worse or offensive than "_". We did not came to any agreement although I did give a brief history of private member naming convention.

I favor the non-prefix convention for private member for several reasons:
1) it is consistent and looks even better in WinForm programming. If you use _, you have to make sure you name your control accordingly. I guess same for m_. Then if you have an event, say a click event, the event handler looks like this:
private void _myButton_Click(....)

Personally, I do not like seeing leading underscore.
myButton_Click(...)

reads better.

2) In coding, the statements are prefixed with leading underscore like this:
hasFound = false;

instead without underscore like this:
hasFound = false;
or
this.hasFound = false;

True, it has more typing and litter by this. When using intellisense, the moment you type "this.", the intellisense pops up with the member data. I guess you get the same treatment for _ as well as m_.

Also true is if you have a long function (note: code smell), you may be wondering if that is an auto-variable if you do not have any prefix. This is particularly true in those poorly crafted ridiculous C++/CLI standard that tries to retain the C heritage for no good reason other than failure to let go.

Anyway, I thought my convention with the support of zillion lines of code, which does not arouse FxCop ver 1.35.51212.0, is the right convention until I use the static analyzer in VSTS. The analyzer is a lot stricter than FxCop and is complaining usage like this:
class ClassFieldVarSameAsParameter
{
int someValue;

public ClassFieldVarSameAsParameter( int someValue ) // This is fine
{
this.someValue = someValue;
}

public int SetValueTo ( int someValue ) // CA1500
{
int oldValue = this.someValue;
this.someValue = someValue;
return oldValue;
}
}
The SetValueTo() function generates the warning CA1500 - VariableNamesShouldNotMatchFieldNames message while the constructor does not.

That really turns my convention, and I am sure many as well, upside down. This discovery is a great shock to the system because this usage has been almost universal from day one. It is also universally used in designers or code generators within VS, including WinForm and dataset designer.

Should we use custom dictionary to rule this out? Not too sure and I hate exceptions.

It appears that the convention used by Microsoft is "m_" internally and this may explain why this rule is introduced into the static analyzer.

May be this signals the end of the debate?

PostScript

For those wanting to retain the no-prefix convention, one sensible way to remove the CA1500 warning in the VSTS static analyzer is to adopt the following convention.

For those situations where CA1500 are generated, append an underscore suffix. Since this usage is localized to a particular function in the parameter names, the ugliness of the underscore is not so common. If the suffix is unacceptable, people can use alternate names for the parameter.

The underscore suffix does not confuse those that have already adopted the underscore prefix. This then allows member variables to have no prefix.

However, renaming parameter name of any externally visible method is a breaking change.

Monday, July 9, 2007

Delphi.Net assembly loading inefficiency

Further to my reporting on the poor performance and scalability of VCL.Net, Delphi.Net also has assembly loading inefficiency that is opposite to what can be produced with .Net languages. This message is to describe this cost and how one could use design pattern to ease the pain - not totally removing it.

Consider the following UML diagram describing a very simplified Delphi program:

This is a very common approach. So in the unit that contains TForm2, you will have a uses statement mentioning the unit for MyClass3 and so on.

The following sequence diagram describes what happens when one double clicks on TestClient.exe to launch it from Windows Explorer:
In other words, as soon as the DPR is loaded, it starts to load not only the MyDemo3.dll contains the class that TForm2 requires but it transverses right down to the lowest level, loading each DLL as it goes. At each loading, it executes any code that is in the initialization section of the unit. Delphi.Net compiler translates each unit into a static class whose name is the name of the unit protected inside a namespace whose name is formed with the unit name plus a suffix '.Units'. Any code defined in the initialization section is placed in the static constructor of this class.

This kind of loading is opposite to .Net programs developed with other languages, such as VB.Net or C#. Programs produced by those language only load the DLLs until code in those assemblies are executed and the JIT compiler only compiles what is needed.

In a non-trivial solution, Delphi.Net will produce a solution that literally loads up all the DLL, jits the classes that are in the unit namespace, run their static constructor code. In other words an awfully inefficient loading engine and solution and the time taken to carry out all these actions can become very significant portion of the start up cost.

This is the code in the static constructor of MyClass3.Units.MyClass3:
static MyClass3()
{
RuntimeHelpers.RunClassConstructor(System);
RuntimeHelpers.RunClassConstructor((RuntimeTypeHandle) MyClass2);
RuntimeHelpers.RunClassConstructor((RuntimeTypeHandle) MyClass1);
MyClass3();
}
This is the source of where all the loading begins, the DPR code, TestClient.Units.TestClient's static constructor:
static TestClient()
{
RuntimeHelpers.RunClassConstructor(System);
RuntimeHelpers.RunClassConstructor(SysUtils);
RuntimeHelpers.RunClassConstructor(Forms);
RuntimeHelpers.RunClassConstructor((RuntimeTypeHandle) MainForm);
}
The last line kicks off the loading. When the MainForm.Units.MainForm's static constructor is executed, it loads that for MyClass3, and so on.

Here is System.Diagnostic.Debug.WriteLine() traces that I've placed in each unit's initialization section.
[5988] MyClass2.initialization
[5988] MyClass1.initialization
[5988] TMyClass3.initialization
[5988] TForm2.initialization
So beware when you are migrating code from VCL.Win32 to VCL.Net. You need to do extra work in VCL.Net to make your program runs efficiently and this can be a signficant cost or at least more than what CodeGear leads to believe.

While this 'load-just-in-case' attitude is always present in Delphi.Win32 but because it does not require jitting and all those processes, the cost in Win32 is not so significant. Nevertheless, it does defeat DLL delay loading that has been around in Win32 for years. Inefficiency nevertheless!

So how to protect yourself from this wastage? The idea is to apply the Dependency Injection or Inversion principle to loosen the coupling. Using this principle, the naive implementation becomes something like this:
Many who are familiar with COM would recognize this pattern is something they have been using for years. The Publisher.dll is nothing more than the type library carrying DLL.

If you run TestClient.exe up, all you see being loaded is Publisher.dll. You will not see the rest of the DLLs being loaded until you need to create MyClass3. To avoid binding to the definition of MyClass3, you should use System.Activator.CreateInstance() to create MyClass3 and then to use IDemo3 to invoke methods. This is exactly the same programming model that is being used in COM, just like what Don Box mentioned in relation to answering the question "Is COM dead?". This is what he said:
COM is many things to many people. To me, COM is a programming model based on integrating components based on type. Period. This was COM's primary contribution to the field of component software, and that contribution has changed the way millions of programmers build systems today.
Now, if Delphi.Net/Pascal has assembly visible type, which it does not have, MyClass3 can be marked in such a manner further restricting user from directly binding to MyClass3 resulting in the inefficiency that we are trying to minimize.

Tuesday, July 3, 2007

A positive outcome for Delphi Win32 COM developers

With the release of the much heralded "Delphi 2007 for Win32" by a company with a new name, finally it appears pure mathematical logic has won out over ego and pigheadedness that have prevailed for the past 8 years or so.

The issue with Delphi COM local server problem that I've blogged so passionately has finally be fixed in "Delphi 2007 for Win32". This problem exists in Delphi 3 and Borland over the years has steadfastly refused to fix it or to even acknowledge that it is a bug. May be it is Vista in particular with the UAC forcing them to fix it. I dare not claim credit for this turn around despite my submission through the normal channel and the numerous brush off.

The fix is almost identical to what I've described here. The important things to note is that they should now obey their documentation in relation to the local server command line switches and that it will not bother to re-register it after a successful COM activation. The latter is the most stupid of all. Programming is pure logic.

There are implications for many who are not fluent with COM local server and may have used this 'bug' to register COM servers without the switch. Or others that are aware of this problem but have cooked up their special work around that may now be rendered ineffective or may even fail.

So they have to check with their usage to determine if they now conform with the general COM local server registration usage.

Monday, July 2, 2007

Comodo Anti-Virus Ver 2 beta not suitable for Tablet PC

Over the weekend, I decided to trade my trust AVG 7.5 with a new boy on the block called the Comodo Anti-Virus Version 2 beta, which is also free.

Anti-Virus these days in my mind has kind of grown beyond what they are suppose to do - catching virus. But this thing seems to do more - HIPS (Host Intrusion Protection System). Isn't that is your Comodo Firewall's role?

Anyway, this tool is not suitable for Tablet PC because it prevents the TIP (Tablet Input Panel) from coming up. If you cannot use TIP, you may as well be throwing the tablet away. It is probably being too aggressive equating to being dumb. It keeps asking me to allow and disallow things that Comodo Firewall is fully aware as harmless. Kind of like the Mac Vs Vista advertisement poking fun at the Vista UAC. Both Comodo Anti-Virus and Firewall are extremely dumb!

After trying in vain to get the TIP up, the next best thing was to uninstall it and put my trusty AVG back on. So good bye Comodo Anti-Virus.

Blog Archive