Erlang(またはJoe Armstrong?)のアドバイス防御プログラミングを使用しないそしてプロセスをクラッシュさせる(コードを汚染するのではなく)残骸を追跡しようとする不必要な警備員)は、私にとって非常に理にかなっているので、何年にもわたってエラー処理に多くの労力を費やしたのはなぜだろうと思います!
私が疑問に思うのは、このアプローチはErlangのようなプラットフォームにのみ適用できるのでしょうか? ErlangにはVMで、プロセス監視ツリーの単純なネイティブサポートがあり、プロセスの再起動は本当に高速です。トップレベルの例外ハンドラー、エラーコード、nullの結果などで自分自身を悩ませるのではなく、監視ツリーを再作成するための開発努力(Erlangの世界にいない場合)。
このアプローチの変更は、(たとえば).NETまたはJavaスペースでうまく機能すると思いますか?
どこにでも適用できます 。ソフトウェアを「クラッシュさせる」パターンで記述しているかどうかに関係なく、ハードウェアに障害が発生した場合など、とにかくクラッシュします。 「クラッシュさせて」は、現実に耐える必要がある場所ならどこでも適用できます。 Quoth James Hamilton:
ハードウェア障害が即時の管理アクションを必要とする場合、サービスは単に費用効果が高く確実に拡張できません。サービス全体は、人間の管理者の介入なしに障害を乗り切ることができなければなりません。障害回復は非常に単純なパスである必要があり、そのパスは頻繁にテストする必要があります。スタンフォード大学のアルマンドフォックスは、障害パスをテストする最善の方法は、サービスを正常にシャットダウンしないことであると主張しています。ただハード失敗します。これは直感に反するように聞こえますが、障害パスが頻繁に使用されない場合、必要なときに機能しません。
ただし、これは「ガードを使用しない」という意味ではありません。しかし、クラッシュすることを恐れないでください!
はい、それはどこにでも適用できますが、どのコンテキストで使用されるのかを注意することが重要です。 notは、アプリケーション全体がクラッシュすることを意味します。これは、@ PeterMが指摘したように、多くの場合、壊滅的である可能性があります。目標は、全体としてクラッシュすることはないが、内部でエラーを処理できるシステムを構築することです。私たちの場合、1年に数分のオーダーのダウンタイムが予想されるのはテレコムシステムでした。
基本的な設計は、システムを階層化し、システムの中央部分を分離して、作業を行う他の部分を監視および制御することです。 OTPの用語では、supervisorおよびworkerプロセスがあります。スーパーバイザーには、ワーカーや他のスーパーバイザーを監視する役割があり、ワーカーが実際のすべての作業を行っているときにクラッシュしたときに正しい方法で再起動することを目的としています。機能を厳密に分離するというこの原則を使用してシステムをレイヤーに適切に構造化することで、ワーカーからスーパーバイザーへのエラー処理のほとんどを分離できます。最終的にsmallフェイルセーフエラーカーネルを作成しようとします。これが正しければ、システムの他の部分のどこでもエラーを処理できます。この文脈で、「let-it-crash」哲学が使用されることが意図されています。
できるだけ少ない場所で実際にエラーや障害を処理することを目標に、どこでもエラーや障害について考えているというパラドックスが発生します。
エラーを処理するための最良のアプローチは、もちろんエラーとシステムによって異なります。プロセス内でローカルにエラーをキャッチしてそこで処理しようとするのが最善の場合もありますが、それが機能しない場合は再度失敗するオプションがあります。多数のワーカープロセスが連携している場合は、それらすべてをクラッシュさせて再起動するのが最善の場合がよくあります。これを行うのはスーパーバイザーです。
何かがうまくいかなかったときにエラー/例外を生成する言語が必要です。そうすれば、それらをトラップしたり、プロセスをクラッシュさせたりすることができます。エラーの戻り値を無視することは同じではありません。
私は実際の状況からのデータに依存するプログラムを作成し、それらがクラッシュした場合、物理的な損傷で大きな$$を引き起こす可能性があります(収益の損失で大きな$$は言うまでもありません)。防御的にプログラムしなければ、私はあっという間に仕事を失ってしまいます。
そうは言っても、Erlangは、すぐに再起動できるだけでなく、再起動したプログラムがポップアップして周りを見回し、「ああ、それが私がやっていることだった」と言うことができる特別なケースに違いないと思います。
これはフェイルファストと呼ばれます。失敗に対応できる(そして迅速に対応できる)チームがあれば、それは良いパラダイムです。
NAVYでは、すべてのパイプと電気が壁の外側(できれば壁のより公共の側)に取り付けられています。そうすれば、リークや問題が発生した場合に、迅速に検出される可能性が高くなります。 NAVYでは、障害に応答しなかったために人々が罰せられるため、非常にうまく機能します。障害は迅速に検出され、迅速に対応されます。
誰かが障害に迅速に対応できないシナリオでは、障害がシステムを停止できるようにするか、障害を飲み込んで続行を試みる方が有益かどうかが意見の問題になります。
私の同僚と私は、このトピックについて、特にテクノロジーの観点からではなく、ドメインの観点から、安全性に重点を置いて考えました。
問題は「クラッシュさせても安全ですか?」です。 「Erlangの「クラッシュさせて」のような堅牢性パラダイムを安全関連のソフトウェアプロジェクトに適用することさえ可能ですか?」.
答えを見つけるために、私たちは産業的、特に医学的背景を持つ現実に近いシナリオを使用して小さな研究プロジェクトを行いました。ここを見てください( http://bit.ly/Z-Blog_let-it-crash )。ダウンロード用の紙もあります。あなたの考えを教えてください!
個人的には、多くの場合に適用可能であり、特にエラー処理が多い場合(セーフティ関連システム)には望ましいと思います。常にErlangを使用できるとは限りません(リアルタイム機能がない、実際の組み込みサポートがない、コスチュームが欲しいなど)が、それ以外の方法で実装できると確信しています(スレッド、例外、メッセージパッシングなどを使用)。まだ試していませんが、やってみたいです。
IMHO一部の開発者は、チェックされた例外をほとんど価値のないコードで処理/ラップします。処理して値を追加する場合を除いて、メソッドが元の例外をスローできるようにする方が簡単な場合がよくあります。