用做同样事情的公共函数包装受保护函数的目的是什么?


What is the purpose or wrapping a protected function with a public one which does the same thing?

我有一些遗留代码,我目前正在寻找削减,使在一个新的项目中可用。我遇到过下面这个类,它有很多受保护的方法,这些方法执行预期的功能,但它们是通过一个公共方法访问的,这个公共方法只是像这样包装它们:

/**
 * method used to perform a fetch both using passed in SQL and optional params
 * @param string - SQL to be executed
 * @param array - optional - used if the query is to be prepared
 * @return mixed - false on failure or array on success
**/
protected function _fetcharray($sql, $params = [])
{
    //execute the query and return the results  
    return $this->execute($sql, $params)->fetch(PDO::FETCH_BOTH);
}
/**
 * Public implementeation of __fetcharray
 * @param string - SQL to be executed
 * @param array - optional - used if the query is to be prepared
 * @return mixed - false on failure or array on success
 **/
public function fetcharray($sql, $params = [])
{
    //execute the query and return the results
    return $this->_fetcharray($sql, $params);
}

我可以理解可能有必要私下做一些你不想公开的事情,但是考虑到一个函数只是调用另一个函数,这是什么意思呢?也就是说,我在这里遗漏了什么?

受保护函数的"所有者"可以更改实现细节——甚至可能添加新的函数参数——因为它不会像直接更改公共函数那样破坏大量代码。

技术上,public函数可以称为存根

如果将内部函数标记为private,则封装程度将更大。

实际上,这似乎毫无意义。作者可能打算在某处保持一些灵活性,并能够交换出公共方法的实现细节……但在我看来,他们并没有完全考虑到这一点。

核心问题是API稳定性。这意味着,一旦您公开了public function fetcharray($sql, $params = []),就会编写调用该函数的其他代码。如果你以后想改变 public接口,即重命名函数或改变其参数的数量或含义,你就会被卡住,因为现在有一大堆其他代码依赖于名称和参数。

但是,您仍然可以完全自由地完全更改函数的内部结构。只要函数名、参数和返回值不变,就可以随时重新编写函数。

那么拥有一个"私有"实现并通过它代理public函数的优势是什么?一个也没有。它仍然要求你保持public API的稳定,并且它没有提供比你已经拥有的更多的灵活性。

也许作者打算让继承类调用protected函数,让其他外部代码调用public函数,这似乎是合理的;但是他们没有给出任何理由,也没有给出这两种不同函数的明确区别。如果protected函数的行为与public略有不同,这可能是有意义的;但既然他们没有,这似乎是一个简单的大脑放屁。现在他们要维护的是两个 api,而不是一个,这无疑降低了可维护性,而不是增加了可维护性。

正如其他答案所指出的,如果作者打算让public函数是可调节的,而protected函数保持绝对,这是有意义的(如果我们假设这里有意义的话)。因此,作者总是可以依赖private方法按照预期的方式工作,而让其他开发人员在他们的实现中编辑公共方法。

然而,这并不是很有意义,因为protected函数本身仍然是可调节的。作者可能应该设置privatefinal函数,以防止编辑。

除了意图之外,这仍然是一个非常糟糕的实现,因为_fetcharray只是包装execute,假设_fetcharray中的下划线被用作"非公共"的标准,可能是public方法。所以你有一个public方法,包装了一个private方法,包装了一个public方法,在第一个地方使用它总是更有意义。

我叫意大利面