Writing Code That Is Easily Understood


Recording a simple macro here or there might not seem much like programming, but after you start creating them by hand, recording and editing more complex macros, or even writing what amount to full-fledged computer programs, some general principles of software development become more important. One of these principles is using a consistent system of coding conventions.

Coding conventions result in code that is self-documenting , which is to say, written in such a way that it describes what it is and what it's used for. Different aspects of self-documenting code can be accomplished through several methods , some of which have been touched on earlier in this chapter:

  • Naming conventions

  • Constants for procedures and variables

  • Explicit declarations

  • Named arguments

  • Modularized code

  • Formatted code

You know that your coding conventions work when someone unfamiliar with your code can rely upon the code itself to "explain" what procedures do, what type of data they accept or return, which variables have local or global scope, and so on.

Tip  

Use comments       Use comments liberally throughout your code. Strictly speaking, of course, comments have nothing to do with self-documenting code, but they are used to make your code as readable and easy to understand as possible.

Comments in Visual Basic begin with an apostrophe ('). Anything that comes after the comment character, even if it's in the middle of a line of code, is considered a comment and is ignored by Visual Basic. (An apostrophe that is inside a set of quotation marks is not treated as a comment character.)

Naming Conventions

Using a system of naming conventions is one of the easiest things you can do to make your code self-documenting. Using naming conventions means doing two things: using descriptive names for procedures and variables; and using prefixes that describe the data type, scope, and function of the procedure or variable.

Assigning descriptive names to procedures and variables doesn't have to mean that names will be long and complicated. All that is required is that the name indicate roughly what the procedure is used for or the type of information represented by the variable. Mixed case should be used to make the name easier to read, such as AddTask, FormatTableForPrinting, or TaskName.

Prefixes can be used to describe many things about the procedure or variable, such as type, scope, and function. In fact, there is a commonly used system of prefixes for Visual Basic, examples of which are shown in Tables 30-3 through 30-6.

Table 30-3 shows prefixes that describe data types, such as strTaskName.

Table 30-3: Data Types

Prefix

Type of Variable

bln

Boolean

str

String

int

Integer

lng

Long

obj

Object

var

Variant

Table 30-4 shows prefixes that describe controls, such as cmdOK and txtTaskName.

Table 30-4: Controls

Prefix

Type of Control

chk

Check box

cmd

Command button

frm

Form

lbl

Label

lst

List box

mnu

Menu

opt

Option button

txt

Text box

Table 30-5 shows prefixes that describe scope, such as the local variable strTaskName and the global gstrTaskName.

Table 30-5: Scope

Prefix

Type of Scope

no prefix

Procedure (local)

m

Module (private)

g

Global (public)

Table 30-6 shows prefixes that describe function, such as c_gstrTaskName for a global String constant and a_intTaskList to describe a local Integer array.

Table 30-6: Function

Prefix

Type of Function

c_

A constant

a_

An array

The following example of a sub and a function, taken from the discussion on procedures earlier in this chapter, illustrates the use of prefixes and descriptive names:

 Function strNewTask(strName As String, intBefore As Integer) As String     ActiveProject.Tasks.Add strName, intBefore         If ActiveProject.Tasks(intBefore).Name = strName Then         strNewTask = "Success!"     Else         strNewTask = "Failed to create task!"     End If End Function     Sub AddTask()     MsgBox strNewTask("Write chapter", 3) End Sub 

Suppose that you were reading the code for the first time, the two procedures weren't right next to each other, and all you saw was AddTask. Suppose further that AddTask was written as follows :

 Sub AddTask()     MsgBox strNewTask(strTaskName, intTaskNum) End Sub 

Because of a consistent pattern of naming conventions, you can infer a lot about strNewTask, including:

  • strNewTask is a function.

  • Functions use a prefix, and subs do not.

  • The function returns a String.

  • The prefix str denotes a String variable.

  • The function takes at least two arguments.

  • You do not know, however, if either argument (or both) is optional.

  • The first argument requires a String representing the name of a task.

  • The prefix str denotes a String variable, and the name of the variable indicates the type of information it contains.

  • The second argument requires an Integer representing the position of the new task in the task list.

    The prefix int denotes an Integer variable and the name of the variable indicates the type of information it contains.

Declarations

As described earlier in this chapter in the discussion on data types, variables (including functions, which you can think of as a special type of variable) can be declared implicitly or explicitly. Although there's nothing fundamentally "wrong" with using implicit declaration, explicit declaration is generally a good idea because:

  • Using the right data type is simply a matter of using the right tool for the job. The smaller a data type is (the less memory it uses), the faster it runs.

    Note  

    Although there might be situations in which you don't know the data type returned by a called procedure, which might make you inclined to rely upon implicit declaration, you should still explicitly declare the variable as Variant. Doing this doesn't create any performance gains, but you still get the other benefits of explicit declaration.

  • Explicit declaration means if you mistype a variable name, Visual Basic recognizes the error and warns you of the mistake. Implicit declarations mean that any variable name not already known by Visual Basic results in a new variable.

  • If you want to declare a variable with module-level or global scope, you have to explicitly declare the variable with the Dim, Private, or Public keywords.

  • It's easier to find and understand the uses for variables that are explicitly declared, especially if they are consistently grouped at the beginning of a module or procedure.

Named Arguments

When supplying arguments for a method, each argument is separated from the next with a comma; for example:

 ActiveProject.Tasks.Add "Write chapter", 3 

When it comes to self-documenting code, however, that code isn't especially descriptive. You can probably guess that "Write chapter" is the name of the new task, but it's harder to guess what the3is for. This is one way in which named arguments can be valuable .

Using named arguments means that instead of supplying just the values for each argument, you precede each value with the name of the argument. The argument name is then separated from the argument value with a colon and an equal sign:

 ActiveProject.Tasks.Add Name:="Write chapter", Before:=3 

It is now clear that the name of the new task is "Write chapter" and that it appears before the task that is currently third in the task list.

Named arguments are also used for methods that have many optional arguments, some of which you aren't using. Without named arguments, you must supply a comma as a placeholder for each optional argument, so that the arguments you are using appear in the expected order and position. This results in code that can be quite cryptic:

 Application.WBSCodeMaskEdit , , , 2, "-" 

The only way to find out what the two values are being used for is to look up the method in Help. If you use named arguments, however, you don't need to use placeholder commas and the code is very descriptive:

 Application.WBSCodeMaskEdit Length:=2, separator:="-" 

When you use named arguments, you can specify them in any order you choose. The code in the previous example could have been written with the two arguments in reverse order:

 Application.WBSCodeMaskEdit separator:=-, Length:=2Constants 

Constants are an important and useful feature of Visual Basic that makes code self-documenting. In fact, Visual Basic is full of constants, including what is probably the most common constant of all: vbCrLf. This constant, which represents a carriage -return and linefeed , is used to format text for display. The following code displays a sentence in two lines:

 MsgBox "Here is a long sentence, " & vbCrLf & "broken into two lines." 

The vbCrLf constant is much more user -friendly, not to mention convenient , than the old method of using Chr$(13) & Chr$(10) to do the same thing.

As mentioned earlier in this chapter, constants are frequently used to represent fixed numeric data, such as the Microsoft Project constant "pjFinishToStart." The name of the constant, especially when you know that it's a member of the PjTaskLinkType enumeration ("enum"), is very effective at describing what kind of link is being applied with the LinkPredecessors method, for example. Using just the numeric value of pjFinishToStart doesn't provide you with any real information at all.

You can create your own constants much as you would a variable, except you use the Const keyword and immediately assign a value to it:

 Const c_lngMyFinishToStart As Long = 10 

Modularized Code

When you record a macro, all the code generated by the macro recorder is written into one procedure. As you learn to write code by hand and begin to write more complex procedures, you might be inclined to continue this practice. Breaking your code into separate components for easily identifiable tasks, however, makes reading, debugging, maintaining, and modifying your code much simpler.

Looking again at the AddTask and strNewTask procedures, for example, you can see that there's no reason the functions of the two procedures couldn't have been combined into one. Keeping them separate means that AddTask could be modified to perform additional tasks by simply calling new procedures in addition to strNewTask, such as SearchForUnassignedResources and AssignResources.

Another aspect of modular code is that it makes writing new code faster and easier. A procedure that searches for overallocated resources, for instance, could be called from many other procedures rather than rewriting the same code for every procedure that needed it.

Formatted Code

Part of what makes something easy to read ”whether it's a book, a Web site, or computer code ”is its layout. Formatting your code for readability doesn't just make things easier on your eyes; it makes writing and debugging your code easier, too. As with naming conventions, there are some practices that have been standardized for Visual Basic:

  • Indenting, typically4spaces, is used to help differentiate the "contents" of a construct from the statements that define the construct. For example, the contents of a sub are indented from the Sub and End Sub statements. Similarly, the contents of a decision structure are indented from, for example, the If Then and End If statements.

  • Grouping declarations of variables and constants at the beginning of modules and procedures makes them easier to find.

  • Using blank lines before and after procedures, variable declarations, and decision and loop structures makes them easier to find and read.

  • Using multiple, indented lines for If Then statements not only makes it easier to differentiate the condition from the action taken when the condition is met, but simplifies the work necessary to add additional actions.

    For example, the line

     If ActiveCell.Task.PercentComplete = 100 Then MsgBox "Task complete!" 

    from the discussion of If Then statements could have been written as

     If ActiveCell.Task.PercentComplete = 100 Then     MsgBox "Task complete!" End If 

    Although Visual Basic supports placing multiple statements on one line, each separated from the others with a colon (:), doing so makes your code much harder to read.

  • Breaking long lines into multiple lines with an underscore (_) prevents excessive horizontal scrolling. The line continuation character can be used only after an operator (such as the &, +, And, and Or operators) or between arguments of a procedure. For example:

     ViewEditCombination Name:="Check Resources View", Create:=True, _   TopView:="Gantt Chart", BottomView:="Resource Sheet" 

    and

     If blnThis = True And blnThat = True And blnThose = False And _   blnOthers = True Then     MsgBox "Hey!" End If 
    Tip  

    When using the line continuation character, it's customary to indent the continued lines by two characters .

  • When breaking long lines of quoted text into multiple lines, the & operator and the line continuation character must be used outside of the quotation marks or they will be considered as part of the text:

     MsgBox "This is a very long line of text and would scroll " & _   "horizontally for quite a ways, which is why it was broken " & _     "into several lines of code." 



Microsoft Office Project 2003 Inside Out
Microsoft Office Project 2003 Inside Out
ISBN: 0735619581
EAN: 2147483647
Year: 2003
Pages: 268

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