changed indentation to tabs
[opensync.git] / CODING
blob5dccc8f99358e41cfe239f1d8df362a824de7289
1 INTRODUCTION
2 ---------------------------------------------------------------------
3 Here will you find coding standards to the project. Requirements are
4 listed in their respective files and can be considered an adendum to
5 this document.
8 CODING STYLE
9 ---------------------------------------------------------------------
10 See linux/Documentation/CodingStyle.
12 Some highlights:
14 - Outside of comments and documentation, never
15   use spaces. Identation is done using tabs only.
17 - Do not use tabs to align text documentation. Changing tab
18   width should not interfere with the layout/alignment of code,
19   only indentation.
21 - functions are declared like this:
22    char *function(const char *test)
23    {
25    }
27 - if you use brackets INSIDE a function put them on the same line
29     Wrong:
30     if (condition)
31     {
32         do_something;
33     }
35     Right:
36     if (condition) {
37         do_something;
38     }
40 - Do not put actions in the same line of conditions:
42     Wrong:
43     if (condition) do_this;
45     Right:
46     if (condition)
47         do_this;
49 - Also it is a good practice to use always brackets in conditions:
50          
51          if (condition) {
52                 do_only_this;
53          }
54          
55 - Variables are always in lower case (like tmp_buf)
56 - New defined types are capitalized (like OSyncEngine)
57 - Never use typedefs just to hide pointers
59 - External APIs, used for integration between components may
60   look like this:
62         osync_engine_init()
64 - Always add the osync_ prefix to your functions
66 - Do not return function calls, like "return do_something();",
67   instead, use a auxiliar variable (rationale: easy trace).
69 - When doing error checking, use goto to help creating a single
70   return point. Do not abuse goto usage though... never goto up,
71   never create more than one label and do not "gotoo far".
73 EMACS
74 ---------------------------------------------------------------------
75 For the above indentation rules, you can add the following 
76 to your .emacs file:
78 ;; Additional setting to have linux kernel style
79 ;; indentation. Argument lists in next line will only
80 ;; be indented by tabs
81 (defun c-lineup-arglist-tabs-only (ignored)
82   "Line up argument lists by tabs, not spaces"
83   (let* ((anchor (c-langelem-pos c-syntactic-element))
84      (column (c-langelem-2nd-pos c-syntactic-element))
85      (offset (- (1+ column) anchor))
86      (steps (floor offset c-basic-offset)))
87     (* (max steps 1)
88        c-basic-offset)))
90 (defun my-c-mode-hook ()
91   (setq indent-tabs-mode t)
92   (c-set-style "linux")
93   (c-set-offset 'arglist-cont-nonempty 
94                 '(c-lineup-gcc-asm-reg c-lineup-arglist-tabs-only))
97 (add-hook 'c-mode-hook 'my-c-mode-hook )
99 CODE DOCUMENTATION
100 ---------------------------------------------------------------------
102 * Add FIXME, TODO and XXX comments appropriately.
104 * Use Doxygen (http://www.stack.nl/~dimitri/doxygen/) to document your code
106 * Add your doxygen annotations in the header files. This allows other
107   developers to read the documentation without having installed the source.
109 * Add simple READMEs and pictures as needed, but concentrate
110   on doxygen.
112 * Recommended to watch for leading and trailing empty spaces on comments
113 (vim and emacs can be set to display them).
115 * Try to describe the *why* of a function and not just the *what* (e.g.
116 'This function is required by module foo because of protocol X. It does
117 something'
119 Some examples:
121 a) Say that you have a function (e.g. foo) and its declaration in a header
122 file (foo.h), a good way to document that would be:
124  - in foo.h
126  /** @brief This functions does something funny.
127   *
128   * Here you can put further details.
129   *
130   * @todo something is missing
131   *
132   * @param bar This is the parameter, please refer \ref bar_func to create
133   * this value.
134   * @return Returns -1 for failure, 0 for success.
135   */
136 char foo(int bar);
139 - Implementation must be almost free of comments, because it helps to read the
140 code. Only really trick parts should be commented (even better, re-written
141 to be more simple). The wise use of XXX/FIXME/TODO can help a lot to
142 identify hot spots in the code. So, say in foo.c
144 void foo(int bar)
146         /* TODO: write a unit test */
148         /* XXX: a dirt trick to workaround a bug in protocol */
149         /* here goes the code */
152         /* FIXME: this should be moved to another module */
153         /* here goes the code */
157 CODE INSTRUMENTATION
158 -----------------------------------------------------------------
160 Always:
161     * Use const;
162     * Use static for internal functions;
163     * Use safe glib functions where possible;
164     * Check validity of all received parameters;
165     * Use osync_assert() while developing;
166     * Do not use alloca() or other non-recommended functions;
167     * Check for return errors even from malloc() and other
168       standard system calls;
170 Regularly:
171     * Use valgrind to profile you application and find memleaks
173 About header files:
174     * Source code has to be split into modules, which are defined as
175       a collection of implementation files (.c) with an interface
176       exported through a header file (.h).
177     * The inclusion (#include) of headers must reflect the dependencies
178       between modules in the implementation. The most important
179       implications from this statement are:
181         . implementation files (.c) *must* include *all* headers it
182           directly depends;
183         . implementation files (.c) *must not* include headers it
184           doesn't directly depend;
185         . headers should include headers only when needing a
186           definition or declaration;
187         . headers should never include other headers just to create a
188           "single point of inclusion".
190       These rules may sound obvious, but they're actually hard to
191       follow.
194 COMMITS AND CHANGELOGS
195 ---------------------------------------------------------------------
196 Descriptive and small.
198 General rules:
199    - *Always* do a svn diff and a svn status before a commit and
200      document the diff(s) in the changelogs;
201    - What matters is not what but why;
202    - Several commits are usually better than a big one;
203    - Do not commit unrelated modifications at once unless they're
204      really trivial;
205    - Commit ASAP.
207 BUILD-SYSTEM
208 ---------------------------------------------------------------------
209 Standard instructions:
211   Code should compile with no warnings, using the following GCC
212   options:
214     -Wall
215     -Werror
217     Recomended but not mandatory (for now):
218     -W
219     -Wmissing-declarations
220     -Wmissing-prototypes
221     -Wredundant-decls
222     -Wshadow
223     -Wbad-function-cast
224     -Wcast-qual
225     -std=iso9899:1990
226     -D_FORTIFY_SOURCE=2
228     Hint:
229     For developers using GCC there is a CMAKE_BUILD_TYPE "hacking" which sets
230     the default compiler flags to a recommended compiler flag set.
232 LOGS and TRACES
233 ---------------------------------------------------------------------
234 There are two types of logs that must be handled by almost all
235 applications:
237  * HIGH-LEVEL LOGS: these are standard, high-level logs usually
238    enabled by default. Useful to advanced users, support-centers and
239    alike. Should include basic information, including but not limited
240    to:
241      - start/end of application
242      - errors
243      - complex operations
245    The requirements document specifies if logs are needed or not.
247  * TRACES: traces are a particular kind of log used to debug the
248    application. They're used mostly by black-box testers to submit
249    failure reports.
251    Traces should be enabled in a per-application basis using an
252    environment variable or at compile time, to be yet defined.
254 UNIT TESTS
255 -----------------------------------------------------------------
257 * All code should be written together with unit-tests. The tool
258   used to implement the tests is "check", available on
259   http://check.sourceforge.net/.
261   The build-system infra-structure provides a configure option to
262   allow check usage. If possible use the CMake macro ADD_CHECK_TEST
263   to introduce new tests, for building and integration as testrun
264   in the build-environment.
266   When using Make, the test can be locally run via:
267   $ make test
269   Results can also be sent to central testing dashboard CDash at
270   http://opensync.org/testing. Command to run tests and send results
271   to CDash:
272   $ make Experimental
274   The tests must be implemented inside a sub-directory called test
275   with the following modules:
277   check_<component name> --> the test-manager
278   check_<unit name>      --> implements tests for interfaces
279                              exported by unit
280   check_<...>
282   Just to remember, an unit, or module, is a collection of
283   souce-code files (.c) with an interface exported through
284   a header file (.h).
286   All interfaces exported by units must be tested (that is,
287   all non-static functions). The tests should implement at
288   least the following test cases:
290     - standard usage
291     - upper and bottom limits of buffers and variables as
292       needed
293     - error conditions
294     - critical paths
296   Use incremental tests, that is, test functions before using them in
297   other test-cases (for example, if you need to call function A to
298   prepare the environment to test function B, test function A first).
300   Try to write the test-case before the unit or function itself.
302   If the test needs an external entity to work (for example, it needs
303   a device connected on a specific port), put the test inside a
304   condition for an environment variable and document it in a README
305   file.