Failure and Exceptions (James Gosling氏へのインタビューより)

前回、続きを「数日中に書きます。」と言ったくせにその後いろいろ忙しかったり酒飲んだりしていて書いている余裕がなくて、そうこうしている間に、以前のC#作者Anders Hejlsbergのインタビュー記事へのJames Goslingからの反論を見つけてしまいましたので(こちら経由)また訳してみました。「The trouble with Checked Exceptions」は有名ですし以前から知っていましたが、これの存在は今回はじめて知りました。

例によって私の英語力はアレなので、間違いや訳し切れなかったところについてはご指摘をよろしくお願いいたします。

原文はこちら。
http://www.artima.com/intv/solid.html
Summary

James Gosling talks with Bill Venners about how to build solid apps, organize your catch clauses, scale checked exceptions, and deal with failure.

James Goslingが、いかにして頑健なアプリケーションを構築し、あなたのcatch節を体系化し、検査例外をスケーリングし、どのように失敗に対処するかについて、Bill Vennersと対話する。

Much has been written recently about the value that checked exceptions add, or subtract, from Java. Some programmers feel that checked exceptions help them build robust applications. Others find that checked exceptions are an annoyance that hinders their productivity. In this article, Java's creator James Gosling voices his opinions about checked exceptions and error handling.

検査例外がJavaに加える、あるいは減じる価値について、最近多くのことが書かれています。あるプログラマは、検査例外が頑健なアプリケーションを構築する助けになると感じています。別のプログラマは、検査例外は彼らの生産性の邪魔になる苛立ちの元であると感じています。この記事では、Javaの作者であるJames Goslingが、検査例外とエラーハンドリングについて自分の意見を述べます。

In this interview, which will be published in multiple installments, James Gosling talks about many aspects of programming.

いずれ複数回に分けて出版されるであろうこのインタビューでは、James Goslingは多くのプログラミングの局面について語ります。

  • In Part I: Analyze this!, Gosling describes the ways in which Jackpot can help programmers analyze, visualize, and refactor their programs.
  • In this installment, Gosling talks about how to build solid apps, organize your catch clauses, scale checked exceptions, and deal with failure.
  • Part I: Analyze this!においては、James Goslingは、Jackpotがプログラマが彼らのコードを分析したり可視化したりリファクタリングしたりすることをどのように助けるかについて説明します。
  • 今回は、Goslingはいかにして頑健なアプリケーションを構築し、あなたのcatch節を体系化し、検査例外をスケーリングし、どのように失敗に対処するかについて語ります。

Creating Solid Software(Solidなソフトウエアを作る)

Bill Venners: In your weblog, you wrote:

Bill Venners: ブログであなたはこう書きました。

Lots of newbie's coming in from the C world complain about exceptions and the fact that they have to put exception handling all over the place―they want to just write their code. But that's stupid: most C code never checks return codes and so it tends to be very fragile. If you want to build something really robust, you need to pay attention to things that can go wrong, and most folks don't in the C world because it's just too damn hard.
One of the design principles behind Java is that I don't care much about how long it takes to slap together something that kind of works. The real measure is how long it takes to write something solid.

Cの世界からきた多くの初心者は、例外と、彼らがあちこちに例外のハンドリングを書かなければならないという事実に対して不平を言います―彼らはただ自分のコードを書きたがっているのです。しかし、それは愚かなことです。ほとんどのCのコードは決して戻り値をチェックせず、そのため非常に脆弱な傾向があります。もしあなたが何か本当に頑健なものを作りたければ、あなたは支障を起こす可能性があるものに対して注意を払う必要がありますが、Cの世界のほとんどの人は、単にそれがひどく難しいために、それをしません。Javaの背景にある設計原則のひとつは、私が、何かそこそこ動くものを適当にでっちあげるのにどれぐらい時間がかかるか、ということは気にしない、ということです。真の尺度は何かSolidなものを書くのにどれぐらいかかるのかということです。

What does "solid" mean?

「Solid」とはどのような意味でしょうか?

