我应该在我的PHP代码中使用assert吗?

一个同事已经在我的图书馆里几次的地方添加了assert命令,在那里我会使用一个if语句并引发一个exception。 (我从来没有听说过在此之前断言)。这是他如何使用它的一个例子:

assert('isset($this->records); /* Records must be set before this is called. */'); 

我会做:

 if (!isset($this->records)) { throw new Exception('Records must be set before this is called'); } 

从读取断言的PHP文档看起来,build议您确保assert处于活动状态,并在使用assert之前添加处理程序。 我找不到他在做这个的地方。

所以,我的问题是,正在使用上面给出的一个好主意,我应该更频繁地使用它,而不是如果和例外?

另外需要注意的是,我们计划在各种项目和服务器上使用这些库,包括我们甚至可能不属于的项目(这些库是开源的)。 这使用assert有什么区别吗?

适用于大多数语言的经验法则(我隐约知道的一切)是assert用于断言条件总是正确的,而if可以想象它有时会失败,则if是适当的。

在这种情况下,我会说assert是合适的(基于我对这种情况的理解不足),因为在调用给定的方法之前应始终设置records 。 因此,设置logging失败将是程序中的一个错误,而不是运行时间条件。 在这里, assert有助于确保(通过适当的testing)没有可能的程序执行path可能导致被调用的代码被调用而没有设置records

使用assert而不是if的优点是,通常可以在生产代码中closuresassert ,从而减less开销。 在生产系统的运行期间,最好能够处理的情况是可以想像得到的,因此不会因为不能closures而丢失任何东西。

这完全取决于你的发展战略。 大多数开发人员不知道assert()并使用下游unit testing。 但是主动和内置的testingscheme有时可能是有利的。

断言是有用的,因为它可以被启用和禁用。 如果没有定义这样的断言处理程序,它不会消耗性能。 你的同事没有一个,你应该devise一些临时在开发环境中启用它的代码(如果E_NOTICE / E_WARNINGs是打开的,所以应该是断言处理程序)。 我偶尔使用它的地方,我的代码不能混合variablestypes – 我通常不会在弱types的PHP中进行严格的input,但有随机用例:

  function xyz($a, $b) { assert(is_string($a)); assert(is_array($b)); 

例如,将补偿缺lesstypes说明符string $a, array $b 。 PHP5.4将支持他们,但不检查。

想想断言是“权力评论”。 而不是像这样的评论:

 // Note to developers: the parameter "a" should always be a number!!! 

使用:

 assert('is_numeric(a) /* The parameter "a" should always be a number. */'); 

意思完全相同,意思是完全相同的观众,但是第一条评论很容易被人遗忘或者忽略(不pipe有多less惊叹号),而“权力评论”不仅可以供人阅读和理解,在开发过程中也经常进行机器testing,如果您在代码和工作习惯上设置了良好的断言处理,也不会被忽视。

这样看来,assert是一个完全不同的概念,如果(错误)…和exception,他们可以共存。

是的,你应该评论你的代码,是的,你应该尽可能使用“权力评论”(断言)。

断言不是正常stream程控制的替代,就像if或exception,因为它只是用来在开发过程中进行debugging。

断言只能在开发中使用,因为它对debugging很有用。 所以,如果你想要,你可以使用它们来开发你的网站,但是你应该使用例外的网站。

有关在PHP中声明的一个重要说明。 与具有assert结构的其他语言不同,PHP不会将assert语句完全抛出 – 它将其视为一个函数(在由断言调用的函数中执行debug_backtrace())。 车削断言似乎只是在function上变成了无所事事的引擎。

问题在于assert会采取任何参数 – 但是如果参数不是一个string,那么assert会获取expression式的结果,无论assert是打开还是closures。 您可以使用以下代码块进行validation。

 <?php function foo($a) { echo $a . "\n"; return TRUE; } assert_options(ASSERT_ACTIVE, FALSE); assert( foo('You will see me.')); assert('foo(\'You will not see me.\')'); assert_options(ASSERT_ACTIVE, TRUE); assert( foo('Now you will see')); assert('foo(\'both of us.\')'); 

鉴于断言的意图是一个错误,并且自从断言在PHP 4中引入以来就一直存在于语言中,这是一个长期存在的错误。

传递给断言的string被认为是具有所有性能影响和危害的,但这是唯一能够以PHP的方式得到断言的方式。

你的同事真的试图从Eiffel语言应用Design-by-Contract(TM),并基于“面向对象的软件构造”第二版。

他所使用的说法是Hoare Logic或Hoare Triple {P} C {Q}的{P}部分,{P}是前提assert(ion)s和{Q}是post条件断言(离子)。

我将对PHP提供的有关错误的断言特性给予重要的注意。 你不想使用越野车代码。 你真正想要的是PHP的制造商来修复断言中的错误。 直到他们这样做,你可以使用assert,但是使用它注意到它现在的状态。

此外,如果断言function是越野车,那么我build议你不要在生产代码中使用它。 不过,我build议您在适当的时候在开发和testing代码中使用它。

最后,如果你做了一个按契约devise的研究,你会发现,根据面向对象的经典inheritance来使用布尔断言是有后果的 – 也就是说,你必须决不能削弱先决条件,也不能削弱后置条件。 这样做可能会危害您的多态后代对象互相交互。 直到你明白这意味着什么 – 我会放弃它!

此外,我强烈build议PHP制造商对“逐个devise”进行全面的研究,并尝试尽快将其纳入PHP! 然后,我们所有人都可以从具有DbC感知的编译器/解释器中受益,这将解决上述答案中提到的问题:

  1. 一个正确的实现感知式的编译器将(希望)是没有错误的(不像当前的PHP断言)。
  2. 一个正确实施的Design-by-Contract-aware编译器会为你处理多态断言逻辑pipe理的细微差别,而不是在这个问题上绞尽脑汁!

注意:即使使用if语句代替assert(先决条件),如果用来强化先决条件或弱化后置条件,也会遭受严重的后果。 要理解这意味着什么,你需要研究devise合同来了解! 🙂

快乐的学习和学习。