这不一定只适用于PHP,但这是我关注的领域。
我最近写了一些检查函数,它们得到了一些参数,然后用各种方式检查它的有效性。类似地,checkXmlString($xml)将检查给定字符串是否包含格式良好的xml文档等。
问题是,这些函数是应该返回布尔值,还是抛出异常而在成功时不返回任何值。
所以
function checkAbc($arg) { if ($arg is invalid) return false; else return true; }
或者更确切地说
function checkAbc($arg) { if ($arg is invalid) throw new Exception(...); }
您可以抛出InvalidArgumentException来检查参数是否不正确,但我认为对于您的情况,如果您正在编写"checkers",它们应该返回一个布尔值,这样您就知道不要继续操作,例如,如果foobar.xml实际上是一个CSV文件,您不想继续操作,但也不想捕获一个exeption
<?php
class Checker {
function validXml($string)
{
if(!(bool)$string) throw new 'InvalidArgumentException("Cannot pass empty string as argument", 1);
// Check
// Is valid XML ? Return True : return false
}
}
try {
if(new Checker->validXml($xmlString))
{
// Continue Operation
// return
}
// Notify User of invalidity
// return
} catch ('InvalidArgumentException $e) {
// Log args
//
}
根据几乎所有关于该主题的书籍,尤其是根据逻辑,名称应该是函数功能的最大提示。在这种情况下,只有第一个选项适用。正如Bet Lamed之前所说,一个名为"check"的函数不应该抛出异常,只是为了让你知道检查是否正常。
如果您想要异常,您可能需要将其重命名为DeserializationToAbc()或TryParseAbc()或类似的名称。
问题是,这些函数应该返回布尔值,还是抛出例外,成功后不返回任何信息。
首先确定是否是异常情况,而不是使用异常。您的情况似乎不是异常,这只是一种情况,所以将其视为一种情况。如果它是正确的,但在某些情况下失败了,那么您可能无法很好地识别,而您可能会考虑使用异常。
访问这两个链接并了解有关异常的更多信息
PHP 5.3 中的异常最佳实践
PHP异常入门
这当然有点基于观点,但问问自己,你对checkEmail()
这样的函数有什么期望?该方法的目的是验证某些东西,因此您可以预期这个问题的答案。
$isValid = checkEmail($arg);
我认为大多数开发人员都希望得到一个bool作为返回值,它使代码可读。应该有错误的值,所以如果传递了无效的参数,就不能说这是一个异常。为了返回错误消息,我会使用out参数:
function checkAbc($arg, &$errorMessage)
{
if ($arg is invalid)
{
$errorMessage = 'The argument is invalid because of...';
return false;
}
else
{
$errorMessage = '';
return true;
}
}
我真的不太确定哪种形式通常更可取。
一方面,在出现错误的情况下,您想要一条有用的消息,因此最终会出现混合返回(true/string),这很难看,或者返回一个数组(甚至更难看)。一个例外是免费的。
另一方面,一个名为check的函数。。。()不应该引发异常,因为发现"这不是一个有效的东西"并不是什么异常,也不是错误。
第三种方法是称之为"throwIfFalse",但这也很丑陋。。。。
嗯。。。。
一种可能的解决方案:
interface Checker {
public function check();
public function getMessage();
}
class WhateverChecker implements Checker { ... }
class ClientOfChecker {
public function doStuff() {
$checker = new Checker();
if (! $checker->check() )
throw new Exception($checker->getMessage());
}
}
然而,这似乎非常冗长,我可以说,对我来说,这是Java风格的。
关于您的问题,通常有两种类型的函数:
-
测试条件是否成立的纯函数。
-
确保条件成立并在不成立时更改控制流的功能。
不同的编程语言可能对这两种类型的命名有不同的约定。以C++
为例,一种常见的命名是类型2的CHECK_XXX
和类型1的IsXXX
。下面是一个来自谷歌日志库教程的例子:
CHECK(fp->Write(x) == 4) << "Write failed!";
CHECK_NE(1, 2) << ": The world must be ending!";
另一个例子是Vimscript
的maktaba实用程序库,其中maktaba#value#IsXXX()
用于测试参数是否为特定类型,而maktaba#ensure#IsXXX()
用于确保IsXXX
保持并抛出异常。
function! TakeAString(name)
" Ensure argument type is String.
let name = maktaba#ensure#IsString(a:name)
endfunction
if maktaba#value#IsString(name)
" Branch if name is a String.
echo name
endif
所以重点是:选择最适合您需要的函数,并根据语言惯例命名函数。就两者的用例而言,大致上,使用类型2来检查类似前置条件的参数类型,并在条件语句中使用类型1。