1 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
4 <META http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
5 <TITLE>Gdcm Developpers</TITLE>
10 <!#######################################################################>
11 <H1>Gdcm coding style (and other religious/agnostic beliefs)</H1>
12 <HR size="1"><ADDRESS style="align: right;"></ADDRESS>
16 The following coding style intends to ease the work of developpers
17 themselves but also of users who will study, maintain, fix, and extend
18 the code. Any bread crumbs that you can drop in the way of explanatory
19 names and comments will go a long way towards helping other readers and
21 Keep in mind that to a large extent the structure of code directly
22 expresses its implementation.
25 - C++ (for the kernel) and Python (for the wrappers).
26 - all the names (variables, members, methods, functions) and comments
27 should be based on English. Documentation, guides, web site and other
28 informations should be in English.
29 Make sure you use correct (basic) English and complete, grammatically
30 correct sentences for comments and documentation.
33 - Each line of code should take no more than 79 characters. Break the code
34 across multiple lines as necessary.
35 - Methods and functions should keep a reasonable number of lines when
36 possible (a typical editor displays 50 lines). Avoid code duplication.
37 Always prefer creating a new method or function to duplication.
38 A high indentation level generally suggests the need for a new
40 - All the code should be properly indented. The appropriate indentation
41 level is three spaces for each level of indentation. DO NOT USE TABS.
42 Set up your editor to insert spaces. Using tabs may look good in your
43 editor but will wreak havoc in others, or in external tools (e.g. side
45 - The declaration of variables within classes, methods, and functions
46 should be one declaration per line. Provide them with default values
47 and don't rely on compilers for default initialization.
51 In general, names are constructed by using case change to indicate
52 separate words, as in ImageDataSize (standing for "image data size").
53 Underscores are not used. Variable names are choosen carefully with the
54 intention to convey the meaning behind the code. Names are generally
55 spelled out; use of abbreviations is discouraged.
56 [Note: abbreviation are allowable when in common use, and should be in
57 uppercase as in LUT or RGBA.]
58 While this does result in long names, it self-documents the code.
60 Files should have the same name as the class, with a "gdcm" prepended.
61 Header files are named .h, while implementation files are named either
62 .cxx or .txx, depending on whether they are implementations of templated
63 classes. For example, the class gdcm::Document is declared and defined
64 in the files gdcmDocument.h and gdcmDocument.cxx.
65 - Naming Class Data Members, Methods, and Functions:
66 Class data members are named beginning with a capital letter as in
68 Global functions and class methods, either static or class members, are
69 named beginning with a capital letter, as in GetImageDataSize().
70 - Naming Local Variables:
71 Local variables begin in lowercase. There is more flexibility in the
72 naming of local variables although they still should convey some
74 - Naming function parameters:
75 Function parameters begin in lowercase. There is more flexibility in the
76 naming of function parameters although they still should convey some
80 - Don't use the inline keyword when defining an inline function
81 within a class definition.
82 - As stated in the "Naming conventions" section, class data members
83 are named beginning with a capital letter as in GroupPixel.
84 But the parameter names of method should be named with a lowercase
85 letter (in order to distinguish at a glance data members, from parameters
86 and also to avoid potential collisions with data members):
87 void A::SetGroupPixel( int groupPixel )
89 GroupPixel = groupPixel;
91 - Don't use trailing ';' in inline function definition.
93 void A::SetGroupPixel( int groupPixel ){GroupPixel = groupPixel;}
95 void A::SetGroupPixel( int groupPixel ){GroupPixel = groupPixel;};
96 - Do not repeat the virtual keyword when overriding virtual base methods
97 in declaration of subclasses:
100 virtual void foo(...);
104 void foo(...); // and not: virtual void foo(...);
106 - The public, protected, private declarations should be at the
107 same indent level as the class. Use
115 - Method and functions devoided of arguments should not use the void
117 SomeType Header::GetPixelData()
119 SomeType Header::GetPixelData(void).
122 - Braces must be used to delimit the scope of an if, for, while, switch, or
123 other control structure. Braces are placed on a line by themselves, and
124 at the same indentation level as the control structure to which they
126 for (i=0; * i<3; i++)
135 else if ( other condition )
143 You can choose to use braces on a line with a code block when
144 the block consists of a single line:
145 if ( condition ) { foo=1; }
146 else if ( condition2 ) { foo=3; }
149 for (i=0; i<3; ++i) {x[i]=0.0;}
150 Methods and functions should follow the same usage of braces:
151 void File::ParsePixelData()
157 - Avoid code mixed with comments on a single line. Instead, prepend the
158 logical blocks of code with the concerned comments.
159 - Use parentheses around conditions e.g. with an if statement:
160 if ( someLocalVariable == 2 ) { ... }
161 - Add spaces around parentheses, or braces. Use
162 if ( someLocalVariable == 2 ) { ClassMember += 1; }
164 if (someLocalVariable == 2) {ClassMember += 1;}
165 - Add spaces around each side of the assignement operator, and
166 around binary operators used in boolean expression. Use
167 someLocalVariable = ClassMember * 2;
168 if ( someLocalVariable == 2 || ClassMember == 2 ) ...
170 someLocalVariable=ClassMember*2;
171 if ( someLocalVariable==2||ClassMember==2 ) ...
174 - Don't use underscores. Don't use tabs. Don't use control characters
175 like ^M. Anyhow, cvs is configured to reject such commits.
176 - Comments should be in C++ style ("// ...", two slashes, per line). Don't
177 use C style comments ("/* ... */").
178 - The last line of a file should terminate with "\n".
179 - Returned arguments of methods and functions should not be wrapped with
183 return ( iter->second );
185 * Debugging and Verbose modes:
186 Never use std::cout. Instead use the gdcmDebug class through the
187 global instance dbg. Example:
188 #include "gdcmDebug.h"
191 dbg.Verbose(3, "Local function name: entering.");
194 will send the message to std::cout when dbg.Debug() is called
198 The Doxygen open-source system is used to generate on-line documentation.
199 Doxygen requires the embedding of simple comments in the code which is in
200 turn extracted and formatted into documentation. See
201 http://www.stack.nl/~dimitri/doxygen/
202 for more information about Doxygen.
203 - Documenting a class:
204 Classes should be documented using the class and brief doxygen commands,
205 followed by the detailed class description:
208 * \brief Header acts as container of Dicom elements of an image.
210 * Detailed description of the class is provided here
213 The key here is that the comment starts with /**, each subsequent line has
214 an aligned *, and the comment block terminates with a */.
215 - Documenting class members and inline methods:
216 All the members and the inline methods should be documented within
217 the class declaration as shown in the following example:
220 /// True when parsing was succesfull. False otherwise.
221 bool Readable = false;
223 /// \brief The number of lines of the image as interpreted from
224 /// the various elements encountered at header parsing.
225 int NumberOfLines = -1;
227 /// Predicate implemented as accessor around \ref Readable.
228 bool IsReadable() { return Readable; }
230 - Documenting a Method:
231 Methods should be documented using the following comment block style
232 as shown in the following example:
235 * \brief Within the Dicom Elements (parsed with the public and private
236 * dictionaries), look for the element value representation of
238 * @param group Group number of the searched tag.
239 * @param elem Element number of the searched tag.
240 * @return Corresponding element value representation when it exists,
241 * and the string "gdcm::Unfound" otherwise.
243 std::string Document::GetEntryByNumber(guint16 group, guint16 elem)
248 * External includes and C style:
249 - Only the C++ standard library and the STL includes should be used.
250 When including don't use the .h extension (use #include <iostream>
251 instead of #include <iostream.h>).
252 Note: include the stl header AFTER the gdcm ones (otherwise pragma
253 warnings won't work).
254 - Don't use the C standard library. Don't include stdio.h, ctype.h...
255 Don't use printf(), sprinf(), FILE*...
256 - Don't use the NULL notation (neither as macro, nor as const int NULL=0).
257 A pointer that doesn't refer to an object should simply be defined as
258 DataPointer* MyDataPointer = 0;
261 - Assume T is a given type. When declaring or defining with the
262 "pointer to T" notation, the * character must be adjacent to
263 the variable and not the type. That is use
269 - Assume T is a given type. When declaring or defining with the
270 "reference to T" notation, the & character must be adjacent to
271 the variable and not the type. That is use :
276 (Doxygen will not have any longer to correct)
278 - Always define a typedef for a new type and be consistent in usage.
280 typedef Header *HeaderPointer;
281 HeaderPointer MyHeaderPointer;
282 - One notorious counter example for non using C style inclusion concerns
283 exact-width integers (since there seem to be no equivalent for C++).
284 When using exact-width integers use the typedef names defined by
285 the Basic ISO C99: 7.18 Integer types i.e.
286 int8_t int16_t int32_t int64_t (signed integers)
288 uint8_t uint16_t uint32_t uint64_t (unsigned integers).
289 Conversion table is then:
290 unsigned char -> uint8_t;
291 unsigned short -> uint16_t;
292 unsigned int -> uint32_t;
293 unsigned long -> uint32_t;
294 unsigned long long -> uint64_t;
295 (signed) char -> int8_t;
299 long long -> int64_t;
300 Hence do not use declarations like "unsigned int".
301 With g++, accessing those typedef is achieved by the following
302 #include < stdint.h >
306 <!#######################################################################>
307 <HR size="1"><ADDRESS style="align: right;"></ADDRESS>