提供对外接口时,要注意的地方

提供对外接口时,要注意的地方

本篇仅是个人经验的总结,以及自己的看法。欢迎指正和讨论。

在实际工作中,如果你提供的接口,需要被下游多个部门依赖。那么,在接口设计的时候就一定要考虑一个问题:如何在给其他人提供接口后,增加或优化自身代码时,不会束手束脚?

以下是我的一些实际经验:

1. 对外不要直接提供实现功能的类,而是提供对应的接口类和一个创建/删除对象的函数

例如,对外提供三种图形(省略构造和析构函数):

// 反例
class Shape
{
public:
    virtual void Draw() = 0;
};

class Square : public Shape
{
public:
    virtual void Draw();
private:
    ...
};

class Rect : public Shape
{
public:
    virtual void Draw();
private:
    ...
};

class Circle : public Shape
{
public:
    virtual void Draw();
private:
    ...
}

建议修改为这样

class Shape
{
public:
    virtual void Draw() = 0;
};

enum SHAPE{
Squre,
Rect,
Circle
};

Shape* createShape(SHAPE SH);
void DestructShape(Shape* sp);

对外展示的东西越少,自己可以操作的东西就越多。这也是我们为什么强调封装的重要性。
如果提供Shape接口的是个平台部门,那么如果修改Circle的一个bug时,必须在Circle中增加一个方法,那么,如果使用第一个头文件,则所有使用此头文件的部门,都需要重新编译代码。平台修改问题,还需要其它部门重新编译,本身就不是个好的设计;如果使用第二种方法,则仅需要编译Shape相关代码并重新链接一下。

2. 对外的接口,仅提供能满足需求的最小功能

同理,对外展示的东西越少,自己可以操作的东西就越多。如果我们提供了多余的功能,今后在做优化或裁减的时候,这部分本来多余的东西,还需要下游部门的配合才可以裁减掉,想想就头痛。

3. 接口中尽可能使用 “const”

const的好处太多了,可以参考Meyers的Effective C++。
在这里,我仅想补充一个我遇到的好处:
做单元测试的时候,如果接口的参数是const,那就表明这个参数是个单纯的入参,校验UT的结果时,可以不用校验这个入参;如果接口方法是const,则表明此方法不会修改类成员,因此校验UT结果时,可以不用考虑类的成员。

4. 不要返回类成员的引用或指针(不要使用全局变量)

本条建议也包括,不要把类成员定义成public或protected。
撇开外部可以直接修改对象成员这么大的劣势不说。从另一个角度看,对外展示过的东西,可没那么好修改。如果修改成员的类型(比如从short修改为int),使用此接口的地方会有多少编译错误啊。编译错误还好办,如果有人使用“<<”或“>>”这种流操作,那么就相当于埋下了个雷,什么时候会炸呢?

5. 多考虑一下拷贝构造和拷贝赋值

如果对外的接口中,不得不提供非抽象类,那么请多考虑一下拷贝构造和拷贝赋值。(禁止还是重写)

猜你喜欢

转载自blog.csdn.net/svp_Charles/article/details/78238006