|
|
Offline Programming Recommendations: General
On this page:
[General Guidelines]
Other pages:
[Background Info:
Justification,
Languages,
Bibliography
]
Recent Changes
- Feb 21, 2000 -- Added architecture paragraph (Bob)
- Jan 27, 1999 -- Created by merging older pages into new web form (Bob)
The following guidelines are language-independent
-
Because of the size of what its meant to do, there's a lot
of BaBar offline software. As you contribute to it, please
try to make your changes in a way consistent with the existing
architecture. This includes our techniques for minimizing
dependence between packages, for finding external information,
etc. Please take some time to learn how problems similar to the
one you're working on have been solved in the past, what
exists that you can adapt, and how to introduce your changes.
One effective way to do this is to talk (in person or by phone)
with the package coordinator(s) of related packages.
-
Every package must have a README or README.html file.
This is where people will look first for basic information
about the package. You don't want to disappoint them.
It must contain at least
the name of the package
coordinator, a brief description of the purpose of the package, a
brief list of classes and their functionality, and a description
of the external dependencies.
-
Because BaBar code releases have to run at a large number of heterogenous
sites, on several different architectures, one can't always count on a
favorite utility being installed. This lead to the establishment of a
list of
required software.
Note that its "required" in the sense that you can count on a BaBar site
to have it installed; you are certainly not required to use all of it.
Because you can't count on something that's not on this list, please
don't write packages that require more than this.
-
Use the standard link support, including SoftRelTools
and PackageList.
This will permit compiler changes needed to use
of automated leaker checkers, etc. See
the SoftRelTools HOWTO,
PackageList/README, the
PackageList user guide, and the
header of PackageList/link_all_reco.mk for more information.
-
There should be no architecture-specific if's in the GNUmakefiles. Include
an arch_spec_*.mk file, or if need be create a new one. See the
SRT how-to page for additional info.
-
When including a non-system header file, its important that it be written as
#include "packagename/filename.suffix"
Don't omit the package name.
- Do not use environment variables to get external information into your
code. Proliferation of "magic variables" results in programs that are very
hard to understand and control. Instead, use either parameters (for
Framework-based code, see
the recommended classes page)
or command line options (for standalone code).
-
cpp macros that generate code are generally not acceptable. One exception is "assert"
and similar system-provided macros.
- Use meaningful names.
Generally, the more visible
the name, the more "English-like" it should be.
Data types, like module and class names,
typedefs and enums, should have initial capital letters (LittleObject),
while functions and variables should have initial lower case letters
(setValue, nextChoice). Capitalize each word after
the first, and don't separate words with underscores. Avoid abbreviations
(e.g. use nameLength instead of nLn) and
non-standard acronyms. Using the occasional article (aBMesonCandidate)
or additional information (nextBMesonCandidate) can help
where an identifier looks a bit odd (bMesonCandidate).
Multiple word names let the reader know the intended use of an
item, saving the hassle of inferring from context and avoiding
ambiguities. Does "empty" mean a test for emptiness
or setting the object to empty? Whilst the signature might give
a clue, it is better to use names that unambiguously convey the
intent of the function. In the former case, "isEmpty"
would be better; in the latter case, use "setEmpty"
instead. It is often possible to name functions with a verb phrase
(setValue, fitTrack, complainBitterly) and
variables with a noun phrase (loopIndex, nextWorkItem).
Variables with small, temporary scope can be given small names
(temp, next), although a little effort can make
their content more understandable and save the reader the effort
of figuring out their meaning from how they are filled (trackLoopIndex
instead of temp, nextDaughter instead of next).
Generally avoid single character names except for local loop and
array indices.
Don't put things like "Pointer", "Class"
or "Struct" into the name: it is almost always
clear from the context.
Coding recommendations
These guidelines are broad enough that a wide variety of different
coding styles are still possible. When modifying someone else's
code, adapt to their style rather than imposing your own.
- Provide plenty of comments. The standard templates (available
in the "Code Templates" package)
provide a header and major subdivisions that organize the overall
flow of your code. In general, every function or function member,
unless trivial, should have its own comment that describes the
purpose of the function, the input and output arguments and any
side-effects that the function produces. Within a function, separate
major blocks of code and identify their purpose with a leading
comment. Don't bother to comment individual source lines unless
there is an underlying subtlety that needs to be explained or
you are documenting the arguments to a function or procedure.
- Avoid tricks unless absolutely necessary and explain why a
particular approach has been taken. Terse code might seem clever
when you write it, but it probably won't when you look at it again
in several months time, and it almost certainly won't be understandable
to the person who takes over from you later on.
- Code for clarity rather than efficiency. This is obviously
a generalization, but you should be certain that there is an efficiency
problem (e.g. by profiling your application) before you
start re-arranging (and possibly obscuring) code for efficiency
reasons.
- Attempt to write linear code - i.e. code that starts
at the first executable statement and flows down to a final "return"
or end of block statement.
- Code defensively. Check the return values for functions and
don't assume that the call succeeded. If your function only operates
on a limited range of input values, check at the beginning of
the function and don't assume that the caller has made the check.
For C++ and C, the assert macro can be used for this (see later).
- Avoid complicated "if" constructs. It is better
to use several simpler nested "if" constructs rather
than a complicated compound one. Avoid implicit precedence rules
and use parentheses to identify the components of such constructs.
Even if you can remember all the precedence rules it is likely
that someone else won't and it will make their job easier.
- Indent each nested block in order to highlight the start and
end of each of them. Use trailing comments on the block terminators
if this can guide the eye. An indent of 4 spaces is the recommended
BABAR standard.
It is compatible with the emacs default.
- Avoid implicit data-type conversions and mixed mode arithmetic.
Use explicit operators (e.g. (float)...). The use of explicit
conversions will have no effect on code efficiency and might avoid
any inadvertent rounding or truncation errors and will highlight
the data type conversions to anyone attempting to follow the code.
Return to
BABAR offline software page,
BABAR Computing Home Page,
or
BABAR Home Page.
|
|