zend framework 中的 php 编码标准 (五) - 错误与异常...
时间:2010-08-11 来源:servyo
1. Zend Framework 的代码应该不存在 E_STRICT 兼容问题。在开启错误报告 error_reporting 级别为 E_ALL | E_STRICT 时,Zend Framework 的代码不应该抛出任何警告(E_WARNING, E_USER_WARNING),任何通知(E_NOTICE, E_USER_NOTICE)以及任何兼容问题(E_STRICT)。 这就是说,Zend Framework 尽量避免代码写法上的错误。而如果真的发生程序中断,也只能是逻辑错误。 2. Zend Framework 不应该存在 Php 错误,如果我们不得不遇到错误的话,请用异常来处理。Zend Framework 中有专门的异常类来为用户提供友好的异常处理。 例如 : class Zend_Exception extends Exception { } class Zend_Db_Exception extends Zend_Exception { } class Zend_Db { public static function factory($adapter, $config = array()) { // ... if (!is_array($config)) { /** * @see Zend_Db_Exception */ require_once 'Zend/Db/Exception.php'; throw new Zend_Db_Exception('Adapter parameters must be in' . 'an array or a Zend_Config object'); } } } 3. 在框架模块内的异常统一用 new 关键字构造是公认的良好习惯。 例如 : require_once 'Zend_Component_SpecificException.php'; class Zend_Component { public function foo($condition) { if ($condition) { throw new Zend_Component_SpecificException( '一些友好的信息'); } } } 4. 异常必须延迟加载。 例如 : // 正确 if ($condition) { require_once 'Zend_Component_SpecificException.php'; throw new Zend_Component_SpecificException( '一些友好信息'); } else { // ... } // 错误 require_once 'Zend_Component_SpecificException.php'; if ($condition) { throw new Zend_Component_SpecificException( '一些友好信息'); } else { // ... } 5. 通俗地讲,如果用户希望 Zend Framework 模块做出一些超出其能力范围的工作时,那么抛出异常则是明智而正确的选择。相反,假如该模块能够处理用户的需求,但用户却给出各种意想不到的输入,这个时候,模块就不应该抛出异常,而应该正常运行下去。 例如 : if ($canNotPerformThisAction) { require_once 'Zend/Exception.php'; throw new Zend_Exception('不能执行此动作 !'); } $foo = 'bar'; if ($foo == 'foo') { echo '对的'; } else { // 没必要抛出异常 } 6. 避免抛出 Exception 基类异常,而应该尽量使用派生异常类,这可以让人清楚知道问题所在。 例如 : class Zend_Db { public static function factory($adapter, $config = array()) { if (!is_array($config)) { throw new Exception('我们根本不知问题发生在哪儿。'); } if (!is_array($config)) { require_once 'Zend/Db/Exception.php'; throw new Zend_Db_Exception("我们都知道问题出在 Zend_Db 这儿。"); } } } 7. 尽量避免去捕捉 Exception 基类异常。如果在 try 语句里面可能抛出多种异常的话,那么我们应该为各种异常准备各自独立的 catch 块,而不是仅用一个 catch 块去捕捉 Exception 基类异常。 例如 : // index.php try { $app->run(); } catch (Zend_Db_Exception $e) { die('数据库异常 !'); } catch (Zend_Acl_Exception $e) { die('权限分配异常 !'); } catch (Zend_Auth_Exception $e) { die('身份认证异常 !'); } catch (Zend_Exception $e) { // 所有其它异常 } 8. 我们通常需要在类中通过拓展多个异常类来区分各种不同的情况。例如,我们需要创建两个异常类来区分 "参数错误" 和 "用户缺乏权限" 两种情况。 例如 : class Zend_Db_Exception extends Zend_Exception { // 数据库异常基类 } class Zend_Db_Select_Exception extends Zend_Db_Exception { // 用于处理 select 类异常 } class Zend_Db_Table_Exception extends Zend_Db_Exception { // 用于处理数据库表的异常 } 9. 不要把所有诊断信息都放在异常的 message 里,我们可以在任何需要的时候创建自己的异常类的成员和方法,来为 catch 语句提供帮助。我们需要做的就是在 constructor 构建异常类时,传入正确的参数信息。 例如 : class Zend_Exception extends Exception { } class My_Exception extends Zend_Exception { private $_importantDiagnostic; public function setImportantDiagnostic($value) { $this->_importantDiagnostic = $value; } public function getImportantDiagnostic() { return $this->_importantDiagnostic; } public function __construct($message = null, $code = 0, $value) { parent::__construct($message, $code); $this->setImportantDiagnostic($value); } } try { if ($isMyFault) { throw new My_Exception('没有信息', 0, '信息在这儿'); } } catch (My_Exception $e) { echo $e->getImportantDiagnostic(); } 10. 在错误发生的时候,程序不应该保持沉默,甚至对异常置之不理。而是应该要么修正它,要么抛出新的异常来代替它。 例如 : try { } catch (My_Exception $e) { tryToCorrectIt($e); } catch (My_Exception $e) { throw new My_Exception($e->getMessage(), '110'); } catch (My_Exception $e) { // 不作为是愚蠢的行为! } 11. 我们应该为我们程序的不同层面准备不同的异常处理。例如,我们不应该把数据逻辑层的错误(即俗称 SQLException)搬到业务逻辑层。 例如 : class My_Dao_User_Exception extends Zend_Db_Table_Exception { // 数据层 User 异常类 } class My_Dao_User extends Zend_Db_Table_Abstract { // 数据层 User 对象 } class My_Bis_User_Exception extends Zend_Exception { // 业务层 User 异常类 } /** * 业务层 User 对象 */ class My_Bis_User { private $_daoUser = null; public function setDaoUser($user) { $this->_daoUser = $user; } public function getDaoUser() { return $this->_daoUser; } public function throwSomething() { try { if ($wrong) { throw new My_Dao_User_Exception('你不应该把数据层的异常搬到这里!'); } else if ($right) { throw new My_Bis_User_Exception('这才是正确的。'); } } catch (Zend_Exception $e) { // ... } } } 12. 不要把异常处理机制当成控制流程,或者仅仅是返回某些值。 例如 : function itIsWrong() { try { // 做些小动作 } catch (Exception_One $e) { doSomething($e); } catch (Exception_Two $e) { doSomething($e); } catch (Exception_Three $e) { return true; } } function isRight() { try { // 做些小动作 } catch (Exception_One $e) { correctIt($e); } catch (Exception_Two $e) { correctIt($e); } catch (Exception_Three $e) { // 从不 return; throw new Exception('我们抛出它,而不是返回什么东西!'); } } 13. 在用 catch 语句块处理异常的时候,我们应该首先释放多余的内存资源,如数据库连接,网络资源连接等。Php 并不提供类似 finally 之类的语句来进行垃圾处理。 例如 : try { $db = getDbConnection(); throw new Exception('发生了错误。'); } catch (Exception $e) { unset($db); handleExceptionAndGoOn($e); } |
相关阅读 更多 +