James Gosling: Solid means you can run the software day in and day out. When the usual crazy things happen, the software survives. The software deals with the problems. If you change the system configuration around, the system, as much as possible, copes――or at least recognizes when things are wrong.

James Gosling: Solidとは、あなたがそのソフトウエアを来る日も来る日も実行できる、ということです。よくある狂った事態が発生しても、ソフトウエアは生き残ります。ソフトウエアは問題に対処します。もしあなたがシステムの構成を変えたとしても、システムはできるだけうまく処理しますし、少なくとも何かが間違っているときそれを認識します。

One of the traditional things to screw up in C code is opening a data file to read. It's semi-traditional in the C world to not check the return code, because you just know the file is there, right? So you just open the file and you read it. But someday months from now when your program is in deployment, some system administrator reconfigures files, and the file ends up in the wrong place. Your program goes to open the file. It's not there, and the open call returns you an error code that you never check. You take this file descriptor and slap it into your file descriptor variable. The value happens to be -1, which isn't very useful as a file descriptor, but it's still an integer, right? So you're still happily calling reads. And as far as you can tell, the world is all rosy, except the data just isn't there.

Cのコードにおいて伝統的な失敗のひとつは、読み込みのためにファイルをオープンすることです。リターンコードをチェックしないのはCの世界ではほとんど伝統のようなものです。なぜならあなたはファイルがそこにあることを知っているから。そうだよね? そこで、あなたはただファイルを開き、それを読みます。しかし、今から数ヵ月後のある日、あなたのプログラムが配置された時、システム管理者はファイルを再構成して、ファイルは結局間違ったところに置かれます。あなたのプログラムは、ファイルをオープンしようとします。それはそこになく、openの呼び出しはあなたにエラーコードを返すのですが、あなたは決してそれをチェックしません。あなたはこれをファイルディスクリプタとみなして、あなたのファイルディスクリプタ用の変数にそれを放り込みます。値はたまたま-1*1であり、ファイルディスクリプタとしてあまり役には立ちませんが、それでもそれは整数型です。そうだよね? そこであなたはまだ幸福にreadを呼び出します。あなたが関知する限りにおいて、世界はすべてバラ色です。ただ、データがそこにないということを除いて。

Problems like that are really hard to test for. It is really hard to test the unlikely things, if only because the unlikely things never really occur to you. In this example, the programmer will think, "Well of course the file is there. Why would anybody not have the file there?"

こういう問題は本当にテストしにくいものです。ありそうもない事柄というのは、けっしてあなたの心に浮かばないものであり、それだけでもテストしにくい理由としては十分です。この例では、プログラマはこう考えるでしょう。「もちろんファイルはそこにあるさ。誰がそこにファイルを持っていないって?」

A programming language can't solve all the problems. A language can't guarantee that no matter how screwed up the environment gets the program will survive. But anything the language can do to increase the probability that programs will be reasonably graceful under fire is a good thing. For example, just making people at least willfully ignore return codes helps. In Java you can ignore exceptions, but you have to willfully do it. You can't accidentally say, "I don't care." You have to explicitly say, "I don't care."

プログラミング言語はすべての問題を解決することはできません。言語は、いかに環境がぐちゃぐちゃにされていても動き続けることを保証することはできません。しかし、ひどい状況下でもプログラムが正当に優雅に動く確率を増加させるよう、言語が支援できることは良いことです。たとえば、人々に、少なくとも意識的に無視させるようにすることは、助けになります。Javaでは、例外を無視できますが、あなたは意識的にそれをしなければなりません。あなたは「私は気にしません」とうっかり言うことはできません。あなたは「私は気にしません」と明示的に言わなければなりません。

Bill Venners: You don't have plausible deniability.

Bill Venners: 都合のよい言い逃れ*2を持たないわけですね。

James Gosling: Yeah, there's no plausible deniability when it comes to checked exceptions.

James Gosling: はい。検査例外ということになると、いかなる都合のよい言い逃れもできません。

Orgnanizing Your Catch Clauses(catch節を体系化する)

