Increasing Productivity with Visual Basic 2005
Visual Basic 2005
Visual Studio 2005
Summary: If you work on data access, modeling, or network access, you can see significant gains in productivity in Visual Basic 2005 over Visual Basic 6. Bill Sempf tells you how to utilize new features in Visual Basic 2005 to improve your coding efficiency, including debugging, exception management, and data binding. (21 printed pages)
As programming languages become more and more sophisticated, developer's libraries become more and more useful. Visual Basic is no exception. In Visual Basic 6.0, developers enjoyed a wealth of built-in functionality, like user interface controls and data access.
The same is true in Visual Basic 2005. The .NET Framework also provides a host of 'close to the metal' libraries that empower programmers like never before. These libraries, however, have been written about previously. Today we will look at those parts of the library—some specific to Visual Basic and Visual Studio—that simply make the developer's life easier.
Visual Basic is, by design, a Rapid Application Development language. This just means that it should be easy to work from prototype to beta to finished program, in the least amount of time. Visual Basic 2005 should take this concept to the next level, and that is what we will be testing.
Not surprisingly, there has been a fair amount of research done on the productivity realities of programming in various languages. This is a good place to start when deciding what programming languages provide the highest levels of productivity.
I use two research sources to evaluate productivity. The first is case studies—though those are often funded by the language manufacturer. Since we are looking at Microsoft's own languages here, that isn't as much of an issue. Nonetheless, you can expect a certain bias that must be read through.
The second method I use is Function Point Analysis (FPA). FPA is a methodology that provides a structured way to estimate the time it will take to develop a defined application in a given language.
There is a lot to FPA, and I just use a little part here—specifically the Function Point Gearing Factor of a given language. FPA consists of calculating how many Function Points a given program is 'worth' by looking at data and business object constructs. The Function Point Gearing Factor (FPGF) is the number of Source Lines Of Code (SLOC) per function point that can be expected in a given project. Given the FPGF and the function points of a project, a project manager can get a good idea of how long it will take to develop the analyzed software. We will just be using the FPGF to compare the relative productivity of languages—like a productivity score.
Low Level Languages
A good starting point is low level languages—third generation languages like C. C is a remarkable language, with a plethora of usable libraries, but it isn't really designed for RAD applications. It is designed to work with a small set of libraries at a time, in order to assure the smallish size of the runtime libraries.
C has been the focus of many Functional versus Object Orientation (OO) productivity studies that aren't really fair. OO hides a lot of code lines in shared concepts, and it really is hard to compare the two methodologies. Nonetheless, T.C. Jones makes a good point in "Measuring Programming and Productivity"—the higher the number of lines of code, the higher the incidence of defects. Defects reduce productivity, so the more code you write, the lower the overall productivity.
Obviously, it also takes longer to write more code. But I digress.
C has a FPGF of 148, according to QSM. That means for a given Function Point of a project, a developer will have to write 148 lines of code, on average. This gives a baseline upon which to compare our further study of Visual Basic 6 and Visual Basic 2005.
Visual Basic 6
It is tough to compare C and Visual Basic 6, because Visual Basic 6 is a visual language that hides the implementation of the visual elements, and in C the user interface elements are handled with code. In the final analysis, we have no choice but to not consider the activity of instantiating and placing the user interface objects when determining the SLOC for a Visual Basic 6 application. That gives Visual Basic both a real and paper productivity boost, contributing to its becoming one of the most popular programming languages of all time.
Additionally, Visual Basic 6 has the benefit of being essentially a stand-alone program. It integrates with COM and uses it, but really it is a big program that is used to make other Windows programs. It uses the BASIC language, but it is very tightly integrated. It is almost not a language, but a large toolkit.
Much of the existing literature on the topic gets part of the story on Visual Basic 6. Gordon Mackie, for example, in his August 2004 whitepaper "Moving from Visual Basic 6.0 to .NET," states: "Probably the biggest advantage offered by .NET is that much of the code that would previously have had to have been written on a bespoke basis can now be considered as 'part of the plumbing' provided by .NET. No longer does the programmer need to write a mass of code to cope with, for example, memory management and garbage collection but instead s/he can focus their skills on developing business logic to meet the business need."
This is only partly valid for Visual Basic 6.0; for instance, memory management is handled fairly well by Visual Basic if you destroy your objects. The general attitude is correct, though—Visual Basic was a program for another time. It doesn't handle internetworking or contemporary graphics out of the box, as an example. The time spent building these pieces, or getting them out of the Win32 libraries, could be better spent elsewhere.
What it comes down to is: for what are you going to use Visual Basic? When the goal is writing simple database interaction programs, internetworking and graphics aren't the primary goal and don't enter into the picture. The issue is that more and more application are requiring these things, which are built into the .NET framework, but not the Visual Basic 6 runtime.
QSM has Visual Basic applications at an FPGF of 50, meaning 50 lines of code required per function point. The range is wildly divergent though, from 14 to 276 over nearly 100 projects—likely reflecting the "what are you using it for" problem I mentioned earlier.
Nonetheless, on the average it means that Visual Basic 6 is nearly three times as efficient as C for the same applications, and that is nothing to sneeze at. Even considering all of the differences between the language philosophies, it is a pretty solid upgrade in developer productivity.
Visual Basic 2005
Just as comparing C and Visual Basic 6 is difficult, comparing Visual Basic 6 and Visual Basic 2005 is difficult. Visual Basic 2005, with the .NET Framework, is a different language completely than Visual Basic 6. It also isn't a stand-alone program, but rather a language in a larger environment, Visual Studio. It is again a different beast altogether.
There are a number of productivity enhancing features of Visual Basic 2005 that not only make the coding much more straightforward in today's environment, but also reduce the FPGF.
- The .NET Framework—Basically an updated runtime, the Framework provides a much more in-depth 'library' of code than the Visual Basic runtime.
- The My object—Speed dial into the .NET Framework.
- Object Orientation—Creating objects in of itself will not necessarily save time, but reusing them will. Creating an entity that understands its own functionality and limitations is a massive code savings in most application types.
- Updated controls—New controls for a new era.
- Deployment tools—Though it doesn't relate to direct code lines, it does represent part of the whole picture.
- Inline documentation—Documentation can be generated right from source code comments, saving overall project cost.
Visual Studio 2005 is too new to have format Function Point Analysis statistics. My nine projects under the new version of the language will have to be the focal point of our investigation. I discovered an FPGF of 35 for Visual Basic 2005—the same as what QSM has for Microsoft Access applications.
Now that is pretty significant. There isn't one person among us who would recommend Access for an enterprise quality application, but it is so very easy to program. According to my statistics, Visual Basic 2005 is now just as easy as Access—at least in terms of lines of code. There is still that nasty .NET Framework that you have to learn to be able to code in Visual Basic 2005, but hey—it's a little thing.
To assist in evaluating the productivity enhancements in Visual Basic 2005 using Visual Studio Professional, I'll look at functional demos and code samples in these areas in which I have found the most improvement in productivity:
- Debugging with Edit and Continue
- Internet Access
- Exception Management
- The My object (especially IO, network, Web services)
- Collections with Generics
- Data Binding
There are other areas of productivity, mind you. More or less any place where the My object goes, productivity will be found for instance; and not just because of the My object itself. Microsoft has gone to great pains to increase the efficiency in the language, and it shows in many examples.
Edit and Continue
The development environment is probably the single greatest variable in a developer's productivity. From code completion to debugging, the IDE can help an average programmer code like a pro, and a professional programmer significantly increase quality output.
The ability to debug code a line at a time rather than via output variables is a real benefit to using an IDE. Visual Basic has, since its inception, allowed you to start a program in a debug mode and stop at a particular line and pause execution of a program, to let you see inside. Since that early version there have been many improvements, including the ability to edit that code in a stopped state and continue running the program: thus, edit and continue.
Visual Basic 6
Visual Basic 6 perfected 'Edit and Continue' for the language series. To demonstrate the power of the debugging tool, I simply created a new Windows Forms project with a button and a label. In the button's onclick handler I put this code:
Do Until CInt(Label1.Caption) < 1 Label1.Caption = CStr(CInt(Label1.Caption) - 1) Loop
Set the initial caption of the label to 10. I put a breakpoint on the middle line and started in debug. Click the button and the program will start. Press F8 to step through the code at the breakpoint and watch the caption decrease. The label shows: 10, 9, 8.
Then change the math application inside the loop to subtract 2 from the caption. Don't stop; don't do anything rash. Just change the code then press F8 to keep going. The Label shows: 6, 4, 2. That is Edit and Continue.
Visual Basic 2005
When Microsoft changed over to .NET in 2001, they dropped Edit and Continue as a feature of the IDE. I personally know three Fortune 500 IT departments that did not convert to .NET exactly because of the loss of this very important feature.
In Visual Basic 2005, Edit and Continue is re-added. In fact, you can run exactly the earlier example that I did in Visual Basic 6 with Visual Basic 2005, which is a good thing. At least we didn't lose anything.
What's more, you can attach to and debug external processes, while still editing your local code. If you are in the mood for a long, complicated example, give this a try.
- Create a Web Services project on a remote Web server, and a Windows Forms project locally.
- Make a Web method that has the countdown code in your Web Service project.
- Reference the Web service in the local Windows Forms project.
- Set up the button to call the loop code, and call the Web service with the countdown code.
Congratulations, you have just made the world's most useless scalable loosely coupled distributed application. Now you can debug it!
To debug the remote process, you need to attach to the ASPNET process on the remote server. Go to Tools | Attach to Process, and select the remote server. Note that you will have to have the Microsoft Visual Studio Remote Debugging Monitor installed on that server—it can't just be a production server.
Select the ASPNET process on the server, and click Attach. Now you can run exactly the same exercise as the previous two examples and change the code on the remote machine while still getting the Edit and Continue action.
BASIC, in general, was designed as a language long before internetworking. That doesn't matter so much, because the intrinsics of a good language are platform-independent. Visual Basic 6, however, was also largely designed before Microsoft had realized the importance of internetworking. This, my friends, is a problem.
The problem is that the libraries provided with Visual Basic 6 don't really support internetworking natively. It is a bolt-on, an afterthought. Getting information into and out of remote machines is not what Visual Basic 6 was built for. It's a client/server programming language; distributed networking isn't really Visual Basic 6's bag.
It is a reality today, though, and practically every large program written in any language is expected to do some remote communication. Configuration of this communication is a large part of development, and it weighs in on the question of productivity.
Visual Basic 6
The internetworking controls provided with Visual Basic 6 are effective, but are something of a patchwork. The major features of the internet are handled:
- The Inet control handles getting Web pages and files from FTP sites.
- The WebBrowser control gives users the opportunity to view HTML from a Visual Basic application.
- The MAPI control handles e-mail.
All in all, it's pretty easy to get an FTP site to transfer a file down to an application, for instance.
Inet1.Protocol = icFTP Inet1.URL = "ftp://ftp.msdn.com" Inet1.Execute "ftp://ftp.msdn.com", "Get file.txt C:\file.txt"
At first blush, this seems to be a pretty decent way to implement FTP. Get the format. Pass in the site. Pass in the filename. All in all it seems pretty reasonable.
But something just doesn't seem right. We passed in two generic strings for the Execute property. We passed in an enumerator for the Protocol. In an example like this it seems quick and easy to use, and it is. But what happens when it is in an enterprise environment?
What it means is that the Enterprise Architect will come down to your office next week to ask about SSL. Or the next requirement will be to upload a file. Or use UUCP.
There are components out there that do all of these. But that's not the point. The point is that Visual Basic 6 is based on a model that doesn't include any extensibility.
The reason for this is that it is feature driven. RAD languages—until Visual Basic 2005—were feature driven because that's how RAD was defined.
- Look at what people are doing with languages.
- Filter that down into features.
- Build a language that includes those features.
Fact is, the internet is based on a large selection of protocols that can be built into a programming language. They were not built into Visual Basic 6. These protocols by definition allow for extensibility with constraints. Visual Basic 6 does not allow for that extensibility.
Visual Basic 2005
The internetworking stack in Visual Basic 2005 is based on those protocols. It does allow for the same extensibility with constraints. In fact, it offers so much flexibility that it is possible to hang yourself; we will try and avoid that.
Getting a file from an FTP site has almost nothing similar to Visual Basic 6. There are four times as many lines of code. Yet, it is a better way to do things, and will actually increase your productivity in the long run.
'To accept the file, we have an object, not just a place in memory Dim localFileStream As New FileStream("c:\test.txt", _ FileMode.OpenOrCreate) 'The connection to the FTP server is an object, with properties we can 'modiofy to suit our needs Dim myRequest As FtpWebRequest = WebRequest.Create("test.txt") myRequest.Method = WebRequestMethods.Ftp.DownloadFile myRequest.Credentials = New NetworkCredential("Anonymous", _ "firstname.lastname@example.org") 'The response back fro mthe FTP server is also an object. Dim myResponse As WebResponse = myRequest.GetResponse Dim myResponseStream As Stream = myResponse.GetResponseStream 'Finally, we actually collect the file a bit at a time. 'Admittedly, this is one this that could be abstracted out. 'But hey, we will take what we can get. Dim buffer(1024) As Byte Dim bytesRead As Integer = myResponseStream.Read(buffer, 0, 1024) While bytesRead > 0 localFileStream.Write(buffer, 0, bytesRead) bytesRead = myResponseStream.Read(buffer, 0, 1024) End While localFileStream.Close() myResponseStream.Close()
The fact is that the object that makes that all happen is derived from a high level, protocol-based class called the WebRequest, which handles all socket calls back and forth between communication oriented TCP sockets. WebRequest is an abstract class that defines something very important—how the CLR communicates with the internet. Visual Basic 6 has nothing like that, and you can tell.
Errors, Exceptions and Debugging
A key to dealing with inevitable problems in program code is understanding the difference between an error and an exception. In short, an error is a type of exception. An exception is anything considered out of the range of normality by the program code, while an error is slightly more specific.
An error represents something out of the range of control of a program—something unrecoverable. For instance, breaking a business rule would be considered an exception, like myDate = 1/1/2000 where no date may be before 1/1/2001. An error would be myDate = "Fred". Clearly, Fred isn't a date, and there isn't any recovering from that.
Exceptions and the way they are handled changed dramatically going from Visual Basic 6 to Visual Basic .NET 2002. The trend continues in Visual Basic 2005 with even greater enhancements to the utilization of the Exception classes. While the immediate benefit of using structured error handling in Visual Basic 2005 compared to the GOTO constructs of Visual Basic 6 is mostly tactical, there is a monster productivity increase in the debugging tools that have followed along with the new model.
Visual Basic 6
In Visual Basic 6 the most common method of handling error is the GOTO construct, essentially instructing the runtime engine to watch for errors and move to a specific line of code if one were to occur. There is nothing wrong with this pragmatically—it is exactly how COBOL error handling works, and how much COBOL code has been running for decades with few changes. Error handling with GOTO looks like this in Visual Basic 6.
Private Sub Form_Load() On Error GoTo error_condition Dim x As Integer x = 1 / 0 error_condition: MsgBox (Err.Description) end_condition: End Sub
Nonetheless, it is much harder to debug an application with a GOTO construct that with a structured exception plan. For one thing, only the runtime can define an error condition. All you get to do when an error is triggered is look at it. You can't define errors, or look at what caused the error.
This isn't a deal breaker. I have written a number of applications that had pretty decent logic on only the information provided by Visual Basic 6 error handling. Nonetheless, all you have are the following:
This is not really enough to actually diagnose anything. We don't know what caused the error, unless we are lucky enough that LastDllError has anything. The environment gives us a hand, but the structure really doesn't.
What matters is the fact that the compiler and runtime define those error conditions through. All we can do is ask "So do you think THAT was an error? How about THAT?" and hope we get a decent answer.
Visual Basic 2005
Exception handling fixes all of that. First, developers get to define the error conditions. Don't get me wrong, division by zero like the previous example will always generate an example, but we can still say division by 34.25 is illegal and get caught by the exception handling.
Second, we get a ton more information per exception. Compared to the seven properties and methods of the Visual Basic 6 error, there are 14—twice as many—in the Visual Basic 2005 base Exception object:
Admittedly, some of these are inherited from Object, but there are still a few dingers in there. Specifically, InnerException, which has the opportunity to tell you what CAUSED the error.
We all get the same help from the user environment, but the new structure makes the exception handing easier to… well… handle.
First, the IDE handles the structure of the code block. I typed Try and pressed Enter, and that's about it to get the previous example. Second, we have the ability to specify different processes based on the exception without resorting to checking the text or error number. For instance:
Private Sub Form1_Load(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MyBase.Load Try Dim x As Double = 1 / 0 Catch divex As DivideByZeroException MessageBox.Show("You tried to divide by zero!") Catch ex As Exception MessageBox.Show(ex.Message) End Try End Sub
Third, we can actually define these special exceptions—a major boon to the process of problem resolution. The DivideByZeroException, and all exception classes, are just that—classes. You throw a base exception and define your own parameters, like so.
Private Sub Form1_Load(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MyBase.Load Try Dim x As Double = MyLittleFunction(6, 3) Catch ex As Exception MessageBox.Show(ex.Message) End Try End Sub Private Function MyLittleFunction(ByVal x As Integer, ByVal y As Integer) As Double Dim result As Double = 0 If x / y = 2 Then Throw New ApplicationException("Division can't result in 2") Else result = x / y End If Return result End Function
I realize that this is more code, but think about this in term of problem resolution in test, which is 30 percent of development. No matter from where this MyLittleFunction is called, the business logic will be enforced exactly the same way. No matter who calls this function, the exception can be caught in exactly the same way.
Most importantly, implementing this requires absolutely no opacity on the part of the called function. It doesn't matter what the function does, it will always react the same way.
Long time developers have designed some kind of exception handling into Visual Basic 6—some better, some worse. The benefit here is that it is exactly the same every time, it is transparent, and it is already written for you. It is one less thing that you have to code, teach, and debug.
The My Object
The My object is, as most readers know by now, a speed dial into the Framework. There are 240,000 or so public members in the framework, and you just can't memorize them all. The point of the My object is to make things more, well, findable.
Visual Basic 6
Because Visual Basic 6 has such a specific orientation, toward Windows Forms programming specifically (and data driven programming at that), there is not much need for a speed dial system. There are only 13,000 members in the Visual Basic runtime, and while that is too much to remember all of it, it isn't beyond most programmers to remember what they use often, anyway.
One of the common examples that developers point to is the Form object itself. In Visual Basic 6 the Form object is right out there, defined as Form, and that's that. The productivity is more or less built in to the language. With all of the objects in what is effectively the System namespace it isn't hard to find things—you just need to know that they are there.
The issues in Visual Basic 6 come in when you want to do something outside the scope of the language. To touch a Web service, write a PNG file, or read an Oracle database, you must load a component that is often far out of scope of the rest of the object model. This is where the simplicity of the Visual Basic 6 object model becomes its undoing. Add another function, add another namespace, effectively.
For these out-of-scope functions, the syntax can be practically anything. For an example, I dug up the PNG library by Kevin Wilson—modPNG—which depends on the LSSIBPNG_VB dll, which depends on the ZLIB dll... .you get the idea. In trying to write a PNG file I have had to go back to code written in 95. That is a scary prospect for a contemporary operating system. You can write the image with this function:
png_write_image (ByRef png_ptr As Any, ByRef image As Byte)
Easy to remember? Sure, if that's all you have to remember. No structure or organization—just another function.
Visual Basic 2005
Visual Basic 2005 is organized differently. The namespace structure follows a pattern that is learnable, no matter how much is added in later versions. To write a PNG file, you need just to make one from System.Drawing, then save it:
Dim pic As New System.Drawing.Bitmap(200, 200) Dim MemStream As New MemoryStream() pic.Save(MemStream, ImageFormat.Png)
More code? Yes. But it will be the same no matter what image formats are added later.
We are here to talk about the My object, though. The goal is actually to make programming oft-used functionality more like Visual Basic 6 without losing the benefit of the namespace hierarchy. This is done with a namespace hierarchy, of all things—but a non-cryptic, developer-savvy hierarchy. Open Visual Studio to a Visual Basic project and type My. It is pretty straightforward.
The things that you will find in Application deal with your application. That's not a surprise at all, I hope. The things in Computer deal with the client computer—sound, clock, file system, things like that. It makes a lot more sense than the framework. It's a lot more limited, but it includes all of the things that a working programmer uses every day.
I use it all the time. My current favorite:
My.Computer.FileSystem.WriteAllText("c:\file.txt", _ "This is my text", True)
It is the fastest way to write to a text file I have ever seen. For the performance fanatics, it compiles to a mere seven lines of MSIL. Fast. Don't let people tell you that the My object is a performance hog. It isn't true.
There are only about a thousand public members in the My object, and they are specifically designed for the Visual Basic programmer to find the features that he or she uses the most. Will everything be there? No. (Writing a PNG file isn't.) But if you are at a loss, look there first because a lot of stuff is.
Just a word about Snippets here. For those things that aren't in the My object (and a few things that are) the Snippets tool gives you access to hundreds of code bits that you would otherwise have to go find or figure out. Some of them are pretty snazzy too, like encrypting a string.
Dim fStream As FileStream = File.Open("encrypted.txt", FileMode.OpenOrCreate) Dim RijndaelAlg As Rijndael = Rijndael.Create Dim cStream As New CryptoStream(fStream, _ RijndaelAlg.CreateEncryptor(RijndaelAlg.Key, RijndaelAlg.IV), _ CryptoStreamMode.Write) Dim sWriter As New StreamWriter(cStream) sWriter.WriteLine("Text to encrypt") sWriter.Close() cStream.Close() fStream.Close()
It's just another place to check before you search Google. There is some nice stuff in there. To use just right click and select Insert Snippet:
To model a real world object in programming code, you sometimes need to represent a collection as a property. An apple (or fruit of type apple) has a collection of seeds. A company has a collection of people. A dissertation has a collection of chapters.
Collection managers in programming languages are becoming more and more important as we programmers model more and more of the real world in our applications. We need to iterate through items in an order, count chairs in inventory, and add and subtract people in our organizations. All of these are abstract collections as properties of objects. Once these objects are built, the future ease of programmability goes up tremendously.
Visual Basic 6
Visual Basic 6 supports Arrays like most other languages, but it is keyed, structured collections that we are looking at here, and for that we need the Collection object. The Collection object has four key members that make it perfect for the property that keeps on giving.
- Add—Add to the collection by passing in an Item, its unique key, and the key of the before and after object.
- Count—Get the number of items in the collection.
- Item—Reference one item with an index.
- Remove—Take an item out of the collection.
Here, then, is the Fruit.cls class file in the Grocery application (for sake of example).
Public Color As String Public Kind As String Public Yummy As Boolean Public Seeds As Collection
And to add to the seeds collection we can do something like this:
Dim Apple As New Fruit Dim firstSeed As New Seed Dim secondSeed As New Seed Dim thirdSeed As New Seed Dim aWorm As New Worm Public Sub ClassSetup() Apple.Kind = "Apple" aWorm.isLong = True aWorm.isSlimy = True Apple.Seeds.Add firstSeed, 1 Apple.Seeds.Add secondSeed, 2 Apple.Seeds.Add aWorm, 3 Apple.Seeds.Add thirdSeed, 4 End Sub
Whoa, what happened? I got a worm in my collection of seeds! That's no good! How can I prevent that from happening? Shouldn't the compiler catch that?
Well, yes it should, and that is just one of the many problems with Visual Basic 6 collections, and object programming in Visual Basic 6 in general. You see, the Item property of the Collection object is a variant, and that can be anything in the Visual Basic language, including a string, Seed, Worm or TextBox. And the compiler won't care. In order to work in a world of objects, we need a lot more—and a lot better—collection tools than this!
Visual Basic 2005
The first Microsoft framework with decent support for typed collections is .NET 2.0, and Visual Basic 2005 makes the best sense of it, in my opinion. Here are our base classes of Fruit, Seed, and Worm in Visual Basic 2005—not that much different except for one little thing.
Public Class Fruit Public Color As String Public Kind As String Public Yummy As Boolean Public Seeds As List(Of Seed) End Class Public Class Seed Public Size As String End Class Public Class Worm Public isLong As Boolean Public isSlimy As Boolean End Class
Note that the Seeds property is a list of seeds now, rather than a generic collection. We have typed the list. Now I can't even type in the Apple declaration, like I did before, without getting a hint that there will be a problem:
Then actually typing the phrase gets an immediate response from the compiler (something, by the way, you will not get in C#):
So because my list of seeds is typed now, I can be much more accurate in my coding, and not have to wait for QA to find the worm in my apple.
Generics is a big topic that I won't completely get into here—but what you want to know is that there are a few collection objects in Visual Basic 2005 that support generics, List just being one. Collections, LinkedLists, and Dictionaries also support generic classes. Check out MSDN for more on using generics, or just start working with List(of Type) in your code!
Data Binding is, for the most part, working with user interface objects that follow a standard set of interfaces to data objects. The benefit to productivity is the amount of code that the developer doesn't have to write in order to build a data-active screen. The issues are, of course, that the end user of the software is stuck with the functionality provided by the data binding built into the user interface objects. If there is something special needed, it is at least a custom job, and at worst impossible.
Both Visual Basic 6 and Visual Basic 2005 support data binding, but the data model has changed so much between the two that there is little to compare, line for line. We sure can compare them conceptually, however.
Additionally, the biggest boost to productivity in Visual Basic 2005 is the new Visual Data Designers, which allow for lots of code to be generated for databinding, without the need for black box components or a lot of additional hand-coding.
Visual Basic 6
The Data control runs all databinding for Visual Basic 6 forms projects. It accepts a connection and command, and allows binding to data points in the result set. For instance, if we were selecting inventory from the Items table, our code might look like this.
myDataControl.DatabaseName = "Inventory" 'this is a Data Source Name myDataControl.RecordSource = "SELECT ProductId, ProductName, Price from Products" myDataControl.Refresh
You can also set the DatabaseName and RecordSource properties in the Properties Panel.
Now we have a bindable list of items. To bind, we can set the DataSource and DataField properties for the text boxes appropriately.
That's all there is to it. Now we have a working application, with back and forward buttons, and editable items.
So what's the problem, you might ask? The problem is that once you want to do anything else you have to hand-code it. This is not a code generator at all; it is an ActiveX control that does some of the work for you and allows you to go no further.
The Data control does all of the heavy lifting here. While that initially seems like a good thing, the fact is that leaving you as the developer with absolutely no control causes more problems than it solves. For instance:
- You have no idea what is happening with the data connection under the sheets. Is it leaving the data connection open? Is it using the connection pool? Only its hairdresser knows for sure.
- You have no control at all over the intrinsic data controls. We assume that it is using ADO because that is what the rest of Visual Basic uses, but that is abstracted away from us.
- What if you have a data source that the Data control doesn't support? Well, as it turns out, you are toast.
- How about the -ilities, like scalability, maintainability, and… performability? We don't know because the nuts and bolts code is compiled into the Data control.
Due to these problems, most Visual Basic programs don't use data binding at all, which means that every program uses some different data connection code of its own invention. That's not good for productivity at all, because there are significant differences from programmer to programmer.
Visual Basic 2005
In Visual Basic 2005, any collection that implements the iList interface can be bound to. That alone fixes half of the problems—massively increased flexibility.
Additionally, the data binding tools are truly code generator. You can use the default generated code and it will work just as easily as the Visual Basic 6 example, or you can alter the code all the way down to the data layer level.
First add the data source to your project:
By default you can select a Database, object, or Web service, but we will just be using SQL Server here. The wizard looks much the same no matter which you choose.
I picked my local Northwind database—the same I used in the Visual Basic 6 sample—and sames off the connection string. Then I get to pick the table, view, or stored procedure. I selected the fields I needed—the wizard will generate my inline SQL for me.
Now you have a dataset—Visual Basic 2005's answer to the recordset. It is a disconnected in-memory representation of a database. It also makes generating databinding code very, very easy.
For instance, to make the sample in the Visual Basic 6 example, click on the ProductId in the Data Sources and change the drop-down list to None.
Then use the same technique to change the Products entity to Details from DataGridView. Then drag the whole entity to the form. Press F5 to run the application, and you have the same functionality as the Visual Basic 6 application, with even less hand-coding.
So what is the difference? Check the code for the form by double-clicking on the background (close the debug version first) and you will see the following code.
Private Sub ProductsBindingNavigatorSaveItem_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Me.Validate() Me.ProductsBindingSource.EndEdit() Me.ProductsTableAdapter.Update(Me.NorthwindDataSet.Products) End Sub Private Sub ProductsBindingNavigatorSaveItem_Click_1(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles ProductsBindingNavigatorSaveItem.Click Me.Validate() Me.ProductsBindingSource.EndEdit() Me.ProductsTableAdapter.Update(Me.NorthwindDataSet.Products) End Sub Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As _ System.EventArgs) Handles MyBase.Load 'TODO: This line of code loads data into the 'NorthwindDataSet.Products' table. 'You can move, or remove it, as needed. Me.ProductsTableAdapter.Fill(Me.NorthwindDataSet.Products) End Sub
This is the code that you couldn't see and couldn't alter in Visual Basic 6—the actual databinding code. And it gets better. Return to the Solution Explorer to double-click on the NorthwindDataSet (if you used Northwind). That is your data visualizer. Want to change it? Right click an object and select Configure. It even comes with a Query Builder.
Taking this idea further is the Partial class that backs up the Dataset. While you can technically edit the code that makes the dataset work (unlike the code that makes the Visual Basic 6 Data control up), you don't ever need to. You can just use the Partial class feature of Visual Basic 2005 to add or override code where necessary.
Partial classes are Microsoft's way of separating housekeeping code from the functional code of an application, and the DataSet class is an excellent example. To see what I mean, click the Show All Files button in Solution Explorer and then open the plus sign next to the dataset file. You'll see NorthwindDataSet.Designer.Vb. Open that—there is your plumbing code. Now aren't you glad we have Partial classes?
To make use of the Partial class, go back to the Dataset Designer and double-click on the UnitPrice field.
You will move to Code view, and get a class-within-a-class representing the Products table within the dataset. Note that both of these are Partial classes—the rest of the class is in the Designer file. In here, you can add code to, for example, prevent people from changing a price to anything higher than $100.50.
Partial Class NorthwindDataSet Partial Class ProductsDataTable Private Sub ProductsDataTable_ColumnChanging(ByVal sender As System.Object, _ ByVal e As System.Data.DataColumnChangeEventArgs) Handles Me.ColumnChanging If (e.Column.ColumnName = Me.UnitPriceColumn.ColumnName) Then If e.ProposedValue > 100.5 Then e.Row.SetColumnError("UnitPtice", _ "Prices can not be greater than $100.50"); End If End If End Sub End Class End Class
The inner If statement—the one in bold—is the only one I added.
Refactoring is the fancy name for a second run-through of your code to clean up after yourself. When Visual Basic 6 was developed, there was no fancy name for refactoring. None the less, most people did take a minute and clean up their code, and some even built some tools.
Visual Basic 6
In Visual Basic 6, refactoring support is limited. There is search and replace in the Edit menu, but that is about it. Navigation among members of classes is easy because of the dropdown lists at the top of code view. Because the classes are made up of actual class files, however, moving members around from class to class is a lot harder.
You have to remember, though, that the concept of refactoring didn't filter down until after Visual Basic 6 went to press. C++ developers were refactoring, but the business-programming crowd didn't get there for a while.
Nonetheless, there were some third party packages created to do refactoring in Visual Basic 6, and some of them were pretty nice. CodeShine was a favorite of mine, and it is still popular and available, as of this writing. It allows for extracting a bit of code into a function of subroutine, creating explanatory variables in complex statements and localizing module level variables.
Visual Basic 2005
Visual Basic 2005 is a more mature product in terms of refactoring, but you still have to look to partner add-ins to get the real benefit.
Renaming got a new lease on life, however. When you rename a member, be it public or private, Visual Basic will find all instances of the member and rename them, too:
Refactor! is the best partner refactoring out there. There is a free version on MSDN that will help you with extraction, as well as reordering parameters, flattening and combining conditionals, and a whole lot more. There is a pro version available, too, for a nominal fee.
The first and most obvious implication of all of this is that the developers will code faster if they use Visual Basic 2005. That isn't necessarily the case. Because the framework is so much larger, there will be a learning curve that might be difficult for the project managers to factor in, and the overall productivity might drop for the initial few projects.
More benefit will come in later stages of the project. First, the project will be easier to maintain because the framework is a known quantity, and fewer third party and home grown libraries will be used to handle contemporary development tasks. Second, the significant ease of prototyping will significantly increase the productivity of departments other than IT, because it is so simple to create testable, usable first versions of office information systems.
Ease of Maintenance
Maintenance begins with readable code. If the developer writing the initial program, no matter what the language, writes readable, well-documented code, the follow up programmer will work faster. This isn't an intangible metric, either; applications written with inline documentation in the source controlled version of the code have a 26 percent benefit in maintenance rate, according to Gartner.
With or without inline code, Visual Basic 2005 and its integration with the CLR, ADO.NET, and the other contemporary libraries that are part of the .NET Framework gives inherent documentation. There are few things better than knowing how a task will be accomplished before you look at the code.
Speaking of looking at the code: in 2004, applications that had a flaw in the development stage that was found in production cost 25 times as much as when the flaw was found as part of development. How you find flaws in development is with a good debugger.
The built in debugger with Visual Studio 2005 gives developers the ability to debug their code even as it runs remotely. Finding problems is so much easier in development that fewer will be caught in test or production.
Change is an expectation in today's business environment. I don't have a cool statistic for this, but I know from experience (for what that is worth) that being able to change a parameter in real time while stepping rough code with business analysis looking over your shoulder is, well, priceless. Cue the MasterCard commercial.
Ease of Prototyping
Just today, it was decided that two tables in a SQL Server database were to be replaced with an XML file for an ETL Process configuration. The two tables were related with a foreign key. I needed to generate the XML file and rewrite the ETL process that was based on it.
Generating the XML file took me three minutes and about five lines of code. Rapid prototyping using ADO.NET and other contemporary libraries that are part of the .NET Framework make a significant but slightly intangible difference to the business unit. The analyst on the case knew that he could tell me to convert to an XML file and that it wouldn't be a three day job. He was right.
Outside utility programming, the Collections model presented by Generics allows developers to write simple, straightforward classes that mimic a business process without spending hours writing plumbing code. Frankly, this isn't that much of a benefit in the world of Enterprise development.
Since the IT department can quickly model a business process in code, however, it has the opportunity to automate processes it never would have had the opportunity to automate. This is more of a load on the department, but the benefits to the business units are practically incalculable.
Productivity is one of those things; it is in the eye of the beholder. Some people are less productive when lots of stuff is done for them. Most people aren't, though; most people work well with tools that do some of the work.
Nonetheless, Visual Basic is a RAD tool, and if the end result is an Xbox game, no amount of Visual Basic productivity will help you. This article isn't about writing hardware drivers and video games, though; it is about productivity in business programming. It's not that you can't be artistic with Visual Basic—you can. But when you need to get things done, you can do that, too.
If what you are doing is impacted by the items in this article—data access, modeling, network access—then you are looking at a 30 percent increase in productivity over Visual Basic 6. I realize that FPGF and lines of code aren't everything. Productivity needs to be measured somehow, though, and Function Points are as accurate as anything else out there except the actual time spent programming.
The architecture review that I mentioned for a product that I was rebuilding to take advantage of SQL Server Integration Services is the best example I have seen recently.
In Visual Basic 2005, I set up a data source and wrote exactly six lines of code.
Dim myData As New SourceDataSet Dim sourceAdapter As New _ SourceDataSetTableAdapters.tbl_FileLoaderSourceTableAdapter Dim infoAdapter As New _ SourceDataSetTableAdapters.tbl_FileLoaderFileTableAdapter sourceAdapter.Fill(myData.tbl_FileLoaderSource) infoAdapter.Fill(myData.tbl_FileLoaderFileInformation) myData.WriteXml("c:\Fileloader.xml")
I know it is argument by generalization. Your application doesn't have to write XML from a datatable. All I have are examples, though—this whole article is made of examples.
Fact is, if your application isn't well suited to being a Visual Basic application, the language will not make you more productive. If your application is well suited to being a Visual Basic application, then the language will make you more productive. Review the things that are much improved in Visual Basic:
- Rapid Development and prototyping
- Network access
- Exception management
- Data access
- Refactoring and simplification
Ask yourself: do I need this? Or am I most interested in pointers and binary math? Be honest, and you might find that a move to Visual Basic is the most productive thing you do this month.