anope

- supernets anope source code & configuration
git clone git://git.acid.vegas/anope.git
Log | Files | Refs | Archive | README

CODING (8270B)

      1 Originally pulled from: https://wiki.inspircd.org/Coding_Guidelines
      2 
      3 ---
      4 
      5 InspIRCd Coding Guidelines
      6 
      7 The following are a set of guidelines for writing patches to InspIRCd, or for
      8 creating modules for distribution with the official package. These guidelines
      9 were written a time after InspIRCd development started, and so not all code
     10 yet follows these. This will be rectified with time.
     11 
     12 
     13 1. Comments
     14 
     15    * Multi Line
     16      Multiple line comments should follow the C-style comment, for example:
     17        /*
     18         * This is a multiple line comment, huzzah..
     19         */
     20 
     21    * Single Line
     22      Single line comments should also be in the C style, for example:
     23        /* This is a boring one-line comment */
     24 
     25    * Doxygen commenting
     26      If you wish your comment to show in doxygen, the comment should be directly
     27      above the item you are documenting (a class, function, enum, etc) and the
     28      first line should be "/**". For example:
     29        /** This is a doxygen multiline comment.
     30 	*  Description of thingymebob here.
     31 	*/
     32 
     33      The first line after the "**" is used as the short description of the item
     34      (up to the full stop) and everything afterwards as the detailed description.
     35 
     36 
     37 2. Indentation
     38 
     39    Tabs. Tabs. ONLY TABS. Use a single tab for each level of indentation,
     40    for example:
     41      int main()
     42      {
     43      <tab>if (condition)
     44      <tab>{
     45      <tab><tab>code
     46      <tab>}
     47      }
     48 
     49 
     50 3. Separation
     51 
     52    Always put a space in between a keyword like if/while and the condition,
     53    for example:
     54      if (foo == bar)
     55     NOT
     56      if(foo == bar)
     57 
     58 
     59 4. Braces
     60 
     61    Always put braces opening and closing blocks on separate lines, see the
     62    indentation example. For example, place braces like this:
     63      if (apples == "green")
     64      {
     65          cout << "Apples are green" << endl;
     66      }
     67 
     68    and not:
     69      if (apples == "green") {
     70          cout << "Apples are green" << endl;
     71      }
     72 
     73    The one exception to this is if you are declaring a class method which is
     74    only one line long, in that case the following is acceptable in most cases:
     75      class foo : public bar
     76      {
     77          foo() { }
     78 	 getrandomfoo() { return rand(); }
     79      };
     80 
     81 
     82 5. Templates
     83 
     84    Where possible, use templates rather than #defines. Avoid use of RTTI.
     85 
     86 
     87 6. Structs
     88 
     89    Structs should be declared in the following fashion:
     90      struct BodyPartBasket
     91      {
     92          int arms;
     93 	 int legs;
     94 	 int scrotalsacs;
     95      };
     96    and not like this:
     97      typedef struct
     98      {
     99          int arms;
    100 	 int legs;
    101 	 int scrotalsacs;
    102      } BodyPartBasket;
    103 
    104     The second way is not required in C++ to be able to do this:
    105       BodyPartBasket mybasket;
    106 
    107     Plus, placing the name at the bottom of the declaration makes readability
    108     more difficult (as you have to scroll down to the bottom of the struct to
    109     find its name). (where possible, call them classes rather than structs.)
    110 
    111 
    112 7. Variable naming
    113 
    114    Class and struct names should be in camel case with a leading capital letter,
    115    for example "MyBagOfBones" and not "my_bag_of_bones" or "mybagofbones".
    116    Variable names can be in either camel case with a leading capital letter or
    117    alternatively all lower case, so long as the same naming convention is
    118    adhered to throughout the class. No classes or variables should be named in
    119    capitals unless this makes sense for the name (for example "class DNS").
    120    Constants and enum values should always be completely in CAPITALS and
    121    underscores may be used, for example:
    122      enum DecayState
    123      {
    124          DECAYED_MOULDY  = 0,
    125 	 DECAYED_SMELLY  = 1,
    126 	 DECAYED_MAGGOTS = 2
    127      };
    128    All value names in an enum should be started with the same text which should
    129    be related in some way to the enum's use. For example "DNS_CNAME, DNS_A,
    130    DNS_AAAA".
    131 
    132 
    133 8. Use of references
    134 
    135    Wherever possible, when dealing with any complex class, pass a const reference
    136    rather than a copy of the class. For example:
    137      MyThingy::MyThingy(const std::string &thingyvalue)
    138      {
    139      }
    140    Of course, if you intended to change the string you can just omit the 'const'.
    141 
    142 
    143 9. Use of char pointers
    144 
    145    Whenever you use char pointers (char*, char**) try to use const equivalents.
    146    This is much safer and avoids ugly and dangerous casts. For example:
    147      MyThingy::Thingify(const char* const* wotsits)
    148      {
    149      }
    150    If it is possible without performance loss, consider avoiding char pointers
    151    altogether and using std::string instead.
    152 
    153 
    154 10. Use of STL
    155 
    156     For more information on use of STL in InspIRCd, please see the separate
    157     STL FAQ.
    158 
    159 
    160 11. Making copies of data
    161 
    162    Never ever make a copy of a piece of data unless it is absolutely necessary.
    163    For example, don't use strlcpy() to make a copy of the const char* string
    164    returned by std::string::c_str(), if the change can be done to the std::string
    165    itself. The same goes for unnecessary variable assignments, especially those
    166    which assign large classes.
    167 
    168 
    169 12. namespace std
    170 
    171    Avoid the following:
    172      using namespace std;
    173    It might take a bit more typing, but things work better if you don't set
    174    (then later assume) the namespace -- specify it explicitly when you want to
    175    use it.
    176 
    177 
    178 13. Linefeeds
    179 
    180    Unix linefeeds only please. We do not like to see our screens covered in ^M.
    181 
    182 
    183 14. Portability
    184 
    185    Always make sure your code is portable to all supported operating systems,
    186    remember of course that as of 1.1.8 this includes windows. Don't write code
    187    that only works on windows, or only works on Linux. Test your code on all
    188    platforms or ask for help from other developers who have the platforms you
    189    want to test on.
    190 
    191    * new() and delete(), malloc() and free()
    192      Apart from the fact that using malloc() and free() is bad practice in C++
    193      code, you must never use malloc() or free() in InspIRCd, within its modules
    194      or within the core. This is because if you use malloc() or free() in windows,
    195      the memory is claimed from the program's local heap.
    196      In windows, each shared object (module, dll) has its own heap, which is
    197      protected from other dlls and executables. To get around this issue and
    198      allow more posix-like memory access from other dlls in the program (other
    199      modules), InspIRCd overrides the operators new and delete to ensure that
    200      memory allocated by them comes from the windows global heap. If you use
    201      malloc() and free() for this, the ircd will segfault when another module
    202      tries to access the memory you have allocated!
    203 
    204    * strdup()
    205      As with malloc(), above, strdup() should be avoided. Where strdup() is
    206      absolutely necessary, use strnewdup() which is our strdup() implementation
    207      that calls operator new instead of using malloc().
    208      char arrays allocated by strnewdup() should be deleted with operator delete[].
    209 
    210    * CoreExport and DllImport
    211      Prefix all types you want to import or export to other modules with CoreExport
    212      and DllImport macros. These do nothing in POSIX operating systems, however
    213      in windows these are expanded to the instructions __declspec(dllimport) and
    214      __declspec(dllexport) respectively depending on where they are used and how.
    215 
    216 
    217 15. External Dependencies
    218 
    219    If a module is compiled as standard, or the code is part of the core, you must
    220    not use any dependencies that are not available as standard on all supported
    221    operating systems beyond libstdc++, libc, and whatever else is currently
    222    required to build the core. Modules which use nonstandard dependencies belong
    223    in the modules/extra directory.
    224 
    225 
    226 16. Profiling and Performance
    227 
    228    It is one thing to assume that code performs bad, it is another thing to prove
    229    that it actually is. A lot of experienced programmers talk about 'premature
    230    optimisation', and here is what it means: if you have a piece of code called
    231    once on startup that takes 10 seconds instead of one second to run, and a
    232    piece of code that takes 0.05 seconds to run when it should take 0.01, and
    233    it is called once per second, the second piece of code is the priority.
    234 
    235    In other words, make sure that what you think is slow, and a performance
    236    problem in Insp actually is.
    237    To do this, use the callgrind tool from Valgrind (valgrind --tool=cachegrind
    238    bin/inspircd -nofork -debug), and kcachegrind (or similar) to view the output
    239    files.