Writer/Code Conventions

From Apache OpenOffice Wiki
< Writer(Redirected from Writer Code Conventions)
Jump to: navigation, search

Writer Icon.png

Writer Project

Please view the guidelines
before contributing.

Popular Subcategories:

Extension:DynamicPageList (DPL), version 2.3.0 : Warning: No results.

Internal Documentation:

Extension:DynamicPageList (DPL), version 2.3.0 : Warning: No results.

API Documentation:

Ongoing Efforts:

Extension:DynamicPageList (DPL), version 2.3.0 : Warning: No results.

Sw.OpenOffice.org

How to use these code conventions

Here are some ideas for cpp code conventions for the writer team. They are additions and clarifications to the General OpenOffice coding standards. Most of them are derived directly from common practice.

Naming Conventions

Our current OOo coding standard is rather vague on naming conventions. "When in rome, do as the romans do." doesnt work if existing code is not consistent in itself. This is a proposal for naming conventions for new code. It tries to incorporate most current customs and only introduces new conventions where current practice does not suffice (e.g. differentiate between members, parameters and local variables). If parts of OOo code use a conflicting convention that need to be kept this should be documented.

project layout, filenames, namespaces

  • project directory layout: The source code should be in the directory source/ in the module root. The include files should be in source/inc or inc/ in the module root.
  • inc/foo.hxx or source/inc/foo.hxx are for internal headers, while inc/$PRJ_NAME/foo.hxx is for exported headers (thanks, mst)
  • Make a header only external, if it is needed outside the module. Try to keep inter-module dependencies minimal. If you have a header that has parts that need to be external and parts that need not, split the header.
  • filenames are match [a-zA-Z][a-zA-Z0-9.-]* and have the extensions cxx for implementation and hxx for header files (c and h for plain old c files). For new files it is recommended to use UpperCamelCase matching classnames.
  • namespaces are all lowercase and alphanumeric only
namespace com { namespace sun { namespace star { }}}
Old modules are using prefixes instead of namespaces. Try to put new code in namespaces in these modules too. Do not introduce new modules on the toplevel, always contain them in a namespace named as the module:
namespace sw { namespace newnamespace {}}

classes, methods and functions

classes and interfaces

  • Classes are named using UpperCamelCase
namespace sw
{
    class SomeClassExample;
}

Classes in module sw need to be prefixed Sw when in global namespace.

class SwSomeClassExample;
  • Interfaces have the capital letter I prefixed. They should be pure abstract base classes. Exception: You may overload operators in the interface (e.g. comparison).
namespace sw
{
    class ISomeInterfaceExample;
}

free functions and methods

  • Free functions and methods are using lowerCamelCase or UpperCamelCase and should always start with a verb
void SomeClassExample::appendChild();
void fixUrlHeaders();
Note that even abbreviations that are usually all uppercase will only have the first letter uppercase. If a class does not follow this convention, use the old convention or update the class to be completely consistent with this convention.
  • functions/methods need to be UpperCamelCase or lowerCamelCase. When implementing an UNO-Interface, all methods of a class need to be lowerCamelCase.
  • Mark local functions static, keep them in a anonyomous namespace and prefix the function name with lcl_
  • functions and methods returning a boolean value should "answer" a question:
bool hasChild();
bool isLeaf();

variables, parameters, members and constants

local variables

  • local variables start with an lowercase letter for minimal apps hungarian notation (a for value, p for pointer, r for reference) followed by a UpperCamelCase name:
const sal_Int32 aParameterName;
const OUString& rParameterByReference;

required hungarian prefixes

prefix meaning
r reference
x UNO-Reference
p pointer (including stl-style iterators and any kind of smart pointer but UNO-Reference - they share the same semantic)
a some kind of value

optional hungarian prefixes for values instead of "a"

prefix meaning
b/is/has boolean types (see example below, prefer is/has over b in new code as it "speaks")
c some kind of character
e enumeration
f some kind of floating point value
n some kind of integer
s some kind of string
v some kind of container (vector)
If a function does not follow this convention, use the old convention or update the function to be completely consistent with this convention. Use p for all kinds of pointers (::boost::shared_ptr, stl-iterators). It is only required to use hungarian notation for the kind of variable (semantic information), but type information is optional.
Here are some links about the badness/goodness of hungarian notation:
bool isLeaf;
bool hasChild;

