首先,我知道这个问题在这里已经不止一次了:
- 为什么要修复E_NOTICE错误
- 为什么要修复E_NOTICE错误?优点和缺点
但我越是修复所有E_notice(人们说你应该这样做),我就越注意到:
- 我在微观优化
- 实际上,我正在制作更多的代码,使我的代码更难维护,速度也更慢
举个例子:
假设您使用MongoDB PHP驱动程序,并且在一个表示数据库中集合中单行的类中的一个名为ts
的类var中有一个MongoDate
对象。现在您可以访问这个var,比如:$obj->ts->sec
,但PHP抛出了一个fit(E_NOTICE),因为在这种情况下,ts
本身并没有定义为对象,因为这个特定的行没有ts
字段。所以你认为这是可以的,这是所需的行为,如果它没有设置为返回null,我会在解释器自己的机器人工作之外自己处理它(因为你把它封装在date()
函数中,如果var是null
或none-object
,它只返回1970
)。
但现在要像另一个开发人员真正希望我的那样修复E_NOTICE,因为拥有ANY E_NOTICE非常糟糕,而且不根据错误进行操作会使代码变得更慢。因此,我在$obj
类中创建了一个名为getTs
的新函数,并给它3行代码,实际上只是检查ts
var是否是MongoDate
对象,如果它是…
为什么?PHP在它比在应用程序本身的运行时更快的解释器中做这件事对我来说不是很好吗?我的意思是,每当我不得不在代码中添加无用的bumpth,几乎是空的函数来检测变量时,我实际上只是用PHPs自己的能力来处理这些变量,当我真正需要时(当这对所述函数的操作和行为至关重要时),可以返回null
或检查它们的instanceof
,并且不让我开始使用isset()
s。我已经添加了大约300行isset()
s,它正在失去控制。我当然必须让这个getTs
功能,因为你不能做:
class obj{
public $ts = new MongoDate();
}
我要么必须将ts
存储在__constructor
中(我对此也不太满意,我现在使用了很多魔法),要么使用一个函数来检测它是否已设置(我现在这样做)。
我的意思是,我理解为什么我应该修复:
- 未定义的变量
- 分配未设置变量的属性(
null
变量) - 恒定误差等
但是,如果你已经测试了你的代码,并且你知道它是安全的,并且只能按照你想要的方式工作,那么修复所有undefined index
或none-object
错误有什么意义呢?在代码中添加一堆isset()
和2行函数难道不是真正的微优化吗?
我注意到,在使我的网站符合E_NOTICE的一半之后,实际上它现在使用了更多的CPU、内存和时间。。。那么,处理每一个E_NOTICE错误,而不仅仅是那些错误,有什么意义呢?
感谢您的想法,
使用isset()
,您肯定会得到更好的性能。不久前,我做了一些基准测试,仅仅隐藏错误就慢了大约10倍。
http://garrettbluma.com/2011/11/14/php-isset-performance/
也就是说,性能通常不是PHP的关键因素。所做的,个人让我发疯的是无声错误。
当解释器选择不将某个东西标记为错误(这可能导致不稳定)时,这是一个巨大的问题。PHP特别倾向于
- 警告应该发生的错误(例如,无法连接到数据库),以及
- issue注意到应该警告的事情(例如,试图访问null对象的成员)
也许我只是对这类事情过于固执己见,但我以前也被这些无声的错误所折磨过我建议在错误报告中始终包含E_NOTICE
您是否应该修复它们当然是有争议的,这将取决于您的情况的回报;例如,如果代码的寿命更长,开发人员更多,这一点更为重要。
一般来说,假设您的功能将被其他人使用(或错误使用)是最佳实践,因此您应该执行isset/!empty/is_object检查对此进行了说明。通常,您的代码会发现它进入了您从未想过的用途和情况。
就性能而言,每次抛出任何类型的错误(包括E_NOTICE)时,解释器都会启动错误处理程序,构建堆栈跟踪,并格式化错误。关键是,无论你是否让他们报告,错误总是会减慢执行速度因此,2-3个函数调用以避免E_NOTICE仍将提高您的性能。
编辑:上述示例的替代方案
我不一定要创建额外的对象来避免错误;你可以优雅地避开它们。这里有几个选项:
1) 处理缺失ts的功能:
SpecialClass class {
funciton getTs () {
return !empty($this->ts) ? $ts->sec : false;
}
}
2) 处理模板/程序中丢失的ts:
if (!empty($obj->ts->sec)) {
//do something
}
我特别喜欢empty()
,因为您可以使用它来替换(isset($var) && ($var or 0 != $var //etc))
,从而为目标var或属性保存多个调用/比较和空从不抛出通知。如果你在一个不存在的变量的proptery/member上调用它,它会抛出一个错误。