Visible Progress Home We make progress visible.
Search Site:
Resources > VB6 Coding Tips  
VB Quality Zone
VB6 Coding Tips
Self-documenting Code
Coding Standards
Naming Conventions
Error Handling
Binary Compatibility
Performance Tuning
Source Metrics
Process Tips
Testing Tips

Our Customers...
What Customers Say...

VS Law 2005 - VB.NET 2005 coding standards enforcement.
Try our products for free today.
VS Law .NET - VB.NET 2002/2003 coding standards enforcement.
Try our products for free today. VB Law - VB6 coding standards enforcement.
 
  VB Law - Quality assurance for Visual Basic source code.  
 

Self-documenting Source Code

In this article, we explore ways to make your Visual Basic source code self-documenting and thereby make it easier to read, understand and maintain. Although we will be referring to Visual Basic, it is worth noting that the techniques discussed in this article are equally applicable to most other programming languages too.

Keep It Simple

However over used you believe the phrase "Keep It Simple" to be, it is still ignored too often during software development. To make your source code self-documenting you must be prepared to take this phrase to heart. Simplicity itself aids understanding and therefore by definition makes your code easier to test and maintain.

Make simplicity and ease of understanding a deliberate goal. Avoid "clever" code whose intent is not obvious or complex code which requires detailed comments. Under such circumstances it is often better to simplify the code than attempt to explain it.

Let The Compiler Do The Work

Modern optimising compilers take much of the pain-staking effort out of memory management and performance tuning. The extra lines of code you might employ to ease understanding are therefore likely to have little additional impact on memory usage or performance.

Commenting Code Effectively

Comments can add considerable value to the achievement of self-documenting source code. To be relevant, comments must be located close to the code with which they are associated. The best comments summarise the purpose of a piece of code or explain the intent of the code which follows, leading the reader into what is about to happen next. The emphasis placed on comments therefore is to document "what" or "why" rather than "how". The code itself describes "how".

