The oldest tricks are the best tricks. Very early on some practical strategies were developed for writing robust code. Some of the most useful I ever read about came from Dave Thielen’s book, “No Bugs!“. Dave Thielen wrote the book describing debugging and testing strategies used to produce MS-DOS 5.0. It is likely that some of you won’t remember DOS 5, but it was hailed as one of the most reliable versions of DOS at the time. For this reason I was compelled to read Dave’s book. Interestingly enough DOS 5 was implemented in C, but the strategies for building robust applications have not changed that much. The tools available for writing robust code have evolved yes, but fundamentally they have not changed that much.
Around the time DOS 5 was available C supported the assert macro. VB .NET supports an Assert function. Programmers used the printf statement to write debug output, perhaps to a second monitor. VB .NET programmers can use Debug.WriteLine or Console.WriteLine to achieve the same result. Ultimately what we want to know as developers is what is going on internally inside of our applications while they are running. Dave’s book demonstrated some great techniques for discovering this information.
One such excellent technique is the ability to turn debugging code off and on from an external source. Until recently you would have to roll your own solution. Perhaps you could write a simple text file reader that examined the state of a flag or use GetSettings to read a value from the registry. If you read Dave’s book, someone demonstrated the technique, or you invented it on your own, you could have figured this out. But, most importantly is that .NET has made the ability to change the internal behavior of an application without recompiling a supported feature in VB.NET.
The class is named BooleanSwitch, and it is defined in the System.Diagnostics namespace. The BooleanSwitch class will read a <switch> element in an external XML configuration file. The configuration file is a text file that contains XML. Modify the configuration file and the behavior of your application changes according to how you used the switches in your code. The greatest benefit is that you do not need to modify the code, recompile, or be running the application in Visual Studio .NET.
The state of a switch defaults to off. If you do not provide the .config file then the any BooleanSwitch objects will be in the disabled state. A good scenario where this might come in handy is tracing down errors at a user location. A user calls will a problem. You email them a configuration file and then all kinds of new information is pumped back to you, without changing anything else about the user’s environment than the configuration file. The number and variety of switches is up to you. Very complex applications might use a complex system of switches; simpler applications might use a simpler approach.
I will demonstrate the mechanics of using a BooleanSwitch and leave the creative applications up to you.
Implementing the XML Configuration File
Now you know you are going to use a switch at some point. You need to define the .config file. Our example application when compiled is named switch.exe. Accordingly we name the configuration file switch.exe.config and place it in the bin directory where our executable assembly (or .DLL) will be. You can add a basic configuration file from the Add new Item dialog by selecting the Application Configuration file template as shown in figure 1. You will need to name the .config file app.ext.config where app is literally the name of your application and ext represents the extension of the compiled assembly.
Figure 1: Select the Application Configuration File template to create a .config file with the <configuration> element.
The Add New Item dialog will generate a .config file containing the XML version and encoding element and the <configuration></configuration> element pair. You will need to include the rest of the XML that defines the switch. Listing 1 implements a .config file that defines a BooleanSwitch named Switch. Scan the listing then read the synopsis in the paragraph that follows.
Listing 1: An XML configuration file for managing BooleanSwitches.
<?xml version="1.0" encoding="utf-8" ?> <configuration> <system.diagnostics> <switches> <add name="Switch" value="1" /> </switches> </system.diagnostics> </configuration>
The first line defines the XML version and encoding. The second line starts the extent of the configuration file. Elements usually have a beginning and ending element. The ending element contains a / (whack) followed by the element name or is abbreviated to />. The <system.diagnostics> element is used to group diagnostics switches like the BooleanSwitch. (After you have finished this article you should be able to figure out how to implement a TraceListener by using the .config file and the help documentation in .NET as a guide.) The <switches> element contains the actual definition of the switches, in our example a single BooleanSwitch. The <add> element defines a named switch and the value of the switch. The value property, as it is applied to BooleanSwitches, is understood to mean that zero is equivalent to False and non-zero is equivalent to True. The remaining tags are simply closing tag elements.
The XML in listing 1 defines a BooleanSwitch that will be enabled. If we want to disable the switch then we modify the .config text file, changing “1” to “0”.
Declaring the BooleanSwitch
The BooleanSwitch class is defined in the System.Diagnostics namespace. Add an imports statement to the module where you want to define an instance of the BooleanSwitch class or import the namespace at the project level on the Imports page of the Property Pages dialog, as shown in figure 2.
Figure 2: You can import a namespace at the project level or by adding an Imports statement to a module.
Once you have imported the Systems.Diagnostics namespace you can declare a BooleanSwitch variable. By passing in the name of the switch as it is defined in the XML .config file as an argument to the constructor, the BooleanSwitch class will read the state of the switch. Here is the code to declare and instantiate a BooleanSwitch to read the switch defined in listing 1.
Private Shared switch As New _ BooleanSwitch("Switch", "codeguru demo")
The .NET help file suggests that performance is improved by declaring the BooleanSwitch variable as shared. The BooleanSwitch instance is declared as a field, which just means that it is a data property of the class in which it is defined. The first argument must match the name property of the <add> tag in the .config file and the second argument is a description that we want to associate with the switch.
Now that you have the configuration file and an instance of the switch object, you can write conditional code that evaluates the state of the BooleanSwitch.Enabled property. If the value is not equal to “0” as is the case in our XML configuration file then BooleanSwitch.Enabled evaluates to True.
Using the Boolean Switch
You already know how to write conditional code. To use our switch object we could write code like the following:
If(switch.Enabled)Then MessageBox.Show("Switch Enabled") End If
What you put inside the conditional code is up to you. Use BooleanSwitch to provide extra information, like writing information to the EventLog conditionally. The conditional statement is identical whether you are simply display a message or performing a more complex object.
There are several good techniques for managing debug code. Just a few years ago you and I had to know about the techniques and figure out how to implement them ourselves. Tools have evolved significantly in the last ten years, and more substantially with the release of .NET.
The System.Diagnostics namespace contains dozens more capabilities than did the Debug object in VB6. A perfect example is the BooleanSwitch class we talked about in this article. The BooleanSwitch class allows you to write conditional code and manage it from an external XML file. No more rebuilding every time you need to enable your debug code.
A reasonable strategy might be to deploy beta software with the debug code in it. If your users need diagnostic support then send them a .config file that will turn on your conditional debug code. The BooleanSwitch is one more step in the right direction: allow developers to perform more complex operations more easily.
About the Author
Paul Kimmel is a freelance writer for Developer.com and CodeGuru.com. Look for cool Visual Basic .Net topics in his book Visual Basic .Net Unleashed.
Paul founded Software Conceptions, Inc. in 1990. Contact Paul Kimmel at [email protected] for help building VB.NET applications or migrating VB6 applications to .NET.