Bill Venners: I recently published an interview with C#'s creator Anders Hejlsberg in which we talked about checked exceptions and why C# doesn't have them. I wanted to ask you about some of his comments. He said:

Bill Venners: 私が最近発表したC#作者のAnders Hejlsbergとのインタビューにおいて、我々は、検査例外と、なぜC#がそれを持たないのかについて話しました。彼のコメントについてあなたに聞きたいと思います。彼はこう言いました:

It is funny how people think that the important thing about exceptions is handling them. That is not the important thing about exceptions. In a well-written application there's a ratio of ten to one, in my opinion, of try finally to try catch.

どうしたわけか、例外について重要なのはそれをハンドルすることだと考えられていますが、それはおかしな話です。それは例外について重要なことではありません。よく記述されたアプリケーションにおいて、私の意見では、try finallyはtry catchの10倍もあるのです。

In the finally, you protect yourself against the exceptions, but you don't actually handle them. Error handling you put somewhere else. Surely in any kind of event-driven application like any kind of modern UI, you typically put an exception handler around your main message pump, and you just handle exceptions as they fall out that way. But you make sure you protect yourself all the way out by deallocating any resources you've grabbed, and so forth. You clean up after yourself, so you're always in a consistent state. You don't want a program where in 100 different places you handle exceptions and pop up error dialogs. What if you want to change the way you put up that dialog box? That's just terrible. The exception handling should be centralized, and you should just protect yourself as the exceptions propagate out to the handler.

finallyの中では、あなたは例外から自分自身を防御することになります。しかし、自分で例外をハンドルするわけではありません。あなたは例外処理をどこか他の場所に置くわけです。近代的なUIのようなどんな種類のイベントドリブンアプリケーションにおいても、あなたは、通常メッセージポンプの外側に例外ハンドラを置きます。そして、あなたは、そこまで落っこちた例外のみをハンドルするのです。しかし、あなたは、あなたが確保したあらゆるリソースを開放等することで、自分自身のコードを確実に防御できます。自分で後始末するので、あなた自身は常に一貫した状態にあります。あなたは100の異なった場所において、自分で例外をハンドルし、エラーダイアログをポップアップするプログラムを欲しくはありません。あなたがそのダイアログボックスを提供する方法を変えたい場合、どうなるでしょうか? それはまさにひどいものとなります。例外処理は集結されるべきです。そして、例外がハンドラの外に伝播するとき、あなたはただ自分自身を防御すべきです。

I do catch exceptions in an outer loop sometimes. But most times my catch clauses tend to be spread around the program. I find that catch clauses usually have a natural home――the method that has enough contextual knowledge to know how to deal with the exception. How would you recommend people organize their catch clauses?

私は時々外側のループで例外をcatchします。しかし、多くは、私のcatch節はプログラムの周りに配置されます。私は、通常、catch節には本来あるべき場所があると感じています――例外をどう扱えばよいか、文脈上十分な知識のあるメソッドです。あなたは、人々がどのようにcatch節を体系化するよう勧めますか?

James Gosling: I tend to do catches much more frequently than Anders would have you do, because the knowledge of the situation is always fairly localized. When you try to open a file and it's not there, you're coping strategy is really determined by what you were going for. Some guy miles away isn't going to know what to do. The code that tried to open the file knows what to do, whether it be trying a backup file, looking in a different directory, or asking the user for another filename.

James Gosling: 私は、Andersがあなたに勧めるよりも頻繁に例外をcatchする傾向があります。なぜなら、状況に関する知識はいつも相当に局所化されているからです。あなたがファイルを開こうとしてそれがなかったとき、あなたの対処方法はあなたが何をしたいかによって真に決定されるのです。何マイルも離れたところでは、何をすべきかわからないでしょう。ファイルを開こうとしたコードは、何をすべきか知っています。それがバックアップファイルを試すことであれ、別のディレクトリを見に行くことであれ、別のファイル名をユーザに聞くことであれ。

