Coding standards - there's an expression that will strike fear and anger into the
hearts of many programmers. Don't let that happen to you. Coding standards aren't
about rules that have been carved in stone, they're about practical guidelines
that in the end will make your life as a programmer easier and your programs
better. My intent in presenting this page 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 I've learned on my own, often the hard way, and some
are things I've read about and implemented. Whatever the source, they've worked
well for me.
Parts of what you'll find here you can also find in more depth on my
documentation and naming
convention pages. On this page, I'll focus primarily on the guidelines I
use for application design and code construction. Since this is only a simple
web page there won't be a lot of depth to each section, but hopefully it will
be enough to get you started. If you're interested in a book length discussion
of coding standards, I highly recommend that you read Code Complete by
Steve McConnell, published by
Microsoft Press. It's the best
book on good programming practices that I've read. Many of the concepts you'll
find here were taken in large part from McConnell's book.
Application Design
- Introduction
- Program Design
- User Interface Design
Introduction
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.
Program Design
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
Introduction
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 VB4 Pro (or better) on CD. Under "Product Documentation", open
"SDKs" and review the Windows Interface Guidelines for Software Design.
I'll just outline a few of the basics here. It's also possible to meet
Windows 95 logo requirements using Visual Basic. I've made a copy of a
white paper from the Microsoft
Visual Basic web site which
outlines the logo requirements.
-
Put control in the hands of the users.
Windows provides 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 colors, 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.
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.
Coding Standards
I'll state right from the beginning that I don't claim to have developed a set of standards that
are right for everyone. 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
- Modules
- Procedures
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 VB
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's been a ton of paper used writing articles on optimizing Visual Basic code, and
I'm not going to waste a lot of space repeating that information here. First, you can
find it elsewhere easily and second, much of it is often unrelated to the true performance
of an application. Here's a short outline of some of the common points that are often made.
-
Avoid the use of variants.
Variants are generally VB'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.
Frankly, I don't think that the true performance of an application is relevant in the
vast majority of cases. 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 VB 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.
Modules
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 VB 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.
Procedures
I use one rule for coding procedures that has served me well. 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.
As an example, I'll illustrate a mistake I made coding an early add-on feature
to a database application. Part of a system within the application was a
procedure where the end-user would handle a paper application form for a
program, do some data entry, approve or deny the application, and then
send a letter to the applicant informing them of the status. This was a
single step of many in handling these application forms. Other included
pre-qualifying applicants and sending blank forms, answering status inquiries,
and so on. When I originally organized this sub-system of the main
application, I organized the code to follow the steps in the program. For this
particular step, the procedure would go through several steps to acquire the
necessary data, write a few records to the database, and then used Word to
generate either an approval or denial letter. As you can imagine, there were
times when failures could occur during the processing. The failures occurred
in one of three areas: coding errors, user errors, and physical printing
errors (paper jams, etc.). Since the process was written as a monolithic
procedure, a failure in any area forced the end user to start the entire
procedure from the beginning.
The mistake was really more a design problem than a coding problem. The code
was in fact broken down into probably 50 or 60 separate function calls and
was fairly well organized. The various functions were for the most part
well written and concise. There was a group of functions to manage sending
data to and controlling Word, a group of functions to write database
records, and several generic utility functions that were used throughout
the application. The problem is that the procedure was designed so that
it was impossible to generate the letters (the most failure prone part
of the procedure) without running the entire procedure.
You can avoid the problems I had 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
my 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.
Summary
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.
I'll repeat one other piece of advice I gave at the top of the page. Get
yourself a copy of
Code Complete by Steve McConnell. It's one of the
best texts on coding standards that I've read. Although it's not written
specifically for Visual Basic, this one book will teach you more about
programming (in VB or any other language) than any other book I've read.
I have one entire bookshelf dedicated to programming topics, and this is
one of about three books that I return to again and again.
Originally written by Joe Garrick
just a comment
thanks! you have taught me how to change my coding style for someone else to come and read and understand my code.
Thanks!
Hey, Thanks for sharing. I had the same experience wherein I had to learn to code VB6 on my own. ^_^
think you for your help
think you for your help
Post new comment