123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709 |
- <?xml version="1.0"?>
- <?xml-stylesheet type="text/xsl" href="styleguide.xsl"?>
- <GUIDE title="Objsim C++ Style Guide">
- <p align="right">
- Revision 0.1
- </p>
- <address>
- Frank Michler
- </address>
- <OVERVIEW>
- <CATEGORY title="Important Note">
- <STYLEPOINT title="Displaying Hidden Details in this Guide">
- <SUMMARY>
- This style guide contains many details that are initially
- hidden from view. They are marked by the triangle icon, which you
- see here on your left. Click it now.
- You should see "Hooray" appear below.
- </SUMMARY>
- <BODY>
- <p>
- Hooray! Now you know you can expand points to get more
- details. Alternatively, there's an "expand all" at the
- top of this document.
- </p>
- </BODY>
- </STYLEPOINT>
- </CATEGORY>
- <CATEGORY title="Background">
- <p>
- The objsim library is written in C++.
- This style guide is adapted from the "Google C++ Style Guide".
- </p>
- <p>
- The goal of this guide is to manage this complexity by describing
- in detail the dos and don'ts of writing C++
- code. These rules exist to
- keep
-
- the
- code base manageable while still allowing coders to use C++ language
- features productively.
- </p>
- <p>
- <em>Style</em>, also known as readability, is what we call the
- conventions that govern our C++ code. The term Style is a bit of a
- misnomer, since these conventions cover far more than just source
- file formatting.
- </p>
- <p>
- One way in which we keep the code base manageable is by enforcing
- <em>consistency</em>.
-
- It is very important that any
-
- programmer
- be able to look at another's code and quickly understand it.
- Maintaining a uniform style and following conventions means that we can
- more easily use "pattern-matching" to infer what various symbols are
- and what invariants are true about them. Creating common, required
- idioms and patterns makes code much easier to understand. In some
- cases there might be good arguments for changing certain style
- rules, but we nonetheless keep things as they are in order to
- preserve consistency.
- </p>
- <p>
- Another issue this guide addresses is that of C++ feature bloat.
- C++ is a huge language with many advanced features. In some cases
- we constrain, or even ban, use of certain features. We do this to
- keep code simple and to avoid the various common errors and
- problems that these features can cause. This guide lists these
- features and explains why their use is restricted.
- </p>
-
- <p>
- Note that this guide is not a C++ tutorial: we assume that the
- reader is familiar with the language.
-
- </p>
-
- </CATEGORY>
- </OVERVIEW>
- <CATEGORY title="Header Files">
- <p>
- In general, every <code>.cpp</code> file should have an associated
- <code>.hpp</code> file.
- </p>
- <p>
- Correct use of header files can make a huge difference to the
- readability, size and performance of your code.
- </p>
- <p>
- The following rules will guide you through the various pitfalls of
- using header files.
- </p>
- <STYLEPOINT title="The #define Guard">
- <SUMMARY>
- All header files should have <code>#define</code> guards to
- prevent multiple inclusion. The format of the symbol name
- should be
- <code><i><PROJECT></i>_<i><PATH></i>_<i><FILE></i>_HPP_</code>.
- </SUMMARY>
- <BODY>
-
- <p>
- To guarantee uniqueness, they should be based on the full path
- in a project's source tree. For example, the file
- <code>foo/src/bar/baz.hpp</code> in project <code>foo</code> should
- have the following guard:
- </p>
- <CODE_SNIPPET>
- #ifndef FOO_BAR_BAZ_H_
- #define FOO_BAR_BAZ_H_
- ...
- #endif // FOO_BAR_BAZ_H_
- </CODE_SNIPPET>
-
- </BODY>
- </STYLEPOINT>
- <STYLEPOINT title="Header File Dependencies">
- <SUMMARY>
- Don't use an <code>#include</code> when a forward declaration
- would suffice.
- </SUMMARY>
- <BODY>
- <p>
- When you include a header file you introduce a dependency that
- will cause your code to be recompiled whenever the header file
- changes. If your header file includes other header files, any
- change to those files will cause any code that includes your
- header to be recompiled. Therefore, we prefer to minimize
- includes, particularly includes of header files in other
- header files.
- </p>
- <p>
- You can significantly minimize the number of header files you
- need to include in your own header files by using forward
- declarations. For example, if your header file uses the
- <code>File</code> class in ways that do not require access to
- the declaration of the <code>File</code> class, your header
- file can just forward declare <code>class File;</code> instead
- of having to <code>#include "file/base/file.hpp"</code>.
- </p>
- <p>
- How can we use a class <code>Foo</code> in a header file
- without access to its definition?
- </p>
- <ul>
- <li> We can declare data members of type <code>Foo*</code> or
- <code>Foo&</code>.
- </li>
- <li> We can declare (but not define) functions with arguments,
- and/or return values, of type <code>Foo</code>.
- </li>
- <li> We can declare static data members of type
- <code>Foo</code>. This is because static data members
- are defined outside the class definition.
- </li>
- </ul>
- <p>
- On the other hand, you must include the header file for
- <code>Foo</code> if your class subclasses <code>Foo</code> or
- has a data member of type <code>Foo</code>.
- </p>
- <p>
- Sometimes it makes sense to have pointer (or better,
- <code>scoped_ptr</code>)
- members instead of object members. However, this complicates code
- readability and imposes a performance penalty, so avoid doing
- this transformation if the only purpose is to minimize includes
- in header files.
- </p>
- <p>
- Of course, <code>.cpp</code> files typically do require the
- definitions of the classes they use, and usually have to
- include several header files.
- </p>
-
- </BODY>
- </STYLEPOINT>
- <STYLEPOINT title="Inline Functions">
- <SUMMARY>
- Define functions inline only when they are small, say, 10 lines
- or less.
- </SUMMARY>
- <BODY>
- <DEFINITION>
- You can declare functions in a way that allows the compiler to
- expand them inline rather than calling them through the usual
- function call mechanism.
- </DEFINITION>
- <PROS>
- Inlining a function can generate more efficient object code,
- as long as the inlined function is small. Feel free to inline
- accessors and mutators, and other short, performance-critical
- functions.
- </PROS>
- <CONS>
- Overuse of inlining can actually make programs slower.
- Depending on a function's size, inlining it can cause the code
- size to increase or decrease. Inlining a very small accessor
- function will usually decrease code size while inlining a very
- large function can dramatically increase code size. On modern
- processors smaller code usually runs faster due to better use
- of the instruction cache.
- </CONS>
- <DECISION>
- <p>
- A decent rule of thumb is to not inline a function if it is
- more than 10 lines long. Beware of destructors, which are
- often longer than they appear because of implicit member-
- and base-destructor calls!
- </p>
- <p>
- Another useful rule of thumb: it's typically not cost
- effective to inline functions with loops or switch
- statements (unless, in the common case, the loop or switch
- statement is never executed).
- </p>
- <p>
- It is important to know that functions are not always
- inlined even if they are declared as such; for example,
- virtual and recursive functions are not normally inlined.
- Usually recursive functions should not be inline. The main
- reason for making a virtual function inline is to place its
- definition in the class, either for convenience or to
- document its behavior, e.g., for accessors and mutators.
- </p>
- </DECISION>
- </BODY>
- </STYLEPOINT>
- <STYLEPOINT title="The -inl.hpp Files">
- <SUMMARY>
- You may use file names with a <code>-inl.hpp</code> suffix to define
- complex inline functions when needed.
- </SUMMARY>
- <BODY>
- <p>
- The definition of an inline function needs to be in a header
- file, so that the compiler has the definition available for
- inlining at the call sites. However, implementation code
- properly belongs in <code>.cpp</code> files, and we do not like
- to have much actual code in <code>.hpp</code> files unless there
- is a readability or performance advantage.
- </p>
- <p>
- If an inline function definition is short, with very little,
- if any, logic in it, you should put the code in your
- <code>.hpp</code> file. For example, accessors and mutators
- should certainly be inside a class definition. More complex
- inline functions may also be put in a <code>.hpp</code> file for
- the convenience of the implementer and callers, though if this
- makes the <code>.hpp</code> file too unwieldy you can instead
- put that code in a separate <code>-inl.hpp</code> file.
- This separates the implementation from the class definition,
- while still allowing the implementation to be included where
- necessary.
- </p>
- <p>
- Another use of <code>-inl.hpp</code> files is for definitions of
- function templates. This can be used to keep your template
- definitions easy to read.
- </p>
- <p>
- Do not forget that a <code>-inl.hpp</code> file requires a
- <a href="#The__define_Guard"><code>#define</code> guard</a> just
- like any other header file.
- </p>
-
- </BODY>
- </STYLEPOINT>
- <STYLEPOINT title="Function Parameter Ordering">
- <SUMMARY>
- When defining a function, parameter order is: inputs,
- then outputs.
- </SUMMARY>
- <BODY>
- <p>
- Parameters to C/C++ functions are either input to the
- function, output from the function, or both. Input parameters
- are usually values or <code>const</code> references, while output
- and input/output parameters will be non-<code>const</code>
- pointers. When ordering function parameters, put all input-only
- parameters before any output parameters. In particular, do not add
- new parameters to the end of the function just because they are
- new; place new input-only parameters before the output
- parameters.
- </p>
- <p>
- This is not a hard-and-fast rule. Parameters that are both
- input and output (often classes/structs) muddy the waters,
- and, as always, consistency with related functions may require
- you to bend the rule.
- </p>
- </BODY>
- </STYLEPOINT>
- </CATEGORY>
- <CATEGORY title="Naming">
- <p>
- The most important consistency rules are those that govern
- naming. The style of a name immediately informs us what sort of
- thing the named entity is: a type, a variable, a function, a
- constant, a macro, etc., without requiring us to search for the
- declaration of that entity. The pattern-matching engine in our
- brains relies a great deal on these naming rules.
-
- </p>
- <p>
- Naming rules are pretty arbitrary, but
-
- we feel that consistency is more important than individual preferences
- in this area, so regardless of whether you find them sensible or not,
- the rules are the rules.
- </p>
-
- <STYLEPOINT title="General Naming Rules">
- <SUMMARY>
- Function names, variable names, and filenames should be
- descriptive; eschew abbreviation. Types and variables should be
- nouns, while functions should be "command" verbs.
- </SUMMARY>
- <BODY>
- <SUBSECTION title="How to Name">
- <p>
- Give as descriptive a name as possible, within reason. Do
- not worry about saving horizontal space as it is far more
- important to make your code immediately understandable by a
- new reader. Examples of well-chosen names:
- </p>
- <CODE_SNIPPET>
- int num_errors; // Good.
- int num_completed_connections; // Good.
- </CODE_SNIPPET>
- <p>
- Poorly-chosen names use ambiguous abbreviations or arbitrary
- characters that do not convey meaning:
- </p>
- <BAD_CODE_SNIPPET>
- int n; // Bad - meaningless.
- int nerr; // Bad - ambiguous abbreviation.
- int n_comp_conns; // Bad - ambiguous abbreviation.
- </BAD_CODE_SNIPPET>
- <p>
- Type and variable names should typically be nouns: e.g.,
- <code>FileOpener</code>,
-
- <code>num_errors</code>.
- </p>
- <p>
- Function names should typically be imperative (that is they
- should be commands): e.g., <code>OpenFile()</code>,
- <code>set_num_errors()</code>. There is an exception for
- accessors, which, described more completely in <a HREF="#Function_Names">Function Names</a>, should be named
- the same as the variable they access.
- </p>
- </SUBSECTION>
-
- <SUBSECTION title="Abbreviations">
- <p>
- Do not use abbreviations unless they are extremely well
- known outside your project. For example:
- </p>
- <CODE_SNIPPET>
- // Good
- // These show proper names with no abbreviations.
- int num_dns_connections; // Most people know what "DNS" stands for.
- int price_count_reader; // OK, price count. Makes sense.
- </CODE_SNIPPET>
- <BAD_CODE_SNIPPET>
- // Bad!
- // Abbreviations can be confusing or ambiguous outside a small group.
- int wgc_connections; // Only your group knows what this stands for.
- int pc_reader; // Lots of things can be abbreviated "pc".
- </BAD_CODE_SNIPPET>
- <p>
- Never abbreviate by leaving out letters:
- </p>
- <CODE_SNIPPET>
- int error_count; // Good.
- </CODE_SNIPPET>
- <BAD_CODE_SNIPPET>
- int error_cnt; // Bad.
- </BAD_CODE_SNIPPET>
- </SUBSECTION>
- </BODY>
- </STYLEPOINT>
-
- <STYLEPOINT title="File Names">
- <SUMMARY>
- Filenames should be all lowercase and can include underscores
- (<code>_</code>) or dashes (<code>-</code>). Follow the
- convention that your
-
- project
- uses. If there is no consistent local pattern to follow, prefer "_".
- </SUMMARY>
- <BODY>
- <p>
- Examples of acceptable file names:
- </p>
- <p>
- <code>
- my_useful_class.cpp<br/>
- my-useful-class.cpp<br/>
- myusefulclass.cpp<br/>
- </code>
- </p>
- <p>
- C++ files should end in <code>.cpp</code> and header files
- should end in <code>.hpp</code>.
- </p>
- <p>
- Do not use filenames that already exist
- in <code>/usr/include</code>, such as <code>db.h</code>.
- </p>
- <p>
- In general, make your filenames very specific. For example,
- use <code>http_server_logs.h</code> rather
- than <code>logs.h</code>. A very common case is to have a
- pair of files called, e.g., <code>foo_bar.hpp</code>
- and <code>foo_bar.cpp</code>, defining a class
- called <code>FooBar</code>.
- </p>
- <p>
- Inline functions must be in a <code>.hpp</code> file. If your
- inline functions are very short, they should go directly into your
- <code>.hpp</code> file. However, if your inline functions
- include a lot of code, they may go into a third file that
- ends in <code>-inl.hpp</code>. In a class with a lot of inline
- code, your class could have three files:
- </p>
- <CODE_SNIPPET>
- url_table.hpp // The class declaration.
- url_table.cpp // The class definition.
- url_table-inl.hpp // Inline functions that include lots of code.
- </CODE_SNIPPET>
- <p>
- See also the section <a href="#The_-inl.hpp_Files">-inl.hpp Files</a>
- </p>
- </BODY>
- </STYLEPOINT>
-
- <STYLEPOINT title="Type Names">
- <SUMMARY>
- Type names start with a capital letter and have a capital
- letter for each new word, with no underscores:
- <code>MyExcitingClass</code>, <code>MyExcitingEnum</code>.
- </SUMMARY>
- <BODY>
- <p>
- The names of all types — classes, structs, typedefs, and enums
- — have the same naming convention. Type names should start
- with a capital letter and have a capital letter for each new
- word. No underscores. For example:
- </p>
- <CODE_SNIPPET>
- // classes and structs
- class UrlTable { ...
- class UrlTableTester { ...
- struct UrlTableProperties { ...
-
- // typedefs
- typedef hash_map<UrlTableProperties *, string> PropertiesMap;
-
- // enums
- enum UrlTableErrors { ...
- </CODE_SNIPPET>
- </BODY>
- </STYLEPOINT>
-
- <STYLEPOINT title="Variable Names">
- <SUMMARY>
- Variable names should start with a capital letter and have a
- capital letter for each new word. No underscores, except for cases where underscores
- drastically increase readability. For instance: <code>mNMDA_AMPA_Ratio</code>. Class member variables start with leading letter "m". For
- instance: <code>ExcitingLocalVariable</code>,
- <code>mExcitingMemberVariable</code>.
- </SUMMARY>
- <BODY>
- <SUBSECTION title="Common Variable names">
- <p>
- For example:
- </p>
- <CODE_SNIPPET>
- string TableName; // OK - uses mixed case.
- </CODE_SNIPPET>
- <BAD_CODE_SNIPPET>
- string tablename; // Bad - all lowercase.
- </BAD_CODE_SNIPPET>
- </SUBSECTION>
-
- <SUBSECTION title="Class Data Members">
- <p>
- Data members (also called instance variables or member
- variables) are lowercase with optional underscores like
- regular variable names, but always start with a leading letter "m".
- </p>
- <CODE_SNIPPET>
- string mTableName; // OK - underscore at end.
- </CODE_SNIPPET>
- </SUBSECTION>
-
- <SUBSECTION title="Struct Variables">
- <p>
- Data members in structs should be named like regular
- variables without the leading "m" that data members
- in classes have.
- </p>
- <CODE_SNIPPET>
- struct UrlTableProperties {
- string Name;
- int NumEntries;
- }
- </CODE_SNIPPET>
- <p>
- See <a HREF="#Structs_vs._Classes">Structs vs. Classes</a> for a
- discussion of when to use a struct versus a class.
- </p>
- </SUBSECTION>
-
- <SUBSECTION title="Global Variables">
- <p>
- There are no special requirements for global variables,
- which should be rare in any case, but if you use one,
- consider prefixing it with <code>g_</code> or some other
- marker to easily distinguish it from local variables.
- </p>
- </SUBSECTION>
- </BODY>
- </STYLEPOINT>
-
- <STYLEPOINT title="Constant Names">
- <SUMMARY>
- Use a <code>k</code> followed by mixed case:
- <code>kDaysInAWeek</code>.
- </SUMMARY>
- <BODY>
- <p>
- All compile-time constants, whether they are declared locally,
- globally, or as part of a class, follow a slightly different
- naming convention from other variables. Use a <code>k</code>
- followed by words with uppercase first letters:
- </p>
- <CODE_SNIPPET>
- const int kDaysInAWeek = 7;
- </CODE_SNIPPET>
- </BODY>
- </STYLEPOINT>
-
- <STYLEPOINT title="Function Names">
- <SUMMARY>
- Regular functions have mixed case and start with lower case letter; accessors and mutators match
- the name of the variable: <code>excitingFunction()</code>,
- <code>excitingMethod()</code>,
- <code>ExcitingMemberVariable()</code>,
- <code>setExcitingMemberVariable()</code>.
- </SUMMARY>
- <BODY>
- <SUBSECTION title="Regular Functions">
- <p>
- Functions should start with a lower case and have a
- capital letter for each new word. No underscores:
- </p>
- <CODE_SNIPPET>
- addTableEntry()
- deleteUrl()
- </CODE_SNIPPET>
- </SUBSECTION>
-
- <SUBSECTION title="Accessors and Mutators">
- <p>
- Accessors and mutators (get and set functions) should match
- the name of the variable they are getting and setting. This
- shows an excerpt of a class whose instance variable is
- <code>mNumEntries</code>.
- </p>
- <CODE_SNIPPET>
- class MyClass {
- public:
- ...
- int NumEntries() const { return mNumEntries; }
- void setNumEntries(int Num_Entries) { mNumEntries = NumEntries; }
-
- private:
- int NumEntries;
- };
- </CODE_SNIPPET>
- <p>
- You may also use lowercase letters for other very short
- inlined functions. For example if a function were so cheap
- you would not cache the value if you were calling it in a
- loop, then lowercase naming would be acceptable.
- </p>
- </SUBSECTION>
- </BODY>
- </STYLEPOINT>
-
- <STYLEPOINT title="Namespace Names">
-
- <SUMMARY>
- Namespace names are all lower-case, and based on project names and
- possibly their directory structure:
- <code>google_awesome_project</code>.
- </SUMMARY>
- <BODY>
- <p>
- See <a HREF="#Namespaces">Namespaces</a> for a discussion of
- namespaces and how to name them.
- </p>
- </BODY>
- </STYLEPOINT>
-
- <STYLEPOINT title="Enumerator Names">
- <SUMMARY>
- Enumerators should be named like
- <A HREF="#Constant_Names">constants</A> <code>kEnumName</code>.
- </SUMMARY>
- <BODY>
- <p>
- Preferably, the individual enumerators should be named like
- <A HREF="#Constant_Names">constants</A>. The enumeration name,
- <code>UrlTableErrors</code> (and
- <code>AlternateUrlTableErrors</code>), is a type, and
- therefore mixed case.
- </p>
- <CODE_SNIPPET>
- enum UrlTableErrors {
- kOK = 0,
- kErrorOutOfMemory,
- kErrorMalformedInput,
- };
- </CODE_SNIPPET>
- </BODY>
- </STYLEPOINT>
-
- <STYLEPOINT title="Macro Names">
- <SUMMARY>
- You're not really going to <A HREF="#Preprocessor_Macros">define
- a macro</A>, are you? If you do, they're like this:
- <code>MY_MACRO_THAT_SCARES_SMALL_CHILDREN</code>.
- </SUMMARY>
- <BODY>
- <p>
- Please see the <a href="#Preprocessor_Macros">description of
- macros</a>; in general macros should <em>not</em> be used.
- However, if they are absolutely needed, then they should be
- named like enum value names with all capitals and underscores.
- </p>
- <CODE_SNIPPET>
- #define ROUND(x) ...
- #define PI_ROUNDED 3.0
- </CODE_SNIPPET>
- </BODY>
- </STYLEPOINT>
-
- <STYLEPOINT title="Exceptions to Naming Rules">
- <SUMMARY>
- If you are naming something that is analogous to an existing C
- or C++ entity then you can follow the existing naming convention
- scheme.
- </SUMMARY>
- <BODY>
- <p>
- <dl>
- <dt> <code>bigopen()</code> </dt>
- <dd> function name, follows form of <code>open()</code> </dd>
- <dt> <code>uint</code> </dt>
- <dd> <code>typedef</code> </dd>
- <dt> <code>bigpos</code> </dt>
- <dd> <code>struct</code> or <code>class</code>, follows form of
- <code>pos</code> </dd>
- <dt> <code>sparse_hash_map</code> </dt>
- <dd> STL-like entity; follows STL naming conventions </dd>
- <dt> <code>LONGLONG_MAX</code> </dt>
- <dd> a constant, as in <code>INT_MAX</code> </dd>
- </dl>
- </p>
- </BODY>
- </STYLEPOINT>
- </CATEGORY>
-
-
- <HR/>
- <p align="right">
- Revision 0.1
- </p>
- <address>
- Frank Michler
- </address>
- </GUIDE>
|