Having one big catch clause on the outside really only works if your exception handling philosophy is simply to die. If you have an event loop, you can maybe cause that one event to just be tossed. If you have a plugin architecture, the enclosing environment could respond to a failure in the plugin by disabling it――like an app server deciding to disable a servlet if it sees failures. But if you're not doing an event driven program or plugins, there isn't an outside place where you can take big hunks of functionality and saw them off. On the other hand, typically you should have last ditch try catch blocks. If you're writing a web server, for example, it's a good thing to put a last ditch try catch block around processing a request. But pretty much all that a try catch block like that can do is blow the request away. There's no ability to respond gracefully. There's no ability to take account of local context to cope and adapt, which is really one of the key hallmarks of truly reliable software.

あなたの例外ハンドリングの哲学が、短に死ぬことであるという場合だけ、外側に巨大なひとつのcatch節を持つという方法は真に機能するのです。あなたがイベントループを持っているのなら、あなたはおそらく、その単一のイベントをただ受け渡すだけで済むでしょう。プラグイン構造があるのなら、それを包み込む環境は、それを無効化することにより失敗に対処できます――アプリケーションサーバが、失敗を見つけたときにサーブレットを無効化するように。しかしあなたがイベントドリブンのプログラムやプラグインをやっているのでないのなら、機能性という名の大掛かりな塊を持って来て、それらを切り出す作業のできるような、外側の世界というものがありません。一方で、定型的なことを言えば、最後の牙城としてのtry catch節を書くことも勧めます。たとえば、あなたがウェブサーバを書いているのなら、リクエストの処理の外側に、最後の溝としてのtry catchを置くのはよいことです。しかし、そのようなtry catchブロックができることは、単にリクエストを吹き飛ばすことだけです。優雅に応答する能力はまったくありません。うまく対処したり適応したりするために、局所的な文脈を考慮する能力がまったくないのです。それは、本当に信頼できるソフトウエアの主要な特徴のひとつです。

Bill Venners: It adapts to problems?

Bill Venners: 問題に適応して対処する、ということでしょうか?

James Gosling: Instead of just rolling over and dying.

James Gosling: ただ転んで死んでしまう代わりにね。

Scalability of Checked Exceptions(スケーラビリティと検査例外)

Bill Venners: Another concern Anders Hejlsberg had about checked exceptions, which is a concern I've heard many people express, is scalability. He said:

Bill Venners: Anders Hejlsbergが検査例外に対して持っていた他の懸念事項――それは多くの人が表明しているのを私が聞いた懸念事項なのですが――スケーラビリティです。彼は以下のように言いました。

In the small, checked exceptions are very enticing. With a little example, you can show that you've actually checked that you caught the FileNotFoundException, and isn't that great? Well, that's fine when you're just calling one API. The trouble begins when you start building big systems where you're talking to four or five different subsystems. Each subsystem throws four to ten exceptions. Now, each time you walk up the ladder of aggregation, you have this exponential hierarchy below you of exceptions you have to deal with. You end up having to declare 40 exceptions that you might throw. And once you aggregate that with another subsystem you have 80 exceptions in your throws clause. It just balloons out of control.

小さなプログラムでは、検査例外はとても魅力的です。小さな例で言えば、あなたは、FileNotFoundExceptionをちゃんと捕捉したことを確認した、ということを示すことができます。これってすごくない? さて、あなたがひとつのAPIだけを読んでいる場合、これはすばらしいものです。あなたが4つか5つの異なるサブシステムと対話するような大規模システムを作り始めた時に問題が始まります。各サブシステムは、4〜10の例外を投げます。いまや、あなたはモジュールの階層を上がるたびに、指数関数的に増加する、対処すべき例外を持つことになります。あなたは結局、投げる可能性のある40個の例外を宣言しなければなりません。そして、ひとたびそれを別のサブシステムと組み合わせると、あなたはthrows節に80個の例外を並べることになります。それは制御不能なほど膨張していきます。

James Gosling: I've almost never seen that actually happen in large systems. One of the coping strategies I've seen for dealing with that kind if situation is exception wrapping. If you have a subystem that might be hit with hundreds of different exceptions, you can always take those exceptions and wrap them in a new one. You can create a new exception and list other exceptions as their cause. Also, the exception class hierarchy can help. For example, there are dozens of different IOExceptions, but it's common to not declare that you throw the specific subclasses. You just throw IOException.

