Professional Documents
Culture Documents
Standards and
Conventions
Guide
Introduction
The purpose of this document is to promote a few common practices and
standards to make systems more robust, have fewer errors and be more
maintainable. These conventions and standards are meant to encourage the
development of a common understanding of how a piece of software should
be written and to set minimum expectations of the developers.
These standards are intended to facilitate the exchange of ideas and to assist
developers in understanding others work. They are also intended to reduce
the learning curve of developers who are new to the team.
Note: The terms program and code in this document can be taken to
mean any file or other piece that makes the source for the
executable program or the data on which that program operates.
Development Environment
Conventions
Whenever a program is written, the configuration of the workstation that
created the program may be a determinant in the successful execution and
maintenance of the program. The program may not run properly or be able
to modified on a workstation with a different configuration. In order to avoid
these types of problems all workstations must either be restricted to a
minimum configuration or a standard configuration must be agreed upon.
Directory Structures
In lieu of storing all files in a single directory, an organized structure needs to
be established so that there is no confusion over where a particular piece of
code belongs or over how to find a piece of code. While there are an infinite
number of ways to organize files into directories, in general, the organization
should be on a functional basis.
At the highest level is the enterprise and/or client for whom the work is being
performed, in this case rns. Under the enterprise are the major units of work.
Here we have, gears, ibps, leader, leaderCounts, leaderDetail, legacy,
newR&S and schemas. There is a special unit for code that is common to all
units.
Each unit except for the common unit, may contain any or all of the
following three sub-units: meta, load and prod. Meta is used for storing the
metadata for the unit. This is the information about the data not the actual
data. Load is used for building the production schema from the metadata and
populating the production schema from external sources. Prod is the actual
data.
Within each sub-unit and the common unit are subdirectories for the actual
sources files. For example, classes, reports, prgs, images and forms. The
number of these directories and their names can vary from sub-unit to sub-
unit.
In addition to the source code directory structure there are two other
directory structures, the following is an example of one of these structures:
This structure is the data directory. The data directory contains all data for
every unit and sub-unit in the enterprise. In this case the directory rnsData,
contains a subdirectory for gears which has subdirectories for load, meta-data
and production. These directories contain the database and tables for their
specific sub-units. For the meta sub-unit, this would contain the meta-data,
or data about the data, in the load sub-unit, it would contain any persistent
data required to assist in the loading of the external data, in a prod sub-unit,
the data directory would contain the actual production data.
The inbox directory is for storing external sources of data that are processed
by the sub-unit. In this case the inbox directory is rnsInbox. Like the data
directory, the units with the inbox directory are seperated into sub-units. In
the meta sub-unit this could be documents or tables containing meta-data that
is used to build the meta-database. There can be subdirectories to organize
the external data by set and by type. The load directory would contain flat
files or extracts containing production data from other systems that is to be
loaded into the production database for the unit. Typically there is no
production inbox sub-unit directory.
In order for files to be easily found and executed while developing without
having to explicitly specify a directory, a path can be established to the
various directories containing the needed files. These paths may depend on a
specific default directory requiring the developer to change to the directory in
order for the path to function properly. It is important to note that the
development environment is dependent on the setting of the default directory
and not the executing code.
This path depends on setting the directory to a sub-unit. Relative paths then
allow all the files in the sub-unit as well as the root directory of the unit and
enterprise to be accessed without having to specify a directory when referring
to a file. In addition, absolute paths are used to directories containing files
that are common to all units as well as to the developers own local work
directory.
Path Description
Temporary Files
In order to reduce the clutter created by temporary tables, test programs and
other types of work in progress, all files that are not a permanent part of the
project should be stored in a local directory and not within the enterprise
directory structures. The reason for this is that it can be very difficult to
delete files in a public or shared directory for fear of deleting a file of import
by accident. This results in the bloating of directories with files that are no
longer of use.
The developer should take care whenever a new file is created in a shared
directory to ensure that the new file is indeed a relevant and permanent part
the project. In addition and more importantly, developers need to make sure
that they remove files from the shared directories whenever files become
obsolete and are no longer relevant or needed.
Archives
The shared directories are not to be used to store archives of data files or
code. The shared directories should only contain the current state of the
work in progress.
Configuration
The configuration file can be invoked by using the –c command line option
for VFP. One way to do this is to create a shortcut to the VFP executable
and change the target property to something similar to:
"C:\Program Files\VS\Vfp98\VFP6.EXE" -cc:\work\rns.fpw
Programming Conventions
The localHloaded constant is used to verify that the header file is being
loaded when a program is compiled.
The ENTERPRISEPATH constant defines path where this workstation finds the
enterprise source files. The value pathtoenterprisedirectory is the path to the
root directory of the enterprise source.
#include c:\local.h
#define PEMSTATUSUSERDEFINED 4
#define PEMSTATUSDEFINED 5
#define ZORDERTOBACK 1
* ----------------------------------------------------------- *
* Default paths to sub-units
* >---------------------------------------------------------- *
#define LOADPATH "load\"
#define METAPATH "meta\"
#define PRODPATH "prod\"
* <---------------------------------------------------------- *
* ----------------------------------------------------------- *
* ///////////////////////// UNITS \\\\\\\\\\\\\\\\\\\\\\\\\\\ *
* ----------------------------------------------------------- *
* ----------------------------------------------------------- *
* Gears Unit
* >---------------------------------------------------------- *
* Unit path
#define GEARSPATH ENTERPRISEPATH + "gears\"
#define GEARSDATAPATH ENTERPRISEDATAPATH + "gears\"
#define GEARSINBOXPATH ENTERPRISEINBOXPATH + "gears\"
* Sub-unit paths
#define GEARSLOADPATH GEARSPATH + LOADPATH
#define GEARSMETAPATH GEARSPATH + METAPATH
#define GEARSPRODPATH GEARSPATH + PRODPATH
The enterprise header file must include the VFP header file foxpro.h so that
all routines have access to these predefined constants. The enterprise header
file must also include the local header file so that the enterprise can be
located.
In this example the default sub-unit paths are defined, followed by the most
commonly used paths within each sub-unit. Next the Unit path is defined
using the enterprise path from the local header file. The full sub-unit paths
are defined using the defaults and this is followed by the definition of the
most commonly used subdirectories within each sub-unit.
These definitions would be repeated for each unit in the enterprise changing
the name of the unit.
The unit header file must include the enterprise header file so that the
enterprise paths can be defined..
The sub-unit header file must include the unit header file so that the unit,
enterprise and local constants are defined.
Depending on the location of the code, one of two files should be included in
any code that references any constant.
If the code is part of a common component and not part of any unit or sub-
unit component then the enterprise.h file should be included. This implies,
correctly, that common components cannot reference constants defined in
any unit or sub-unit.
If the code is part of a unit or sub-unit component then the #include should
reference the unit.h or subunit.h file.
Paths
This header file scheme uses nested #include statements to incorporate the
other include files. The subunit.h file includes the unit.h file, which in turn,
includes the enterprise.h file, which then, includes the local.h file and
foxpro.h file. Since the #include statements do not specify the path to the
header files explicitly, the VFP path is used to locate the included files.
Default directory
Since the header files for each unit have the same names, as do the header
files for each sub-unit, it is imperative that the default directory be set
correctly before compiling any code. Otherwise, the wrong header file could
be used or the included file might not be found.
Naming Conventions
Syntax: [Scope]TypeName
l Local lnCounter
t Parameter tnRecNo
Note: The private scope declaration should not be used and all
variables not explicitly declared as global that are not report
variables or view parameters should be explicitly declared as
local.
Prefixes for Type, which are taken from the return value of the vartype
function, are as follows:
Objects
Controls/Containers
Note: Using a prefix does not dictate the contents of an object variable
in Visual FoxPro, prefixes are used as a naming convention. For
example, adding the prefix “cbo” does not check that the object
referenced by the variable is a combo box, but it does help you
remember the object referenced by the variable.
Field Names
Follow this convention for naming fields in tables:
• Prefix any foreign key fields with the foreign key table name followed by
Id… e.g., actId
Coding Conventions
Abbreviations
Do not abbreviate keywords (even if the language “allows” you to
abbreviate) in code.
White space
Use horizontal white space (i.e., spaces) between operators, operands, etc. to
separate the components of commands and expressions.
Use vertical white space (i.e., blank lines) to separate groups of statements
and delineate sections of code. Use the following rules:
All code blocks within a loop or a branch consisting of more than a single
line must begin and end with a blank line. Follow the end of a loop or a
branch with two blank lines. Separate dissimilar statements with a blank
line.
For example:
if lnSpace > 0
lcWord = left( lcLine , lnSpace - 1 )
else
lcWord = allt( lcLine )
endif
enddo
Constants MAX_VALUE
Events getFocus
Methods writeExpression
Objects oEmployee
Properties allowRowSizing
Procedures getNextId
Copyright
Every piece of code created or updated should contain the copyright of the
person who created the code with the understanding that you are granting an
unrestricted license to the client to use the code for the purpose it was
written. This should include the date and time the code was created or
modified, the name of the person who did the work and the company they
were affiliated with at the time the work was done. For example:
Copyright Feb 24, 1999 John M. Miller, Perpetual Data Systems
The purpose of this is to document in the code, the persons responsible for
the code as it exists. If your name is associated with a piece of code,
hopefully you’ll take more care in writing it.
Comments
While the importance of properly documenting work cannot be over
emphasized, it is important to properly comment code in order to get the
expected benefits. First of all, realize that a comment is no different than any
other programming statement. Once it is created, it has to be maintained and
since a comment is not a functional part of the code, it is the last thing to be
changed, if changed at all. Comments are not inherently good and if
incorrect can be detrimental.
When the time comes to document your code try to answer the following
questions:
In general, nothing documents what code does better than the code itself.
Therefore, be careful when adding comments that describe what the code
does. These types of comments can be helpful when the code is difficult to
read or understand. But if the code is difficult to read or understand you
should also think about the possibility that it should be rewritten in a clearer
more readable way.
This is probably the most useful type of comment. Every piece of code has a
purpose and every piece of code should have a comment that explains that
purpose. Sometimes the purpose is due to a business need, in other times the
purpose is purely technical.
This is similar but slightly different and more useful than the “What” type of
comment. In this type you are trying explain in a general sense how the code
meets the purpose of the routine. These types of comment only need to
change when a different approach to implementation is tried.
Program Logs
Every program, form or report should log its execution to a log file located in
the Logs directory. The log should contain any and all information necessary
to determine whether the program executed properly.
Assertions
All situations where an error could occur as the result of a programmer error
should be asserted in the code using the VFP ASSERT command and the
code should be tested with ASSERTS set ON to trap for these conditions.
Runtime Errors
For situations where errors occur at runtime that cannot be avoided the code
should trap for the specific error using the VFP error handling features.
Preferably this would be done using the error method of an object.
VFP Errors
An application level error handler should be used to trap all errors and
respond to the error according to its type and severity. This would typically
be implemented using the VFP ON ERROR command.
Application Errors
The are situations where a routine reaches a point where it cannot continue
and must abort processing. In these situations the routine should generate a
user defined error condition. Then test for continued existence of the
condition before aborting. This allows a subclasses error method or an error
handler to trap the error and resolve the error condition without changing the
code.
VFP will allow you to work fine with files read only. With proper setup in
VFP, (see below), you will be asked to check out any file you wish to modify
as a reminder. If you choose ‘CANCEL’, VFP will open the file in read only
mode, thereby protecting the source.
Very Important
Forced reminder
Rns
Under the text box ‘Create a new project in folder’, select the sub-unit
directory where project exists.
Change the ‘Working Directory’ to your local drive (d:\rns – see below).
This will create the rns folder and other folders on your local drive.
General Policies
In order to insure the integrity of the enterprise project, certain policies need
to be adhered to. Because the directory structure for enterprise was created
for maximum flexibility for both developers and SourceSafe, projects and
even files must be added in a certain manner. For now this will be the
responsibility of the team manager.
Read-only files
As per the setup instructions, files on the local drive MUST be read-only
unless checked out. Under no circumstances should the read-only status of a
file be changed without explicit approval of the
Any team member can add a new file to the project with notification to the
team manager so he can broadcast an e-mail message to other team members
of the need for a refresh of the project.
No files outside of the current sub-unit can be added to source code control.
This will invalidate the way SourceSafe refreshes and controls the project.
Offsite work
When checking out files for work off-site, check out the entire sub-unit.
Daily Procedures
Check all files into source control each day, finished or not. This will ensure
backup of files. A ‘WORKING’ version will be created frequently so as to be
able to refresh a ‘LATEST WORKING’ version. This is also a good habit to
get into in case you need to back up and go down another path.
Quality Control
Testing
All code must be tested prior to being released into a production
environment.
Code Reviews
All code must be reviewed before it can be released into a production
environment. Someone other than the author of the code must review the
code.
General Recommendations
Parameters
If a routine requires a parameter, unless otherwise agreed, pass an object that
contains the required data and let the receiving routine or method determine
how to handle the object.