Coding conventions : RTEMS

From my experience till now, If you desire to contribute to open source, it's necessary to adapt!! Your old sluggish, inconsistence coding practices wont do any good, neither to you nor to the community.

^^ That was my story!! After a month of working with professionals , I realized that my 5 years of coding was trash! It's not about logic, it's about ethics. To be a good coder, you don't only need to work on your algorithmic skills, but one should also have some ethics, a set of rules to which he adheres.  Earlier, I used to code the way i want to, the way i like. Nevertheless, I am really glad to have some one (In fact a lot of well wisher) trying to improve my skills, trying to lift me up towards professionalism. GSoC does pays it's purpose!! Thanks a lot, Mentors! I really learned a lot, even during my application period.

So, this blog post is for new applicants or for someone willing to contribute to any open source community. I spent a lot of time and went through a lot of coding practices given by various major developer communities like RTEMS, GNU etc and made few notes which i'll be presenting below:

Note: Select a good text editor! i used Sublime Text, it has a lot of plug-ins available which can automatize general formatting.

TODO: Write a plug-in for sublime text to check for all the below mentioned coding practices.

Good formatting practices:


Indentation and Spacing


  • Use spaces instead of tab

  • Use 2 spaces for indentation and 4 for hanging indentation.

    • Hanging indentation is like:
      This is an example code
      where except first line
      all other lines are indented
      This type of formatting is
      called hanging indentation.




  • Put no space between function name and opening parenthesis like:
    void my_function(void)
    {
    /* ..... */
    }


  • Always put space

    • Between a conditional expression and it's closing braces

    • inside and outside of each parenthesis of a conditional expression

    • before and after binary/ternary operators
          if (bp->enabled && bp->address == pc) {
      return bp->length;
      }




  • Don't put space

    • between unary operators (e.g. *, &, !, ~, ++, --) and their operands

    • around dereferencing operators (-> and .)



  • Don't leave any trailing whitespace after a line.

    • How will you keep a check of this?

      • By making changes in GIT settings :
        git config --global color.ui auto


      • By using sublime text plug-in like trailing space checker





  • It's quite important, as it leaves a lot of warning while applying patch.

  • Always leave a blank line at the end of the file. Why?

  • Don't use more then one blank line consecutively.


Character limit per line

  • Each line shouldn't have more then 79 characters!

    • for maximum readability in the widest range of environments



  • To adhere to this rule you need to break big lines. That too have a syntax:

    • While, For, if should have their condition expression aligned and each should be on a different line. There should be a different line for closing parenthesis. (Source: see here)
      /* For breaking function definitions - 4 spaces with hanging indents */
      for (
      initialization = statement;
      a + really + long + statement + that + evaluates + to <
      a + boolean;
      another + statement++
      ) {
      z = a + really + long + statement + that + needs +
      two + lines + gets + indented + four + more +
      spaces + on + the + second + and + subsequent +
      lines + and + broken + up + at + operators;
      }

      /* For breaking if statements */
      if (
      this + that < those &&
      this < those &&
      those < that
      ) {
      /* ... */
      }

      /* For breaking function declarations - 2 space indent */
      int this_is_a_function(
      int arg1,
      int arg2,
      int arg3,
      int arg4
      );

      /* For breaking macros - use 2 space indent with \ at the end of each line */
      #define A_LONG_MACRO_NAME ( \
      AND + EXCESSIVELY + LONG + EXPANSION + WITH + LOTS + OF + EXTRA + STUFF + \
      DEFINED \
      )

      /* For excessively long comments */
      /* Excessively long comments should be broken up at a word boundary or
      * somewhere that makes sense. Also, at the begining of each line add
      * an astrik. */





Commenting format

  • use /* */ of comments only!

  • Don't be very verbose while commenting and use proper English.

  • Use TODO: with a comment to indicate code that needs improvement.

  • Use XXX or FIXME to indicate an error/bug/broken code.

  • Always use period(full stop) in comments after a sentence ends

  • Write a brief comment at the start of each source file, with the file name, it's group, and it's purpose, like this(It's called Doxygen header):
    /**
    * @file
    *
    * @ingroup TheGroupForThisFile
    *
    * @brief Short "Table of Contents" Description of File Contents
    *
    * A short description of the purpose of this file.
    */


  • Note above that first @brief content shouldn't end with a fullstop.

  • Always put a blank line between above Doxygen header and Below license type:

  • Use apt license and add it like:
    /*
    * Copyright (c) year name <email>.
    * All rights reserved.
    *
    * Redistribution and use in source and binary forms, with or without
    * modification, are permitted provided that the following conditions...
    */


  • Every endif should have a comment like
    #ifdef foo

    #else /* not foo */


  • The variable name itself should be lower case, but write it in upper case when you are speaking about the value rather than the variable itself.

  • There should be a comment on each static variable.


Good Documenting Practices:


Use Doxygen! Doxygen is a documentation generator, a tool for writing software reference documentation.

  • For documenting a function:

    • Use: @param, @retval like:
      /**
      * @brief Copies from a source to a destination memory area.
      *
      * The source and destination areas may not overlap.
      *
      * @param[out] dest The destination memory area to copy to.
      * @param[in] src The source memory area to copy from.
      * @param[in] n The number of bytes to copy.
      *
      * @retval RTEMS_SUCCESSFUL what it means
      * @retval RTEMS_INCORRECT_STATE what it means.
      */




  • For documenting an enum or struct

    • Always put comment above definition like:
      /**
      * @brief Object containing multiple flip-flops.
      *
      * Encapsulates multiple flip-flops.
      */
      typedef struct {
      /**
      * @brief Primary flip-flop.
      */
      flip_flop_state primary;
      /**
      * @brief Secondary flip-flop.
      */
      flip_flop_state secondary;
      } flip_flop_multiple;


    • Note that it's not recommended to use typedef for hiding pointers/volatile etc, just use it to remove struct.




Good Naming Practices:



  • Prefer to use underscore to separate words rather then CamelCase

  • Avoid abbreviation

  • Use highly descriptive variable name at the same time try to keep local variables of shorter length.

  • Don't use very long name for a file. This might create an issue on MS-DOS system.

    • doscheck tool can be used to point out files with larger names.




For Improving Readability and Performance



  • Declare variable at the start of the block

  • Avoid complex initializing a variable during it's declaration.

  • CPP macros should use a leading underscore with for parameter names

  • Prefer to ++preincrement instead of postincrement++.

  • Avoid using floating point except where absolutely necessary.


 

Comments

Popular posts from this blog

Understanding SD, SDIO and MMC Interface

Software licensing : Introduction and it's types

Implementing a MMC/SD/SDIO stack using CAM framework(Part 2)