James Gosling: 私は大規模システムでそんなことが起きているのを見たことはほとんどありません。私が見たことがある、その手のシチュエーションに対応する対処戦略のひとつは、例外ラッピングです。もし何百もの異なる例外を起こすサブシステムがあるのなら、あなたはひとつの新しい例外でそれをラッピングできます。あなたは新しい例外を生成し、他の例外は、その原因(cause)として記載できます。また、例外のクラス階層も助けになります。たとえば、たくさんの異なったIOExceptionがありますが、特定のサブクラスを投げると宣言しないのは一般的です。あなたはただIOExceptionを投げるだけなのです。

But in general, when you are writing a declaration in a throws clause, it is good to try to be as specific as possible.

しかし、一般的に、throws節を書くときには、できるだけ特有であろうとすることは、よいことです。

Bill Venners: Why?

Bill Venners: なぜでしょうか?

James Gosling: Because it gives more information to the context about what exactly went wrong. That helps client programmers discriminate among the different sources of failure in their catch clauses.

James Gosling: 正確に何がおかしくなったのかという文脈についてより多くの情報を与えるからです。それは、クライアントプログラマがcatch節においてさまざまな原因を区別することを助けます。

Bill Venners: Have you seen the throw clause scalability problem in your visits out in the industry?

Bill Venners: あなたが業界に出向いて行った際に、throws節のスケーラビリティの問題を目にしたことがありますか。

James Gosling: I've never seen issues where people have a gazillion items in their throws clause. Three, four, or five, maybe?and even those numbers are rather large. Almost always it's zero or one.

James Gosling: 私はthrows節に何億兆もの項目があるような問題は見たことがありません。3つか4つ、5つぐらいでしょうか? それらの数さえかなり大きいほうです。たいていは0か1です。

Bill Venners: I've found that many people don't seem to think about programming so much in terms of the interface as an abstract contract and the implementation as one way to implement that contract. They just think in terms of "the code." But the throws clause is part of the interface. If someone makes an implementation change that results in a method being called that throws a new checked exception, that doesn't mean that exception should necessarily appear in throws clauses up the call stack. If you automatically plop exceptions into throws clauses, you're letting the implementation drive the interface, instead of thinking about what the throws clause should contain at the abstract contract level.

Bill Venners: 多くの人々は、抽象的な契約としてのインタフェースと、その契約を実践するためのひとつの方法としての実装という観点からのプログラミングについて、よく考えているようには見えません。彼らは単に「コード」の観点から考えます。しかし、throws節はインタフェースの一部です。もし誰かが実装を変更して、その結果として新しい例外を投げるメソッドが呼ばれることになったとしても、その例外は必ずしもコールスタックをさかのぼってthrows節に現れるはずだ、ということにはなりません。機械的に例外をthrows節にどさどさ書いていくなら、あなたは実装からインタフェースを変化させることになります。抽象的な契約のレベルでthrows節が何を含むべきかを考える代わりに。

James Gosling: That's a place where exception translation can be a good thing. If you have something that's supposed to be reading a database, and somewhere deep inside it, it could conceivably get a MalformedURLException, it probably doesn't make sense to propagate that outward as a MalformedURLException. It's better to think about what kind of exceptions are really a part of the interface, and not just an artifact of how the underlying method was implemented. In the Java exceptions mechanism, exceptions can have a reference to other exceptions as their cause. So you create a new IOException, and you set its cause to this MalformedURLException. And you bundle them together. That's been very effective.

James Gosling: それは例外翻訳がうまく使える場所です。データベースを読んでいると仮定される何かがあるとき、その中の奥深いどこかで、もしかしたらMalformedURLExceptionを得るかもしれません。それはおそらくMalformedURLExceptionとして外部に伝播させることは無意味です。下層のメソッドの実装のされ方によって生じた単なる遺物だと考えるのではなく、どのような種類の例外が真にインタフェースの一部であるべきかを考えるほうが良いです。Javaの例外メカニズムでは、例外はその原因(cause)として他の例外への参照を持つことができます。そこで、あなたは新しいIOExceptionを生成し、そのcauseとしてこのMalformedURLExceptionをセットします。そしてあなたはそれらを一緒にまとめます。それは非常に効果的です。

