Visual Basic Programming Design Standards
Visual Basic Programming Design Standards for coding aren’t about rules that have been set in stone, they’re about practical guidelines that in the end will make your life as a programmer easier and your programs better. The intent in presenting this content isn’t to hand down a set of programming commandments, but to offer a set of guidelines for good coding. Some of what’s presented here are things we have learned from projects we’ve worked on, often the hard way, and some are things gathered and read about from respected sources and implemented as standard practice in development projects.
If you’re interested in a book length discussion of coding standards, we recommend that you read Code Complete by Steve McConnell, published by Microsoft Press. It’s one of the best books on good programming practices around. Many of the concepts you’ll find here are drawn from McConnell’s book.
- Program Design
- User Interface Design
There are many issues involved in building a good design. You not only have to consider the design from the programmer’s point of view, but also from the user’s point of view. I’ve divided this section into program design – meaning the internal workings of the application, and user interface design – what the user sees and interacts with.
Understand the Problem
Getting started on any project, especially a large and complex program, can be an intimidating task. You need to decide what the purpose of the application will be, what features it will support, how the user interface will look and behave, how the program will be structured, and much more.
However, the first task must always be to understand the problem. If you’ve been programming for a while, you may have experienced a situation where you sat down with a group of users, defined a problem, and laid out a prototype of a program – only to build the program and be told “Well, that’s not really what we wanted.”
The way to avoid this common scenario is to completely define the problem before you begin construction of the program. This is, of course, easier said than done. Often the users of an application don’t really know what they want the program to do or can’t express it in terms that communicate the objective fully. While they may have asked for a contact management program, what they may really want is a tool that allows them to communicate with and sell to their customers more easily and effectively. Perhaps that tool is a contact management system, but it may be something else entirely.
As the application designer, its up to you to make sure that what you’re building will do the job that needs to be done.
Break Down the Problem
There are a lot of different ways to go about designing an application, but I’ve found that what works best for me is to break down the problem into components. By breaking the program down in this manner, you can treat each component as much as possible as an independent entity, making the programming task easier and the application more flexible. If, for example, you are working on a customer database, you might break it down into a data access component, a business rule component, and a user interface component. By handling each component independently, you can change any of the components without needing to redesign the others.
Integrate the Solution
Once you have fully defined the problem and broken it down into independent components, you are ready to begin building and integrating the solution. Start by defining the interfaces between the components. As long as there are well defined and stable interfaces between the components, you can change the internal workings of any component without redesigning the application.
User Interface Design
Building a user interface according to accepted standards is the one area where I’ll approach the idea of laying out rules for design. Part of the success of Windows and Microsoft applications in particular is due to the common user interface across applications. Users gain a tremendous advantage if they have an idea of how to use an application right from the start. This can only happen if the design of the interface has the look, feel, and functionality of the applications they are already using.
If you’re looking for a complete and definitive reference to designing a user interface, you can find it in the MSDN Visual Basic Starter Kit that ships with VISUAL BASIC. Under “Product Documentation”, open “SDKs” and review the Windows Interface Guidelines for Software Design.
- Put control in the hands of the users.
Microsoft Windows operating systems provide a vast array of capabilities for users to customize their environment. Take advantage of this in your applications by using customizations that users have already defined, such as colours, date and time settings, etc. The user can modify these settings through control panel applets. If you use the already defined settings, you not only give the user additional control over the application, you also present a more consistent interface as well as saving yourself the trouble of building an interface for customizing the settings in your app.
- Use system tools where they are available.
Using established tools for things such as common dialogs, etc., gives users an advantage of already knowing how to use parts of your application before ever running it.
- Don’t assume that your app is the only program in use.
Microsoft Windows is a multi-tasking environment. Users – advanced users in particular – will often be running several applications at once. Keep this fact in mind when you are building your app and make sure that you don’t attempt to take over the system. This also means that you should not attempt to control settings that are normally handled by the user, such as display resolution, the window state of the application, etc.
- Follow established conventions for layout of interface elements.
The Windows Interface Guidelines for Software Design covers the arrangement of menus and controls in considerable detail. By following the established standards, you can give your application a professional appearance and give the users an extra degree of familiarity with the application.
- Integrate your application with the operating system.
Your application should support common operating system extensions, such as properly registering and associating file types with your application, supporting drag and drop if applicable, and supporting mail features.
Programmers have many varied and strong opinions on coding standards, so you’ll have to decide on your own what’s right for you. The one thing I will suggest as a key point to remember is that sooner or later, someone else will need to read and understand your code.
- Layout & Style
- Coding for Efficiency
Layout & Style
The main point to remember here is that the layout of your code can have a significant impact on the ability to read it later. While it may be perfectly valid to the compiler to pack five VISUAL BASIC statements on a single line or to write a procedure with no indentation, the code will be nearly unreadable to another human – and probably even yourself.
Here’s the short version of the layout guidelines I use when writing code:
- Place a block header comment at the top of each module and procedure. This should outline the purpose, rather than the implementation, of a section of code.
- Indent properly.
Indent all the code within a procedure and indent all conditionals and loops. This makes it substantially easier to follow the logic of the code. Additionally, I’ve redefined the standard indentation to be two characters rather than the default of four. I find two characters to be sufficient to recognize the indentation and allows deeply nested code to be easier to read without horizontal scrolling.
- Use white space liberally.
Adding blank lines between sections of code to separate groups of data declarations and blocks of code makes the program easier to read and makes it easier to follow the logic.
- Use inline comments liberally.
Add inline comments to describe data declarations and blocks of code. You should also add an inline comment at any point in the program where the purpose of a statement is not entirely obvious. A good guideline to use is that a person should be able to understand the purpose of the code without reading the code, and should be able to understand how the code works without reading the comments. If the former isn’t true, you need to add additional comments. If the latter isn’t true, you need to rewrite the code to make it less obscure.
Coding for Efficiency
There have been countless articles on optimising Visual Basic code; here’s a short outline of some of the common points that are often made.
- Avoid the use of variants.
Variants are generally Visual Basic’s slowest data type.
- Use integers where possible.
Integers and long integers are fast because they are the native data type of the computer hardware.
- Use variables to represent controls.
Retrieving and setting control properties is inherently slow. Using a variable reference instead of directly referencing the control in several statements can help improve performance.
- Use single statement methods rather than a series of property assignments.
While you can set the Left, Top, Height and Width properties of a text box, its much more efficient to simply use the Move method and reassign all four properties in a single statement.
There are lots of other commonly repeated optimization tips, but like these, many will often have minimal impact on performance. When looking at improving performance in an application, there are two things to consider:
- True Performance
This is the actual speed at which the code is executing and is for the most part completely irrelevant.
- Perceived Performance
This is the performance as perceived by the user.
What is important is that the user can move efficiently through an application and get their work done. There are two basic ways to increase the perceived performance of an application:
- Distract the user during long processes.
Splash screens, pretty pictures, and progress meters are common tools used to give users something to look at while a long running process is taking place.
- Give users something else to do during long processes.
When possible, you should try to move time consuming tasks into a background process and allow the user to continue with something else while the process is running.
Lets take a closer look at the second item. While Visual Basic doesn’t provide a means to start background threads in an application, you can use out-of-process OLE servers to hand off long processes. Another technique is to use a “just-in-time” strategy for presenting data. Disk operations are expensive from a performance perspective, even with today’s high-speed disks and networks. By delivering only the data that’s needed at the time that it’s requested, you can minimize disk i/o delays to the user. Caching frequently used disk data is also a method you can use to reduce delays, but take care not to try to store so much disk data in memory that your application becomes a memory hog, forcing the operating system to page additional memory to disk.
VB4 took a first step into object oriented programming by providing the ability to create class modules. However, you don’t necessarily need OOP features in the language to use modules effectively. Modules can be used to consolidate related code and to restrict access to data to those procedures that need it. This allows you to write code which is better organized and allows you to protect your data and avoid the use of global variables.
If you’ve written any serious applications which used a number of global variables, you’ve probably also spent some time working out bugs caused by inappropriate access to the global data. By using module level data and access routines for the data which is global in nature, you can control the means used to read and write the data and coordinate related procedures and data.
There are two basic ways to organize the procedures in a module:
- Group procedures that use the same data.
This allows you to protect access to data that is shared by several procedures. Also, since VISUAL BASIC loads modules on demand, you can use memory more efficiently by grouping the code that is using the shared data.
- Group procedures that perform related tasks.
If you followed the previous item, this has probably also been done. However, you may have related procedures that don’t share any data. For example, I always create a module of procedures that act as wrappers around API functions I use. In these procedures, I handle any setup operations (such as initializing return variables) required. By grouping all the API calls together, I can quickly locate and debug the code.
Another benefit of well organized and self-contained modules is that you can often drop a fully functional module into a new application with little or no modification – saving yourself a considerable amount of coding effort on new projects.
A procedure should perform one task and do it well. It’s often tempting when adding a feature to an application to wrap all of the feature’s functionality into a single procedure. The problem with this approach is that you end up with a lot of large, monolithic procedures with a lot of code repeated throughout the application. The result is an application that’s hard to debug, maintain, and modify.
You can avoid problems if you follow a few simple guidelines in writing procedures:
- Each procedure should perform only one task.
Don’t consolidate a bunch of unrelated tasks into a procedure just because they happen to occur together in the application.
- Separate data management from the user interface.
Write separate procedures to manage data and call them from the user interface code. This allows you to redesign the interface (a more common change) without redesigning the data management code.
- Give the procedure a clear, simple name that indicates what it does.
If you can’t do this, you probably need to rewrite the code. In the above example, I would have ended up with a procedure name something like this: AquireDataWriteRecordsApproveOrDenyApplicationAndGenerateLetters. If I had rewritten the program, I might have ended up with several small procedures with names like CreateDenialLetter and CreateApprovalLetter being called from other procedures.
There’s a lot more involved in writing good code than the few simple points I’ve outlined here, but this will give you a start. Keep in mind some of these key points when you’re sitting at the keyboard in front of a code window:
- Understand the problem before you begin building the solution.
- Follow accepted standards for user interface design.
- Write code that is readable.
- Separate user interface and data management.
- Design for the most efficient use of the program by the user.
- Design code that can be re-used.
Get yourself a copy of Code Complete by Steve McConnell. It’s one of the best texts on coding standards around. Although it’s not written specifically for Visual Basic, this one book will teach you more about programming (in VISUAL BASIC or any other language) than any other book I’ve read.
Programming Standards & Guidelines
Documenting Your Work
In any serious application, the importance of documenting your work can’t be overemphasized. Its nearly a certainty that you will need to return to the code later to correct a problem, integrate a new feature, or tune for performance. If you’re unable to determine what you were doing without reading the code line by line, you’ll not only waste a tremendous amount of time, but may misinterpret the original intent and cause additional errors to be introduced.
While you cannot use commenting and documentation as a substitute for an understanding of the source code, a well documented program will be easier to modify, debug, and maintain.
There are almost as many different opinions on what makes for good commenting and documentation as there are programmers, so I won’t claim to have a definitive set of rules for documentation, but I can say that this has worked well for me. Feel free to define your own standards for documentation. What’s more important than following any particular standard is to set a standard and follow it faithfully.
I’ve broken down my documentation standards into three basic areas:
- Application Design Documentation
- Source Code Documentation
- End-user Documentation
Application Design Documentation
Depending on the size of the application, this may be a few short pages describing the goals and overall design of the application, or may be a long series of formal documents. You may keep permanent bound copies filed with the rest of the documentation for the application, or just use it as a tool to organize your thoughts.
Whatever approach you take, its important to sit down before you start coding to plan out what it is you want to do and how you want to do it. You wouldn’t take off on a trip across the country without an idea of why you’re going or how to get there. You shouldn’t just sit down and start coding either. Here’s a few things I like to do at this stage.
- Give the application a name.
Even if its just an informal code name for the project, it helps to bring the project to life.
- State the goal of the application.
Forget design and implementation at this point. Decide what the application is supposed to do and how having this kind of tool will help the overall objectives of yourself or the intended users. Its often helpful to use a problem and solution approach – state the problem that the intended users are having and how the application would be a solution to the problem.
- Describe the features of the application.
Provide a list of the features the application will support and how the features will be integrated into the final product.
- Develop a design strategy.
Break down the major components of the application design, describing how each will be implemented into the application and integrated with the other components.
This is a very informal list. On a large application, you may have detailed requirements documents, change control procedures, and so on. For a small application, this may or may not be necessary – you’ll have to make your own choices based on your needs and the needs of the customer. If you’re writing a little utility for personal use, a page or two may do the job. Large applications may have hundreds or even thousands of pages of documentation written before one line of code is entered.
Once again, what’s important is that the documentation is appropriate to the project and that you do take some time, even for small projects, to think through why and how you will reach your objective.
Source Code Documentation
Programmers have widely varying opinions on writing source code comments. Some say they are a waste of time, or can even be harmful if they are not done correctly. Others say that no application is complete without good commenting in the source code. Some will even impose rules such as one line of comments for every five lines of code. I won’t suggest any such rules for you. The level of comments you find useful may be dramatically different from what I find useful. One thing to keep in mind, however, is that for any serious application, its likely that eventually someone other than you will need to read and understand the code. Even if you’re the only programmer in a five person company, you may one day leave the job and need to be replaced. If the next person who reads the code can’t understand it, chances are they won’t think of you as a mystical coding genius, but rather as a lazy bum who didn’t finish his work.
Here’s a few things that I find helpful in writing source code comments:
- Create a block comment for each module.
Describe the purpose of the module, the use of module level data, major procedures, and major interfaces to other modules.
- Create a block header for each procedure.
At the top of each procedure, create a short (one or two lines should suffice) comment describing the purpose of the procedure. I also find it helpful to describe the purpose of any parameters used by the procedure in this area.
- Sketch out a procedure with comments before you write it.
Write comments indicating each step in a procedure, telling why the step is taken and describing the logic of the code. Once this point is reached, you can simply fill in the code between the lines of comments to complete the task.
- Describe the use of data declarations.
If you are declaring variables and the purpose of the variable isn’t obvious, write a comment describing the purpose of the variable.
- Use comments to describe the intent of the code.
A decent programmer should be able to figure out the details of the code by reading it. Its more useful to have your comments describe what the code is supposed to do than to describe how it is done. This also makes the comments easier to maintain because you can change the implementation without rewriting the comments.
- Don’t use comments as an excuse for poor code.
If you are writing elaborate comments because part of the code is “tricky”, consider rewriting the code to be straightforward rather than documenting the “trick”. While there are times when you need to employ a shortcut in the code for the sake of efficiency, in most cases you’ll be better off in the long run to leave out the shortcut and write the code so that you can come back later and figure out what you did.
There’s nothing more frustrating for a user than to be sitting in front of an application and not know how to accomplish a task that the application is capable of doing. While it is an admirable goal to have an application with a user interface that’s so well designed that no one ever needs to consult the manual or help file, it probably isn’t possible. What’s obvious or intuitive to you may be cryptic to the next person to use the program.
The key point to remember when you are writing end-user documentation is to write the documentation at the level of understanding of the people who will use the software. In most cases, this will not be programmers or even power users, but normal people who use the computer as tool to accomplish a task.
Here’s a few things to keep in mind when writing help files and manuals:
- Describe the overall organization of the program.
New users in particular often need to get a “birds-eye” view of a piece of software in order to understand where to start. Provide an introduction to the program where you describe its capabilities and major features and how they can be used to complete an objective of the user.
- Tell how to use the program, not how it works.
The end user doesn’t care if the program has 10 lines of code or 10 million. They just want to get their work done. Don’t give your users a programming lesson – teach them how to do what they want to do.
- Provide a decent table of contents and an index.
Once most users become familiar with the program, they will use the manuals and help files mainly as a reference. Make their life easier by making the information they need easy to find. Although you can now do full text searches on help files if you are using Windows 95 or Windows NT, that’s no substitute for a well done index.
- Cross-reference appropriately.
No part of your application exists in a vacuum. Provide links in help files and written documentation to other relevant topics.
- Provide a means to obtain further assistance.
Even the most expert user working with the most complete help files and manuals may occasionally get stuck on a problem or not understand a feature. While you may not have the resources to provide a tech-support phone number, you should at least have available an e-mail or web address where users can go if they can’t figure out a problem or need to report an error in the application.
Clearly, there’s a lot more to writing good documentation than this. You may wish to start by reading the introductory chapters of the Help Compiler Guide, which will give you some excellent ideas about creating well written and well organized help files, and the The Windows Interface Guidelines for Software Design. Both of these will give you a good start toward creating well designed and useful documentation.