/* Please note the following comments we may use everywhere NOTE: Notes TODO: something should be added here FIXME: something needs to be fixed OBSOLETE: something could be removed from here QUESTION: I had some questions at this point but I could not get an answer OPT: something is commented out to improve performance As an example: */ Harbour Coding Standards ======================== (based heavily on coding standards placed in PHP) NOTE: For the best demonstration of Harbour coding style, please refer to real .c and .prg code inside /src and /include. Real-life style always overrides this doc if there are doubts. Code Implementation ------------------- [0] Document your code in source files and the manual. [tm] [1] Functions that are given pointers to resources should not free them For instance, function int mail(char *to, char *from) should NOT free to and/or from. Exceptions: - The function's designated behavior is freeing that resource. E.g. hb_xfree() - The function is given a boolean argument, that controls whether or not the function may free its arguments (if true - the function must free its arguments, if false - it must not) [2] Functions that are tightly integrated with other functions within the same module, and rely on each other non-trivial behavior, should be documented as such and declared 'static'. They should be avoided if possible. [3] Use definitions and macros whenever possible, so that constants have meaningful names and can be easily manipulated. Use HB_TRUE instead of 1 (in boolean context) Use HB_FALSE instead of 0 (in boolean context) Use NULL instead of 0 (in pointer context) Always use 'HB_' prefix for definitions of new datatypes and macros. Use either 'PHB_' prefix for datatypes that are pointers. e.g. HB_ITEM PHB_ITEM [4] When writing functions that deal with strings, be sure to remember that Harbour holds the length property of each string, and that it shouldn't be calculated with strlen(). Write your functions in a such a way so that they'll take advantage of the length property, both for efficiency and in order for them to be binary-safe. Functions that change strings and obtain their new lengths while doing so, should return that new length, so it doesn't have to be recalculated with strlen() [5] NEVER USE strncat(). If you're absolutely sure you know what you're doing, check its man page again, and only then, consider using it, and even then, try avoiding it. [6] Use assert(). Not only does good assertion catch bugs, but it also helps with code readability. - Do not use assert for error handling. Use assert only for the condition that must be always true. - Do not use assignments in assert conditions. If you assign inside an assert condition, you risk an elusive bug that would be very difficult to spot in a debug build, due to the side effect of the assignment. Function calls in assert conditions may also cause this problem, if they modify one of their arguments or global variables. [7] Use hb_xgrab()/hb_xalloc(), hb_xfree(), hb_xrealloc(), hb_xsize() to manage memory allocations. These functions implement an internal "safety-net" mechanism that ensures the deallocation of any unfreed memory at the end of an application. They also provide useful allocation and overflow information while running in debug mode. Naming Conventions ------------------ [1] Function names for user-level functions defined in C code should be enclosed with in the HB_FUNC() macro. They should be in uppercase. The name should be prefixed with 'HB_' if this function is an extension to functions set defined in Clipper Abbreviations should not be used when they greatly decrease the readability of the function name itself. [2] Variable names must be meaningful. One letter variable names must be avoided, except for places where the variable has no real meaning or a trivial meaning (e.g. for (i=0; i<100; i++) ...). [3] Variable names should use so-called Hungarian notation. Use lowercase letters however use underscores to separate between words. Good: pMemoryPtr Bad: p_memory_ptr [4] Static variables should be prefixed with 's_' [5] Global variables (variables shared between modules) should be prefixed with 'hb_', e.g. hb_vm_bDebug, hb_gc_pStart Syntax and indentation ---------------------- [1] Never use C++ style comments (i.e. // comment). Always use C-style comments instead. Harbour is written in C, and is aimed at compiling under any ANSI-C compliant compiler. Even though many compilers accept C++-style comments in C code, you have to ensure that your code would compile with other compilers as well. [2] Do not use K&R-style. Of course, we cannot and do not want to force anybody to use a style he or she is not used to, but, at the very least, when you write code that goes into the core of Harbour or one of its standard modules, please don't use the K&R style. This applies to just about everything, starting with indentation and comment styles and up to function declaration syntax. (see also http://www.catb.org/~esr/jargon/html/I/indent-style.html) [3] Be generous with whitespace and braces. Always prefer: if( foo ) { bar; } to: if(foo)bar; and to: if( foo ){ bar; } Keep one empty line between the variable declaration section and the statements in a block, as well as between logical statement groups in a block. Maintain at least one empty line between two functions. [4] When indenting, use three spaces. It is important to maintain consistency in indenture so that definitions, comments, and control structures line up correctly. Documentation -------------- [1] Whenever be possible document yourself functions you developed. Usually it's hard to understand code written by other person, moreover when it involves some obscure algorithm, system's vars or attributes or data unavailable for the documentation writers. This is particularly evident for low-level functions. [2] After some time function was written, work becomes more difficult because it's needed to read the code several times (even for the own developer). This is evident when variables don't have useful names (and uses only letters). Because that, please DO NOT leave functions without documentation. [3] If function made calls to other non-documented functions, and the original developer are not available anymore, could be so hard and even impossible to document it. [4] Tracking which functions are documented and which are not, and if they are total or partially documented are a waste of resources in time and people. [5] If you are the developer of the function don't worry by your narrative skills, concentrate in what functions do, which arguments it gets, which are its purpose and specially what information function returns. [6] If you are the developer of the function, and you are using system's functions or vars undocumented, please explain it as much as possible. If you use a obscure or strange algorithm please explain what it does and how it works. [7] Notes, remarks and explaining enclose always between the /* */ pair, please don't use the double bar // because it may break portability. [8] Remember... documentation it's a much time consuming work, usually takes more time writing the documentation of a function that writing the function itself.