Exception Handling versus the One True Path(例外処理 vs. ひとつの正しい経路)

Bill Venners: What percentage of time do you think people should be spending programming the one true path――the path taken if nothing goes wrong――versus handling all the potential errors?

Bill Venners: 潜在エラーのすべてをハンドリングするのと対比して、何パーセントぐらいを、ひとつの正しい経路*3――何もおかしくならなかった場合の経路――を書くために費やすべきだと思いますか?

James Gosling: It's all over the map. Ideally you should be spending almost all of your time on the one true path. But if you look at various domains, the percentages are different. The worst case would be people doing avionics software. If they spend a few percent of their time working on the one true path, they feel very good about themselves. That's the kind of area where the high nineties percentage of your time is spent dealing with things that could go wrong, and speculating about things that could go wrong. In that area, life is truly dynamic. There are real random number generators up there, with turbulence doing strange things to wing tips and all kinds of weird stuff that may never actually happen.

James Gosling: 場合によります。理想的には、あなたはほとんどすべての時間をひとつの正しい経路(正常系)に費やすべきです。しかし、いろいろなドメインを見るなら、割合は変わってきます。最悪のケースは、航空電子工学ソフトウエアを書く人々でしょう。彼らにとっては、労働時間のほんの数パーセントを単一の正常経路に割くだけでも、ずいぶん気持ちのよいものでしょう。それは、90パーセント台後半の時間が、何かがおかしくなったり、おかしくなることが推測される場合の対応に費やされる領域です。その領域では、人生は本当にダイナミックです。そこには本当の乱数発生器があって、ウイングチップ*4におかしなことをしようとする乱気流や、実際には決して起こらないであろうあらゆる奇妙なことがあります。

Almost as bad as avionics is networking software. When you're trying to write some piece of software that is dealing with something across the network, trying to make that truly reliable can be a lot of work. I've done code that tries to maintain reliable database access, for example, and that can be 90% error handling. You look at most protocol implementations and at some level they're almost all error handling. If you believed everything was perfect all you would do was spew packets. You wouldn't worry about timeouts, flow control negotiations, and any of the other things that go on. Networking is all about how you deal with errors at all various different levels. But when you're in a fairly well-controlled regime like, "Here's a web request, compute the result please," there shouldn't be a whole lot that you're actually worried about.

航空電子工学ソフトウエアとほとんど同じぐらいに悪いのは、ネットワークソフトウエアです。あなたがネットワークをまたがって何かを扱うソフトウエア片を書こうとしたとき、それが真に信頼性があるようにするのは大変な仕事となるでしょう。私はたとえば信頼性のあるデータベースアクセスを維持しようとするコードを書いたことがありますが、90%がエラー処理だったかもしれません。たいていのプロトコル実装を考えてみても、ある意味で、それらはほとんどエラー処理なのです。あらゆるものが完璧だと信じられるようなことにでもなれば、あとはパケットを吐くだけでよくなります。あなたはタイムアウトや、フローコントロールネゴシエーション、その他起こりうることを何も心配しないでしょう。ネットワークは、あなたがさまざまな異なるレベルでどうエラーに対処するかということがすべてです。しかし、あなたが「ここにWebリクエストがあります。結果を計算してください」といったようなよく管理された体制の中にいるとき、あなたが実際に心配することはそんなに多くはないはずです。

Bill Venners: Yeah, I think there's a spectrum. At one end you have pace makers and airplanes. If you don't deal with certain kinds of unexpected situations people can die. At the other end you have one off scripts. I remember one script I wrote that was pulling information out of web pages and putting it into XML files, and the script worked on maybe 90% of the pages I was processing. And that was good enough because it was faster for me to fix the other 10% by hand than to make the script better at dealing with badly formed input files. In that case, there was a system administrator who was quite happy to spend an hour fixing things by hand, because that was cheaper than spending 2 or 3 hours trying to get the script to be more solid.

