Comparing VB Migration Partner with Upgrade Wizard

clock August 27, 2008 08:27

A few potential customers asked for a detailed comparisons of our VB Migration Partner with Upgrade Wizard, the conversion tool provided for free inside Microsoft Visual Studio, in terms of compilation errors and warnings. Instead of just providing a series of unverifiable numbers we run both tools against a group of open source code samples which offer a variety of challenges, including rarely-used controls, data-binding, graphic methods, and drag-and-drop.  We benchmarked the Upgrade Wizard installed with Microsoft Visual Studio 2005 and the forthcoming release 1.00.06 of VB Migration Partner, on a Intel Core Duo 7800 @ 2.66GHz running Microsoft Windows Vista 64-bit SP1.

The results are available in a Microsoft Excel spreadsheet for all to see.

A summary of the results:

  • VB Migration Partner generates nearly 5x fewer compilation errors than the Upgrade Wizard before adding a single pragma. In most cases just one or two pragmas are sufficient to generate an error-free application.
  • Considering all the pragmas used in all samples delivers we get an average of one pragma every 430 line of code, but in a real application you need even fewer pragmas because a single pragma can affect all the files and statements in the project.
  • The Upgrade Wizard processes about 46 LOCs per second on the average, VB Migration Partner runs at 187 LOCs per second, i.e. 4 times faster. However, these timings are misleading, because at the end of the process VB Migration Partner generates code statistics and reports that the Upgrade Wizard doesn't.
It should be noted that compilation errors and warnings tell only a part of the story, because even a VB.NET project with zero compilation errors might raise one or more runtime errors. This means that even the samples that show few compilation errors after the migration with the Upgrade Wizard (e.g. CodeLibrary or AldInvaders) might require a lot of additional work to run correctly. By comparison, the column labeled as Number of pragmas indicates how many pragmas were neeed to have a fully functional VB.NET application that raises no runtime errors

Laughable business practices - Part 3, hopefully the last one

clock August 25, 2008 06:56

As you can read in Part 2 of this saga, Mauricio Rojas, a developer who works for a competing company, decided to write a series of articles with the only purpose of proving me wrong on my opinions about VB6-to-C# converters.

Writing one or more essays to counter your competitors' ideas is quite acceptable. However, Mauricio went a bit too far when he attacked me personally and questioned my expertise in code migration. (For the record, I am sure it's a personal initiative by Mauricio and that his company isn't involved in it.)

Mauricio wrote two articles, one on the translation of On Error statement and another on the translation of late-binding code to C#. I posted long comments to both articles, explaining that he made a few mistakes and that his examples were flawed. Unbeliably, Mauricio never published these comments!  This is the very first time I hear of a blogger exercising cersorship on someone who doesn't agree with him or her.

He did something worse, though. When Mauricio realized that the article about late-binding was filled with mistakes, he silently deleted the article, without offering any explanation! This is why this URL now points nowhere. By withdrawing the article, the author implicitly admitted that he was wrong. He could have written an errata, or just fixed the mistakes; instead, he took the easiest path and pretended that he never wrote it.

The fact that the original article isn't available any longer would put me in a weird situation, because my last post is a reply to an article that was never "officially" written. Fortunately, I had saved Mauricio's posts offline and you can download them from here (MHT format, for Internet Explorer) or here (HTML version in ZIP file, for all browsers) Call it premonition, if you prefer! Cool 

Laughable business practices - Part 2

clock August 15, 2008 16:22

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:

  1. the System.IO.File class doesn't even expose such a method Wink... or maybe he was thinking of the Copy method? (Tip: never trust your memory when writing a technical article...)
  2. the System.IO.File.Copy method doesn't accept wildcards in its first argument, whereas the FileSystemObject.CopyFile method does.
  3. 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
End Sub

Sub Test()
    ChangeValue Me.Button1, False
End Sub

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)

void Test()
    ChangeValue(this.Button1, false);

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

  1. 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.)
  2. 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?

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.

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.

Laughable business practices

clock August 14, 2008 01:24

First, a little personal background…

I have always been interested in programming languages, compilers, and code translators. Actually, compilers and code translators are quite similar: both parse a program written in a source language and transform it into something else: native CPU opcodes or IL opcodes in the former case, high-level language statements in the latter.

I wrote my first compiler 28 years ago on a pocket calculator, the mythical HP 41 CV, that had just 2.8K of RAM – it’s not a typo, I really mean 2800 bytes of memory! Shortly after I published my first BASIC compiler on a computer with 48K of RAM. I graduated at Computer Science University presenting my implementation of a PROLOG-like language, my first serious program for the IBM PC. A few years later I started my own software company and made some good money selling an MSDOS batch language compiler and a custom language for authoring expert systems. In the last decade I wrote at least one dozen parsers, interpreters, cross-reference tools, and code analyzers, either for internal use at Code Architects or for our customers. None of them ever became a commercial product, yet they allowed me to fine-tune the skills that made VB Migration Partner a reality.

All these details came to my mind when I read this post by Mauricio Rojas of Artinsoft. Let me quote him verbatim:

I hate to be disappointed. Specially if it is by a person you had respect for. And that's exactly what Francisco Balena from VB Migration Partner, has done. I have respected him for his books and all his VB6 experience. In terms of legacy VB6 code he is a monster. He is the man. But in terms of code migration...

The author doesn’t complete the sentence, but it’s evident he believes that I am just an apprentice in code migration, who can’t compete with all the experience he and all his colleagues have in this field.

Mauricio is so upset about my supposed ignorance that he forgets to mention when and how I disappointed him. He doesn’t even provide a URL for reference. He isn’t fair to his readers, who are deprived of the possibility to share his grief and concerns; and of course he isn’t fair to me, because he insults me without giving the opportunity to reply on concrete facts.

In the absence of more precise clues, I can only guess that Mauricio is thinking of this article, where I expose my opinion about the limitations of VB6-to-C# converters. His distress is understandable, because Artinsoft sells such a tool, a detail that makes his post look suspiciously closer to a (rather questionable) business trick than to the genuine grief of a disappointed reader.

Let me quickly recap the facts. In this article I affirmed that a VB6-to-C# converter can’t be as effective as a VB6-to.VB. NET converter. Some days later this post appeared on Artinsoft site, where the author declares that their tool can handle *all* the differences between VB6 and C#. That was a very strong claim, thus I decided to illustrate a few VB6 code snippets that no C# tool can translate in a satisfying manner, IMO.

Mauricio could have argued by showing how their tool converts these specific snippets. He could have commented my opinions and replied to my observations with concrete facts (and real code). Instead, he preferred to attack me personally, saying that my code generation experience is “disappointing” but carefully avoiding any detailed explanation.

I don’t know how effective this questionable business practice can be. In this specific case, however, it is more ridiculous than offensive, and the reason should be obvious:

I am the main author of VB Migration Partner’s parser, code analyzer, and code generation engine. Our tool runs many times faster and generates about 15x fewer compile and runtime errors than the Upgrade Wizard. Also, VB Migration Partner has many features that Artinsoft’s VB Upgrade Companion still doesn’t have after 6 years and two major versions.

Not bad for a code generation newbie, uh?