Declaring and Initializing Variables

Team-Fly    

 
Visual Basic .NET Unleashed
By Paul Kimmel
Table of Contents
Chapter 3.  Basic Programming in Visual Basic .NET

Declaring and Initializing Variables

There is one significant difference in the way you write declarations for simple types and object types. That difference is the use of the keyword New. (We'll look at New more in the section "Using Objects.")

Variables can be declared and initialized in Visual Basic .NET on a single line. In addition to resulting in fewer lines of code, this new feature can be applied with some simple rules to make code more robust.

Before we look at several declarative statements, here is an overview of the best practices regarding variables that we will follow throughout this book:

  • Always provide an initial value for variables.

  • Declare and initialize variables in a single statement.

  • Declare variables immediately before they are used.

  • Declare variables in the narrowest scope possible.

  • Use the refactoring "Replace Temp with Query" to keep the number of temporary variables to an absolute minimum.

In each of the subsections, I will demonstrate several declarators supporting each of these best practices. In the final subsection, I will demonstrate the concept of refactoring, and illustrate benefits derived from refactored code.

Initialize Variables

In programming, so many things can go wrong that we need to hedge as often as possible to make things go right. These hedges , like splitting aces in blackjack, are good practices that help us progress deliberately without sweating details. By providing an initial value for variables, we are providing a reference point, or known state, that we can use to evaluate a variable. Essentially, by providing an initial state and controlling the value of variables, we can always evaluate a variable to determine whether its value is within an acceptable range. However, if we never expressed what an acceptable initial value was, we can't test the initial state.

The desirability of a variable having an initial state is exactly why object-oriented languages have constructors and parameterized constructors (the section "Using Objects" in this chapter covers these more). It's so that we can initialize even objects.

The general form of a variable declaration is as follows :

 Dim  varname  As  datatype  =  expression  

Note

Although VB6 code often was encumbered with a pseudo-Hungarian notation prefix for variables, we will not use the Hungarian notation in this book. The first reason is that no single notation existed, resulting in many inconsistencies. A second reason is that we are working with a strongly typed, object-oriented language, which mitigates the need for prefixes. Consequently, a notation would only increase our labor.

We will use a very simple notation in this book (you can adopt it or not). Fields will be prefixed with an F and properties will have an identical name, without the F, as their underlying field values. This convention was borrowed from Object Pascal and helps us name fields and properties consistently and quickly and makes the job of matching fields to properties trivial.


varname is replaced with a suitable variable name. Generally, whole words, no non-standard abbreviations, and no prefixes are used for variable names (see the note). datatype is the name of a class, structure, or ValueType like Double. Expression is a suitable expression for the data type. (The syntax changes slightly for objects and events. See the section "Using Objects" for object declarations and Chapter 8 for an example of WithEvents statements.) Listing 3.1 demonstrates several declarations, including suitable initial values.

Listing 3.1 Several declaration and initialization statements.
  1:  Module Module1  2:   3:  Sub AHandler(ByVal o As Object, ByVal e As System.EventArgs)  4:  Debug.WriteLine("Read chapter 9")  5:  End Sub  6:   7:   8:  Sub Main()  9:   10:  Dim S As String = Command()  11:  Debug.WriteLine(S)  12:   13:  Dim TodayDate As DateTime = Today()  14:  Debug.WriteLine(TodayDate)  15:   16:  Dim MyArray() As Double = {3.14159, System.Math.Sqrt(2)}  17:  Debug.WriteLine(MyArray(1))  18:   19:  Dim MyHandler As EventHandler = AddressOf AHandler  20:  MyHandler(Nothing, Nothing)  21:   22:  Try  23:  Dim MyException As Exception = New Exception("Raise an exception!")  24:  Throw MyException  25:  Catch e As Exception  26:  Debug.WriteLine(e.StackTrace())  27:  End Try  28:   29:   30:  End Sub  31:   32:  End Module 

Tip

If you are debugging in the IDE, you set the command-line arguments by opening the project's properties pages. Choose Project, Properties, Configuration Properties, Debugging to open the view. Modify the command-line argument's value to set the command-line argument.


Listing 3.1 defines some spurious declarators. The examples typify some of the declarations you are likely to encounter in everyday code. Line 10 demonstrates declaring a string and initializing it to the command-line arguments. The value of Command will include all of the arguments that follow the /cmd switch.

Line 13 demonstrates how to initialize a DateTime to today's date. Line 16 demonstrates initializing an array of doubles; MyArray is initialized to contain an approximate value for and the square root of 2, returned from System.Math.Sqrt.

Line 19 declares MyHandler as the Delegate type EventHandler and initializes it to the address of the subroutine AHandler. Lines 19 and 20 illustrate that Visual Basic .NET can work with function pointers and introduce the subject of delegates. Delegates are special classes that support function pointers and are used to implement event handling in Visual Basic .NET. Chapter 9, "Understanding Delegates," gives more information on this subject. (For now, suffice it to say that when MyHandler is called on line 20, the subroutine on lines 3 through 5 is actually called.)

Lines 22 to 27 demonstrate declaring and initializing the root exception object. Line 24 demonstrates throwing an exception, which is similar to raising an error in VB6. Lines 25 through 27 demonstrate a Catch block. The last section of this chapter covers exception handling.

Declare and Initialize Variables in a Single Statement

The biggest problem with uninitialized variables is related to pointers in C and C++. Because C/C++ pointers can point to any memory location, an uninitialized C/C++ pointer might be pointing to BIOS memory. Visual Basic .NET has limited support for pointers, so we are able to get away with the default initialization of variables to the null equivalent more often.

Tip

By default VB .NET initializes numeric types to 0, strings to empty strings, and objects to Nothing.


However, Visual Basic .NET does support delegates and dynamic object creation. It is preferable that these types have an initial value; otherwise , your code will be littered with checks for Nothing or an equivalent. Calling an uninitialized Delegate results in a NullReferenceException, which is cleaner than crashing because of a pointer trashing BIOS memory, but still annoying.

As a convenience, it is easier to have one rule for all cases than to make exceptions to the rule. Thus it is easier to always declare and initialize variables in a single statement.

Declare Variables Immediately Before First Use

There is no compelling reason to declare variables at the top of a procedure. Declaring them immediately before first use makes it easy to track the type and purpose of a local variable.

As an added benefit, if you are able to apply the refactoring "Replace Temp with Query," having the temporary variable close to its point of use makes getting rid of the temporary variable easier too. (See the section "Employ Refactoring: Replace Temp with Query" for more information on refactoring.)

Declare Variables in the Narrowest Scope Possible

Global variables are bad. The reason global variables are bad is because the opportunity for misuse is greatest. The opportunity for misuse of data should be reduced as much as possible; or, simply put, the narrower the scope, the better.

You are familiar with module, class, structure, and procedure scope. You may also use accessibility specifiers to further reduce opportunity for misuse. Accessibility specifiers like Public, Private, Protected, Friend, and Protected Friend are discussed in Chapter 7. Block-level scope has been added to Visual Basic .NET. Block-level scope is the narrowest scope of all. Refer to the section "Working with Block-Level Scope" for more information.

Employ Refactoring: Replace Temp with Query

This book does not cover all the details of refactoring. A great book on refactoring is Martin Fowler's Refactoring: Improving the Design of Existing Code , published by Addison-Wesley. However, where it is suitable to mention refactoring, I will do so.

What Is Refactoring?

Refactoring is an outgrowth of XP (Extreme Programming), which has been popularized by Kent Beck and others. XP includes concepts like pair programming and resolving problems in the structure of code with refactoring. Refactoring stems from a dissertation by William Opdike.

My definition of refactoring is "factoring out common code." The real benefit of refactoring is that it provides a language, or a frame of reference, for talking about improving code, and offers a set of almost algebraic rules to make refactoring an orderly process.

We can't summarize Martin Fowler's book here, so for now, just accept that refactoring is a good thing. Refactoring helps move towards the fewest occurrences of repetitive code and helps achieve greater opportunity for reuse. Refactoring may also lead to a means of measuring the qualitative value of code. Good code is refactored code; bad code often is not.

Replace Temp with Query

"The problem with temps is that they are temporary and local. Because they can be seen only in the context of the method in which they are used, temps tend to encourage longer methods" (Fowler, p. 120). Long methods are less desirable than short methods .

By replacing a temporary variable with a querya function that returns the value previously maintained by the temporary variablewe shorten the procedure and increase the likelihood that other fragments of code can use the query method instead of reconstructing the temporary variable.

Assume that we have two properties: Sale and TaxRate. TotalSale is defined as the sale plus the cost of taxes. Also, suppose that we have a fragment of code that declares a local temporary variable to store TotalSale:

 Dim TotalSale As Decimal = Sale * (1 + TaxRate) Debug.WriteLine(TotalSale) 

The Debug.WriteLine statement plays the role of using the temporary variable.

To replace temporary variables with a query method, first look for temporary variables that are assigned a value just once, as is TotalSale. (If it is assigned values more than once in a procedure, you may need to simplify the procedure or keep the temporary.) Having identified the temporary, perform the following steps to complete the refactoring:

  1. Define a function, adding a Get to the temporary variable name. Define the function to return the calculated value of the two fields. (In the example, Sale and TaxRate represent the two fields.)

     Function GetTotalSale() As Decimal   Return Sale * (1 + TaxRate) End Function 
  2. Replace the initialization of the temporary with the function call.

     Dim TotalSale As Decimal = GetTotalSale Debug.WriteLine(TotalSale) 
  3. Compile and test the modification to ensure that the code behaves identically and yields the same results.

  4. Having confirmed identical behavior, remove the temporary variable and replace the use of the temporary with the call to the query method.

     Debug.WriteLine(GetTotalSale()) 
  5. Compile and test.

The purpose of refactoring is to get the same result with simpler code. Testing after each phase of the refactoring makes it easier to roll back changes if the code behaves differently.

Critical to Extreme Programming and refactoring is the testing process. The benefit of the refactoring "Replace Temp with Query" is that long procedures become shorter, while performing the same operations, and the frequency of debugging the local temporary calculation decreases to one time, in the query method.

The benefit of such refactoring often rises over time. The more times you would have written the calculation for the temporary again, the more savings you achieve.


Team-Fly    
Top
 


Visual BasicR. NET Unleashed
Visual BasicR. NET Unleashed
ISBN: N/A
EAN: N/A
Year: 2001
Pages: 222

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net