Bill Venners: はい。私はスペクトラムがあると思います。その片端にはペースメーカーや飛行機があります。もしあなたがある種の予期しない状況に対処しなければ、人が死ぬかもしれません。もう片端には使い捨てのスクリプトがあります。私は、Webページから情報を引っ張り出してXMLファイルに出力するために自分で書いたスクリプトのことをおぼえています。そのスクリプトは、私が処理したページの90%でちゃんと動きました。そして、残りの10%を手で修正するほうが、おかしなフォーマットの入力ファイルを処理するためにスクリプトを直すより早かったので、それは十分によいものでした。このケースでは、手で直すために1時間を費やしても幸せであるシステム管理者がいたわけです。なぜなら、スクリプトをよりsolidにするために、2〜3時間を費やすより安いので。

James Gosling: Right. It all depends on what the consequences of failure are. If you're just extracting information from pages like that and you're a system administrator, the consequences of failure are pretty minor. But if you're writing transaction reconciliation software for some bank, you could find that oh, thirteen billion dollars leaked out of some system because of a bug. I actually had a friend who basically lost thirteen billion dollars in one night because of a bug.

James Gosling: そのとおり。すべては失敗の結果がどうなるかに依存します。もしあなたがそのようにページから情報を引っ張り出そうとしているだけで、かつあなたがシステム管理者だったら、失敗の結果はごく小規模なものです。しかし、もしあなたが、銀行向けのトランザクション調整ソフトウエアを書いているのであれば、あなたは見つけることでしょう――バグのため、システムから漏れた130億ドルとか。私には、バグのため、一晩で130億ドルを失った友人が実際にいたのです。

Bill Venners: Thirteen billion dollars?

Bill Venners: 130億ドル?

James Gosling: Yep. Thirteen billion. They were actually able to reconstruct it from transaction logs, but it was a real big mess. Thirteen billion dollars is real money, so you're actually probably willing to test, willing to spend some time in dealing with handling those exceptions and making things reliable.

James Gosling: そう、130億ドル。彼らはトランザクションログからそれを再構築できましたが、それはまったく大混乱でした。130億ドルは本当のお金ですから、あなたはきっと喜んでテストするでしょうし、例外に対処して高信頼性にするために喜んで時間を費やすことでしょう。

Bill Venners: I have heard a lot of people complain that in practice Java's checked exceptions encourage a lot of empty catch clauses. This empty catch clause problem seems to be more common than exceptions being propagated in throws clauses going all the way up the call stack. The compiler forces a programmer to catch an exception, so they catch it but they don't do anything. Then if the exception is ever thrown, it ends up being swallowed. It is not handled and not propagated. It is lost. Do you think that in a lot of places there's a lack of a culture of programmers wanting to deal with failure, perhaps because in the past they didn't have to deal with failure as much?

Bill Venners: 私は、多くの人が、現実にはJavaの検査例外は空のcatch節を奨励していると不満を言うのを聞きました。この空のcatch節問題は、コールスタックをさかのぼることでthrows節に増殖する例外の問題よりも一般的であるように見えます。コンパイラプログラマに例外をcatchすることを強制するので、彼らはそれをcatchするものの、何もしないのです。そのため、例外が投げられても、結局それは飲み込まれます。それはハンドルされませんし、伝播もしません。それは失われてしまうのです。多くの場所で、失敗に対処しようとするプログラマの文化が欠如している――おそらくは、過去には彼らはそれほど失敗に対処する必要がなかったため――ことについてどう思われますか?

James Gosling: Anytime somebody has an empty catch clause they should have a creepy feeling. There are definitely times when it is actually the correct thing to do, but at least you have to think about it. In Java you can't escape the creepy feeling.

