PHP中静态方法的缺点

Bru*_*ros 8 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.在我看来,这是迄今为止最好的方法,但我想知道你对它的看法.

irc*_*ell 10

好的,让我逐一回答这些问题......

1.值得做这样的事情

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

他们更难测试

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

3.扩展课程

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

4.全球登记处

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

一般来说

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

我希望有帮助......

祝好运!