try catch throw new exception,这是一个好习惯吗?
try catch throw new exception, is this a good practice?
这个 try catch 是个好习惯吗?如果我实施这个,我会遇到问题吗?还要考虑单元测试。
public function index($user)
{
try {
$message = $this->_validate($user);
} catch (MyCustomException $e) {
$message = $e->getMessage();
}
return $message;
}
private function _validate($user)
{
if ($user != 'test') throw new MyCustomException('Invalid User');
return 'Valid User';
}
已更新(添加了另一个示例)
如果我从 SQL 检索数据,那么当没有检索到任何记录时,抛出异常。
怎么样?
public function retrieveData($args)
{
$codeTable = $model->getCodeTables('code_tables', $args);
if (empty($codeTable)) throw new MyCustomException($this->getCustomMessage()['sysMsgDataDoesNotExists']);
// more codes here
return $codeTable;
}
public function index($args)
{
try {
$this->retrieveData($args);
// if data retrieve is not empty, execute codes here like insert, delete, update other records or other fancy logic
$message = 'success';
} catch (MyCustomException $e) {
$message = $e->getMessage();
}
return $message;
}
在第二个示例中,我的目标是在没有检索到数据时立即去捕获。而不是我做这样的事情。
public function retrieveData($args)
{
$codeTable = $model->getCodeTables('code_tables', $args);
if (empty($codeTable)) return $this->getCustomMessage()['sysMsgDataDoesNotExists'];
// more codes here
return $codeTable;
}
public function index($args)
{
$data = $this->retrieveData($args);
if (is_array($data)) {
// if data retrieve is not empty, execute codes here like insert, delete, update other records or other fancy logic
$message = 'success';
} else {
$message = $data;
}
return $message;
}
这不是异常的预期用途,是不好的做法。例外情况适用于当前开发人员无法控制的 and/or 不可预见的情况。
在您的情况下,您可以预测某些用户不会是 'test' 用户,否则为什么要进行测试。您在这里所做的是仅对 return 一条您随后回显的替代消息使用异常。所以你不需要抛出异常,只需 return 一条指示这一点的替代消息。
遇到无法处理的情况时,应该只throw
,而不是为了处理某事而throw
。
在这种情况下,true
或 false
的标志是合适的。
public function index($user)
{
return isValid($user) ? 'Valid user' : 'Invalid user';
}
private function isValid($user)
{
return $user === 'test';
}
一个示例,其中 throw
如果您编写的函数需要传递一个参数,而该参数未被传递,则该函数是有意义的。那说明开发者忘记传了,让他知道的最好方式就是抛出,这样一切就都停止了。
function foo($a, $b) {
if (!$a || !$b) {
throw new Exception('Gotta have parameters, dude!');
}
// etc
}
有些人会争论说在使用数据库时可能会出现 sql 错误,应该捕获这些错误并将它们记录 them/bubble 给用户。
其他人会在 try catch 中包装任何外部库。
就我个人而言,我想将我的所有代码包装在 try catch 中并冒出异常(将它们一直扔到控制器),我将在其中记录它们,如果找到它们,则处理输出采用用户友好的格式。
要点 - 如果发生任何不可预测的事情,它们只是一种以优雅的方式跳出逻辑的方法。
这是我如何包装索引以使其始终保持一致的示例:
public function index( $args )
{
// Init return.
$aReturn = array(); // Or object.
try
{
$aFetch = $this->retrieveData( $args );
if (!empty( $aFetch) )
{
$aReturn = $aFetch;
}
}
catch( Exception $oException )
{
// Optionally log exception or do nothing.
// log( $oException );
}
// Return will always be an array either with data or empty.
return $aReturn;
}
对于其他示例,我想这取决于您实际查询内容的上下文。
例如:
如果查询是某种搜索,那么您可能得不到任何结果。您的 wrapper/orm 应该只是 return 一个空数组并将其视为正常情况。您可以检查行数并决定要做什么。
如果查询类似于 "what's the tax rate I should use on this date" 并且应用程序应该在使用之前预加载信息,那么这可能是异常的原因。但仅来自 get_tax_rate()
-like 函数,而不是来自通用数据库查询代码。 (即便如此,如果有一些用于定义税率的用户公开页面并且 "I don't have a tax rate, please define one" 是有效的错误消息,则可能不需要例外)
任何你无法真正控制的情况,比如断开连接、超时、获取不符合你的模型的数据等等,绝对是抛出异常的原因。
这个 try catch 是个好习惯吗?如果我实施这个,我会遇到问题吗?还要考虑单元测试。
public function index($user)
{
try {
$message = $this->_validate($user);
} catch (MyCustomException $e) {
$message = $e->getMessage();
}
return $message;
}
private function _validate($user)
{
if ($user != 'test') throw new MyCustomException('Invalid User');
return 'Valid User';
}
已更新(添加了另一个示例) 如果我从 SQL 检索数据,那么当没有检索到任何记录时,抛出异常。
怎么样?public function retrieveData($args)
{
$codeTable = $model->getCodeTables('code_tables', $args);
if (empty($codeTable)) throw new MyCustomException($this->getCustomMessage()['sysMsgDataDoesNotExists']);
// more codes here
return $codeTable;
}
public function index($args)
{
try {
$this->retrieveData($args);
// if data retrieve is not empty, execute codes here like insert, delete, update other records or other fancy logic
$message = 'success';
} catch (MyCustomException $e) {
$message = $e->getMessage();
}
return $message;
}
在第二个示例中,我的目标是在没有检索到数据时立即去捕获。而不是我做这样的事情。
public function retrieveData($args)
{
$codeTable = $model->getCodeTables('code_tables', $args);
if (empty($codeTable)) return $this->getCustomMessage()['sysMsgDataDoesNotExists'];
// more codes here
return $codeTable;
}
public function index($args)
{
$data = $this->retrieveData($args);
if (is_array($data)) {
// if data retrieve is not empty, execute codes here like insert, delete, update other records or other fancy logic
$message = 'success';
} else {
$message = $data;
}
return $message;
}
这不是异常的预期用途,是不好的做法。例外情况适用于当前开发人员无法控制的 and/or 不可预见的情况。
在您的情况下,您可以预测某些用户不会是 'test' 用户,否则为什么要进行测试。您在这里所做的是仅对 return 一条您随后回显的替代消息使用异常。所以你不需要抛出异常,只需 return 一条指示这一点的替代消息。
遇到无法处理的情况时,应该只throw
,而不是为了处理某事而throw
。
在这种情况下,true
或 false
的标志是合适的。
public function index($user)
{
return isValid($user) ? 'Valid user' : 'Invalid user';
}
private function isValid($user)
{
return $user === 'test';
}
一个示例,其中 throw
如果您编写的函数需要传递一个参数,而该参数未被传递,则该函数是有意义的。那说明开发者忘记传了,让他知道的最好方式就是抛出,这样一切就都停止了。
function foo($a, $b) {
if (!$a || !$b) {
throw new Exception('Gotta have parameters, dude!');
}
// etc
}
有些人会争论说在使用数据库时可能会出现 sql 错误,应该捕获这些错误并将它们记录 them/bubble 给用户。
其他人会在 try catch 中包装任何外部库。
就我个人而言,我想将我的所有代码包装在 try catch 中并冒出异常(将它们一直扔到控制器),我将在其中记录它们,如果找到它们,则处理输出采用用户友好的格式。
要点 - 如果发生任何不可预测的事情,它们只是一种以优雅的方式跳出逻辑的方法。
这是我如何包装索引以使其始终保持一致的示例:
public function index( $args )
{
// Init return.
$aReturn = array(); // Or object.
try
{
$aFetch = $this->retrieveData( $args );
if (!empty( $aFetch) )
{
$aReturn = $aFetch;
}
}
catch( Exception $oException )
{
// Optionally log exception or do nothing.
// log( $oException );
}
// Return will always be an array either with data or empty.
return $aReturn;
}
对于其他示例,我想这取决于您实际查询内容的上下文。
例如:
如果查询是某种搜索,那么您可能得不到任何结果。您的 wrapper/orm 应该只是 return 一个空数组并将其视为正常情况。您可以检查行数并决定要做什么。
如果查询类似于 "what's the tax rate I should use on this date" 并且应用程序应该在使用之前预加载信息,那么这可能是异常的原因。但仅来自
get_tax_rate()
-like 函数,而不是来自通用数据库查询代码。 (即便如此,如果有一些用于定义税率的用户公开页面并且 "I don't have a tax rate, please define one" 是有效的错误消息,则可能不需要例外)任何你无法真正控制的情况,比如断开连接、超时、获取不符合你的模型的数据等等,绝对是抛出异常的原因。