Skip to content

Latest commit

 

History

History
360 lines (256 loc) · 12.3 KB

12.md

File metadata and controls

360 lines (256 loc) · 12.3 KB

OpenOffice 代码约定规范

原文: https://wiki.openoffice.org/wiki/Writer/Code_Conventions
作者:OpenOffice.org 译者:aqcoder([email protected])

如何使用本代码约定

本约定为作为OppenOffice.org 代码规范的附加说明为开发者制定 cpp 代码的编写约定。约定基本有实践总结得到。

命名约定

目前 OOo 代码命名规范是相当模糊的。“入乡随俗。”如果现有代码本身就是不一致将不对其做改动。本约定只做为新代码的命名约定。

工程结构、文件名、命名空间

  • 工程目录结构:源文件必须在模块的 source/ 目录下,包含头文件必须在模块的 source/inc/ 或者 inc/ 目录下。
  • inc/foo.hxx 或者 source/inc/foo.hxx 是给模块内部使用的头文件,而 inc/$PRJ_NAME/foo.hxx 是导出头文件。
  • 对于导出的头文件,尽量减小头文件的内部依赖,如果一个导出头文件一部分需要导出一部分内部使用,则切分这个头文件。
  • 文件名只能匹配为 [a-zA-Z][a-za-z0-9.-]*,且头文件/源文件的扩展名为 hxx/cxx。类名推荐使用驼峰法。
  • 命名空间全为小写。
namespace com { namespace sun { namespace star { }}}

有些老的模块使用前缀来代替命名空间,当在其加入新代码时使用包含在内的命名空间,不要新建模块。

namespace sw { namespace newnamespace {}}

类名、方法名

类名和接口

  • 使用大写前缀驼峰法命名类名
namespace sw
{
    class SomeClassExample;
}

在 sw 模块,在全局命名空间的类需要加前缀 Sw

class SwSomeClassExample;
  • 接口以 I 为前缀,接口必须是纯虚基类。
namespace sw
{
    class ISomeInterfaceExample;
}

方法

方法使用小写前缀驼峰法或者大写前缀驼峰法,通常以动词开头。

void SomeClassExample::appendChild();
void fixUrlHeaders();

注意,甚至缩写通常大写都只有第一个字母大写。如果一个类没有遵循这个惯例,使用旧的惯例或更新类是完全符合本约定的。

  • 关于方法名使用大写前缀驼峰法还是小写驼峰法:当实现 UNO 接口时类的方法使用小写前缀驼峰法。
  • 本地方法使用静态函数,并且定义在匿名命名空间中,以 lcl_ 做为前缀。
  • 函数返回布尔值需要以回答问题的方式(译者注:应该是指一些成员函数)
bool hasChild();
bool isLeaf();

变量、参数、成员、常亮

局部变量

  • 局部变量使用匈牙利命名法,用个小写字母做为前缀,紧跟着大写前缀名称。
const sal_Int32 aParameterName;
const OUString& rParameterByReference;
前缀 含义
r 引用
x UNO 引用
p 指针(包括 STL 风格的迭代器和智能指针,UNO 引用除外)
a 一些值

有些值类型使用特定前缀而不是使用 a

前缀 含义
c 字符型
e 枚举类型
f 浮点型
n 整型
s 字符串型
v 容器 (vector)

如果一个方法没有遵循本约定,保持原来的约定或者更新到现有约定。 下面给出一些好的/坏的匈牙利符号

bool isLeaf;
bool hasChild;

参数

参数命名遵从的规则和局部变量一致,但是有一些附加前缀:

前缀 含义
i_ 传入参数
o_ 传出参数
io_ 传入传出

如果函数没有遵从本约定,则保留原来的约定或者都改为遵从本约定。

成员变量

成员变量命名遵从局部变量的约定,但是需要加上前缀 ‘m_’。

SwPosition m_aPosition;
Node const * const m_pParent;

如果函数没有遵从本约定,则保留原来的约定或者都改为遵从本约定。

静态成员变量

成员变量命名遵从局部变量的约定,但是需要加上前缀 ‘our_’。

static ::osl::Mutex our_aFileMutex;

如果函数没有遵从本约定,则保留原来的约定或者都改为遵从本约定。

常量

  • 不要使用预处理宏代替常量,尽量不要使用全局常量。
  • 如果可能的话尽量使用 static const 修饰常量。
  • 在 cxx 文件中,常量成员放到匿名命名空间中。(不要将他们放到头文件中)
namespace
{
    static const OUString sLogging = OUString::createFromAscii("com.sun.star.logging");
}

typedefs 和模板参数

typedefs 必须以 _t 或者 _type 结尾。

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

模板参数必须以大写字母 t 开始,紧接着小写开头单词:

template<typename Tparam> class MyTemplateClass {};

一般命名规则和语义

命名前缀规则:

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

scope-prefix 是如下其中一个:

前缀 含义
局部变量
i_ 传入参数
o_ 传出参数
io 传入传出参数
m_ 成员变量
our_ 金泰成员变量
g_ 全局变量
lcl_ 文件局部成员函数或变量

匈牙利前缀参考上文所述。

书写格式

