Find out the future of black-belt VB .NET—Francesco Balena

Want to go black-belt with VB .NET? Francesco Balena, founder of VB2TheMax and a leading black-belt developer himself will show you how. As a sneak peak to his VSLive! San Francisco session, "What Happened to Class Terminate?" check out his answers to questions on the future with VB .NET.




What are some cool things you can do in Visual Basic. NET that you just couldn't do in VB 6 no matter how hardcore you were?
I believe that in VB 6 you can do almost everything that you do in VB .NET, but in most cases you have to accept so many compromises that the result isn't worth the extra effort. Take multithreading as an example: VB 6 has the ability to create new threads in an ActiveX EXE program, but you get single-apartment (STA) threads that can't easily communicate with each other, can't be debugged in the IDE, and aren't as efficient as they should be.

Inheritance is another example: you can simulate inheritance using a delegation technique in VB 6, but at the expense of a lot of more code and reduced performance. To tell the truth, in his "Advanced Visual Basic 6" — the bible for all real hardcore VB programmers — Matt Curland explains how you can do free-threading in VB 6 and how you can simulate inheritance in VB 6 without a loss of performance, but of course the VB .NET implementation is cleaner and safer.

Function pointers (known as delegates in VB .NET) are also possible with some trickery in VB 6, but they aren't type-safe: if you make a mistake in your code VB will punish you with a GFP — unlike VB .NET, which emits a kinder and less disturbing compile error.

Most of the features of ASP.NET can be achieved in plain ASP as well, unlike what many developers believe. For example, you can do page postbacks and persist the value of controls quite easily, using classes written in VBScript. Similarly, you can create database-based sessions objects for use in web farms, and even cache HTML output to speed up subsequent requests to the same page. (I have demonstrated these techniques in my "ASP for smarties" VBITS sessions). Nevertheless, you can't compete with the built-in features of ASP.NET, because they are better integrated, require little or no code, and are much more efficient than what you can do in plain ASP, regardless of how smart you can be.

You see, the list of things that you can't do in VB 6 (or ASP) is shorter than one may think. But the price you have to pay to implement these hardcore techniques in VB 6 is just too high in most cases.

Are you saying that VB .NET isn't the revolutionary product that Microsoft says it is?
No, I am saying just the opposite: Visual Basic .NET is a revolutionary product, but not because it allows things that weren't possible before. It is revolutionary because it allows you to do those things with less code, fewer errors, and better performance. Of course, the merit should really go to the Common Language Runtime (CLR) and the hundreds of classes in the .NET Framework. The language just isn't as important as it used to be.

Take garbage collection as an example. In VB 6 and all COM-based languages, creating a complex hierarchy of objects has always been a challenge, because mutual relations between objects are virtually unavoidable in such complex systems. Alas, circular references can prevent an object from being released, and the application eventually runs short of memory and progressively slows down until it becomes unusable. This is a serious problem especially with server-side applications that are meant to stay alive for weeks or months. The .NET garbage collector makes this problem vanish away: circular references aren't a problem any longer and developers can adopt advanced object-oriented design techniques, without worrying about their practical implementation.

For a developer, recognizing the importance of .NET is relatively easy. However, you must be an experienced developer to fully understand the technical innovations behind the .NET Framework: VB developers writing simple desktop applications that don't need to scale and don't require any advanced techniques might not appreciate these innovations and might tout VB .NET as an unnecessary complication.

So, only developers of large enterprise and Internet-oriented apps will benefit from .NET?
Not exactly. Every VB developer can benefit from the innovations of VB .NET and of the .NET Framework Class Library (FCL). If you compare the amount of code that you have to write in VB 6 and in VB .NET to achieve the same result, you might be surprised to see how concise the new version can be. Because developers tend to write a given amount of lines per day (and produce more or less the same number of bugs for a given number of lines), it means that VB .NET lets you get the job done in less time.

Here's an example: some years ago I spent more than a week to write, optimize, and debug a string-intensive VB 5 application which resulted in about 2,000 lines of code. Lately I decided to rewrite it for VB .NET, replacing all the string operations with .NET regular expressions. The result was an application of only 120 executable statements, which I wrote in less than 2 hours!

The downside is that you must learn a lot about .NET before you can leverage its huge potential. In the case I just mentioned, I had to spend some hours reading about the classes in the System.Text.RegularExpression namespace. The .NET Framework is so vast that you might be tempted to reinvent the wheel only because you don't know that the classes you need to do the job are already there.

