【问题标题】:How Bad Are Singletons?单身人士有多糟糕?
【发布时间】:2011-01-01 01:26:21
【问题描述】:

所以....

显然有很多关于单例、全局状态变量和所有很棒的东西的问题。我的问题是,

如果 Singletons 和 Globals 如此糟糕,为什么会如此频繁地使用它们?

以下示例只是我脑海中浮现的示例,我认为它们已被很多人使用。

我给你一个来自 CodeIgniter 的函数,它使用一个伪单例函数:

(系统\codeigniter\Common.php 第 89 行)

/**
* Class registry
*
* This function acts as a singleton.  If the requested class does not
* exist it is instantiated and set to a static variable.  If it has
* previously been instantiated the variable is returned.
*
* ......
*/
function &load_class($class, $instantiate = TRUE)
{
    static $objects = array();

    // Does the class exist?  If so, we're done...
    if (isset($objects[$class]))
    {
        return $objects[$class];
    }
  .......
}

通过将每个对象放入单个注册表中,您不能使用它们的 load_class 函数来创建任何东西的多个实例。当您想将类用作数据结构时,这尤其不方便。

此外,因为所有这些类只有一个实例,它导致了反对全局状态的论点。这导致我......

整个 Wordpress 系统,主要在全局变量上运行。用于循环访问帖子的所有数据都散布在各种全局变量中。

(wp-includes\query.php 第 2644 行)

/**
 * Setup global post data.
 *
 *....
 */
function setup_postdata($post) {
    global $id, $authordata, $day, $currentmonth, $page, $pages, $multipage, $more, $numpages;

    $id = (int) $post->ID;

    $authordata = get_userdata($post->post_author);
    ....
}

这些只是使用 Singleton/Globals 作为整个系统基础的框架的两个主要示例!

那么 .. 仅仅是因为这些系统没有赶上 OOP 方法吗?当你有这么多人告诉你不要使用全局变量或单例来让你的整个系统基于上述做法时,这是没有意义的。

当然还有关于向后兼容 PHP4 的争论。我仍然认为有一些方法可以在 PHP4 中进行 OOP 编程,因为类仍然可用。

【问题讨论】:

  • 您的问题假设这些项目是如何做事的好例子。 Wordpress 是如何 构建 PHP 应用程序的一个巨大示例……它的代码库很糟糕。我没有足够的评论空间来表达 Wordpress 的编程有多糟糕。至于 CodeIgniter,为了实现与 PHP 4 的向后兼容性,他们牺牲了很多清洁度和可读性。当然,您的问题仍然完全有效,因为许多其他项目确实使用全局和单例。
  • WP = 很棒的应用程序,但是组织得很差,而且写得也很差。可悲的是 WP 仍在使用 PHP4 标准。在这一点上,我很期待 PHP 5.4 的特性之类的!

标签: php oop wordpress codeigniter


【解决方案1】:
  1. 全局变量和单例很受欢迎,因为它们简单方便。
  2. 依赖注入,唯一合理方便的全局事物替代品,在 PHP 社区中仍然相当陌生。
  3. PHP 社区通常更喜欢简单的技巧而不是适当的解决方案。
  4. 许多 PHP 开发人员对编程一窍不通,对使他们的程序正常工作的知识也知之甚少。

【讨论】:

    【解决方案2】:

    在清理单例的过程中,代表将污垢隐藏在黑暗的角落而不是清理。

    它被广泛使用是因为它可以很好地隐藏问题。

    对于那些要打扫但不想打扫的人来说是件好事。

    对于那些真正想要清理东西的人来说,这是一件坏事。

    考虑依赖注入http://martinfowler.com/articles/injection.html 如果 Singleton 引起了问题,你就不能再隐藏了。

    【讨论】:

      【解决方案3】:

      人们不鼓励使用全局变量,因为它会增加错误的可能性。如果程序中的每个函数都访问相同的全局变量,那么在某个地方出错就容易多了,而且调试起来也困难得多。它也更难测试。

      我想它们仍然经常被使用,因为程序员很懒。我们不想在前期花时间使代码井井有条且美观,我们只想完成工作。只编写一个全局函数/变量/任何东西比对其进行模块化要容易得多,而且一旦你开始沿着这条路走下去,回去重构太痛苦了。也许这就是原因:他们一开始就是这样,根本就没有回头。

      【讨论】:

      • 我明白了全局变量的概念。我的问题是,为什么在流行的系统中使用了这么多。
      • 我认为他不是在问为什么单身人士不好,而是为什么他们一直被知名项目使用。
      • 我想我在第二段中提到过,不是吗?
      • 现在你做到了。之前只有第一段的一部分。
      • 此处相同 :) 我的原始答案几乎从未接近最终产品。
      【解决方案4】:

      如果单例和全局如此糟糕, 为什么经常使用它们?

      我认为它的要点是单例使事情变得简单。至少乍一看。我对这件事没有足够的经验来说更多有用的话,但是我发现以下内容不错:

      Singleton Considered Stupid (Steve Yegge)

      【讨论】:

        【解决方案5】:

        因为使用单例相对容易,并且不使用单例需要对应用程序的结构进行更详细的规划。我前段时间问了question about alternatives,得到了有趣的答案。

        【讨论】:

          【解决方案6】:

          在基于 PHP4 的应用程序(如 WP 或 CI)中,部分原因是 PHP4 对 OOP 结构的支持更差。

          全局和单例也很简单:与使用适当的 OOP 实践构建它相比,在全局中添加一些东西所需的思考要少得多。访问它们也更简单,只需将代码指向名称即可,无需从其他地方传入对象。

          全局状态(全局变量、单例等)的一个负面影响是它使单元测试变得更加困难。

          ps:根据我的经验,wordpress 通常的代码质量很差。我不会用它来衡量任何东西......

          【讨论】:

          • 在某些情况下,使用全局变量或单例更容易重用资源以提高效率。例如,在脚本的整个生命周期中保持单个全局数据库连接。然而,在查看了一些 WordPress 的代码之后,它在某些地方大量使用了全局变量,对函数将被调用的上下文做出了广泛的假设,而这只是毫无头绪的设计。
          • 我只是指出 Wordpress 被很多人使用。
          【解决方案7】:

          可能是因为 GoF 的设计模式书。它变得太普遍了,人们认为它是绝对可靠的。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2010-10-15
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2015-07-16
            • 2010-11-24
            • 1970-01-01
            相关资源
            最近更新 更多