简体   繁体   English

php中的异常真的有用吗?

[英]Are exceptions in php really that useful?

3 days ago I started rewriting one of my scripts in OOP using classes as a practice after reading a lot about the advantages of using OOP. 3天前,在阅读了很多关于使用OOP的优点后,我开始使用类作为练习在OOP中重写我的一个脚本。

Now I'm confused weather I should use exceptions or not. 现在我很困惑天气我应该使用例外与否。 They seem to make my work harder and longer. 他们似乎让我的工作更努力,更长久。

My application check if the data was sent through an Ajax request or not then uses that info through the script. 我的应用程序检查数据是否是通过Ajax请求发送的,然后通过脚本使用该信息。

Check this example : 检查此示例:

 /*
 * The older way
 */

if($ajaxEnabled) {
    $error = errorWrap('Ajax error');
} else {
    $error = errorWithBackLinkWrap('NoAjax error');
}

function doSomething() {
    if(empty($POST['name'])) {
            die($error);
    }
}

/* 
 * OOP way
 */

class someClass {
    private $_ajaxEnabled;

    public function doSomething() {
        try {
            if(!$this->_isDateValid()) {
                if($this->$_ajaxEnabled) {
                    throw new ajaxException('Ajax error');
                } else {
                    throw new noAjaxException('NOAjaxError');
                }
            }
        } catch(ajaxException $e) {
            echo $e->getErrorMessage();
        } catch(noAjaxException $e) {
            echo $e->getErrorMessage();
        }
    }
}

This code is only for demonstrating the problem, so I know there are some undefined functions in it :). 此代码仅用于演示问题,因此我知道其中有一些未定义的函数:)。

So before going oop, error handling was easier for me because I only had to echo the appropriate error. 所以在开始之前,错误处理对我来说更容易,因为我只需要回应相应的错误。

Now using exceptions, in every function I have to check the type of connection first then write 2 catch functions for each thrown exception, which lead to a much larger code. 现在使用异常,在每个函数中我必须首先检查连接类型,然后为每个抛出的异常编写2个catch函数,这会导致更大的代码。

I'm really new to OOP in php so maybe there is a cleaner and a better way to do this, is there ? 我在php中对OOP真的很新,所以也许有一个更清洁,更好的方法来做到这一点,是吗?

Your question is not uncommon, whether/when to use exception is sometimes a philosophical decision and many experienced developers can't wrap their heads around it. 你的问题并不少见,是否/何时使用例外有时是一个哲学决定,许多有经验的开发人员无法围绕它。

That being said, I've found that listing out the distinct properties of each way of handling error makes it easy to choose your preferred way: 话虽这么说,我发现列出每种处理错误方式的不同属性可以很容易地选择你喜欢的方式:

Return code 返回代码

  • The caller can ignore it or forget to check it 呼叫者可以忽略它或忘记检查它
  • The caller usually needs more documentation reading before he can use it (does 0 mean success or failure?) 调用者在使用之前通常需要更多的文档阅读( 0表示成功还是失败?)
  • Object destruction is not guaranteed -- it all depends on the caller to clean up properly 不保证对象破坏 - 这一切都取决于调用者是否正确清理

When to use : It's pretty obvious. 何时使用 :这很明显。 Use return codes when you trust the caller (internal code or trivial errors which can be safely ignored). 当您信任调用者时使用返回代码(内部代码或可以安全忽略的普通错误)。