James Gosling: 誰かが空のcatch節を書くときはいつだって、彼らは気持ち悪く感じるべきです。それが実際に正しいことであることもありますが、少なくともあなたはそれについて考えなければなりません。Javaでは、あなたはその気持ち悪さから逃れることができません。

It really is a culture thing. When you go through college and you're doing assignments, they just ask you to code up the one true path. I certainly never experienced a college course where error handling was at all discussed. You come out of college and the only stuff you've had to deal with is the one true path. You get a job working in some IT department's data center, and they're using the software in production runs. If it doesn't work, it's a real problem. All of a sudden there's all this painful stuff that you don't like to do, and you're feeling grumpy about it because this isn't as much fun as just writing clean code.

これはまさに文化の問題です。あなたが大学に通って課題をしているとき、それはあなたにひとつの正しい経路をコード化させます。私は確かに大学でエラー処理についてとにかく議論したコースを経験しませんでした。あなたが大学からでてきて、あなたが対処する必要に迫られたことがあるものは、ひとつの正しい経路だけです。あなたはどこかのIT部署のデータセンターで働く仕事を得て、そこではソフトウエアを生産工程に使っています。それが動かなければ、それは実際の問題になります。突然、あなたがやりたくないすべての苦痛なものが現れます。そして、これは単にクリーンなコードを書くほど面白いことではないので、あなたは不機嫌になります。

There's really nothing a hacker likes more than having an empty editor buffer. You can just start to write code. That's the way university assignments are: here's a problem, just write the code. The real world is much cruftier.

空のエディタのバッファ以上にハッカーが望むものは何もありません。あなたは単にコードを書き始めることができます。それは、大学の課題での方法です――問題がある。コードを書け。実際の世界は、もっと粗雑なものです。

But there's also a spectrum. You talk to people in banks, where large quantities of money get lost if there's a problem. They take failure very seriously. The spookiest folks are the people who have been doing real time software for a long time. I've spent a certain amount of time with that crowd. By and large these folks are very conservative and very careful. A lot of them know what it's like to go visit the family of the deceased and explain the bug to them. There are a number of places that have policies that if a test pilot augers in, then once it's all figured out what happened, the people who engineered the thing that failed have to go explain it to the family. I've actually only met one person who has ever actually had to do that. That would change your attitude about dealing with failure really quickly.

しかしそこにもまたスペクトラムがあります。あなたは銀行の人々と話します。そこでは、もし問題があれば多くのお金が失われます。彼らは失敗をとても真剣に受け止めます。最も神経質な人々は、リアルタイムソフトウエアを長年やっている人々です。私はそういった人々とある程度の時間を過ごしたことがあります。概して、これらの人々は、非常に保守的であり、かつ非常に慎重です。彼らの多くは、遺族を訪問してバグについて彼らに説明することがどんなことであるかを知っています。多くの場所に、テストパイロットが墜落し、何が起きたのかが解明できたら、失敗したものを設計した人がそれについて遺族に説明しに行かなければ行けない、というポリシーがあります。私は、ひとりだけ、実際にそれをしなければならなかった人に会ったことがあります。それは、失敗に対して対処することについてのあなたの態度をあっという間に変えることでしょう。

感想

――そうだよねえ、としか。Goslingがこう言ってくれるなら私はもうなにも言うことはありません。

You can't accidentally say, "I don't care." You have to explicitly say, "I don't care."

特にこのあたりなんか、前回の記事で私が書いたこととそっくりで、わが意を得たりと思ったことですよ。

2010/2/11追記:メールでご指摘をいただきあちこち修正しました。

*1:ここでの「open」はUNIXシステムコールを指していると思います。UNIXシステムコールのopen()は、エラー時、-1を返します。

*2:「plausible deniability」は、「秘書がやったことで、わしは知らん」といったように、地位の高い人間が、地位の低い人間から事を知らされなかった事を理由に、実際は存在する責任を逃れようとすることを意味するそうです参考

*3:one true pathって「正常系」のことですよね。

*4:飛行機の翼の先についている小さな翼。よく考えたら航空電子工学ソフトの話なんだから当たり前じゃないか。…とはいえ訳に自信がないことに変わりなし。