General Coding Conventions
This document attempts to outline the coding conventions used
currently by myself, and is intended to serve as a guideline for
anyone wishing to contribute code back to the projects hosted on this
website. These guidelines will help ensure that everybody can read
and understand the software hosted here.
These guidelines were developed over several years of working with
several different languages, independent of other styles of
programming. I was shocked to find that Kent Beck's Smalltalk style
mirrors my own very closely. In fact, the fact that I can't seem to
find his Smalltalk style guide on the Internet anymore is what
provided the inspiration to post my own guide.
The rules of thumb listed herein is applicable to all
languages, and I use these with languages as diverse as Forth to
C to Python to even assembly language.
Variables
-
Variables tend to be nouns, written as leading lower-case camelCaps.
For example: aRecord, synapse, theLampShade, anyHandle, etc.
Functions and Methods
-
Functions and methods tend to be verbs, also written using leading
lower-case camelCaps. For example: openFileWith, importTicket,
etc.
-
A special class of methods are those that do nothing but provide a
read-only interface to some object state. In this case, a method's
name may be a noun. For example: Timer.timeLeft(). You'll
want to be careful with such methods, however. See Martin
Fowler's article on some additional guidelines and rationale on
the careful use of so-called getters.
-
Another special class of functions or methods are those that return
boolean values. These should always have an is or has somewhere
in their name. For example: isWaterTooHot? ,
anErrorHasOccored(), isCongruent(), etc.
Types
-
Types are expressed as nouns, but written in leading uppercase
CamelCaps. For example: Window, File, BoxedArrayOfIntegers,
ListOfEvents, etc.
Miscellaneous
-
Test first by Intention. In other words, use
test-driven or behavior-driven development techniques. It really
does make a difference.
-
Where at all possible, Tell,
Don't Ask, even in procedural code.
-
Please follow the Law of Demeter as closely as you
are able. Between Tell, Don't Ask and LoD, you'll find your code is
substantially more maintainable, regardless of what language you
write it in. However, it's not suitable for performance-critical
code due to all the delegation going on.
Violations to Law of Demeter
For performance critical code, you should still follow Law of
Demeter for development purposes, and then inline knowledge and
behaviors as appropriate just enough to meet performance
requirements.
-
Inlined code must be derived from a function or method
which is still invokable elsewhere in a program (even if it
actually isn't), or in a debugger. This function is said to be the
"master function."
-
At the beginning of a chunk of code inlined from elsewhere, include
a comment showing how the function would have been called to
produce the effects desired. For example: /* Inlining:
blitRasterLine( srcBitmap, dstBitmap, 0, 639, MODE_XOR ); */
-
If you need to make changes to the code, always follow these
steps:
-
Remove inlined code completely and uncomment the equivalent
function call. Test! Behavior should be slower, but
otherwise the same.
-
Affect your changes in the function being tested.
-
Re-inline the function from scratch, once again commenting out the
equivalent call. The new behavior should be the same as in step
2, only faster.
-
Violations of the Law of Demeter must include evidence of
performance gains in the comments at the "inlined" call-site. This
can be in the form of high-level tests or low-level profiling data,
but it must be relavent data. For example:
// Before optimizing, "time myProgram -param=foo" gave 54 seconds.
// After inlining, "time myProgram -param=foo" gave 34 seconds.
// My box is an 800MHz Athlon Slot-A processor on an ASUS
// motherboard.
//
// Inlining: result = doSomeCalculation( onSomeData );