In case you haven’t read my last post, here’s a short recap. Some days ago Mauricio Rojas of Artinsoft publicly claimed that my knowledge in code translation is “disappointing”. Mauricio didn’t provide any fact to support his words, however he announced a new series of articles named “VB Migration not for the weak of mind” where he would prove his point.
Mauricio has finally published the first two articles of the series, one on the translation of On Error Resume Next statement to C# and the other on implementing late-binding in C#. Both articles are filled with mistakes, so a few hours ago I posted a comment for each of them.
Neither comment has appeared yet on Mauricio’s blog, but I hope it’s just a matter of time. If you publicly denigrate someone you should give him the opportunity to answer and illustrate his point of view. I am sure Mauricio doesn't ignore that transparency and intellectual honesty is the very essence of blogging.
In the meantime, I’ll expose my ideas and criticisms here. The text here is slightly different from my original (yet unpublished) comments to account for the different context.
Update (Aug 25): not only Mauricio never published my comments, he went as far as deleting one of the two articles. You can read the whole story and read an offline copy of his posts here.
My comment to “VB Migration (not for the weak of mind) Part 2”
I read with interest Mauricio’s funny stories about human language dialects. I am sure that everybody agrees that it's easier to translate from Russian to Ucranian rather than to English or Spanish, even though both tasks can be successfully completed by a human that is skilled enough.
But the analogy is pointless in this specific context: Mauricio’s article was supposed to focus on *automatic* translation between *programming* languages, not manual translation between natural languages. It's like comparing apples to bicycles, for those who like analogies.
Mauricio announced he wanted to prove me wrong and that he knows how to automate the translation of *any* VB6 method to a piece of C# that is functionally equivalent. I don't see anything like that in this article. I only see some advice about what you should or shouldn't do in VB6 or C#, which is a completely different matter.
For example, we all know that On Error Resume Next can bring to hard-to-find bugs, nevertheless millions of VB6 projects use this statement and a conversion tool should account for this fact. The article was supposed to show how a VB6-to-C# translator can do it. We'll have to wait for a long time, I am afraid.
The real pearl in this article is where the author states that:
When you do a translation, you should try to make it as native as possible. So why will you keep using a COM function when there is an equivalent in .NET. So why not use System.IO.File.CopyFile("sourcefile1", "destfile1", true); instead?
I am sorry to inform Mauricio that he cannot replace the FileSystemObject.CopyFile method with a System.Io.File.CopyFile method for at least three reasons:
the System.IO.File class doesn't even expose such a method
... or maybe he was thinking of the Copy
method? (Tip: never trust your memory when writing a technical article...)
the System.IO.File.Copy method doesn't accept wildcards in its first argument, whereas the FileSystemObject.CopyFile method does.
the System.IO.File.Copy method requires a complete file name in its 2nd argument, whereas the FileSystemObject.CopyFile method also accepts a folder name.
If you buy a conversion tool converts calls to the FileSystemObject.CopyFile method into calls to the System.IO.File.Copy method, then you have to carefully check that the original VB6 code never uses wildcards or folder names. If the method is located inside a library or in a source file that is shared by hundreds different VB6 projects you have to scrutinize each and every project. In a real-world application this job alone can take hours.
We at Code Architects are aware of these subtle differences, which Mauricio apparently ignores. To spare our customers’ time and effort, our VB Migration Partner tool converts the CopyFile method into a call to a helper object that behave *exactly* like the original FileSystemObject class, except it's fully .NET and has no COM dependencies. If you use a conversion tool that takes a different approach we can only be sorry for you.
My comment to “Late-binding migration to C#”
In this article Mauricio introduces the following VB6 code snippet to show how a converter can translate VB6 late-bound methods:
Sub ChangeValue(x As Object, newValue As Object)
x.Value = newValue
ChangeValue Me.Button1, False
A VB6-to-C# converter can translate late-bound code in basically two ways: by using .NET reflection or by generating an overloaded method for each possible argument type. Mauricio shows the output of a code translator that takes the latter approach:
void ChangeValue(Button x, object newValue)
Unfortunately for Mauricio, this is the poorest example he could ever think of. In fact, the only thing that it proves is that people should never write - or be allowed to write - technical articles if they are too lazy to double-check every single code snippet that they publish. In fact
If he had tested the VB6 code he would have realized that it cannot run at all, because you can’t pass False to the newValue Object parameter. (Of course, that parameter must be declared as Variant, not Object.)
The original VB6 code never triggers the button's Click event, because the Value property is assigned False. If he had tested the equivalent (!) C# code he would have realized that it behaves exactly in the opposite way, in that it always raises the event! A converter which blindly converts all assignments to the Button.Value property into a PerformClick method has a severe bug that should be fixed as soon as possible.
Regardless of this specific (and flawed) example, let me comment on the technique itself.
Using overloads of C# methods to simulate late-binding is surely feasible, but for completeness' sake it should be explained what happens when applying this technique to real-world apps instead of toy examples.
If you have a method whose object argument can receive any of the 30 control types used in the project, then this technique generates as many as 30 methods. If the method takes 2, 3 or more object arguments, then you have to account for all possible combinations of argument types. In a real-world program you might end up with hundreds methods.
Maintaining this redundant code over the years is a nightmare. For example, what if you later want/need to change one statement and forget to propagate the changes to all other overloaded methods?
B) CODE SIZE
These additional methods significantly increase the memory footprint of the application and slow down execution because each method must be JIT-compiled separately. If a given overload is used sparingly, this overhead can offset the speed advantage of early-binding.
C) FUNCTIONAL EQUIVALENCE
If a late-bound object doesn't expose a given method you receive runtime error #438 both under VB6 and VB.NET. Expert VB developers often leverage this behavior and the On Error Resume Next statement to write code that adapts itself to different object types. During the conversion to C# you lose functional equivalence, which means more work for those developers who have to check that the converted code works like the original one.