PHP中静态方法的缺点

PHP中静态方法的缺点,php,Php,在一个理论上的数据库访问类中,我发现我在类中使用了相当多的帮助函数,它们与类的实例无关(还有其他的,可以通过依赖项注入将其操纵为与类的实例无关) 例如,我有一个函数,它获取变量中两个其他字符串之间的字符串。我一直在考虑把它转移到一个String\u助手类,或者类似的东西。此函数已被设置为静态 另外,我还有一个查询数据库的函数,query($sql)。连接细节由实例提供,但我一直在考虑将其设置为静态,并使用query($sql,$connection)。然后,开发人员就可以静态地调用它,而根本不需

在一个理论上的数据库访问类中,我发现我在类中使用了相当多的帮助函数,它们与类的实例无关(还有其他的,可以通过依赖项注入将其操纵为与类的实例无关)

例如,我有一个函数,它获取变量中两个其他字符串之间的字符串。我一直在考虑把它转移到一个String\u助手类,或者类似的东西。此函数已被设置为静态

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

对我来说,问题是:

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

  • 我知道静态函数很难测试,但如果我确保它们的代码完全没有依赖关系(或者在必要时使用依赖关系注入),那么它们就和其他任何东西一样容易测试,是吗

  • 目前这不是一个问题,但是如果将来我决定用静态函数扩展类,那么我就不可能让当前代码使用我的扩展函数。我想到了单例,但同样的问题也出现了:代码将调用
    Singleton\u Class::getInstance()
    ,而不是
    My\u Extended\u Singleton\u Class::getInstance()
    。依赖项注入似乎是解决此问题的唯一方法,但它可能会导致一个更笨拙的API,因为每个依赖项都必须赋予
    \uu construct()
    上的对象

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


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

    1。这样做值得吗

    是和否。将助手函数拆分为它们自己的类是一个好主意。它严格定义了每个类的“范围”,而您不会得到creap。但是,不要仅仅因为可以,就将方法设置为静态。查询方法可以通过管理连接使您的生活更轻松,那么您为什么要失去这一好处呢

    2。它们更难测试

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

    3。扩展课程

    这是一个合理的担忧。如果将
    String\u Helper::foo()
    放入类本身,则会遇到问题。但是一个选项是将字符串帮助器的名称设置为类变量。因此,您可以执行
    {$this->stringHelper}::foo()
    (注意,仅限PHP5.3)。要覆盖该类,只需更改该实例中的字符串帮助器类。这个框架做了很多

    4。全球注册中心

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

    一般来说

    当你在做这样的事情时,我喜欢在遇到这样的问题时停下来。停下来坐下来想一想,我想解决的是什么实际问题?明确地列举问题。然后拿出我们假设的解决方案,看看它们是否真的解决了问题。如果真的解决了,那么想想未来,以及这些解决方案是否真的可以长期维护(从bug修复的角度和功能添加的角度)只有当你对这两种答案感到满意时,你才应该考虑去做。哦,而且记住要保持简单。编程不是要制造最复杂、最聪明或最令人惊奇的解决方案。它是关于解决问题的最简单的解决方案……< 我希望这有助于


    祝你好运!

    有了这些问题,我试图解决两个问题:第一,使事物保持静态是否值得,以及这样做可能会带来哪些问题/缺点。第二,我想找到最简单的方法来存储一组对象实例,同时在需要时随时提供它们。你对我们的看法为可能需要依赖项的任何函数注入一个注册表是非常棒的,因为这意味着API不会被所有依赖项的参数弄得乱七八糟,而且我仍然有办法管理任意数量的实例