问题描述
我一直在研究一款经常使用 try / catch
的Android应用,以防止它甚至在没有必要的地方崩溃。例如,
I have been working on an Android app which uses try/catch
frequently to prevent it from crashing even on places where there is no need. For example,
xml布局
中的视图,其中 id = toolbar
被引用如下:
A view in xml layout
with id = toolbar
is referenced like:
// see new example below, this one is just confusing
// it seems like I am asking about empty try/catch
try {
View view = findViewById(R.id.toolbar);
}
catch(Exception e) {
}
这在整个应用程序中使用方法。堆栈跟踪没有打印,很难找到出错的地方。该应用程序突然关闭而不打印任何堆栈跟踪。
This approach is used throughout the app. The stack trace is not printed and it's really hard to find what went wrong. The app closes suddenly without printing any stack trace.
我让我的大四学生向我解释并且他说,
I asked my senior to explain it to me and he said,
我完全不同意它即可。对我而言,这不是阻止应用程序崩溃的方法。它表明开发人员不知道他/她在做什么并且有疑问。
I totally disagree with it. To me this is not the way to prevent apps from crashes. It shows that developer doesn't know what he/she is doing and is in doubt.
这是行业中使用的方法吗?阻止企业应用程序崩溃?
Is this the approach being used in industry to prevent enterprise apps from crashes?
如果尝试/捕获
真的,我们真的需要它可以附加一个带有UI线程或其他线程的异常处理程序并捕获所有内容?如果可能的话,这将是一个更好的方法。
If try/catch
is really, really our need then is it possible to attach an exception handler with UI thread or other threads and catch everything there? That will be a better approach if possible.
是的,空的尝试/捕获
是坏的,即使我们打印堆栈跟踪或日志异常到服务器,在所有应用程序中随机包装 try / catch
中的代码块对我没有意义,例如当每个函数都包含在 try / catch
中。
Yes, empty try/catch
is bad and even if we print stack trace or log exception to server, wrapping blocks of code in try/catch
randomly across all the app doesn't make sense to me e.g. when every function is enclosed in a try/catch
.
UPDATE
由于这个问题引起了很多关注,而且有些人误解了这个问题(也许是因为我没有明确表达过这个问题),我将对其进行改写。
As this question has got a lot of attention and some people have misinterpreted the question (perhaps because I haven't phrased it clearly) I am going to rephrase it.
这是开发人员在这里做的事情
Here is what developers are doing here
-
一个功能是写入和测试,它可以是一个只是初始化视图或复杂视图的小函数,在测试之后它被包裹在
try / catch
块中。即使对于永远不会抛出任何异常的函数也是如此。
A function is written and tested, it can be a small function which just initializes views or a complex one, after testing it is wrapped around
try/catch
block. Even for function which will never throw any exception.
这种做法在整个应用程序中使用。有时打印堆栈跟踪,有时只是一个调试日志
,带有一些随机错误消息。此错误消息因开发人员而异。
This practice is used throughout the application. Sometime stack trace is printed and sometime just a debug log
with some random error message. This error message differ from developer to developer.
使用此方法,应用程序不会崩溃,但应用程序的行为将不确定。甚至有时候很难跟上出错的地方。
With this approach, app does not crash but behavior of the app becomes undetermined. Even sometime it is hard to follow what went wrong.
我一直在问的真正问题是: 是否在行业中遵循以防止企业应用程序崩溃的做法?而且我不是在询问空的try / catch 。是不是,用户喜欢不会比意外行为的应用程序崩溃的应用程序?因为它真的归结为崩溃或用空白屏幕显示用户或行为用户不知道。
The real question I have been asking was; Is it the practice being following in the industry for preventing the enterprise applications from crashes? and I am not asking about empty try/catch. Is it like, users love application which do not crash than applications which behave unexpectedly? Because it really boils down to either crash it or present the user with a blank screen or the behaviour user is unaware of.
我发布了一些片段来自这里的真实代码
I am posting a few snippets from the real code here
private void makeRequestForForgetPassword() {
try {
HashMap<String, Object> params = new HashMap<>();
String email= CurrentUserData.msisdn;
params.put("email", "blabla");
params.put("new_password", password);
NetworkProcess networkProcessForgetStep = new NetworkProcess(
serviceCallListenerForgotPasswordStep, ForgotPassword.this);
networkProcessForgetStep.serviceProcessing(params,
Constants.API_FORGOT_PASSWORD);
} catch (Exception e) {
e.printStackTrace();
}
}
private void languagePopUpDialog(View view) {
try {
PopupWindow popupwindow_obj = popupDisplay();
popupwindow_obj.showAsDropDown(view, -50, 0);
} catch (Exception e) {
e.printStackTrace();
}
}
void reloadActivity() {
try {
onCreateProcess();
} catch (Exception e) {
}
}
推荐答案
当然,规则总是有例外,但如果你需要一个经验法则 - 那你是对的;空抓块是绝对不好的做法。
Of course, there are always exceptions to rules, but if you need a rule of thumb - then you are correct; empty catch blocks are "absolutely" bad practice.
让我们仔细看看,首先从您的具体示例开始:
Let's have a closer look, first starting with your specific example:
try {
View view = findViewById(R.id.toolbar);
}
catch(Exception e) { }
所以,引用创造了一些东西;当它失败时......没关系;因为首先没有使用该引用!上面的代码绝对是无用的线路噪声。或者编写该代码的人最初是否认为第二次类似的调用会神奇地不再抛出异常?!
So, a reference to something is created; and when that fails ... it doesn't matter; because that reference isn't used in the first place! The above code is absolutely useless line noise. Or does the person who wrote that code initially assume that a second, similar call would magically no longer throw an exception?!
也许这看起来像是:
try {
View view = findViewById(R.id.toolbar);
... and now do something with that view variable ...
}
catch(Exception e) { }
但是,这又有什么帮助?!您的代码中存在通信和传播错误情况的例外情况。忽略错误很少是个好主意。实际上,可以通过以下方式处理异常:
But again, what does this help?! Exceptions exist to communicate respectively propagate error situations within your code. Ignoring errors is rarely a good idea. Actually, an exception can be treated in ways like:
- 您向用户提供反馈; (例如:您输入的值不是字符串,请再试一次);或者进行更复杂的错误处理
- 也许问题是以某种方式预期的并且可以减轻(例如,当某些远程搜索失败时给出默认答案)
- ...
长话短说:最小你的事做例外是记录/跟踪它;所以,当你稍后调试一些问题时,你会理解好的,此时发生异常。
Long story short: the minimum thing that you do with an exception is to log/trace it; so that when you come in later debugging some problem you understand "OK, at this point in time that exception happened".
正如其他人所指出的那样:你也避免一般情况下捕获异常(好吧,取决于层:可能有充分理由为 Exception 捕获一些,甚至是最高级别的某些错误,确保没有迷失; 永远)。
And as others have pointed out: you also avoid catching for Exception in general (well, depending on the layer: there might be good reasons to have some catch for Exception, and even some kinds of Errors at the highest level, to make sure that nothing gets lost; ever).
最后,让我们 Ward Cunningham:
Finally, let's quote Ward Cunningham:
你知道你正在使用干净的代码,因为你读到的每个例程都是你所期望的。当代码看起来像是针对问题的语言时,你可以把它称为漂亮的代码。
让它沉入并思考它。干净的代码不让您大吃一惊。您向我们展示的示例令人惊讶所有人正在关注。
Let that sink in and meditate about it. Clean code does not surprise you. The example you are showing to us surprises everybody looking at.
更新,关于OP询问的更新关于
Update, regarding the update that the OP asks about
try {
do something
}
catch(Exception e) {
print stacktrace
}
同样的答案:这样做到处都是也糟糕练习。因为此代码也让读者感到惊讶。
Same answer: doing that "all over the place" is also bad practice. Because this code is also surprising the reader.
以上内容:
- 在某处打印错误信息。 完全没有保证这个某处类似于合理的目的地。与此相反的。示例:在我正在使用的应用程序中,此类调用将神奇地出现在我们的跟踪缓冲区中。根据具体情况,我们的应用程序有时会将大量数据和大量数据输入这些缓冲区;每隔几秒使这些缓冲区修剪。所以只是打印错误通常会转换为:只是丢失所有信息的错误。
- 然后:你没有尝试/ catch,因为你可以 。你这样做是因为你了解你的代码正在做什么;而且你知道:我最好在这里尝试/捕捉做正确的事情(再次看到我的答案的第一部分)。
- Prints error information somewhere. It is not at all guaranteed that this "somewhere" resembles a reasonable destination. To the contrary. Example: within the application I am working with, such calls would magically appear in our trace buffers. Depending on context, our application might pump tons and tons of data into those buffers sometimes; making those buffer prune every few seconds. So "just printing errors" often translates to: "simply loosing error all that information".
- Then: you don't do try/catch because you can. You do it because you understand what your code is doing; and you know: I better have a try/catch here to do the right thing (see the first parts of my answer again).
所以,使用try / catch作为模式就像你正在展示的那样;如上所述:仍然不是一个好主意。是的,阻止崩溃;但会导致各种未定义的行为。你知道,当你只是抓住一个例外,而不是正确处理它;你打开一罐虫子;因为您可能会遇到大量后续错误,而这些错误是您以后无法理解的。因为你早先消耗了根本原因事件;把它印在某处;那个某处现在已经消失了。
So, using try/catch as "pattern" like you are showing; is as said: still not a good idea. And yes, it prevents crashes; but leads to all kind of "undefined" behavior. You know, when you just catch an exception instead of properly dealing with it; you open a can of worms; because you might run into myriads of follow-on errors that you later don't understand. Because you consumed the "root cause" event earlier on; printed it somewhere; and that somewhere is now gone.
这篇关于使用try / catch防止应用程序崩溃的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!