parameters

  • parameters follow the convention defined for local variables, but are have an additional prefix showing the scope of the parameter:
prefix meaning
i_ in parameter (optional)
o_ out parameter
io_ in and out parameter
If a function does not follow this convention, use the old convention or update the function to be completely consistent with this convention.

member variables

  • member variables follow the convention for local variables, but have a m_ prefixed
SwPosition m_aPosition;
Node const * const m_pParent;
If a function does not follow this convention, use the use old convention or update the function to be completely consistent with this convention. Be careful with public members!

static member variables

  • static member variables follow the parameter convention, but have a our_ prefixed
static ::osl::Mutex our_aFileMutex;
If a function does not follow this convention, use the use old convention or update the function to be completely consistent with this convention. Be careful with public members!

constants

  • Do not use the preprocessor for constants, if it can be avoided. Really try to keep global constants to a minimum.
  • If possible, make the constant a static const member of a class - use the our_ prefix described elsewhere in this guide.
  • use an anonymous namespace for non-member constants in cxx files (but never use them in header files):
namespace
{
    static const OUString sLogging = OUString::createFromAscii("com.sun.star.logging");
}

typedefs and template parameters

typedefs should end in _t or _type:

class MyClass
{
    typedef ::rtl::OUString string_t;
    typeded sal_Int32 element_t;
};

template parameters should start with a uppercase t and continue with lowercase letters:

template<typename Tparam> class MyTemplateClass {};

generic naming scheme for variable scope and semantic type

Here are is an overview of all scope prefixes:

<scope-prefix>_<hungarian-prefix>VariableName;

Scope-prefix is one of:

prefix meaning
<none> local variable
i_ in parameter (optional)
o_ out parameter
io_ in and out parameter
m_ member (instance variable)
our_ static member (class variable not bound to an instance)
g_ global variable (external linkage)
lcl_ file-local method or variable

For the required and optional hungarian prefixes, see above.

Formatting

  • lists in makefiles should have one entry per line if possible and be sorted alphabetically to ease merging
SLOFILES= \
    $(SLO)$/config.obj \
    $(SLO)$/corecontroller.obj \
    $(SLO)$/errormail.obj \
    $(SLO)$/invitejob.obj \
    $(SLO)$/logpacker.obj \
    $(SLO)$/logstorage.obj \
    $(SLO)$/myconfigurationhelper.obj \
    $(SLO)$/onlogrotatejob.obj \
    $(SLO)$/oooimprovement_exports.obj \
    $(SLO)$/soaprequest.obj \
    $(SLO)$/soapsender.obj \
  • cpp files should have the following general layout:
  1. license
  2. includes
  3. defines (if any)
  4. global using statements
  5. anonymous namespace with local functions and data (implementation files only)
  6. anything else
  • try to keep lines shorter than 80 chars (you need to consider refactoring if lines are longer), if possible. However, this might be impossible for the following reasons:
    • header files, where using-statements are not permitted, and typenames are very long
    • listing of base class (virtual) functions in the derived class should use just one line.
    • definition of string constants
    • strings for assertions etc.
Dont break lines in these cases, if it does not help readability. Keep in mind though, that you can break string constants:
static const SOME_STRING = ::rtl::OUString::createFromAscii(
    "Libertatem quam peperere maiores digne studeat servare posteritas.\n"
    "means\n"
    "May the freedom won by our forefathers be conserved in dignity for posterity.\n");
  • Indent according to Allman-Style
  • Use one line if-statements only when its idiomatic and short. Examples are preconditions:
if(!pData) return;

Keep in mind, that even short statements might prevent setting meaningful breakpoints on the test - so it is probably best to not use one line if-statements at all.

  • when breaking lines in a statement (if-conditions, parameterlists), do not use space to align statements. Its bad to maintain and looks awful in tools like lxr. Simply indent lines that continue a statement:
    Reference<XInterface> MyConfigurationHelper::openConfig(
        const Reference<XMultiServiceFactory> xSMGR,
        const OUString& sPackage,
        sal_Int32 eMode)
    { }
When breaking a list (for example of parameters or of the statements in a for-statement) put each statement on its own line.
  • When you edit methods with timestamps ("created on", "last modified by") in comments, remove the timestamps (as they are invalid anyway). Keep comments to bugs/issues - especially when they are regarding just a few lines. This is to prevent regressions.

