X-Git-Url: https://git.creatis.insa-lyon.fr/pubgit/?a=blobdiff_plain;f=DEVELOPPER;h=fd8a67964977e52c0eae3955c520a58f77b13ed1;hb=f163238b46fdd5a54c1b6b70549ab9466c101d14;hp=46152df1afdf219f3b1fa607efa460f0520544bb;hpb=de937e2bcf29f51c7903cf1a2e72f6fb9e5eb1d9;p=gdcm.git diff --git a/DEVELOPPER b/DEVELOPPER index 46152df1..fd8a6796 100644 --- a/DEVELOPPER +++ b/DEVELOPPER @@ -48,7 +48,10 @@ The following comments are intended for core gdcm developpers. ctest -D Experimental The results should appear in http://public.kitware.com/dashboard.php?name=public - under the name GDCM-* within the "Experimental Builds" entry. + under the name of your machine (uname), but for ease of use you can + change the SITE variable in your CMakeCache.txt to something more + accurate such as: GDCM-my_machine_name. The entry will then be within + the "Experimental Builds" entry. * Install gdcm (as specified by CMAKE_INSTALL_PREFIX) make install @@ -57,7 +60,7 @@ The following comments are intended for core gdcm developpers. followed the above instructions). * Python related section. - Depending on the automake/autoconf/autogen.sh flags you used gdcm could + Depending on the cmake flags you used in order to compile gdcm could be wrapped in two ways: - the first python wrappers of gdcm uses Swig (http://www.swig.org). These are the one generated when using autogen.sh --enable-python. @@ -100,3 +103,274 @@ The following comments are intended for core gdcm developpers. to vtkGdcmReader.py which also uses vtkWrapPython wrapped classes ("from gdcmPython.vtkgdcmPython import *"). +------------------------------------------------------------------------------ +gdcm coding style and religious/agnostic beliefs (proposition) + +* Introduction: + The following coding style intends to ease the work of developpers + themselves but also of users who will study, maintain, fix, and extend + the code. Any bread crumbs that you can drop in the way of explanatory + names and comments will go a long way towards helping other readers and + developers. + Keep in mind that to a large extent the structure of code directly + expresses its implementation. + +* Language: + - C++ (for the kernel) and Python (for the wrappers). + - all the names (variables, members, methods, functions) and comments + should be based on English. Documentation, guides, web site and other + informations should be in English. + Make sure you use correct (basic) English and complete, grammatically + correct sentences for comments and documentation. + +* General layout: + - Each line of code should take no more than 79 characters. Break the code + across multiple lines as necessary. + - Methods and functions should keep a reasonable number of lines when + possible (a typical editor displays 50 lines). Avoid code duplication. + Always prefer creating a new method or function to duplication. + A high indentation level generally suggests the need for a new + method or function. + - All the code should be properly indented. The appropriate indentation + level is three spaces for each level of indentation. DO NOT USE TABS. + Set up your editor to insert spaces. Using tabs may look good in your + editor but will wreak havoc in others, or in external tools (e.g. side + by side diffs). + - The declaration of variables within classes, methods, and functions + should be one declaration per line. Provide them with default values + and don't rely on compilers for default initialization. + +* Naming conventions: + - Generalities: + In general, names are constructued by using case change to indicate + separate words, as in ImageDataSize (standing for "image data size"). + Underscores are not used. Variable names are chosen carefully with the + intention to convey the meaning behind the code. Names are generally + spelled out; use of abbreviations is discouraged. + [Note: abbreviation are allowable when in common use, and should be in + uppercase as in LUT or RGBA.] + While this does result in long names, it self-documents the code. + - Naming Files: + Files should have the same name as the class, with a "gdcm" prepended. + Header files are named .h, while implementation files are named either + .cxx or .txx, depending on whether they are implementations of templated + classes. For example, the class gdcm::Document is declared and defined + in the files gdcmDocument.h and gdcmDocument.cxx. + - Naming Class Data Members, Methods, and Functions: + Class data members are named beginning with a capital letter as in + GroupPixel. + Global functions and class methods, either static or class members, are + named beginning with a capital letter, as in GetImageDataSize(). + - Naming Local Variables: + Local variables begin in lowercase. There is more flexibility in the + naming of local variables although they still should convey some + semantics. + +* Classes: + - Don't use the inline keyword when defining an inline function + within a class definition. + - Do not repeat the virtual keyword when overriding virtual base methods + in declaration of subclasses: + class A + { + virtual void foo(...); + }; + class B: public A + { + void foo(...); // and not: virtual void foo(...); + }; + - The public, protected, private declarations should be at the + same indent level as the class. Use + class A + { + private: + void foo(...); + public: + void bar(...); + }; + - Method and functions devoided of arguments should not use the void + notation. Use + SomeType Header::GetPixelData() + and not + SomeType Header::GetPixelData(void). + +* Use of braces: + - Braces must be used to delimit the scope of an if, for, while, switch, or + other control structure. Braces are placed on a line by themselves, and + at the same indentation level as the control structure to which they + belong: + for (i=0; * i<3; i++) + { + ... + } + or when using an if: + if ( condition ) + { + ... + } + else if ( other condition ) + { + ... + } + else + { + .... + } + You can choose to use braces on a line with a code block when + the block consists of a single line: + if ( condition ) { foo=1; } + else if ( condition2 ) { foo=3; } + else { return; } + or + for (i=0; i<3; ++i) {x[i]=0.0;} + Methods and functions should follow the same usage of braces: + void File::ParsePixelData() + { + ... + } + +* Special layout: + - Avoid code mixed with comments on a single line. Instead, prepend the + logical blocks of code with the concerned comments. + - Use parantheses around conditions e.g. with an if statement: + if ( someLocalVariable == 2 ) { ... } + - Add spaces around parantheses, or braces. Use + if ( someLocalVariable == 2 ) { ClassMenber += 1; } + and not + if (someLocalVariable == 2) {ClassMenber += 1;} + - Add spaces around each side of the assignement operator, and + around binary operators used in boolean expression. Use + someLocalVariable = ClassMember * 2; + if ( someLocalVariable == 2 || ClassMember == 2 ) ... + and not + someLocalVariable=ClassMember*2; + if ( someLocalVariable==2||ClassMember==2 ) ... + +* Miscelaneous: + - Don't use underscores. Don't use tabs. Don't use control characters + like ^M. Anyhow, cvs is configured to reject such commits. + - Comments should be in C++ style ("// ...", two slashes, per line). Don't + use C style comments ("/* ... */"). + - The last line of a file should terminate with "\n". + - Returned arguments of methods and functions should not be wrapped with + parantheses. Use + return iter->second; + but do not use + return ( iter->second ); + +* Debugging and Verbose modes: + Never use std::cout. Instead use the gdcmDebug class through the + global instance dbg. Example: + #include "gdcmDebug.h" + ... + { + dbg.Verbose(3, "Local function name: entering."); + ... + } + will send the message to std::cout when dbg.Debug() is called + in your main. + +* Documentation: + The Doxygen open-source system is used to generate on-line documentation. + Doxygen requires the embedding of simple comments in the code which is in + turn extracted and formatted into documentation. See + http://www.stack.nl/ dimitri/doxygen/ + for more information about Doxygen. + - Documenting a class: + Classes should be documented using the class and brief doxygen commands, + followed by the detailed class description: + /** + * \class Header + * \brief Header acts as container of Dicom elements of an image. + * + * Detailed description of the class is provided here + * ... + */ + The key here is that the comment starts with /**, each subsequent line has + an aligned *, and the comment block terminates with a */. + - Documenting class members and inline methods: + All the members and the inline methods should be documented within + the class declaration as shown in the following example: + class Header + { + /// True when parsing was succefull. False otherwise. + bool Readable = false; + + /// \brief The number of lines of the image as interpreted from + /// the various elements encountered at header parsing. + int NumberOfLines = -1; + + /// Predicate implemented as accessor around \ref Readable. + bool IsReadable() { return Readable; } + }; + - Documenting a Method: + Methods should be documented using the following comment block style + as shown in the following example: + + /** + * \brief Within the Dicom Elements (parsed with the public and private + * dictionaries), look for the element value representation of + * a given tag. + * @param group Group number of the searched tag. + * @param element Element number of the searched tag. + * @return Corresponding element value representation when it exists, + * and the string "gdcm::Unfound" otherwise. + */ + std::string Document::GetEntryByNumber(guint16 group, guint16 element) + { + ... + } + +* External includes and C style: + - Only the C++ standard library and the STL includes should be used. + When including don't use the .h extension (use #include + instead of #include ). + - Don't use the C standard library. Don't include stdio.h, ctype.h... + Don't use printf(), sprinf(), FILE*... + - Don't use the NULL notation (either as macro, or as const int NULL=0). + A pointer that doesn't refer to an object should simply be defined as + DataPointer* MyDataPointer = 0; + +* Basic types: + - Assume T is a given type. When declaring or defining with the + "pointer to T" notation, the * character must be adjacent to + the type and not the variable. That is use + T* foo = 0; + and not + T *foo = 0; + - Always define a typedef for a new type and be consistent in usage. + Use + typedef Header* HeaderPointer; + HeaderPointer MyHeaderPointer; + - One notorious counter example for non using C style inclusion concerns + exact-width integers (since there seem to be no equivalent for C++). + When using exact-width integers use the typedef names defined by + the Basic ISO C99: 7.18 Integer types i.e. + int8_t int16_t int32_t int64_t (signed integers) + and + uint8_t uint16_t uint32_t uint64_t (unsigned integers). + Conversion table is then: + unsigned char -> uint8_t; + unsigned short -> uint16_t; + unsigned int -> uint32_t; + unsigned long -> uint32_t; + unsigned long long -> uint64_t; + (signed) char -> int8_t; + short -> int16_t; + int -> int32_t; + long -> int32_t; + long long -> int64_t; + Hence do not use declarations like "unsigned int". + With g++, accessing those typedef is achieved by the following + #include +------------------------------------------------ +CVS policy +* All the commits should be atomic. They must preserve the compilation + in order to prevent checkouts with broken code. +* All the commits must correspond to a stade of the code where ctest + runs and has no failing subtest. Always run ctest before commiting. + Note: * you can start ctest in verbose mode through the command + ctest -V >& log + * you can start a single test through ctest with + ctest -R FailingTestName -V >& log +------------------------------------------------