279 lines
		
	
	
		
			6.7 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
			
		
		
	
	
			279 lines
		
	
	
		
			6.7 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
| The purpose of a coding style and accompanying guidelines is to make the
 | |
| reading and comprehension of the code easier. Reading prose would also be
 | |
| much harder, should the punctuation rules differ from chapter and paragraph
 | |
| to the next.
 | |
| 
 | |
| ## Coding Style
 | |
| ### astyle
 | |
| MaxScale comes with a Astyle configuration file used to format the source
 | |
| code. To use it, run the following in the source root.
 | |
| ```
 | |
| astyle --options=astylerc <path to source>
 | |
| ```
 | |
| This will format the source file according to the MaxScale coding style.
 | |
| 
 | |
| ## Consistency
 | |
| Be consistent. In a particular context, everything should style wise look
 | |
| the same.
 | |
| 
 | |
| ### In Rome do as the romans do.
 | |
| If something is done in a particular way in some context, then follow that
 | |
| same way when doing modifications, even if it violates what is stated
 | |
| here. If you want to fix the style of a file, then do so in one separate
 | |
| change; not as part of other modifications.
 | |
| 
 | |
| ## General
 | |
| * Only spaces, no tabs.
 | |
| * Indentation depth 4 spaces.
 | |
| * No trailing white space.
 | |
| * Maximum line length 110 characters.
 | |
| 
 | |
| ## Indentation Style
 | |
| 
 | |
| We follow the
 | |
