让接口程序化而不是语义化意味着什么
What does it mean to make an interface programmatic instead of semantic?
现在我正在读《代码完整,第二版》一书。在第6.2章中,作者讨论了类和接口,并给出了以下建议:
尽可能使接口程序化而非语义化
每个接口由一个程序部分和一个语义部分组成。程序部分由数据类型和其他属性组成可以由编译器强制执行的接口的。语义界面的一部分包括关于将使用接口,而编译器无法强制执行该接口。这个语义接口包括诸如"例程A必须在RoutineB之前调用"或"如果dataMember1不是,则RoutineA将崩溃在传递给例程A之前已初始化。"语义接口应该在注释中记录,但尽量减少接口取决于文件。接口的任何方面编译器强制执行是一个可能被误用的方面。寻找将语义接口元素转换为程序化的方法接口元素。
我理解作者所说的语义和编程的含义,但我不明白的是如何将语义接口函数转换为编程函数。他提到使用断言或其他技术来实现这一点。
让我们以作者为例:
必须在例程B之前调用例程A。我假设这些例程是接口(公共函数)的一部分,因为这就是丑陋的接口。
所以,如果在调用RoutineB之前确实必须调用RoutineA,您将如何使用断言或其他技术重新组织这个接口?
我对此有一些想法,但我不确定这些想法是否正确。
假设RoutineA和RoutineB都是公共函数,这意味着它们应该彼此独立可用,但唯一的限制是,在独立调用RoutineNB之前,必须首先调用RoutineA。
如果确实是这样的话,那么你将如何使用断言或其他技术来解决这个问题?
如果我的假设有错误,请随时更正。
此外,我有意将其发布在当前标签下,因为像面向对象编程/设计/接口这样的标签点击率很低,这意味着我的问题可能不会经常出现。
两个可能的答案:
- 将
assert( a_called );
放入例程RoutineB
- 从类的接口中删除
RoutineB
,并使RoutineA
返回一个具有RoutineB
成员的新对象
在后一种情况下,您可能希望将外部类作为指向内部类的智能指针的精简包装器,然后RoutineA
只复制指针。
class Impl;
class SecondClass;
class FirstClass
{
std::shared_ptr<Impl> pimpl;
public:
FirstClass();
SecondClass RoutineA(...);
...
}
class SecondClass
{
std::shared_ptr<Impl> pimpl;
friend class FirstClass;
SecondClass(const std::shared_ptr<Impl>& impl) : pimpl(impl);
public:
void RoutineB(....);
}
SecondClass FirstClass::RoutineA(...)
{
// Do stuff
return SecondClass(pimpl);
}
您也可以使用unique_ptr
来完成此操作,但代码要长一些。
我认为您应该在运行时检查限制("RoutineA必须在RoutineB之前调用")。标记中的编程语言在编译时无法检查这样的限制。您的代码可能看起来像:
RoutineA()
{
aCalled = true;
//some operations..
}
RoutineB()
{
if(!aCalled) // or an assertion
{
throw NotReadyException("RoutineA must be called");
}
//some operations..
}
- 何时在引用或唯一指针上使用移动语义
- 如何从具有移动语义的类对象中生成共享指针
- Boost Spirit,获取迭代器内部语义动作
- 这行代码在C++类中意味着什么
- 可以使用移动语义更改或改进此C++代码吗?
- c++在使用指针时移动语义
- 在C++17中,引用const字符串的语义应该是什么
- 这对"With a stackless coroutine, only the top-level routine may be suspended."意味着什么
- Xcode 语义问题引用或以前定义的代码
- 寻找地理和伤害意味着超载
- 使用移动和复制语义时函数匹配如何工作?
- @CPPFLAGS@在 Makefile.in 中意味着什么?
- 将向量从 N1 缩小到 N2 项,而不触发默认构造函数并仅使用 move 语义
- 在C++标准中做格式好意味着代码可以编译
- 移动语义和深层/浅层复制之间有什么关系?
- 了解构造函数在移动、复制、赋值语义中的行为
- std::unique_lock移动语义
- 移动语义和运算符 + 重载
- C++中的禁止值语义意味着什么
- 让接口程序化而不是语义化意味着什么