It's important that Rivet code be fairly homogeneous in coding style, so that all the analyses and projections are good examples for non-core developers to copy, and so that everyone can read each class without having to double-think.
Some of the rules below might seem rather petty, but please stick by them (and complain at Andy if you think you've got a good reason for doing otherwise!) As with all rules, they're there to be broken, but only if you can justify doing so :-)
*.hh
suffix, implementation files with a *.cc
suffix;_
prefix followed by a ''lower case'' letter, e.g. private: int _myFoo;
. Don't use starting underscores followed by capital letters, or double underscores at all - both can clash with internal symbols;++i
rather than i++
. For e.g. iterators, this can be a not-insignificant performance boost, and since this is a well-known idiom it's lazy to do otherwise - when I see post-increments in code, it makes me wonder if the author really knows what they're doing!Your code will be more readable if you space things out a bit:
// prefer
if (foo < bar) {...
// to
if(foo<bar){...
,
// prefer
for (int i = 0; i < N; ++i) {
// to
for(int i=0;i<N;++i){
and
// prefer
if (foo == bar) {
// to
if(foo==bar){
It's not Fortran: spaces are not expensive! We will edit code not supplied in this format. * Also leave a couple of blank lines between function definitions, and occasional blank lines between blocks inside functions and class definitions to better emphasise the algorithm/data structures; * Use two spaces rather than tabs for indentation. You should be able to set up your code editor to do this automatically - for example, try adding this to your .emacs
file if you're an emacs user:
(setq-default c-basic-indent 2)
(setq-default tab-width 4)
(setq-default indent-tabs-mode nil)
While silly flame wars rage on this topic, most people are agreed that consistency is important: since most editors these days should be able to indent "to the correct amount" automatically, using spaces is completely unambiguous, with no extra typing required.
typedef
, or a temporary variable - often sensible anyway;#endif
s in header guards - it just leads to inconsistencies when new header files are made by "copy and paste". Similarly, don't use comments which mention the filename: they lead to inconsistencies via renamings and copyings, and if you need to print the source then the IDE/editor will probably attach the filename to the printout anyway.#include
that might induce a transitive dependency._hist
";Analysis
interface, and virtually no analyses inherit from any base class other than Analysis
. Hence there is no need for header files, and analyses should be written completely inline with the implementations as part of the class definition, all in the .cc
file.MSG_DEBUG(...)
, MSG_INFO(...)
etc. macros in place of getLog() << ... << endl;
._hist_blah_900GeV
, _hist_blah_7000GeV
, etc.: just make one _hist_blah
and use the sqrtS()
function in the init()
method of the analysis to book it from the appropriate histogram code. Then in the analyze()
method, you can just call fill()
without having to work out which variable you should be filling. This can save a ''lot'' of repetitive copy 'n' paste code, and we will reject supplied analyses which should do this and haven't, since otherwise they are a maintenance nightmare.The "don't use pointers" rule may seem particularly perverse. Aren't they core to how C++ works? Well, for most purposes the answer is "no". While there are certainly areas of C++ code where pointers are useful, they tend to only be the places where references can't be used: polymorphic containers, storage of abstract base classes, and member variables with reference semantics. References are safe, while pointers are the single most common cause of segfaults and difficult-to-find bugs: prefer references whenever possible.
One particular reason to discourage pointers is that we want analysis and projection classes to be writeable by non-C++ experts: if pointers are involved, the level of required expertise is immediately raised (even if you don't realise that that's the case). Using pointers also forces projection authors to have to write custom constructors, destructors, copy constructors and copy assignment operators (cf. the "if you need one, you'll need all three" idiom): that's a lot of work and potential bugs that could have been avoided. This rule is sometimes referred to as the Law of the Big Three: see http://www.parashift.com/c++-faq-lite/coding-standards.html#faq-27.10 (and the rest of this excellent C++ resource!) for details.