Things to do when commenting code:
  • Make each comment count - be concise and precise.
  • Describe the purpose of each source file.
  • Describe the purpose of each procedure.
  • Include the name of the author of each source file and procedure.
  • Describe the inputs and outputs of each procedure.
  • Explain assumptions made by code such as execution sequence, valid values or range limits.
  • Include references to formal documents such as test plans and specifications.
  • Explain work-arounds such as code that avoids an error or improves performance.
  • Explain undocumented features.
  • Explain global/module-level declarations.
  • Explain units of data declarations (e.g. hours, minutes, seconds etc.).
  • Explain enum element value meanings (at bit level if necessary).
  • Explain global variable declaration and usage.
  • Explain use of abbreviations (preferably avoid them).
  • Remove redundant comments.
  • Remove commented-out dead code.
  • Correct erroneous comments.
  • Things to avoid when commenting code:
  • Avoid comments which echo the code in different words.
  • Avoid use of abbreviations within comments whenever possible.
  • Avoid commenting styles that are time-consuming to maintain or difficult to amend.
  • Avoid inaccurate comments as these serve only to mislead the reader.
  • Avoid self-indulgent comments.
  • Avoid cryptic comments.
  • Avoid end-line comments which can become cryptic and are difficult to format.
  • Avoid verbose and superfluous comments.
  • Avoid littering code with vast amounts of comments for version history information.
  • Avoid commenting-out redundant code - delete it.
  • Don't document bad code - re-write it.
  • Reminder comments (distinguished by a common starting prefix such as 'TODO:) can offer valuable advice to the reader regarding work which is still to be done or currently in progress. Such comments should include the date, author name and reason for the reminder.

    Commenting Technique

    Don't leave commenting until the end, either do it first or as you go, otherwise it won't get done.

    A good coding technique, which promotes the logical breakdown of code and also encourages commenting, is to first write the header comments of a high level procedure and then write individual comments within the body of the procedure separated by blank lines. Next write the code itself (supported by additional comments) to implement each of the logical comments. This approach ensures that most of the comments are written first and therefore don't get forgotten.

    Choice Of Names

    The choice of names used in code construction is fundamental to the writing of self-documenting source code. We believe this to be so important that we have dedicated an entire article to the subject entitled 'Visual Basic Naming Conventions' which we recommend reading in addition to this article.

    Source Files

    Source files are the base building blocks of projects and usually the first thing the reader will look at (most likely via the Project Explorer).

    The names you select for Name attributes and filenames should be chosen carefully to direct the reader as early as possible to the appropriate source file. On opening a source file, the source file header comments should clarify the source file's purpose and therefore immediately confirm or deny the reader's expectations.

    Source files should group related functions and demonstrate high levels of cohesion. Loose coupling to other source files will promote re-use potential. Classes should be used to encapsulate complex data.

    Code Layout

    Indent Code Consistently

    The layout of well formatted code emphasizes the code's structure making the logic easier to read and understand and making the code path easier to follow. Agree the number of spaces to use per indent level (Visual Basic defaults to 4 spaces).

    Always align the following code block statements and indent statements nested within them:
  • Enum ... End Enum
  • For ... Next
  • Function ... End Function
  • If ... ElseIf ... Else ... End If
  • Do ... Loop Until
  • Do ... Loop While
  • Do Until ... Loop
  • Do While ... Loop
  • Property ... End Property
  • Select ... Case ... Case Else ... End Select *
  • Sub ... End Sub
  • Type ... End Type
  • While ... Wend
  • With ... End With
  • * Some developers do not align 'Case' and 'Case Else' statements with the associated 'Select' and 'End Select' statements but instead indent them a further level. Which ever convention you favour, ensure that convention is applied consistently.

    Use Continuation Characters To Break Long Lines

    Use a single statement per line and avoid using the colon (':') character to concatenate multiple statements onto a single line. Use continuation characters to break long lines. Make incomplete lines obvious and indent continuation lines to at least the same level as a nested statement.

    Use White Space Effectively

    Use blank lines to separate logical statement blocks. Always precede line labels with a blank line.

    Always insert a blank line after the following statements:
  • End Enum
  • End Function
  • End If
  • End Property
  • End Select
  • End Sub
  • End Type
  • End With
  • Loop
  • Loop Until
  • Loop While
  • Next
  • Wend
  • Adopt A Coding Style Which Is Easy To Maintain

    It is important that code is formatted consistently and avoids styles that increase maintenance effort. The example code below shows formatting of variable declarations with 'As' clauses aligned which, although attractive, unfortunately causes increased maintenance effort.

    
        Dim bExpired    As Boolean
        Dim dtStartDate As Date
        Dim dtEndDate   As Date

    Procedures

    Structure Procedures Consistently

    Adopt the following template when structuring procedures:
  • Comment header block.
  • Procedure declaration.
  • Constants.
  • Variables.
  • Error trap statement.
  • Argument assertions.
  • ... code block ...
  • Exit point.
  • Cleanup code.
  • Exit statement.
  • Error handler.
  • Always precede procedures with a comment header summarising the purpose of the procedure and documenting parameter usage.

    Ensure each procedure performs a specific, single task. Avoid adding parameters to existing procedures which pervert the single purpose of a procedure, instead add an alternative procedure to perform the desired task.

    Avoid creating "monster" sized routines. Split high level tasks into logical smaller, concise tasks. Consider the use of modelling tools which permit careful consideration of methods and arguments prior to coding the implementation. The iterative process of modelling can be extremely valuable prior to coding.

    Name Procedures Carefully

    The name of a procedure should state exactly what the procedure does - nothing more, nothing less. Badly named procedures often understate or simply fail to explain what the procedure does and can therefore mislead the reader.

    Assert Procedure Arguments Are Valid

    Within a procedure which accepts parameters, use 'Debug.Assert' statements for arguments that expect a particular value or limited range of inputs. The 'Debug.Assert' statements thus function with twin purpose: providing supporting documentation of the procedure arguments and as defensive coding constructs when tracing code execution in the IDE.

    Ensure Procedures Have Only A Single Exit Point

    Procedures should always have a single exit point. Avoid using multiple 'Exit' statements within a procedure. Having a single exit point helps to ensure that cleanup code is executed prior to exiting the procedure.

    Minimise Decision Points

    Seek to minimise nesting and conditional logic within procedures as much as possible. Particularly avoid deep nesting of conditional logic as this can lead to increased complexity.

    Functions which contain deep nesting and large numbers of decision points are best simplified by breaking down the code into multiple but simpler procedures.

    Note: See our article entitled 'Cyclomatic Complexity Metrics' for an explanation of how to measure the complexity of your Visual Basic source code.

    Simplify Expressions And Conditional Logic

    Use parentheses to clarify expressions (not everyone can or cares to remember operator precedence!). Where appropriate, move complex boolean expressions to their own separate functions where the logic can be isolated and documented with a meaningful function name and a clear function header comment.

    Avoid Code Bloat

    Some coding styles lead to code bloat i.e. too much code. An example of this is the use of return codes for communicating success or failure as compared to the technique of raising exceptions. Each time a call is made to a procedure which returns success or failure, the return code must be tested and appropriate actions taken according to the value of the return code.

    If a number of such calls are made within a single procedure then each call becomes ever more nested within the condition tests of previous calls. The additional code to trap return codes combined with the increased levels of nesting adds to the complexity making the procedure more difficult to understand, test and maintain.

    Note: For an explanation of the benefits of raising exceptions for error handling see our article entitled 'Make Your Error Handling Exceptional'.

    Loops

    Always indent the statements within the body of a loop. Try to minimise the number of statements within the loop as loops which contain sufficient statements to overflow screen size can become difficult to understand. Ideally, perform a single task only within a loop making it easy to view and the intent more obvious. Never leave the body of a loop empty and always ensure loops are entered from the top only.

    For 'For ... Next' loops, use a sensible name for the index counter and avoid using the index counter outside of the loop itself. Avoid using enumeration values for loop ranges.

    Use Of Constants And Enums

    Avoid magic numbers and string literals and use named constants instead. Use enumerations to define named lists of valid values and avoid bit-level values whenever possible. Always use comments to explain the purpose and values assigned to constant and enum declarations. Sensible names can also provide strong indications of their intended purpose.

    Use Of Variables

    Don't be afraid to make use of extra variables to make complex expressions, intermediate results and conditional logic easier to understand. Avoid using the same variable for different purposes merely to avoid declaring an extra variable.

    Related Documents

    Source code alone cannot be used to document all attributes of a piece of software. Most applications are often accompanied by supporting documents such as specifications for functional and non-functional requirements, test plans and technical documentation describing architecture, design goals, program structure etc.

    Visual Basic permits related documents to be associated with a project. To add a related document, right click the Project Explorer window and select the "Add" menu "Add File..." option. Select the appropriate filename and check the "Add As Related Document" checkbox. The related document will now be listed in the Project Explorer window within the "Related Documents" folder.

    Relating source code to supporting documents is more likely to allow both to remain synchronised and also points the reader in the direction of further related information.

    Automate code reviews with VB Law.

    How VB Law Can Help

    Having coding and naming conventions is one thing, enforcing them successfully is another. To ensure coding and naming conventions are implemented correctly you may wish to extend your VB Coding Standards and include such conventions as topics to be covered during peer code reviews.

    Find out how VB Law can quickly help define and enforce VB coding and naming conventions. VB Law has in-built support for scope tags, data type tags and control tags and comes with sample rules to enforce both coding and naming conventions.

    Visit our downloads page and trial VB Law for free today.

    Recommended Book Recommended Book ...
    Code Complete 2, Steve McConnell