I believe that Microsoft is emphasizing the Internet-oriented features of the .NET Framework — namely, Web Forms and Web Services — without making it adequately clear that also developers of client-side applications can greatly benefit from .NET. An example? The Windows Forms package contains features that VBers have always asked for — easy localization for foreign languages and global error handlers, just to name a couple — yet you can hardly find these features mentioned in white papers and other promotional documents. Microsoft shouldn't forget that a large portion of the millions VB developers out there don't work with the Internet and might never need to create a Web Service.

Are there any projects that could be done more easily with VB 6 than with .NET? If a corporate developer needs to choose between a language for a given project what types of projects would still require VB 6 if any?
If we talk about projects in their entirety, I'd say that VB .NET is always a better choice than VB 6, because it delivers more robust code in less time. Moreover, Visual Studio .NET is so superior to the old VB 6 IDE that it would make a difference even if the languages were equally powerful. For example, you can automate tedious chores with VS .NET macros, debug your apps down to the CPU registry level, and use many controls and design-time components that aren't available in VB 6.

Among the few things that you can do more easily with VB 6 are operations with databases targeting single-users or small LANs, such as Microsoft Access. Classic ADO gives you more recordset and locking options, for example server-side cursors. ADO .NET is specifically targeted to larger client/server applications: it delivers more scalable code but requires a lot more work on your part, so some VB developers might decide that ADO suits their needs better.

Another limitation of ADO .NET is that, at this time, it officially supports only Access, SQL Server, and Oracle (with a native provider only for SQL Server), so you might have to stay with VB 6 and ADO if you work with other data sources. However, this is a temporary problem that will be solved soon, when other .NET Data Providers are released by Microsoft or third-party vendors.

A problem with VB .NET apps — and all .NET managed applications, for that matter — is that the intermediate MSIL code they produce can be decompiled more easily than the native Intel code that you get from VB 6. This doesn't mean that you easily can reverse-engineer an entire .NET application, but undoubtedly it is difficult to hide sensitive information in a VB .NET application. So you might opt for VB 6 if this is a concern for you — or at least use VB 6 for those components that contain sensitive information or proprietary algorithms. I heard that Microsoft is working at an obfuscator utility that will make decompilation more difficult, so this shouldn't be a serious issue in the long run.

How is multithreading in .NET different from multithreading in VB 6?
The main difference is that VB 6 multi-threading is apartment-based, whereas VB .NET uses free threading. Free threading is more efficient, because threads can share data and because free-threaded components run faster in ASP.NET and can be pooled under COM+. The great thing about .NET multi-threading is that it is built in the Framework, so all methods can be called asynchronously on a separate thread. For example, ADO .NET doesn't expose asynchronous methods to open a connection and execute a query (as ADO does), because all its methods can be invoked asynchronously. Same thing for file operations, background printing, and so on.

The downside is that writing free-threaded applications is very difficult, as many C++ developers can attest. You must learn about SyncLock blocks and the many synchronization classes that the framework gives you, such as Monitor, Mutex, Interlocked, ReaderWriterLock, ManualResetEvent, and AutoResetEvent. You also have to learn about the Thread and the ThreadPool classes, attributes such as ThreadStatic, asynchronous delegates, and callback notifications.

The multi-threaded world is full of traps. You must arbitrate access to every shared resource (be it a file or a simple variable), identify synchronization regions, and detect potential deadlocks. You must ensure that the objects you're sharing among threads are thread-safe, but some important objects in the framework aren't — most notably, arrays, collections, and all Windows Forms controls.

Debugging a multi-thread application is a nightmare: most thread-related bugs are hardly reproducible, because they depend on race conditions and the way the CPU is shared among threads and processes. Visual Studio .NET gives you a great, threading-aware debugger, but the task is challenging nevertheless. The bottom line: use multi-threading only if you really believe that your app can benefit from it. And do it only after all the implications and possible pitfalls are well clear to you.

However, you have to understand multi-threading even if you don't plan to use it explicitly, because it shows up anyway in VB .NET: for example, the Finalize method usually runs in a separated thread, so it can't safely access any variable without precautions.

In your opinion, how does OOP change with .NET?
It changes a lot, and I wonder how quickly VB developers will learn how to use the new features. The .NET framework is all about inheritance. If you don't know about overriding methods, polymorphism, shared methods, interfaces, and object finalization you can't create good code in VB .NET, period. For example, many of the tasks you perform under VB 6 by setting one or more properties — such as creating an MTS/COM+ component — now require that you create a class that inherits from a class or implement an interface defined in the .NET Framework. Even basic features — such as Windows Forms, Web Forms, and Web Services — are heavily based on inheritance.

Inheritance offers a great opportunity to VB developers: at last, we can design our apps using pure object-oriented techniques without having to accept the compromises of the VB 6 language. Future VB .NET applications will (hopefully) be cleaner and easier to maintain. But more powerful OOP feature require more discipline when designing the application: instead of rushing to the keyboard, developers should spend more time figuring out how classes should be organized, which one should inherit from which, which interfaces they implement, and so on.