Exceptions 例外

  • The caller cannot ignore it 来电者不能忽视它
  • The caller can still suppress it if he wants (with an empty try/catch ) 如果他想要调用者仍然可以抑制它(使用空的try/catch
  • Object destruction takes places properly -- most of the time 对象破坏适当地发生 - 大多数时候

When to use : When you don't trust your caller as much (third party) or you really need to make sure your error code doesn't go ignored. 何时使用 :如果您不信任您的呼叫者(第三方),或者您确实需要确保您的错误代码不会被忽略。

Die

  • Cannot be ignored and cannot be suppressed 不容忽视,无法抑制

When to use : It's usually obvious enough. 何时使用 :通常很明显。 You need everything to stop immediately. 你需要立即停止一切。

(In a PHP context, I don't think it makes much difference. The above suggestions should still apply.) (在PHP环境中,我认为它没有多大区别。上述建议仍应适用。)


(Aside) (在旁边)

Usually it's tempting to just write out an error message when something bad happens (especially when the first programming language you learned is PHP :P). 通常,当发生不良事件时(例如,当您学习的第一种编程语言是PHP:P时)写出错误消息是很诱人的。 But if you really want to grok OOP, it's not a proper way to handle errors. 但是如果你真的想要理解OOP,那么它不是处理错误的正确方法。

Every object or every function should ideally only perform one function. 理想情况下,每个对象或每个函数只应执行一个函数。 If one function writes error to the screen and does its own thing, it's difficult to later switch to a DatabaseErrorLogger or TextFileErrorLogger or etc. One approach would be to supply a logger to use (this is called Dependency Injection). 如果一个函数将错误写入屏幕执行自己的操作,则以后很难切换到DatabaseErrorLoggerTextFileErrorLogger等。一种方法是提供一个使用的记录器(这称为依赖注入)。 Another way to do it is to use exception -- this way, the caller gets to choose which ErrorLogger to use. 另一种方法是使用异常 - 这样,调用者可以选择使用哪个ErrorLogger

You shouldn't use exceptions when your code can handle the error gracefully using an if statement (like you did there on your example). 当您的代码可以使用if语句正常处理错误时,您不应该使用异常(就像您在示例中所做的那样)。

Exceptions are for situation that are well, exceptional. 例外情况适用于特殊情况。 Unfortunately this is not very straightforward, so it's up to you, the programmer, to decide what is exceptional or not. 不幸的是,这不是很简单,所以由程序员来决定什么特殊的。 I think a good rule of thumb is: 我认为一个好的经验法则是:

Avoid using exceptions to indicate conditions that can reasonably be expected as part of the typical functioning of the method. 避免使用异常来指示可以合理预期的条件,作为该方法典型功能的一部分。

From: http://www.codeproject.com/KB/dotnet/When_to_use_exceptions.aspx 来自: http//www.codeproject.com/KB/dotnet/When_to_use_exceptions.aspx

Exceptions as an error handling mechanism are VERY different in concept and implementation than function return codes. 作为错误处理机制的异常在概念和实现方面与函数返回代码非常不同。 You cannot/should not simply map one to the other. 你不能/不应该简单地将一个映射到另一个。 You should read and digest this article (and then a few more including this one* ) before proceeding further. 在继续进行之前,您应该阅读并消化这篇文章 (然后再包括这篇文章 * )。

If you're going to favor exceptions instead of return codes for error reporting/handling then the structure of your code should change significantly. 如果您打算使用异常而不是错误报告/处理的返回代码,那么代码的结构应该会发生显着变化。

(*The CodeProject link is .NET-specific but there's little code ti digest. It's mostly a best-practices article easily applicable to any language.) (* CodeProject链接是特定于.NET的,但是代码很少。它主要是一个易于应用于任何语言的最佳实践文章。)

Exceptions' usefullness is not in printing error codes. 例外的有用性不在于打印错误代码。 It's in catching error so you can try to solve them instead of crashing with fireworks. 这是捕捉错误,所以你可以尝试解决它们,而不是与烟花崩溃。

If I understand how you're doing it, I think you're doing it wrong. 如果我理解你是怎么做的,我认为你做错了。 Exceptions for not for errors. 没有错误的例外情况。 They are for exceptional circumstances. 它们适用于特殊情况。 Errors can mean any number of things (for example, a user didn't enter a long enough user name on a registration form). 错误可能意味着任何数量的事情(例如,用户没有在注册表单上输入足够长的用户名)。 That itself shouldn't be an exception. 这本身不应该是一个例外。 You could however use an exception to show that registration itself failed (Depending on the situation)... 但是,您可以使用例外来显示注册本身失败(根据具体情况而定)......

And you don't need to have a try/catch block at every level. 并且您不需要在每个级别都有try / catch块。 In fact, that's bad practice. 事实上,这是不好的做法。 Only catch exceptions if you either can handle the exception, or need to do something else before letting the exception continue. 如果您可以处理异常,或者在让异常继续之前需要执行其他操作,则仅捕获异常。 So, for example: If you are connecting to a remote set of websites, and the first one fails. 因此,例如:如果您要连接到一组远程网站,并且第一个网站失败。 You can catch the exception for that one, and retry with a second website. 您可以捕获该异常,并使用第二个网站重试。 And keep going until you have no more left (at which point you'd throw another exception to indicate that no websites could be fetched). 并继续前进,直到你不再离开(此时你会抛出另一个例外,表明没有网站可以被提取)。 Another example would be if you're generating images. 另一个例子是如果你正在生成图像。 You have a method that does some computation while generating the image that throws an exception. 你有一个方法在生成抛出异常的图像时进行一些计算。 You'll want to catch that exception so that you can "clean up" from the image process (to save memory, etc) and then re-throw it once you're done: catch (ImageSomethingException $e) { /* Clean up here */ throw $e; } 您将要捕获该异常,以便您可以从映像进程中“清理”(以节省内存等),然后在完成后重新抛出它: catch (ImageSomethingException $e) { /* Clean up here */ throw $e; } catch (ImageSomethingException $e) { /* Clean up here */ throw $e; } ... catch (ImageSomethingException $e) { /* Clean up here */ throw $e; } ...

The true power of exceptions is that it lets you handle the situations however you want (since the exception can just bubble up to the top of the program). 异常的真正威力在于它可以让你按照自己的意愿处理情况(因为异常只能冒泡到程序的顶部)。 But only catch exceptions where you know you can deal with them (or at least need to clean up). 但是只捕获您知道可以处理它们的异常(或者至少需要清理)。 You should almost never do print $e->getMessage() inside of production code. 你几乎不应该在生产代码中print $e->getMessage()

Personally, I have a default exception handler that I always install. 就个人而言,我有一个我总是安装的默认异常处理程序 Basically, if an exception is not caught, it will log that exception and then generate a 500 error page. 基本上,如果未捕获异常,它将记录该异常,然后生成500错误页面。 That lets me focus on what exceptions I can deal with in code instead of trying to catch everything (which isn't usually a great idea)... 这让我可以专注于我可以在代码中处理的异常,而不是试图捕捉所有东西(这通常不是一个好主意)......

Good luck... 祝好运...

I personally hate exceptions. 我个人讨厌异常。 I don't work with them in my applications. 我不在我的应用程序中使用它们。 I prefer functions returning (and expecting) defined status codes, and dealing with recoverable errors on that level. 我更喜欢函数返回(和期望)定义的状态代码,并处理该级别上的可恢复错误。

In truly exceptional situations (like an unreachable database server, a file I/O error etc.) that are an immediate emergency, I tend to trigger and handle a fatal error. 在真正异常的情况下(如无法访问的数据库服务器,文件I / O错误等),这是紧急情况,我倾向于触发并处理致命错误。 (Object shutdown will still take place, so any connections that need closing etc. will still be handled as long as they are placed in destructor functions .) (对象关闭仍将发生,因此只要将它们放在析构函数中 ,任何需要关闭等的连接仍将被处理。)

Third party libraries' exceptions I strive to catch as quickly as possible, and deal with them in my own way. 我努力尽快赶上第三方图书馆的例外情况,并以自己的方式处理它们。

Joel Spolsky puts the reasons much better than I could in his notorious Exceptions essay . 乔尔·斯波尔斯基(Joel Spolsky)在他臭名昭着的“ 例外文章”(Exceptions essay)中提出了比我更好的理由。

Note that this is one view and one school of thought. 请注意,这是一种观点和一种思想流派。 There is a lot of brilliant software whose error handling is based entirely on exceptions, and that is perfectly fine. 有很多出色的软件,其错误处理完全基于异常,这非常好。 The key is consistence - either you make the design decision to use them, or you don't. 关键是一致性 - 要么你做出设计决定来使用它们,要么你做不到。

There is a finite capacity to most development processes - ie even where its possible to predict all possible circumstances that the code might run in (ie all possible combinations of inputs, all possible states for supporting systems like database, DNS, existing data etc) then its just not practical to deal with every scenario. 大多数开发过程都有一个有限的容量 - 即使可以预测代码可能运行的所有可能情况(即所有可能的输入组合,支持系统的所有可能状态,如数据库,DNS,现有数据等),处理每一个场景都是不切实际的。 Using exceptions allows you: 使用例外允许您:

  1. to bundle a series of operations into one entity for the purposes of determining success/ failure as a whole 将一系列操作捆绑到一个实体中,以便确定整体的成功/失败

  2. handle multiple different modes of failures with a single bit of code 使用一位代码处理多种不同的故障模式

So yes - I'd say that exception handling is a useful practice - but not a substitute for handling the common failure modes specifically, intelligently and informatively (and typed exceptions are IMHO a complete oxymoron). 所以是的 - 我会说异常处理是一种有用的做法 - 但不是替代处理常见故障模式的具体,智能和信息(并且类型异常是恕我直言,完全矛盾)。

Its a developers call.. not mandatory as kizzx2 told. 它是开发人员打电话..不是强制性的,因为kizzx2告诉。 But if you are writing up some util or library kind of class its always good to throw exception as this lib or util may be used by others in future. 但是如果你正在编写一些util或library类的类,那么抛出异常总是好的,因为将来可能会被其他人使用。

If all you need is to display error message, why don't you use 如果你只需要显示错误信息,为什么不使用

catch (Exception $e)
{ print ($e->getMessage()); }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM