diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 09:49:46 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 09:49:46 +0000 |
commit | 50b37d4a27d3295a29afca2286f1a5a086142cec (patch) | |
tree | 9212f763934ee090ef72d823f559f52ce387f268 /doc/developer/coding-methods.rst | |
parent | Initial commit. (diff) | |
download | freeradius-50b37d4a27d3295a29afca2286f1a5a086142cec.tar.xz freeradius-50b37d4a27d3295a29afca2286f1a5a086142cec.zip |
Adding upstream version 3.2.1+dfsg.upstream/3.2.1+dfsgupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'doc/developer/coding-methods.rst')
-rw-r--r-- | doc/developer/coding-methods.rst | 242 |
1 files changed, 242 insertions, 0 deletions
diff --git a/doc/developer/coding-methods.rst b/doc/developer/coding-methods.rst new file mode 100644 index 0000000..444696d --- /dev/null +++ b/doc/developer/coding-methods.rst @@ -0,0 +1,242 @@ +Helpful coding methods +====================== + +The following is a short set of guidelines to follow while +programming. It does not address coding styles, function naming +methods, or debugging methods. Rather, it describes the processes +which SHOULD go on in the programmers mind, while he is programming. + +Coding standards apply to function names, the look of the code, and +coding consistency. Coding methods apply to the daily practices used +by the programmer to write code. + + + +1. Comment your code. + + If you don't, you'll be forced to debug it 6 months later, when + you have no clue as to what it's doing. + + If someone REALLY hates you, you'll be forced to debug + un-commented code that someone else wrote. You don't want to do + that. + + For FreeRADIUS use doxygen @style comments so you get the benefits + of docs.freeradius.org. + +2. Give things reasonable names. + + Variables and functions should have names. Calling them 'x', + 'xx', and 'xxx' makes your life hell. Even 'foo' and 'i' are + problematic. + + Avoid smurfs. Don't re-use struct names in field names i.e. + struct smurf { + char *smurf_pappa_smurf; + } + + If your code reads as full english sentences, you're doing it + right. + + +3. Check input parameters in the functions you write. + + Your function CANNOT do anything right if the user passed in + garbage, and you were too lazy to check for garbage input. + + assert() (rad_assert()) is ugly. Use it. + + GIGO is wrong. If your function gets garbage input, it + should complain loudly and with great descriptiveness. + + +4. Write useful error messages. + + "Function failed" is useless as an error message. It makes + debugging the code impossible without source-level instrumentation. + + If you're going to instrument the code at source level for error + messages, leave the error messages there, so the next sucker won't + have to do the same work all over again. + + +5. Check error conditions from the functions you call. + + Your function CANNOT do anything right if you called another + function, and they gave you garbage output. + + One of the most common mistakes is:: + + fp = fopen(...); + fgetc(fp); /* core dumps! */ + + If the programmer had bothered to check for a NULL fp (error + condition), then he could have produced a DESCRIPTIVE error + message, instead of having his program core dump. + + +6. Core dumps are for weenies. + + If your program core dumps accidentally, you're a bad programmer. + You don't know what your program is doing, or what it's supposed + to be doing when anything goes wrong. + + If it hits an assert() and calls abort(), you're a genius. You've + thought ahead to what MIGHT go wrong, and put in an assertion to + ensure that it fails in a KNOWN MANNER when something DOES go + wrong. (As it usually does...) + + +7. Initialize your variables. + + memset() (talloc_zero()) is your friend. 'ptr = NULL' is + nice, too. + + Having variables containing garbage values makes it easy for the + code to do garbage things. The contents of local variables are + inputs to your function. See #3. + + It's also nearly impossible for you to debug any problems, as you + can't tell the variables with garbage values from the real ones. + + +8. Don't allow buffer over-runs. + + They're usually accidental, but they cause core dumps. + strcpy() and strcat() are ugly. Use them under duress. + + sizeof() is your friend. + + +9. 'const' is your friend. + + If you don't mean to modify an input structure to your function, + declare it 'const'. Declare string constants 'const'. It can't + hurt, and it allows more errors to be found at compile time. + + Use 'const' everywhere. Once you throw a few into your code, and + have it save you from stupid bugs, you'll blindly throw in 'const' + everywhere. It's a life-saver. + + +10. Use C compiler warnings. + + Turn on all of the C compiler warnings possible. You might have + to turn some off due to broken system header files, though. But + the more warnings the merrier. + + Getting error messages at compile time is much preferable to + getting core dumps at run time. See #7. + + Notice that the C compiler error messages are helpful? You should + write error messages like this, too. See #4. + + +11. Avoid UNIXisms and ASCIIisms and visualisms. + + You don't know under what system someone will try to run your code. + Don't demand that others use the same OS or character set as you use. + + Never assign numbers to pointers. If foo is a char*, and you want it + to be be null, assign NULL, not 0. The zeroth location is perfectly + as addressable as any other on plenty of OSes. Not all the world + runs on Unix (though it should :) ). + + Another common mistake is to assume that the zeroth character in the + character set is the string terminator. Instead of terminating a + string with 0, use '\0', which is always right. Similarly, memset() + with the appropriate value: NULL, '\0', or 0 for pointers, chars, + and numbers. + + Don't put tabs in string constants, either. Always use '\t' to + represent a tab, instead of ASCII 9. Literal tabs are presented to + readers of your code as arbitrary whitespace, and it's easy to mess + up. + + +12. Make conditionals explicit. + + Though it's legal to test "if (foo){}", if you test against the + appropriate value (like NULL or '\0'), your code is prettier and + easier for others to read without having to eyeball your prototypes + continuously to figure out what you're doing (especially if your + variables aren't well-named). See #2. + + +13. Test your code. + + Even Donald Knuth writes buggy code. You'll never find all of the + bugs in your code unless you write a test program for it. + + This also means that you'll have to write your code so that it + will be easily testable. As a result, it will look better, and be + easier to debug. + +Hints, Tips, and Tricks +----------------------- + +This section lists many of the common "rules" associated with code +submitted to the project. There are always exceptions... but you must +have a really good reason for doing so. + + 1. Read the Documentation and follow the CodingStyle + + The FreeRADIUS server has a common coding style. Use real tabs + to indent. There is whitespace in variable assignments. + (i = 1, NOT i=1). + + When in doubt, format your code to look the same as code already + in the server. If your code deviates too much from the current + style, it is likely to be rejected without further review, and + without comment. + + 2. #ifdefs are ugly + + Code cluttered with ifdefs is difficult to read and + maintain. Don't do it. Instead, put your ifdefs in a header, and + conditionally define 'static inline' functions, or macros, which + are used in the code. Let the compiler optimize away the "no-op" + case. + + Simple example, of poor code:: + + #ifdef CONFIG_MY_FUNKINESS + init_my_stuff(foo); + #endif + + Cleaned-up example: + + (in header):: + + #ifndef CONFIG_MY_FUNKINESS + static inline void init_my_stuff(char *foo) {} + #endif + + (in the code itself):: + + init_my_stuff(dev); + + 3. 'static inline' is better than a macro + + Static inline functions are greatly preferred over macros. They + provide type safety, have no length limitations, no formatting + limitations, and under gcc they are as cheap as macros. + + Macros should only be used for cases where a static inline is + clearly suboptimal [there a few, isolated cases of this in fast + paths], or where it is impossible to use a static inline + function [such as string-izing]. + + 'static inline' is preferred over 'static __inline__', 'extern + inline', and 'extern __inline__'. + + 4. Don't over-design. + + Don't try to anticipate nebulous future cases which may or may + not be useful: "Make it as simple as you can, and no simpler" + + Split up functionality as much as possible. If your code needs + to do two unrelated things, write two functions. Mashing two + kinds of work into one function makes the server difficult to + debug and maintain. + |