Guidelines for ejabberd developers

This page lists guidelines recommended for ejabberd developers.

Note: many parts of ejabberd don't fully respect those guidelines, but the code works correctly and is bug-free. Hence, it will not be rewritten just for satisfy those guidelines.

Coding style

  • Use the standard Erlang code indentation
  • Write lines no longer than 80 columns
  • One instruction per line is usually enough (but less than one is fine).
  • Use spaces around operators, including equal (=), example: X = [Y + 2 | Z].
  • Add a space after a comma (,) if it's not at the end of the line.
  • Try to avoid useless spaces (at the end of lines, in empty lines).
  • Unused variables must be prefixed by _ to avoid compilation warning.
  • Avoid nesting many control sequences (Case, If...).
  • Avoid writing large functions. They include code that do many things, and span over 100 or 200 lines of code.
  • Use English for variable and function naming and comments.

Check this document for the basic Erlang coding guidelines: Erlang Programming Rules and Conventions

Compilation warning

The code SHOULD NOT have warning at compilation. If the code produces warning, the line causing the warning MUST be commented to explain why the warning is present.

Put related functions next to each other

  • Try to not separate the functions that perform related tasks.
  • Sometimes it may seem difficult. For example, in OTP module skeletons all the exported functions have several clauses, and the internal functions are in the end of the module.
  • The solution is that the exported functions (like handle_info, handle_cast...) do the barely minimum, and then call internal functions.
  • Then, the internal functions implement all the functionality, and are grouped by the kind of functionality they provide.
  • In the case of mod_muc_room:
    %%%
    %%% gen_server api
    %%%
    
    normal_state({route, From, "", {xmlelement, "message", Attrs, Els} = Packet}, StateData) \->
        route_message_to_room(...)
    normal_state(...) \->
        route_private_message(...)
    ...
    
    %%%
    %%% Internal functions
    %%%
    
    %%% message to room
    
    route_message_to_room() \->
    
    auxiliary_route_message_function() \->
    ...
    
    %%% private message
    
    route_private_message() \->
    

Documentation

  • An option that is not documented does not exist. Document all the options in the ejabberd Guide, and probably also in ejabberd.cfg.example.
  • An option badly documented is a bug, because it can't be used as it was intended.
  • When you write code that adds, modifies or removes an option, exported function, hook, process state, ETS table, Mnesia table or ODBC table, you must mention the change in the patch description, ChangeLog file and SVN log. You may also need to modify the ejabberd Guide or the ejabberd module development doc to reflect the change.

Module development

Module options

  • All code that adds, modifies or removes an option must be mentioned in the patch description, ChangeLog file SVN log and the ejabberd Guide.
  • The module must check the validity of the option value's format and exit with a proper error message if it's not correct.

Module database

  • All code that changes the database schema (mnesia or sql) must also include a data migration function that automatically translate old schema to new at module start.

Submit a Patch

Prepare your patch based in the updated development branch, not in a very old release or on a not updated development branch.

A patch must fix only one problem: don't mix unrelated fixes in a single patch.

When you publish your patch, it must be clear to what source code the patch is intended to be applied: to 2.1.x branch? or to master branch? or to a specific version, like 2.1.5?

Where to announce and publish your patch, depends on what you prefer:

  • ML: Send an email to the ejabberd mailing list, explaining the problem you found and the solution that you propose. This is useful to get discussion and feedback, so you can use this method if you aren't sure of the problem and the solution.
  • Ticket: Create a ticket and attach the patch. Those tickets are usually read only by the ticket manager and few other people, so this is useful if you are almost sure the problem or the solution are correctly explained by you, and that it's just needed for the ticket manager to find an expert to review the ticket and patch.
  • Github: Send a Pull Request in Github. If you use Github frequently, you may want to send a Pull Request. If you don't get any response in a few days (for example 1 week), please announce your Pull Request also in the ML and/or Ticket.

SVN

  • To generate a patch with the changes you made in your local repo, go to the main directory of the project:
    $ svn diff >fix-room-configure.diff
    
  • To apply a patch that was generated with SVN:
    $ patch -p0 <fix-room-configure.diff
    

Git

  • If you use Git to track ejabberd source code, when you plan to write new code you must create a new branch for that particular feature/improvement/bugfix. Example to create a topic branch based in 2.1.x:
    git checkout -b fix-room-configure origin/2.1.x
    
  • Once your local branch has the final code you want to publish, you can generate the patch in several ways
    • Compare this branch against the original:
      $ git diff 2.1.x > fix-room-configure.diff
      
    • Export each commit to a file:
      $ git format-patch 2.1.x
      
  • To apply a patch that was generated with Git:
    $ patch -p1 <fix-room-configure.diff
    
Syndicate content