SourceForge.net Logo LinuxFund.org Logo
Home Press Mailing Lists Documentation Screenshots People SourceForge Downloads

CinePaint Authors Style Recommendation (CASR)
by Robin Rowe

Developers who follow this style recommendation will make life easier for others, especially me. Please don't get too worked up about coding style. It isn't going to be dictated. Style choices are often driven by personal preference more so than logic. It's a religious question. NO STYLE DEBATES ON OUR MAILING LISTS! Don't post your style guides or opinions about style to the list. We have better things to do than debate this stuff. What is given here is my personal preference, not a group consensus -- as if that's even possible! If you have to get it off your chest you can email me advice about style off-list.

Function is more important than style, but style effects function. We're writing CinePaint in C++ not C, and CASR has a definite C++ feel to it. However, this is very conservative C++. Template and exceptions enthusiasts are sure to be disappointed, but our C programmers gain a much easier learning curve. Note that plug-ins by their self-contained nature are less of an issue than code design in the core. You can use just about any popular consistent coding style in plug-ins without too much impact on others. The openexr plug-in, for instance, uses the STL.

Format/Whitespace

  1. Write a 1-page overall design document that explains how your program works and with what components. A good 1-page README is more valuable (time-saving) than a bunch of inline comments in your code.
  2. Be neat and consistent.
  3. Don't do anything that's so clever nobody else will be able to understand it.
  4. Avoid mind-numbing "This is a comment" type of comments in the code. Use such clear names for variables and functions that a comment is unneeded.
  5. Tabs or 4-space indentation.
  6. Do not doublespace code. Conserve vertical whitespace to make it easier to see code in debugger window.
  7. Align braces vertically C++ style. Do not dangle opening brace to the right as with C style.
  8. Use braces with single-line if or else statements.
  9. Functions and methods use UpperAndLowerCase().
  10. Variables use lower_case_with_underbars.
  11. Constants (enum) typically UPPERCASE, but not to excess.
  12. No inner classes. It's confusing and de-optimizes compilers. Use namespaces if necessary.
  13. One class per file. Life is just easier this way.
  14. Use inline functions in .h file anywhere a function body is short and contains no loops.
  15. Only use implicit inlines (by embedding function body in .h file). Do not use inline keyword hint that may be ignored.
  16. Do not create useless empty out-of-line constructor and destructor function bodies in .cpp files. It's sub-optimal for compiler and confusing for code maintainers.
  17. Use returns C++ style with implicit clean-up in destructor, not single-point-exit-at-all-costs of C style.

The C++ Way:

Object ob;// Contains Handle h
if(!ob.Open(res))
{ return false;
}
ob.Process();
// implicit ob.dtor clean-up
return true;
 

Not the C Way:

Handle h=0;
h=Open(res);
if(IsGood(h)){
  Process(h);
}
Close(h); // resource leak if fail to reach this line
return IsGood(h);

Logic/Features

  1. Avoid using sized typedefs for variables. Using built-in types appropriately (e.g., int), produces better optimized code.
  2. Eliminate redundant else clauses. Do not follow a 'return' with a dangling 'else'.
  3. Test return value of all functions that return status. Return false from your function on failure. Functions that don't return an object should return bool (true/false) or nothing if failure is not a possibility (e.g., a function that sets a flag somewhere will always work).
  4. Avoid using signal handlers, but if needed have it only set a flag and immediately return.
  5. Avoid using threads, but if needed use as few threads as feasible.
  6. No calls to exit() or abort(). Always return.
  7. No throwing exceptions. Return false immediately or set a flag (when needed) and limp. It's impossible to ensure that any C++ program that uses exceptions in a non-trivial way won't at some point abort. If a destructor calls a function that throws an exception during stack unwinding before catch it's curtains. GUI programs that use exceptions are illogical. The user isn't at the command-line and therefore won't see any exception trace dump. Using exceptions in batch programs makes the code not be reusable in GUI programs.
  8. Avoid templates. When not used sparingly (by experts) will cause code bloat and make code unmaintainable by non-experts.
  9. No STL. Many programmers can't read the code. It's just not worth it. There are simple containers in our Gel library.
  10. Use iofile in our Gel library as a lightweight substitute for fstreams.
  11. No multiple inheritance. Under the covers MI is implemented as thunks in C++. You don't want this kludge in your code.
  12. Avoid operator overloading. It can make code hard to understand.
  13. Use single inheritance sparingly and only when you intend polymorphism. Often programmers use inheritance where embedding would work just as well and make the code faster and easier to reuse later.
  14. All resource allocations should have implicit clean-up in destructor. Resources should be encapsulated as objects. No bare handles. The destructor should call close and the handle should be set to zero or a known invalid state. Failing to do so can create double close/delete errors.
  15. Don't thrash the heap. Use heap allocation (new/malloc/g_malloc) only when an object is large or its size is unknown at compile time.


Questions to rower@movieeditor.com
Created July 27, 2003; updated Feb 18, 2006