General guidelines about programming ------------------------------------ Write your code so that it may be easily read and understood by another person: use helpful, mnemonic names for functions and variables. Add comments to aid comprehension. KISS = Keep It Simple, Stupid! C.A.R. Hoare reportedly said: “...there are two ways of constructing a software design: one way is to make it SO SIMPLE THERE ARE OBVIOUSLY NO DEFICIENCIES, and the other way is to make it SO COMPLICATED THAT THERE ARE NO OBVIOUS DEFICIENCIES. The first method is far more difficult!" And also: "[almost always] premature optimization is the root of all evil!" ------------------------------------------------------- GOOD QUALITY CODE & LIBRARY CODE Writing good library code is tough: it needs to be portable, efficient, robust, reliable and easy to use (by someone else, not you). Always check that the supplied arguments are sane; if not, report an error! Make your functions "EASY TO USE CORRECTLY, AND HARD TO USE INCORRECTLY" (paraphrasing a book by Scott Meyers). This is much easier said than done! - be consistent if you have several functions with the same name - consider using an enum instead of bool for a fn parameter (example: look at SmallPrime in NumTheory-prime.H) Prefer robustness to speed (or else document clearly!) - a robust "clearly correct" implementation is a good reference for testing your future "clever, fast" implementation. (so you can check automatically that the "clever" one is right). Exceptions .......... Execution of a function may end in one of two ways: - (1) via normal return (e.g. the result has been computed, and is to given to the caller); - (2) via emitting an exception: an exception can be any value (e.g. a string saying what went wrong). Normally a function which receives an exception simply re-emits the exception to its caller; only if the exception is "caught" (by a try...catch block inside the function) does this upward propagation stop. How to signal an error in one of your functions: - Usually throw an exception (maybe different exceptions for different error cases).. - An alternative is to return an "impossible result" (but then the caller has to check the returned value; perhaps this "trick" best used only hidden inside "internal implementation details"). In CoCoALib throwing an exception serves two purposes: - (1) Convey a meaningful/helpful error message [so the caller can understand what went wrong]; - (2) Allow the exception to be caught and handled. In my experience, code which catches and handles an exception is quite rare! One possible use-case is to change the exception object into one more meaningful to the caller. Example: Look at CoCoA's exception class (in exception.H), and at InterruptReceived class (interrupt.H). ------------------------------------------------------- MORE CHALLENGING GOALS (1) Make your code THREADSAFE: your code should run properly even if there are 2 or more threads executing it simultaneously. (aka. RE-ENTRANT code) ==> avoid using vars of global extent (i.e. "globals/static"): ==> avoid I/O; recall that cout, clog, cerr are globals --- memory allocation uses globals safely (but slowly) (2) Make your code EXCEPTION-SAFE: There are 2 good categories - (1) "no throw" (this fn-proc never emits an exception) - (2) "strong": if an exception is emitted then all data outside the fn remain equivalent to values before the call. - (3) other (best avoided unless you are skilled) - You should rarely need try...catch blocks. - If you must use pointers, use "smart pointers" (e.g. see C++ std::unique_ptr and std::shared_ptr) - Be wary of "in place" changes to data-structures passed by reference: a safe way is to compute the new value then "swap" into destination. -------------------------------------------- Special points for LIBRARY CODE Difference between library code and complete programs: - Library code should never crash (regardless of what the caller does) - Library code should "never" print out (except via a verbosity setting, or if the fn is specifically to produce output) - Library code should work on all platforms (and behave the same!) =======================================================