让接口更容易被正确的使用,而且不容易被错误的使用
ps:转载于公司大佬,版权@copyright horizon.ai
Choose good names
class AbcInterface {
public:
bool CreateFilter() { return false; }
};
Create一般用于对象的创建,但是返回值是个bool,Create一个Bool?
class XyzModule {
public:
bool& GetEnable() { return is_enable_; }
private:
bool is_enable_;
};
Get一般用于获取一个值,不改变一个值, 容易造成误导
class XyzModule : public ADASModule {
public:
FORWARD_DECLARE(XyzModule , 0);
FORWARD_DECLARE(XyzModule , 1);
FORWARD_DECLARE(XyzModule , 2);
FORWARD_DECLARE(XyzModule , 3);
FORWARD_DECLARE(XyzModule , 4);
FORWARD_DECLARE(XyzModule , 5);
FORWARD_DECLARE(XyzModule , 6);
...
};
这样看上去,可以得到的有效信息很少,只能从cpp实现中推测函数的功能
Incapsulate
不暴露指针
class TraceObject{
public:
bool Predict(Mat);
TraceObject* related_object_;
};
直接暴露空指针会导致使用者存在很多错误的使用情况
- 有两个线程使用同时操作related_object_
- 指针可能被外部的用户存储,但是这个TraceObject已经被delete了
使用progressive disclosure
class TrackingObject{
public:
virtual int PredictOneFrame(Observation);
int &GetMissDetection();
int &GetMissTracking();
void SetMissDetection(int value);
int GetContinueDetction();
void AddContinueDetction();
void ResetContinueDetction();
// 50 more ...
};
过多的public函数,使用者会无从下手,阅读者很难理解这个类的用途
class TrackingObject{
public:
struct AdvancedFeature {
int &GetMissDetection();
int &GetMissTracking();
void SetMissDetection(int value);
int GetContinueDetction();
void AddContinueDetction();
void ResetContinueDetction();
...
}
virtual int PredictOneFrame(Observation);
AdvancedFeature& Advanced();
...
};
// example
obj.PredictOneFrame(observation);
obj.Advanced().SetMissDetection(1);
引入新类型来杜绝错误的使用
void *BPUMemAlloc(
int32_t core_id, uint32_t byte_size, bool cacheable,
int32_t type = BPUMemOutput, int32_t cam_id = 0);
在参数比较多的情况下,使用者容易发生传入参数顺序错误的情况
enum class MemType : uint32_t {
BPUMemOutput
};
void *BPUMemAlloc(
int32_t core_id, uint32_t byte_size, bool cacheable,
MemType type = MemType::BPUMemOutput, int32_t cam_id = 0);
尽可能的使用explict type来enable编译器的检查
virtual dispatcher alternatives
virtual的实现一般采用virtual table, vtable存在一定的cost,每个对象的会至少多存储一个vtable_ptr, 多重继承会更多,而且会增加一张virtual table,同时也有runtime cost
virtual solution:
class FilterBase {
virtual bool Filter() = 0;
}
class AbcFilter {
virtual bool Filter() override {
...
}
}
possible solution without virtual:
template <typename FilterImpl>
class FilterBase {
bool Filter() {
return static_cast<FilterImpl>(*this).Filter();
}
}
class AbcFilter : public FilterBase<AbcFilter> {
bool Filter() { ... }
}
Pros:No vtable overhead, Cons:代码看起来没有virtual简单
好习惯
写接口前先画UML,写接口文档
// Set image frame info to Frame handle.
// @param[in] frame A handle of Frame.
// @param[in] width The width of Frame.
// @param[in] height The height of Frame.
// @param[in] count The count height of Frame.
// @note All frames are based on frame, so width and height,
// count is required.
ABC_SDK
void SetFrameInfo(Frame frame, int32_t width, int32_t height,
int count);
Q.E.D.