是什么让这段代码变坏了

时间:2015-07-07 22:22:01

标签: c++ class c++11 design-patterns

在我的公司,我遇到了以下两个代码片段,我发现这些代码片段一见钟情,但本着向写这篇文章的工程师提供建设性反馈的精神,我试图提出技术论据为什么这段代码很糟糕:

FileTableEntry * FilerManager::GetFileTableEntry(uint32_t i) const {
  return &(GetFileTable()[i]);
}

…
for (uint32_t i = 0; i < container_.size(); ++i) {
   *GetFileTableEntry(i) = FileTableEntry();
   // GetFileTableEntry ultimately accesses a std::vector in FileManager
}

我的主要论点是:

  1. 这段代码非常间接且误导,不应该使用 getter到initiliaze(FileManager的一部分),但至少是一个 setter:更直接使代码更容易理解。
  2. getter完全泄漏了FileManager的内部状态,因此FileManager的封装在这一点上没有任何意义。更糟糕的是,getter承诺适用于const对象,但是很快就会用来改变FileManager的内部状态。打破封装是使重构更难的必由之路。
  3. 还有其他论据没有编写像我这样的代码吗?

1 个答案:

答案 0 :(得分:3)

针对此代码的另一个参数是GetFileTableEntry的签名在对象始终存在的情况下返回指针。这需要引用,而不是指针:

FileTableEntry& FilerManager::GetFileTableEntry(uint32_t i) const {
    return GetFileTable()[i];
}

这应该解决你的第一点。您的第二点可以通过引用const

来解决
const FileTableEntry& FilerManager::GetFileTableEntry(uint32_t i) const {
    return GetFileTable()[i];
}

这禁止调用者修改GetFileTableEntry返回的内部状态。

注意:要使GetFileTableEntry函数有用,应该添加传入的索引的边界检查以及早捕获错误。