Php 标准化返回值-这是个好主意还是个坏主意
我使用PHP(但在本例中,我认为编程语言并不重要),在我的类方法中,我通常会遇到以下情况:Php 标准化返回值-这是个好主意还是个坏主意,php,Php,我使用PHP(但在本例中,我认为编程语言并不重要),在我的类方法中,我通常会遇到以下情况: 方法必须返回true或false 方法必须返回true或错误消息 方法必须返回true+成功消息或false+错误消息 方法必须返回true+成功结果(对象、数组等)或false 方法必须返回true+成功结果(对象、数组等)或false+错误消息 等等 我的问题是,当我在代码中的某个地方使用这个类方法时,我总是要回到这个类,检查这个方法实际返回的是什么:简单地说是真还是假,是真还是错误消息,等等 将返回
function login($username, $password)
{
// Login logic here ..
if ($logged_in)
{
return TRUE;
}
{
return $error_message;
}
}
所以正确的方法是:返回true,或者抛出异常,当调用login方法时,使用try-catch执行。因此,当某些方法出错(验证失败等)时,我应该使用异常。在特定情况下,返回包含多个元素的数组(这些元素不是同类实体的集合)的解决方案可能是可接受的解决方案。但总的来说,这是一种代码气味 这种设计可能会暗示一些问题:
- 您没有正确使用异常处理
- 你的设计违背了单一责任原则
- 您总是等待返回,直到方法结束
if (!$something)
{
return FALSE;
}
//do some other stuff
return 'great, it worked';
您的特定登录功能不应返回消息。此类特定于操作的用户消息应该被解耦,并由消息队列处理
因此,您可以将Messenger类注入到控制器中,以便您可以在任何地方使用它并将消息添加到队列中
function login($username, $password)
{
// Login logic here ..
if ($logged_in)
{
$this->messenger->addMessage('success', 'You are loggend in.');
return TRUE;
}
{
$this->messenger->addMessage('error', $message);
return FALSE;
}
}
我认为返回布尔值和其他东西的前提是错误的 函数应具有明确的目的和明确的结果。如果可以实现此结果,则返回结果。如果无法获得结果,则函数要么返回
false
,要么抛出异常。哪一个更好取决于情况和您的一般错误处理理念。无论哪种方式,让函数返回错误消息通常都没有用处。该消息对调用函数的代码没有用处
除了返回false
结果:trigger\u error
之外,PHP还有自己的机制来输出错误消息。不过,它纯粹是一个帮助调试的工具,它不会取代标准返回值。不过,它非常适合于只为了帮助开发人员而显示错误消息的情况
如果一个函数足够复杂,可能会导致需要以不同方式处理的几种不同类型的错误,那么应该使用异常来执行此操作
例如,一个用途明确的非常简单的函数,只需要返回true
或false
:
function isUserLoggedIn() {
return $this->user == 'logged in';
}
具有可能无法实现该目的的功能:
function convertToFoo($bar) {
if (!is_int($bar)) {
return false;
}
// here be dragons
return $foo;
}
该函数还触发消息,对调试非常有用:
function convertToFoo($bar) {
if (!is_int($bar)) {
trigger_error('$bar must be an int', E_USER_WARNING);
return false;
}
// here be dragons
return $foo;
}
一个函数可能会合法地遇到调用代码需要知道的几种不同类型的错误:
function httpRequest($url) {
...
if (/* could not connect */) {
throw new CouldNotConnectException('Response code: ' . $code);
}
...
if (/* 404 */) {
throw new PageNotFoundException('Page not found for ' . $url);
}
return true;
}
我也会将此评论粘贴到这里: 不应由职能部门负责准备、返回 或显示最终用户错误消息。如果函数的目的是 就是说,从数据库中获取一些东西,然后显示错误 信息与它无关。调用 从数据库获取函数只需要通知 结果;从这里开始,需要一个代码,它的唯一任务是 如果数据库函数无法获取 所需信息。不要把这两种责任混为一谈
错误消息与返回值无关可能有助于避免已知的编码错误。函数应返回与其目的一致的值,即:
canWriteFile() { return true or false }
writeFile() { should return void }
writeFile()
根据名字,程序员不期望任何价值,他必须学习文档,这需要时间,不直观,可能会导致错误。发明这样的名称,不需要任何文档
您绝对不应该将数组与第一项bool、第二项错误消息一起使用-这将返回复杂的数据类型,而不是简单的直观值,最终将编写通用函数的适配器,并且代码很快就会出错
如何处理错误有3种可能:
1)错误标志/状态对通知有用
$error = "";
function foo() {
if($somethingBad) $error = "error occured";
return !$somethingBad;
}
2)错误处理程序适用于大多数错误
function handleError($message) {
...
}
function foo() {
if($somethingBad) handleError("error occured");
return !$somethingBad;
}
3)错误捕获对于无法处理的错误非常有用(即服务器在请求期间脱机)
尝试例外情况 我建议稍微研究一下例外情况,因为它们会派上用场。首先,消除返回的错误消息:改为抛出异常 第二,您不再需要任何正确或错误的返回代码:如果所有事情都按预期工作,那么您知道这一点,因为不会引发异常 如果你
$error = "";
function foo() {
if($somethingBad) $error = "error occured";
return !$somethingBad;
}
function handleError($message) {
...
}
function foo() {
if($somethingBad) handleError("error occured");
return !$somethingBad;
}
function foo() {
try {
// dangerous code here
}
catch($e) {
// handle error here
}
return !$somethingBad
}
class Error {
const OK = 1;
//general error
const FAIL = 0;
//invalid url
const RequestParseError = -1;
//resource not found
const ResourceNotFound = -2;
....
static public function _($errCode) {
switch ($errCode) {
case Error::OK:
return "OK";
case Error::FAIL:
return "General Failure";
case Error::RequestParseError:
return "Request Parse Error";
.....
}
}
/**
* @param MyInput $input
* @return MyOutput
* @throws MyException
*/
function myOperation(MyInput $input)
{
}
/**
* @param MyInput $input
* @param MyOutput $output
* @return bool
*/
function tryMyOperation(MyInput $input, &$output = null)
{
}
/**
* @param string $input
* @return string
* @throws TypeException
*/
function stringToUpper($input)
{
if (!is_string($input))
{
throw new TypeException('String expected');
}
return strtoupper($input);
}
/**
* @param string $input
* @param string $output
* @return boolean
*/
function tryStringToUpper($input, &$output)
{
try
{
$output = stringToUpper($input);
return true;
}
catch (TypeException $exception)
{
$output = null;
return false;
}
}
try
{
$output = stringToUpper($input);
// use $output
}
catch (TypeException $exception)
{
// recover
}
if (tryStringToUpper($input, &$output))
{
// use $output
}
else
{
// recover
}