5

首先,我知道这个问题在这里不止一次出现:

但是我修复所有 E_NOTICE 的次数越多(正如人们所说的那样),我越注意到:

  • 我正在微优化
  • 我实际上正在编写更多代码并使我的代码更难维护和更慢

举个例子:

假设您使用 MongoDB PHP 驱动程序,并且您有一个MongoDate在类中命名的类 var 中的对象,ts该类表示数据库中集合中的单行。现在你像这样访问这个变量:$obj->ts->sec但是 PHP 抛出一个 fit (E_NOTICE) 因为ts在这种情况下它本身没有定义为一个对象,因为这个特定的行没有一个ts字段。所以你认为这没问题,这是期望的行为,如果它没有设置返回 null 并且我会在解释器自己的机器人工作之外自己处理它(因为你将它包装在一个date()函数中,1970如果 var 是nullnone-object)。

但是现在要修复那个 E_NOTICE,因为另一个开发人员真的希望我这样做,因为拥有任何 E_NOTICE 是非常糟糕的,并且它会使代码变慢而不是根据错误来执行它。$obj因此,我在名为的类中创建了一个新函数,getTs并给它 3 行,实际上什么都不做,只是检查tsvar 是否是一个MongoDate对象,如果是则返回它......

为什么?PHP 不能在其更快的解释器中为我做到这一点,而不是在应用程序本身的运行时中做到这一点吗?我的意思是我必须在我的代码中添加无用的颠簸的每个地方,几乎是空函数来检测我实际上只是用 PHP 自己处理的变量,当我真正需要时返回null或检查它们instanceof(当它对操作和所述函数的行为)并且不要让我开始使用isset()s 我已经添加了大约 300 行isset()s,它已经失控了。我当然必须实现这个getTs功能,因为你不能这样做:

class obj{
    public $ts = new MongoDate();
}

我要么必须将其存储ts在其中__constructor(我对此也不太满意,我正在使用很多魔法),要么使用一个函数来检测它是否已设置(我现在这样做)。

我的意思是我明白为什么我应该修复:

  • 未定义的变量
  • 分配未设置变量 ( nullvars)的属性
  • 不断的错误等

但是,如果您已经测试过您的代码并且您知道它是安全的并且只会按照您希望的方式工作,那么修复所有的undefined indexornone-object错误有什么意义呢?在你的代码中添加一堆isset()s 和 2 行函数实际上不是微优化吗?

在使我的一半站点符合 E_NOTICE 后,我注意到实际上它现在使用了更多的 CPU、内存和时间……那么处理每个 E_NOTICE 错误而不仅仅是那些错误的真正意义何在?

谢谢你的想法,

4

2 回答 2

6

通过使用,您确实会获得更好的性能isset()。不久前,我做了一些基准测试,只是隐藏错误的速度大约慢了 10 倍。

http://garrettbluma.com/2011/11/14/php-isset-performance/

也就是说,性能通常不是 PHP 的关键因素。什么个人让我发疯的是无声的错误

当解释器选择不将某些内容标记为错误(可能导致不稳定)时,这是一个大问题。PHP 尤其倾向于

  • 警告应该出错的事情(例如无法连接到数据库)和
  • 发出关于应该警告的事情的通知(例如,尝试访问空对象的成员)。

也许我只是对这类东西过于固执己见,但我以前曾被这些无声的错误所困扰。我建议始终在错误报告中包含 E_NOTICE。

于 2012-07-16T19:21:20.987 回答
3

您是否应该修复它们当然是有争议的,并且仅取决于您的情况的回报;例如,如果代码具有更长的生命周期、更多的开发人员等,则更为重要。

通常,假设您的函数将被其他人使用(和误用)是最佳实践,因此您应该进行 isset/!empty/is_object 检查以解决此问题。通常,您的代码会发现它进入了您从未打算使用的用途和情况。

就性能而言,每次抛出任何类型的错误(包括 E_NOTICE)时,解释器都会启动错误处理程序,构建堆栈跟踪并格式化错误。关键是,无论您是否让他们报告,错误总是会减慢执行速度;因此,避免 E_NOTICE 的 2-3 次函数调用仍将提高您的性能

编辑: 上述示例的替代方案

我不一定会创建额外的对象来避免错误;你可以优雅地避开它们。这里有几个选项:

1) 处理缺失 ts 的函数:

SpecialClass class {

    funciton getTs () {
        return !empty($this->ts) ? $ts->sec : false;
    }
}

2)处理模板/过程中缺少的ts:

if (!empty($obj->ts->sec)) {
    //do something
}

我特别喜欢empty(),因为您可以使用它来替换 of (isset($var) && ($var or 0 != $var //etc)),保存多个调用/比较,并且 empty 永远不会为目标 var 或属性抛出通知。如果您在不存在的变量的属性/成员上调用它,它将引发错误。

于 2012-07-16T18:57:15.430 回答