Coding Guidelines for Developers

Those guidelines are intended for developers who contribute to eblearn, to provide coherent, easy to read and bug-free code.

Documentation

  1. Comment your code as much as possible so users can understand it.
  2. Use the commenting syntax that can be used to automatically generate the online documentation (with Doxygen):
    1. example: linear_module class documentation generated by Doxygen and its original input.
    2. syntax:
      1. use ! instead of for comments that you want to appear in the online documentation.
      2. use \param to describe a parameter.
  3. If you edit some code that is missing documentation, add it.

General Architecture

The general user interfaces (GUI) have been kept separated from the core code to keep it clean and simple and to allow users to use only the core functionalities when necessary. Thus, try to maintain that separation between essential code and non-essential code (e.g. guis are separate in libidxgui and libeblearngui and helping tools in libeblearntools).

SVN

  1. Merging the trunk into bob's branch:
    1. Find out the latest revision at which a merge was done between the trunk and the branch. Assuming that the merge was documented during the commit, find the revision with 'svn log' from the trunk directory. Or get the branch's creation revision (might run into a lot more conflict): svn log –stop-on-copy
    2. Merge trunk into branch, assuming branch's creation revision is “XXX”. From the branch directory, do: svn merge -rXXX:HEAD https://eblearn.svn.sourceforge.net/svnroot/eblearn/trunk
    3. The branch is now locally updated with the latest trunk, commit to apply the changes to the branch.
  2. Merging bob's branch into trunk:
    1. Get branch's creation revision or the latest merging revision: svn log –stop-on-copy
    2. Assuming branch's creation revision is “XXX”, from the trunk directory, do: svn merge -rXXX:HEAD https://eblearn.svn.sourceforge.net/svnroot/eblearn/branches/bob
  3. Never commit a broken code in the main trunk (allowed in branches).
  4. Run the tester before a commit to make sure nothing is broken.
  5. To work temporarly on code that may not work immediately, create a svn branch in the branches directory. This way you can commit broken code without affecting the main trunk. Once your code works, merge your branch into the trunk.

Debugging

  1. Emacs and GDB form a very convenient debugger: execute debug.sh to open Emacs in a debugging setting. In the top left window, use 'file my_exe' to load your executable, 'r my_arguments' to run it, 'break my_main.cpp:42' to break at line 42 in main.cpp (or click on the line the left-hand side). After a crash or a break, click on the stack lines in the bottom-left window to see the position in the code for each layer of the stack. You can also recompile by pressing F12.
  2. Once in a while, use valgrind to track memory leaks (make executable in debug mode to get precise location of errors):
    valgrind --show-reachable=yes --tool=memcheck --leak-check=yes ../bin/tester_debug
  3. To track idx memory allocations, one can enable the __DEBUGMEM__ flag by first exporting it to the EBLFLAGS environment variable. E.g. under Linux: export EBLFLAGS=-D__DEBUGMEM__. Then inserting calls to pretty_memory(); in different places of the code allows to identify where memory grows.

Timing

To automatically print out general timing information, recompile after setting:

export EBLFLAGS=-D__TIMING__

Testing

  1. When writing a new module or new code, add some unit tests in the tester (eblearn/tester) that test the basic functionalities of the code, to ease the detection of new bugs.
  2. Regularly run the tester when adding code.

Coding Style

  1. 80 columns max (Emacs' default), easier for 80-column developers.
  2. No unnecessary empty lines between code (user can see more code vertically).
  3. Naming convention: no capital letters, use _ instead (C++ style).
  4. Open braces on the same line as function prototype (Java style).
  5. Indent code (use “c++”→“indent region” in Emacs).
  6. Try to keep functions small.
  7. Avoid code redundancy, instead write sub functions.
  8. File directories and extensions:
    1. include/*.h: prototypes of classes, funtions, etc.
    2. include/*.hpp: template implementations.
    3. src/*.cpp: implementations.
  9. namespace do not yield indentation
  10. no trailing withspaces

Put the following code in your .emacs to enforce some of the rules above:

;; show extra spaces
(custom-set-variables '(show-trailing-whitespace t) '(show-lines-whitespace t))
;; delete trailing spaces when saving
(add-hook 'before-save-hook 'whitespace-cleanup)
;; show 80 columns
(dolist (hook '(c-mode-common-hook python-mode-hook emacs-lisp-mode-hook))
  (add-hook hook
           (lambda ()
             (font-lock-add-keywords
              nil
              '(("^.\\{80\\}\\(.+\\)" 1 font-lock-warning-face t)))
             )))
;; remove namespace identation
(defconst my-cc-style
  '("gnu"
    (c-offsets-alist . ((innamespace . [0])))))
(c-add-style "my-cc-style" my-cc-style)
(add-hook 'c-mode-common-hook
          '(lambda()
             (c-set-style "my-cc-style")
             (setq tab-width 2)
             (setq c-basic-offset tab-width)))
coding.txt · Last modified: 2012/09/27 06:48 by sermanet