« Simple Developer Habits and Rules of Thumb | Main | Good Developer Habit #2: Be a Better Logger than Paul Bunyan »

Good Developer Habit #1: Embed RCS ID into EVERY file

Ever run across a file and wondered where the heck it came from? I hated being paged at 3am, only to find a script or class file for something I didn't write having a bug and not being able to track down what branch to make a patch from. IMO, no file should ever be checked into a source repository without an RCS ID tag!

Almost every source control system supports the $Id: $ tag, I know for a fact that Perforce, Subversion, and CVS all support this tag. Use it or lose it (the file's origin that is)!

Scripting Languages

Embedding RCS ID is particularly important for Perl, Ruby, and other scripts as they often get copied around such that no tools can be used to find their origin. Just add a simple comment at the top:

  #!/usr/bin/ruby
  # $Id: $

Config

Again, embedding RCS ID tags enables someone to quickly find exactly where to change the config file in it's permanent repository. There is nothing worse than wasting 5 minutes of time trying to track down exactly how the file got deployed to a box, where it was imported from, and what branch it was released on. Save everyone time by adding tags where. Simple:

  # $Id: $
  
  *.*.SelfImplode = F;

This includes Java properties files, Spring, XML config, JSON, or whatever you might be using to "configure" any software component.

Java

An interesting pattern I've seen lately is to emit software versions into the application log based on log level:

  public class YourObject {
    private static final Logger log = Logger.getLogger(YourObject.class);
    static { log.debug("$Id: $"); }

Note, depending on how many classes your application uses this could increase JVM/application startup time. I suspect in 99.9% of the cases these few extra microseconds won't matter.

For a long time I've wanted a mechanism where, via [[JMX]], I could connect remotely to a running process and inspect which versions of software were loaded.

C++

Embedding RCS ID as a string variable into binaries/shared objects enables executing:

  % strings my-app-binary-file | grep "\$Id"

to find exactly what versions of code are linked in. Extremely useful for reducing MTTR, we've seen it in practice. This simple trick enables an oncall to quickly track back and patch.

It's easy to roll your own based off that macro, just make sure the compiler doesn't optimize out the strings. Create a simple #define macro for embedding these quickly.

Documentation (Javadoc/Doxygen/etc)

All of this applies equally to documentation. Ever read a Javadoc provided by another team and wanted to know where to update it to be clearer? Simply adding @version $Id: $ makes this trivial.

The following example ensures [[Javadoc]] generated docs include exactly what file is being referenced and where to change it!

  /**
   * @class Kryptonite
   *
   * Rock solid implementation, use sparingly.
   *
   * @version $Id: $
   */
  public class Kryptonite {

There are numerous other cases where embedded RCSID make sense, it's just another good habit to leverage them where possible.

TrackBack

TrackBack URL for this entry:
http://www.none-of-yo.biz/MovableType/mt-tb.cgi/46

Post a comment

(If you haven't left a comment here before, you may need to be approved by the site owner before your comment will appear. Until then, it won't appear on the entry. Thanks for waiting.)