Makefile 中的列表您可能的一个入口占一行,且按字母顺序排列,这样容易合并。

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 文件按如下顺序布局
  1. license
  2. includes
  3. defines (if and)
  4. global using statements
  5. anonymous namespace with local functions and data(implementation files only)
  6. anything else
  • 尽量保持每行少于 80 个字符(否则你就要考虑重构了)。在如下条件下可以忽略这条约定:
  1. 头文件声明不允许,类型名很长。
  2. 在子类声明中罗列基类的虚函数时不允许换行。
  3. 定义字符串常量。
  4. 断言字符串,等。

如果对可读性没有帮助,在这些情况下不要断行,记住:字符串常量可以断行:

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");
  • 缩进方法遵循 Allman-Style

  • if 判断时,语义通顺且短,可以放在一行中:

if(!pData) return;

但是要注意即使语句很短,在调试的时候换行对设置断点是很有用的。所以尽量不要在 if 语句中使用一行。

  • 在一份声明中如果使用换行(如果 if 语句, 参数列表),不使用空间对齐语句。其不良维护。简单的缩进线继续发表声明就可以了:
Reference<XInterface> MyConfigurationHelper::openConfig(
    const Reference<XMultiServiceFactory> xSMGR,
    const OUString& sPackage,
    sal_Int32 eMode)
{ }

当在一个列表(如参数列表或 for 语句)使用换行,使每条语句为一行。

  • 代码注释中不要包含时间戳("created on", "last modified by"),因为他们是无效的。在 bug/issues 中注明修改,即使只有简单的几行说明,这是为了方便问题回归。

通用约定

  • 在源文件中不要出现交叉包含。例如:sw/source/ui 下的源文件只能包含 sw 模块的全局包含目录 sw/inc 和 ui 下的包含目录 /sw/source/ui/inc。他不能包含项 /sw/source/core/inc 和 sw/source/filter/inc 这样的其他目录下的头文件。

  • 保证成员变量都是私有的或者是受保护的。如果需要的话生命内联属性器方法 getter/setter。属性器的名称是成员变量的名称去除前缀。如果一定要定义共有的成员请使用结构体关键字 struct 代替 class。

class SomeExampleClass
{
    public:
        ::rtl::OUString getName();
        void setName(const OUString& rName);
    private:
        ::rtl::OUString m_aName;
};
struct AnotherExampleClass
{
   public:
       ::rtl::OUString m_aName;
};
  • 函数实现不要超过 200 行(超过的话请重构)
  • 如果可能的话使用块限制局部变量的范围。一个局部变量应该很少超过一个屏幕的长度(30 - 60 LOC)。
  • 保证头文件的可读性 ** 在头文件中使用 handle/body(pimpl) 或者虚基类来屏蔽具体的实现细节。使用 boost::scoped_ptr<>(详见 http://www.boost.org/doc/libs/1_35_0/libs/smart_ptr/scoped_ptr.htmhttp://www.boost.org/doc/libs/1_35_0/libs/smart_ptr/sp_techniques.html) 代替纯指针,因为具体实现不需要暴露在头文件中。 ** 尽量避免在头文件中定义私有的成员函数。如果实现函数只需访问一些成员对象,在匿名命名空间中实现这些函数。如果需要访问太多的成员对象,请重构。
namespace
{
    static sal_Int32 lcl_countLines(const Sequence<sal_Int8>& rBuffer)
    {
        ...
    };
}
  • 尽量避免暴露纯指针,使用 com::sun::star::uno::Reference 引用 UNO 对象,boost::shared_ptr<> 引用其他对象。如果需要纯指针就使用 shared_ptr<>.get()。无论何时都要保证访问的指针是有效的。很多时候使用 boost::weak_ptr<> 都是使用纯指针好。

  • 断言:在 OOo 中有很多种断言,通常都是一些宏定义: ** OSL_ENSURE 只有在 debug 下才有效。 ** DBG_* 是模块工具定义的。所以(therefore evil by definition?)

  • use mutable and explicit in new code

  • 在新代码里使用英文注释,不要在同一个方法中混合德语和英语,如果重构一个模块,把注释翻译成英语。

  • 不要使用 C-style 的类型转换,使用 C++-style 的类型转换。

  • 提供纯虚函数作为接口。

  • Do not link against specific implementations, link against interfaces.

  • 使用虚共有继承实现接口。

  • 在纯虚基类中使用宏 SAL_NO_VTABLE:

struct SAL_NO_VTABLE IMyInterface
{
   virtual void myMethod() = 0;
};

Use SALDLLPRIVATE 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.

  • 在非 UNO 组件的共享库中使用 SALDLLPRIVATE 和 SAL_DLLPUBLIC* 指定导出,参考例子 svx/svxdllapi.h。

不宜使用的类型(已经被 OpenOffice.org 编码规范覆盖)

  • 不要使用 /svtools/svarray.h 或 /svtools/svstdarr.hxx 中的容器,或类似的代码。使用 STL 的容器。

  • 避免使用 tools/rtti.hxx 中的 rtti(运行时类型识别),使用 C++ 内置的 RTTI(type_info, dynamic_cast, typeid)。

  • 不要使用 "tools/contnr.hhx", "tools/table.hxx", "tools/stack.hxx", "tools/queue.hxx", "tools/dynary.hxx" 中的容器。使用 STL 代替。

  • 不要在新代码中使用 ByteString 或者 std::string,使用 OUString 代替。

  • 不要在新代码中使用 String,使用 OUString 代替。

  • 不要在新代码中使用 BOOL 或者 FASTBOOL,使用 bool 代替,在 UNO 中使用 sal_Bool。

  • 其他:如果 UNO 类型可用,使用 UNO 类型。