1. ホーム
  2. java

[解決済み] アプリのクラッシュを防ぐためのtry/catchの使い方

2023-07-14 12:26:22

質問

私は、Androidアプリで try/catch を頻繁に使用して、必要ない場所でもクラッシュしないようにしています。例えば

のビューは xml layoutid = toolbar のように参照されます。

// 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) {
}

この方法は、アプリ全体で使われています。スタックトレースが出力されないため、何が問題だったのかを見つけるのは本当に困難です。アプリはスタック トレースを出力することなく、突然終了します。

先輩に説明を求めたら、こう言われました。

本番でのクラッシュを防止するためです。

全く同意できない . これは、アプリのクラッシュを防ぐための方法ではないと思います。これは、開発者が が何をやっているのかわからず、疑っていることを示しています。

企業アプリのクラッシュを防ぐために、業界で使われているアプローチなのでしょうか?

もし try/catch が本当に本当に必要なら、UIスレッドや他のスレッドに例外ハンドラをアタッチして、そこですべてをキャッチすることは可能でしょうか?可能であれば、それはより良いアプローチになります。

はい、空の try/catch は良くないし、スタックトレースを表示したり例外をサーバーに記録するとしても、コードブロックのラップは try/catch でランダムに囲むことは、私にとって意味がありません。 try/catch .

アップデイト

この質問は多くの注目を集め、一部の人が質問を誤解しているため(おそらく私が明確に表現していないため)、私はそれを言い換えるつもりです。

開発者がここでやっていることは次のとおりです。

  • ある関数が書かれ テスト済み それはビューを初期化するだけの小さな関数であったり、複雑な関数であったりします。 try/catch ブロックに包まれます。たとえ例外が発生しないような関数であってもです。

  • このプラクティスは、アプリケーション全体で使用されます。あるときはスタックトレースが出力され、あるときは単に debug log というランダムなエラーメッセージが表示されることもあります。このエラーメッセージは開発者により異なります。

  • この方法では、アプリはクラッシュしませんが、アプリの動作が不定になります。何が悪かったのかがわからないこともあります。

  • 私が抱いていた本当の疑問は エンタープライズ・アプリケーションのクラッシュを防ぐために、業界で行われている慣習なのでしょうか? であり、私は 空のtry/catch . ユーザは予期せぬ動作をするアプリケーションよりも、クラッシュしないアプリケーションを好むというようなことでしょうか?クラッシュするか、ユーザーに真っ白な画面を見せるか、ユーザーが気づかない挙動をするか、どちらかに集約されるからです。

  • 実際のコードからいくつかのスニペットをここに投稿しています。

      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) {
        }
    }
    
    

それは ではない の複製です。 Android の例外処理のベストプラクティス プラクティス の例外をキャッチしようとしています。 異なる のために例外をキャッチしようとしています。

どのように解決するのですか?

もちろん、ルールには常に例外があります。しかし、経験則が必要な場合は、そのとおりです。空のキャッチブロックは "絶対に"悪い習慣です。

まずはあなたの具体的な例から、詳しく見ていきましょう。

try {
  View view = findViewById(R.id.toolbar);
}
catch(Exception e) { }

つまり、何かへの参照が作成され、それが失敗しても......問題にはならないのです。上記のコードは、絶対に 無駄な行間ノイズ . それとも、このコードを書いた人は、2回目の同様の呼び出しが魔法のように例外を投げなくなると最初に想定しているのでしょうか!

たぶん、これはこう見えることを意味していたのでしょう。

try {
  View view = findViewById(R.id.toolbar);
  ... and now do something with that view variable ...
}
catch(Exception e) { }

しかし、繰り返しになりますが、これが何の役に立つのでしょうか!?例外が存在するのは 伝える それぞれ 伝える のようなエラー状況が発生する可能性があります。エラーを無視することが良いアイデアであることはほとんどありません。実際、例外は次のような方法で処理することができます。

  • ユーザーへのフィードバック(例:"入力された値は文字列ではありません。
  • 問題が予期されており、軽減できる可能性がある (たとえば、リモート検索に失敗したときにデフォルトの回答を提供するなど)。
  • ...

長い話をまとめると 最小 そうすれば、後で何らかの問題をデバッグするときに、「OK、この時点で例外が発生したんだ」と理解することができます。

また、他の人が指摘しているように 例外 に対するキャッチも避けることができます (まあ、レイヤーによっては 例外 を確実にするために、最高レベルでいくつかの種類のエラーもキャッチする必要があるかもしれません。 何もない が失われないようにするためです。 これまで ).

最後に 引用 ウォード・カニンガム

あなたが読んだそれぞれのルーチンが、あなたが期待したものとほぼ同じであることがわかったとき、あなたはクリーンなコードで作業していることを知っています。また、コードが、その言語が問題のために作られたように見えるとき、あなたはそれを美しいコードと呼ぶことができます。

このことを心に刻み、瞑想してください。きれいなコードとは ではなく はあなたを驚かせます。あなたが見せている例は、私たちを驚かせます みんな を見ている。

更新情報 OPが質問しているアップデートについて

try {
  do something
}
catch(Exception e) { 
  print stacktrace
}

同じ答え:その"すべての場所"を行うこともまた 悪い を実践してください。なぜなら、このコードは であり、読み手を驚かせます。

以上のような

  • エラー情報をどこかに出力します。それは ではありません この "somewhere" に似ていることが保証されています。 合理的 に似ていることを保証します。それどころか。例:私が作業しているアプリケーション内では、そのような呼び出しは魔法のように私たちのトレースバッファに現れるでしょう。コンテキストによっては、私たちのアプリケーションは、時々、それらのバッファに大量のデータを送り込み、それらのバッファを数秒ごとに刈り込んでしまうかもしれません。そのため、quot;単にエラーを表示することは、しばしば、quot;単にそのようなエラー情報をすべて失うことに変換されます。
  • それから:try/catchをしないのは、以下の理由からです。 ができます。 . あなたは自分のコードが何をしているかを理解しているから、それをするのです。私は正しいことを行うためにここでtry/catchを持つ方が良いです(私の答えの最初の部分をもう一度参照してください)。

ですから、あなたが示しているように try/catch をパターンとして使用することは、言ったようにまだ良いアイデアではありません。そして、はい、それは を防ぐことができます。 しかし、あらゆる種類の "未定義" の挙動につながります。例外をキャッチする代わりに の代わりに を処理する代わりに、例外をキャッチすると、無数の フォローオン のエラーに遭遇する可能性があるからです。なぜなら、あなたは「根本的な原因」の事象を先に消費してしまい、それをどこかに印刷してしまい、その結果 どこかで はもうありません。