The way objects are destroyed under .NET — the so-called undeterministic finalization issue — might create problems to developers who have used the Class_Terminate event to release resources, close files and database connections, and similar clean-up code. I suggest that you revise your VB 6 code looking for these events, and attempt to do without them, for example by implementing a method that clients can call when they don't need the object any longer (similar to the Dispose method that many .NET classes expose). The Import Wizard correctly converts Terminate event handlers into Finalize methods, but the resulting code doesn't always behave as expected: .NET objects might be finalized minutes (or hours) after the client set them to Nothing, and you surely don't want to keep a connection or a file open for that long.

I am really fascinated by how .NET garbage collection works: it accounts for much of the speed improvement under VB .NET and offers many possibilities not available to VB 6 developers. For example, in my VBITS session "What Happened to Class Terminate?" I show how you can create an object pool manager that lets you double the overall execution speed in some cases. This is a key COM+ feature, yet I could duplicate it in my programs with fewer than one hundred lines of code.

If you had to tell our attendees three "must do"s in migration their code from VB 6 to Visual Basic .NET what would they be?
First, you should learn as much as you can about .NET before attempting to convert your code. At the minimum, learn about the .NET classes in the areas you are more interested in. Database developers should study ADO .NET, desktop developers should learn about the Windows Forms package, and so forth. But all developers should become familiar with the classes in the System namespace, because these classes are going to be useful in any kind of application.

Second, decide whether you should translate the entire VB 6 application or just selected portions of it. If the existing code performs well, you might keep the kernel of the application in VB 6 and translate only a few portions into .NET components. You can use this approach because .NET objects appear to VB 6 as COM components, thanks to the COM Interop layer of the .NET Framework.

Third, revise your VB 6 code and prepare it for the migration. There are many things you can do to ease the actual migration step. For example, you can wrap all your API calls in separate classes, using the same name of the corresponding .NET class if possible (most API calls have a corresponding method of a .NET class). Next, you can encapsulate all your database-related code in separate routines, so that you'll have to convert fewer lines of code from ADO to ADO .NET. Speaking of databases, it is important that you revise your code to use forward-only read-only recordsets or client-side disconnected recordsets that use optimistic batch updates, because these are the only recordsets types that can be directly translated to ADO .NET. For example, you should replace code that uses dynamic cursors or keysets with code that uses FO/RO recordsets, and update data using direct SQL commands instead. If you revise your code and ensure that it runs well under VB 6, making it work in VB .NET will be simpler.

What are the three pitfalls to avoid?
Don't attempt to migrate entire apps at once. You should adopt a sort of bottom-up approach: start with the simpler routines — the kind of general-purpose routines that all applications contain — and then move to more complex procedures, such as data-processing procedures. Convert one form at a time, preferably without using the Import Wizard. This approach makes it possible to test the .NET application one piece at a time, and you can focus on specific problems without being distracted by too many details.

My next suggestion is: don't use VB .NET just as a better VB 6. Migrating your code to .NET without taking advantage of inheritance, polymorphism, and improved encapsulation just doesn't make sense. Continuing to use tons of API calls instead of using .NET classes is equally nonsense. Don't be lazy and don't stick to the methods in the Microsoft.VisualBasic namespace: these methods make your learning curve smoother, but they keep you from leveraging the full power of the .NET framework.

Third, and more important: migrating a complex application without knowing the inner workings of the .NET framework and VB .NET can be both useless and frustrating. It is useless because you might end up with a VB .NET application that has horrible performance and few new features. It is frustrating because — in spite of the many similarities — there are several minor differences in the languages that might drive you crazy if you are unaware of them. For example, the slightly different behavior of Public variables in classes can introduce subtle bugs in your migrated code, and it might take you hours to spot this kind of problems. (I cover many of such subtleties and hard-learned lessons in my "Take VB .NET to the Max" full-day seminar at VBITS.) To recap: Don't start writing code and then learn about .NET classes and features. This was the old VB 6, RAD-like way of doing things, but rules are different in the .NET game.


Francesco Balena
Francesco Balena is contributing editor and member of the Advisory Board of Visual Studio Magazine; author of Programming Microsoft Visual Basic 6 and of the forthcoming Programming Microsoft Visual Basic .NET, both for Microsoft Press; founder of the popular
VB2TheMax web site and the creator of the VBMaximizer programming tool for VB 6. Francesco regularly speaks at conferences such as VBITS, WinDev, and WinSummit, and teaches a five-day in-depth VB .NET seminar for Wintellect.