General

  • Do not include cross the source code subtrees. For example a file in sw/source/ui must make use only of global includes from sw/inc and local includes from sw/source/ui/inc or from the local folder. It should not include files from /sw/source/core/inc and /sw/source/filter/inc.
  • Keep all member variables private or protected when declaring a class. Provide inline getter/setter-methods if needed. getter/setter-methods should be named as the variable without any prefixes. If you what to declare a class with any public members, use the "struct" keyword instead of "class" to make this explicit.
class SomeExampleClass
{
    public:
        ::rtl::OUString getName();
        void setName(const OUString& rName); 
    private:
        ::rtl::OUString m_aName;
};
struct AnotherExampleClass
{
   public:
       ::rtl::OUString m_aName;
};
  • keep methods shorter than 200 lines (refactor if they get longer)
  • limit the scope of local variables using blocks if possible. A local variable should rarely live longer than one screen length (30-60 LOC).
  • keep header files as simple and readable as possible
    • use either handle/body (pimpl) or abstract base classes to keep implementation details out of the header. When using handle/body, use a boost::scoped_ptr<> to an incomplete type, not an raw pointer. (see http://www.boost.org/doc/libs/1_35_0/libs/smart_ptr/scoped_ptr.htm and http://www.boost.org/doc/libs/1_35_0/libs/smart_ptr/sp_techniques.html). Because of the incomplete type, there is no need to expose the private members of the implementation in the header file.
    • try to avoid declaring private member functions. use static functions in an anonymous namespace instead, if the function only needs to access some of the object state. If a function accesses too much object state, try to refactor.
namespace
{
    static sal_Int32 lcl_countLines(const Sequence<sal_Int8>& rBuffer)
    {
        ...
    };
}
  • Avoid exposing raw pointers. Use com::sun::star::uno::Reference for UNO objects and boost::shared_ptr<> for other objects. If an some code needs a raw pointer it can always use shared_ptr<>.get(). However it than needs to make sure the object pointed to was not deleted when it is accessed, just as with any raw pointer. Most of the time, a boost::weak_ptr<> should be preferable even in these cases.
  • Assertions: there are lots of assertion types in OOo, often defined as macros:
    • OSL_ENSURE is only enabled in builds with debbing enabled (debug=true)
    • DBG_* is defined in module tools, and therefore evil by definition
  • use mutable and explicit in new code
  • comment new code in english. Do not mix german and english comment in the same function/method, translate the comments in the function to english. Try to do the same when refactoring a class in major way (i.e. assure the class has comment completely in english afterwards).
  • dont use C-style casts in new code. Use only C++-style casts: they are explicit and easy to grep. If you are annoyed by the few additional characters to write, you probably are casting carelessly to much. ;-)
  • Provide interfaces (pure abstract base classes) to link against in header files.
  • Do not link against specific implementations, link against interfaces.
  • Use virtual public inheritance to signify that an interface implements an interface (see discussion page for details).
  • Use SAL_NO_VTABLE for pure abstract classes:
struct SAL_NO_VTABLE IMyInterface
{
   virtual void myMethod() = 0;
};
  • Use SAL_DLLPRIVATE and SAL_DLLPUBLIC_* for large shared libraries that are not only exporting the few UNO component access functions. See e.g. svx/svxdllapi.h for a usage example.

Vetoed Conventions

Move conventions that seem wrong here and add a short explanation.

Deprecated Types (already covered by the General OpenOffice coding standards)

  • Dont use container types from "svtools/svarray.hxx" or "svtools/svstdarr.hxx" and the like in new code. Use STL containers instead.
  • Try to avoid the rtti from "tools/rtti.hxx", use C++ build-in RTTI instead (type_info, dynamic_cast, typeid).
  • Try to avoid SwModify and SwClient and use SfxBroadcaster/SfxListener instead.
  • Dont use container types from "tools/contnr.hhx", "tools/table.hxx", "tools/stack.hxx", "tools/queue.hxx", "tools/dynary.hxx". Use STL containers instead.
  • Dont use ByteString or std::string in new code. Use OString instead.
  • Dont use String in new code. Use OUString instead.
  • Dont use BOOL or FASTBOOL in new code. Use bool instead (sal_Bool for UNO).
  • Otherwise, use UNO-Types, if available.
Personal tools