| [Allman](https://en.wikipedia.org/wiki/Indentation_style#Allman_style)
 | |
| indentation style.
 | |
| 
 | |
| Braces are always used and the brace associated with a control statement is
 | |
| placed on the next line, indented to the same level as the control
 | |
| statement. Statements within the braces are indented to the next level.
 | |
| ```
 | |
| if (something)
 | |
| {
 | |
|     do_this();
 | |
| }
 | |
| else
 | |
| {
 | |
|     do_that();
 | |
| }
 | |
| ```
 | |
| 
 | |
| ## Punctuation
 | |
| ### Keywords are followed by a space.
 | |
| ```
 | |
| if (something)
 | |
| {
 | |
|    ...;
 | |
| }
 | |
| 
 | |
| while (something)
 | |
| {
 | |
|    ...;
 | |
| }
 | |
| ```
 | |
| Exceptions are `sizeof`, `typeof` and `alignof`.
 | |
| 
 | |
| ### Function name and opening parenthesis are not separated by a space.
 | |
| ```
 | |
| some_function();
 | |
| ```
 | |
| ### Operators
 | |
| 
 | |
| Use one space around (on each side of) most binary and ternary operators,
 | |
| such as any of these:
 | |
| ```
 | |
| =  +  -  <  >  *  /  %  |  &  ^  <=  >=  ==  !=  ?  :
 | |
| ```
 | |
| but no space after unary operators:
 | |
| ```
 | |
| &  *  +  -  ~  !  sizeof  typeof  alignof  __attribute__  defined
 | |
| ```
 | |
| no space before the postfix increment & decrement unary operators:
 | |
| ```
 | |
| ++  --
 | |
| ```
 | |
| no space after the prefix increment & decrement unary operators:
 | |
| ```
 | |
| ++  --
 | |
| ```
 | |
| and no space around the `.` and `->` structure member operators.
 | |
| 
 | |
| ### Comma is always followed by a space.
 | |
| ```
 | |
| x = some_function(a, b, c + d);
 | |
| ```
 | |
| ### Opening parenthesis and square bracket are not followed by a space, and closing parenthesis and square bracket are not preceded by a space.
 | |
| ```
 | |
| int len = strlen(name);
 | |
| 
 | |
| a = b[5];
 | |
| ```
 | |
| 
 | |
| ## Naming
 | |
| ### enums
 | |
| ```
 | |
| enum gwbuf_type { ... };
 | |
| typedef enum { ... } gwbuf_type_t;
 | |
| typedef enum gwbuf_type { ... } gwbuf_type_t;
 | |
| ```
 | |
| ### structs
 | |
| A `struct` must be a POD type. It must have no non-POD members and it must
 | |
| not have any member functions. Whether a `struct` has been declared in a C
 | |
| or C++ header file, it must be declared as if it would be used from C.
 | |
| 
 | |
| In a C header, a `struct` is declared as:
 | |
| ```
 | |
| typedef struct SOME_TYPE { ... } SOME_TYPE;
 | |
| ```
 | |
| With this arrangement it is possible to refer to the type using `SOME_TYPE`
 | |
| or `struct SOME_TYPE` from both C and C++ code.
 | |
| 
 | |
| In a C++ header, a `struct` is declared without the typedef.
 | |
| ```
 | |
| struct SOME_TYPE;
 | |
| ```
 | |
| 
 | |
| ### functions
 | |
| 
 | |
| Small caps and words separated by underscores
 | |
| ```
 | |
| void server_set_status(SERVER *, int);
 | |
| ```
 | |
| with the exception of names of function pointers in plugin interfaces
 | |
| ```
 | |
| typedef struct filter_object {
 | |
|     FILTER *(*createInstance)(char **options, FILTER_PARAMETER **);
 | |
|     ...
 | |
| } FILTER_OBJECT;
 | |
| ```
 | |
| that are _camelCase_.
 | |
| 
 | |
| ## C++ naming
 | |
| ### namespaces
 | |
| 
 | |
| Small caps and words separated by underscores
 | |
| ```
 | |
| namespace maxscale
 | |
| {
 | |
| 
 | |
| class ...
 | |
| 
 | |
| }
 | |
| ...
 | |
| namespace xyz_filter
 | |
| {
 | |
| ...
 | |
| }
 | |
| ```
 | |
| Note that symbols within a namespace are not indented. Note also that the
 | |
| namespace `maxscale` can only be used by classes belonging to the MaxScale
 | |
| core. An exception is when a template in the MaxScale namespace is
 | |
| specialized for a non MaxScale core class.
 | |
| 
 | |
| ### classes
 | |
| 
 | |
| To distinguish them from plain-old-data, aka structs, class names use camel-case.
 | |
| ```
 | |
| class CacheFilterSession
 | |
| {
 | |
| public:
 | |
|     int some_member_function();
 | |
|     ...
 | |
| };
 | |
| ```
 | |
| Note that the naming of member functions follows the same conventions as the
 | |
| naming of free functions, that is, snake-case is used.
 | |
| 
 | |
| ### member variables
 | |
| 
 | |
| Member variables are prefixed with `m_` and static member variables are
 | |
| prefixed with `s_`.
 | |
| ```
 | |
| class MyClass
 | |
| {
 | |
|     ...
 | |
| private:
 | |
|     int m_size;
 | |
|     static int s_max_size;
 | |
| };
 | |
| ```
 | |
| In general, a class should have no public member variables but all access
 | |
| should be via public functions that can be inline.
 | |
| 
 | |
| ### variable prefixes
 | |
| 
 | |
| The following prefixes are "standardized" and can be used when applied
 | |
| consistently:
 | |
| ```
 | |
| int *pAge;                        // p, for pointers.
 | |
| shared_ptr<NiftyBuffer> sBuffer;  // s, for smart pointers
 | |
| unsigned nItems;                  // n, when a variable denotes a count.
 | |
| ```
 | |
| Note that there is no underscore between the prefix and the actual variable
 | |
| name, and that the character following the prefix is in large caps. Note
 | |
| also that the prefixes can be stacked.
 | |
| ```
 | |
| class SomeClass
 | |
| {
 | |
| private:
 | |
|     int* m_pIndex;
 | |
|     int** m_ppIndex;
 | |
|     shared_ptr<SomeClass> m_sNext;
 | |
| };
 | |
| ```
 | |
| ## Guidelines
 | |
| These are suggestions.
 | |
| 
 | |
| ### Try to have only a single exit-point in each function.
 | |
| 
 | |
| **Rationale**: With multiple exit points it is very easy to overlook the release
 | |
| of some resource in one of those places.
 | |
| 
 | |
| Reasonable exceptions to the single exit point rule are:
 | |
| 
 | |
| * Checking of preconditions at the beginning of the function.
 | |
| ```
 | |
|  int function(int a, int b)
 | |
|  {
 | |
|      if (a < 0)
 | |
|          return -1;
 | |
| 
 | |
|      if (b > 5)
 | |
|          return -1;
 | |
| 
 | |
|      int rv;
 | |
|      ...
 | |
|      return rv;
 | |
| }
 | |
| ```
 | |
| * Functions that are basically only big switches.
 | |
| ```
 | |
| char* toString(enum Color c)
 | |
| {
 | |
|     switch (c)
 | |
|     {
 | |
|         case RED:
 | |
|             return "RED";
 | |
| 
 | |
|         case GREEN:
 | |
|             return "GREEN";
 | |
| 
 | |
|         default:
 | |
|             return "Unknown";
 | |
|    }
 | |
| }
 | |
| ```
 | |
| ### Try to keep the line length less than 80 characters.
 | |
| 
 | |
| **Rationale**: In typography the optimal line length for readability is
 | |
| considered to be around 60 characters. With 5 levels of nesting of 4
 | |
| spaces each, that gives 80 characters. If it is hard to stay within that
 | |
| limit, consider refactoring the function.
 | |
| 
 | |
| ### Use parenthesis to make the precedence explicit, even if precedence rules would not require it.
 | |
| ```
 | |
| if (a != b && !ready()) ...;
 | |
| 
 | |
| if ((a != b) && !ready()) ...;
 | |
| ```
 | |
| **Rationale**: There can never be any doubt about what the _intended_ precedence is.
 | |
| 
 | |
| ### Try to keep the length of each function less than what fits in one screen full (roughly 60 lines).
 | |
| 
 | |
| **Rationale**: That way it is possible with one glance to get a grasp of
 | |
| what the function does. If it's hard to keep within the limit it may be a
 | |
| sign that the function ought to be refactored.
 | |
| 
 | |
| ### Use vertical space (i.e. empty lines) to introduce paragraphs and sections.
 | |
| 
 | |
| **Rationale**: Makes the reading easier. | 
