PHP中静态方法的缺点

时间:2010-12-16 16:57:29

标签: php

在理论数据库访问类中,我发现我在类中使用了很多辅助函数,这些函数与类的实例没有任何关系(以及其他可以被操作与类的实例无关的实例)使用依赖注入)。

例如,我有一个函数,它在变量中的两个其他字符串之间获取一个字符串。我一直在考虑将它移动到String_Helper类,或类似的东西。这个功能已经变得静止了。

另外,我有一个查询数据库query($sql)的函数。连接详细信息由实例提供,但我一直在考虑将其设置为静态,并使用query($sql, $connection)。然后开发人员可以静态调用它,而不需要实例化数据库类。

对我来说,问题是:

  1. 做这样的事情值得吗?像查询函数这样的函数让我想知道这不仅仅是我试图让一切尽可能地保持静态,而不需要任何实际需要。在什么情况下你会认为这有用吗?

  2. 我知道静态函数更难测试,但如果我确保他们的代码完全无依赖(或在必要时使用依赖注入),那么它们就像其他所有东西一样容易测试,当然

  3. 目前不是一个问题,但是如果将来我决定使用静态函数扩展类,那么我将无法使当前代码使用我的扩展函数。我想过Singletons,但同样的问题出现了:代码将调用Singleton_Class::getInstance(),而不是My_Extended_Singleton_Class::getInstance()。依赖注入似乎是解决此问题的唯一方法,但它可能会导致一个笨重的API,因为必须将每个依赖项赋予__construct()上的对象。

  4. 我有一个容器类,它静态保存某些信息,以便可以在脚本中的任何位置访问它们(全局范围)。如果我不能使用静态函数或单例,那么包含不同变量实例的类就会很棒。可以使用例如Container::$objects['MyClass'] = $MyClass_object;,然后其余代码可以访问Container::$objects['MyClass']。如果我扩展了MyClass类,我可以使用Container::$objects['MyClass'] = $MyExtendedClass_object;,而使用Container::$objects['MyClass']的代码将使用MyExtendedClass,而不是MyClass。在我看来,这是迄今为止最好的方法,但我想知道你对它的看法。

1 个答案:

答案 0 :(得分:10)

好的,让我逐一回答......

<强> 1。是否值得做这样的事

是和否。将辅助函数拆分成自己的类是个好主意。它保持每个类的“范围”严格定义,并且你不会得到坍塌。但是,不要因为可以使方法静态。通过管理连接,查询方法可以让您的生活更轻松,那么您为什么要失去这种好处?

<强> 2。他们更难测试

他们不难测试。依赖于状态的静态方法更难测试(访问静态成员变量或全局变量)。但是静态方法通常和实例方法一样容易测试(实际上,它们可以更容易,因为您不需要担心实例化)。

第3。扩展课程

这是一个有效的问题。如果你把String_Helper::foo()放在课堂上,你就会遇到问题。但是一个选项是将字符串帮助器的名称设置为类变量。所以你可以做{$this->stringHelper}::foo()(注意,仅限PHP 5.3)。这种覆盖类的方法,您需要做的就是更改该实例中的字符串帮助程序类。 Lithium框架做了很多......

<强> 4。全球登记处

我会远离这个。你基本上只是让每个班级都成为单身人士而不强制执行。由于您现在依赖于全球范围,测试将是一场噩梦。相反,我将创建一个注册表对象,并通过构造函数(依赖注入)将其传递给类。你仍然可以完成同样的事情,因为你有一个对象/类的商店,但你不再依赖于全局范围。这使测试变得更加容易。

一般

当你看这样的事情时,我喜欢在遇到这样的问题时停下来。停下来坐下来思考*我想解决什么实际问题?“。明确列举问题。然后拉出我们想要的解决方案,看看他们是否真的解决了问题。如果他们这样做了,那就考虑一下未来,如果这些解决方案从长远来看是非常可维护的(从错误修复的角度来看,以及功能增加)。只有当你对这两个答案感到满意时,你才应该考虑这样做。哦,还记得保持简单编程不是要制作最复杂,最聪明或最神奇的解决方案。它是关于制作解决问题的最简单的解决方案......

我希望有帮助...

祝你好运!