LFE Programming Rules and Conventions

8 Documenting Code

8.1 Attribute code

You must always correctly attribute all code. There are two ways to do this:

  1. In a git commit's comment section, complete with names and email public addresses of original authors or URLs for source code.

  2. In the comments section at the beginning of the LFE file where the code has been copied to.

Say where all ideas contributing to the module came from - if your code was derived from some other code say where you got this code from and who wrote it.

Never steal code - stealing code is taking code from some other module editing it and forgetting to say who wrote the original.

8.2 Provide references in the code to the specifications

Provide cross references in the code to any documents relevant to the understanding of the code. For example, if the code implements some communication protocol or hardware interface give an exact reference with document and page number to the documents that were used to write the code.

8.3 Document all the errors

All errors should be listed together with an English description of what they mean in a separate document (see Chapter 10, "Error Messages").

By errors we mean errors which have been detected by the system.

At a point in your program where you detect a logical error call the error logger thus:

(error-logger:error-msg format #(descriptor arg1 arg2 ....))

And make sure that the line #(descriptor arg1 ...) is added to the error message documents.

8.4 Document all the principle data structures in messages

Use tagged tuples as the principle data structure when sending messages between different parts of the system.

The record features of Erlang (introduced in Erlang versions 4.3 and thereafter) can be used to ensure cross module consistency of data structures.

An English description of all these data structure should be documented (see Chapter 10, "Message Descriptions" on page 32.).

8.5 Comments

Comments should be clear and concise and avoid unnecessary wordiness. Make sure that comments are kept up to date with the code. Check that comments add to the understanding of the code. Comments should be written in English.

Comments about the module and important comments that apply to large sections of code in in module should be without indentation and start with four semicolon characters: ;;;; (see this chapter, "File Header, description" and the Style Guide Documentation chapter, "Comment Semicolons").

Comments about a function shall be without indentation and start with three semicolon characters: ;;; (see this chapter, "Comment each function").

Comments within LFE code shall start with two semicolon characters: ;;. If a line only contains a comment, it shall be indented as Erlang code. This kind of comment shall be placed above the statement it refers to. If the comment can be placed at the same line as the statement, this is also acceptable.

Comments that are placed at the end of a line of code should only have a single semi-colon character: ;.

;;;; Great module description
;;;; ...
(defmodule great-module
  (export
    (some-useful-function 1)))

...

;;; Comment about function
(defun some-useful-function (useful-argument)
  (another-function useful-argument)           ; Comment at end of line
  (yet-another-fucntion)                       ; Another one for this line
  ;; Comment about the next chunk of code at the same level of indentation
  ...)

...

8.6 Comment each function

Functions should be commented. You may know exactly what your function does the week after you write it, but six months later when you or someone else is trying to understand the code, the comments can save countless hours and expense.

There are two styles you can use to comment functions in LFE:

  1. the Common Lisp style of using a docstring, or
  2. the Erlang style of commenting the code before the fucntion.

The important things to document are:

  • The purpose of the function.
  • The domain of valid inputs to the function. That is, data structures of the arguments to the functions together with their meaning.
  • The domain of the output of the function. That is, all possible data structures of the return value together with their meaning.
  • If the function implements a complicated algorithm, describe it.
  • The possible causes of failure and exit signals which may be generated by exit/1, throw/1 or any non-obvious run time errors. Note the difference between failure and returning an error.
  • Any side effect of the function.

Example 1:

(defun get-server-statistics
  "Get various information from a process.

  This function returns a list of key/value pairs or a list of
  error/reason."
  ((option pid) (when (is_pid pid))
    ...)
  ...)

Example 2:

;;; Function: get-server-statistics/2
;;; Purpose: Get various information from a process.
;;; Args: Option is normal|all.
;;; Returns: A list of (list key value)
;;;     or (list 'error reason) (if the process is dead)

(defun get-server-statistics
  ((option pid) (when (is_pid pid))
    ...)
  ...)

8.7 Data structures

;;; Data Type: person
;;; where:
;;;    name: A string (default is undefined).
;;;    age: An integer (default is undefined).
;;;    phone: A list of integers (default is a list).
;;;    dict: A dictionary containing various information about the
;;;          person. This is a list of key/value tuples (default
;;;          is the empty list).
;;;    A {Key, Value} list
(defrecord person
  name
  age
  (phone (list))
  (dict (list)))

8.8 File headers, copyright

Each file of source code must start with copyright information, for example:

;;;; Copyright Ericsson Telecom AB 1996
;;;;
;;;; All rights reserved. No part of this computer programs(s) may be
;;;; used, reproduced,stored in any retrieval system, or transmitted,
;;;; in any form or by any means, electronic, mechanical, photocopying,
;;;; recording, or otherwise without prior written permission of
;;;; Ericsson Telecom AB.

8.9 File headers, revision history

Revision history should be tracked in a DVCS, not in the file headers.

8.10 File Header, description

Each file must start with a short description of the module contained in the file and a brief description.

;;;; Description module foobar-data-manipulation
;;;;
;;;; Foobars are the basic elements in the Baz signalling system. The
;;;; functions below are for manipulating that data of foobars and for
;;;; etc etc etc

If you know of any weakness, bugs, badly tested features, make a note of them in a special comment, don't try to hide them. If any part of the module is incomplete, add a special comment. Add comments about anything which will be of help to future maintainers of the module.If the product of which the module you are writing is a success, it may still be changed and improved in ten years time by someone you may never meet.

8.11 Do not comment out old code - remove it

Add a comment in the revision history to that effect. Remember the source code control system will help you!

8.12 Use a source code control system

All non trivial projects must use a source code control system such as git, mercurial, etc., to keep track of all modules.