Programming Conventions and Standards Advanced BioPSE J. Davison de St. Germain Chief Software Engineer SCI Institute 801-581-4078 dav@sci.utah.edu December 2003 NCRR Coding Tools Advanced BioPSE • CVS - Concurrent Versions System - Check in/out code regularly to make sure everyone is working on the newest code base • Regression Tester - Fix regression tester errors as soon as possible • Coding Standards - See following pages NCRR Required Advanced BioPSE 1. All code and comments are to be written in English. 2. All files must include appropriate license information. 3. Use the C++ mode in GNU Emacs and sci-c++-style.el to format code. 4. Include files in C++ always have the file name extension .h. 5. Implementation files in C++ always have the file name extension .cc. 6. Every include file must contain a “guard” that prevents multiple inclusions of the file, for example: #ifndef Geometry_BBox_h #define Geometry_BBox_h // Code... #endif // Geometry_BBox_h The name of the guard should be of the following form: libraryname_filename_h NCRR Required (cont) Advanced BioPSE 7.Use forward declarations wherever possible as opposed to including full definitions for classes, functions, and data: // Class class PointToMe; // Function void my_function(PointToMe &p, PointToMe *ptm); // Data PointToMe *m; 8. The names of variables and functions will begin with a lowercase letter and include underscore word separators. Names of constants should be in all CAPITALS, with underscore word separation: static int CONSTANT_INT_FIVE = 5; void my_function_name(); int my_local_variable_name = 0; 9.The names of class member variables are to end with an underscore, “_”: class MyClass{ int count_; }; NCRR Required (cont) Advanced BioPSE 10. The names of abstract data types (eg: Classes), and structs are to begin with an uppercase letter and each new word in the name should also be capitalized. class MyNewClassName { // ... }; 11. Declare as const a member function that does not change the state of an object. 12. Constants are to be defined using const or enum. Never use #define to create constants. 13. A class which uses new to allocate instances managed by the class must define a copy constructor and an assignment operator. 14. All classes which are used as base classes and which have virtual functions, must define a virtual destructor. 15. Always use delete[] to deallocate arrays. 16. Use exception handling to trap errors (although exceptions should only be used for trapping truly exceptional events). Our exception model includes two levels of exceptions. The top level of exceptions are defined in Classlib/Exceptions.h and are thrown when a class specific exception is not appropriate. The bottom level of exceptions are class specific, defined in the class that throws them, and are subclassed off of the top level exceptions. These class specific exceptions are exceptions that can be caught and handled from the calling function (1 level above the class.) However, if the calling function chooses not to (or cannot) handle the class specific exception, the exception will propagate to the next level at which point it can be trapped and handled in the form of a top level exception. An example of a class specific exception would be a StackUnderFlowException for a stack class. NCRR Required (cont) Advanced BioPSE 17. Comments should support generated documentation format. Comments in declarations should be of the form: //! … or /*! … */ These comments will then be visible in our online documentation. Comments in the definition part of your code need not have the !, as all the code is visible online including comments. Create comments that help the reader navigate your code. Comments should help the reader find the area of code he/she is looking for quickly. 18. Do not use identifiers which begin with one ('_') or two ('__') underscores. 19. Never use the $Id or $Log cvs directives. This confuses merging between branches. 20. Do not use #define to obtain more efficient code — use inline functions instead. 21. Avoid the use of numeric values in code; use symbolic values instead. This applies to numeric values that are repeated within the code but represent the same value. Eg: MAX_ARRAY_SIZE = 1024. 22. Do not compare a pointer to NULL or assign NULL to a pointer; use 0 instead. 23. Avoid explicit type conversions (casts). If you must cast use dynamic_cast and insert a comment explaining why. NCRR Required (cont) Advanced BioPSE 24. Never convert a constant to a non-constant. Use mutable if necesary. However, be aware of the thread safety problems this causes. 25. Never use goto. 26. Do not use malloc, realloc, or free. NCRR Recommended 1. ?Never? use more than 80 columns per line. Advanced BioPSE 2. An include file for a class should have a file name of the form class name.h. Use uppercase and lowercase letters in the same way as in the source code. 3. Never include /usr/include/*.h, for example iostream.h in any header file. This causes a huge amount of code to be recursively included and needlessly compiled. Use forward declarations to avoid this 4. Group local includes together, then group system includes together. 5. Avoid global data if possible. 6. Optimize code only if you know that you have a performance problem. Think twice before you begin. 7. Always force your compiler to compile with the maximum warning setting, and before you check in code, fix all warnings. 8. Place machine-dependent code in a special file so that it may be easily located when porting code from one machine to another. 9. Encapsulate global variables and constants, enumerated types, and typedefs in a class. 10. Functions in general should not be more than 25 lines long. If you find this situation, break the function into several smaller functions. 11. If a function stores a pointer to an object which is accessed via an argument, let the argument have the type pointer. Use reference arguments in other cases. NCRR Recommended (cont) Advanced BioPSE 12. When overloading functions, all variations should have the same semantics (be used for the same purpose). 13. Do not assume that you know how the invocation mechanism for a function is implemented. 14. Do not assume that an object is initialized in any special order in constructors. 15. Do not assume that static objects are initialized in any special order. 16. Use a typedef to simplify program syntax when declaring function pointers, or templated types. 17. When two operators are opposites (such as == and !=), it is appropriate to define both. 18. Use constant references (const &) instead of call-by-value, unless using a pre-defined data type or a pointer. 19. Minimize the number of temporary objects that are created as return values from functions or as arguments to functions. 20. Do not write code which is dependent on the lifetime of a temporary object. 21. Do not assume that the operands in an expression are evaluated in a definite order. Use parenthesis to enforce an order. NCRR Recommended (cont) Advanced BioPSE 22. Use parentheses to clarify the order of evaluation for operators in expressions. 23. Avoid using shift operations instead of arithmetic operations. 24. Use cout instead of printf. 25. Do not assume that an int and a long have the same size. 26. Do not assume that pointers and integers have the same size. 27. Do not assume that longs, floats, doubles or long doubles may begin at arbitrary addresses. 28. Avoid pointer arithmetic. 29. Always use plain char if 8-bit ASCII is used. Otherwise, use signed char or unsigned char. 30. Do not assume that a char is signed or unsigned. 31. Do not depend on underflow or overflow functioning in any special way. NCRR Questions? Advanced BioPSE NCRR Advanced BioPSE NCRR Advanced BioPSE NCRR