見出し画像

try&catchは後から書くほうですか?

某月某日

弊社の若いメンバーのコードを一緒にレビューしていて、try&catchをどのレベルに設定してthrowされたエラーをキャッチして、どうやってハンドリングするかについて質問されてアドバイスする機会があった。

try&catchを複数の関数にまたがって書けば、まとまった単位でシンプルなエラー処理を書くことができる(または結果的にそうなる)が、細かい処理単位でtry&catchを設定すれば、より細かなエラー処理を書くことがでくる。

また細かい単位でエラーをキャッチするコードはデバッグの際にすぐにエラーを出している箇所がわかるのでデバッグが捗るという側面もある。

このような話をしているときに、私がどのレベルでtry&catchを設定するかをどう判断しているのか?一般的なルールのようなものがあるのか聞かれた。

「あぁ、そうか、若い人はこういうことも悩みどころなのか!」

と、(上から目線ではなく)、忘れていたものを気づかせてくれたような気がしたのである。

僕も最初に学んだ言語Javaをつかってプログラムを書いていた初心者プログラマーだった頃、try&catchをまとめたほうがよいのか、また変数やパラメーターのnullチェックはどのくらいやればいいのか迷っていた時期があった。

例えばJavaではnullチェックなどはやろうと思えば、すべての関数やインターフェースの入力部分で必要ではないかと感じてしまう。こういうところ全部でやらなければいけないのかなぁ??と若い頃の自分もなっていた。

SwiftやKotlinのようなモダンな言語ではオプショナル変数という便利なものがあって、思わぬnull値によってプログラムがクラッシュすることを完全に回避したプログラムの書き方を提供してくれているが、JavaやC、Javascriptなどの言語ではnullは自分で明示的に確認しないといけない。若いときの僕はJavaを書きながら

if(someVariable != null){

}

といコードをとにかくそこら中に散乱させた後、じゃあ、elseには何を書けばいいんだ?と呆然としていた。

if(someVariable != null){

}else{
    ?????
}

今回、会社の若いメンバーに質問されてこの時の自分を思い出したのであった。


実はこの状態を抜け出す良い考え方がある。

それは、
                          極力try&catchやnullチェックを書かない 
ことである。

ここで言っているのは、最後までtry&catchやnullチェックを書かない、ということではない。

最終的になにか製品を作るまでになった時点では、必要な箇所にtry&catchやnullチェックを書けばよい、が、それまでの時間、例えば

- プログラミングを学習しているとき

- 学んだことを実践するためのサンプル的なプロジェクトを作っている時

- プロトタイプを作っているとき

- 製品開発の初期段階でコア部分だけを試作的につくっているとき

- Web APIやデバイスなど新しいインターフェースに接続するコードを初めて書いてみるとき

などの時間はまず極力、try&catchやnullを外して書いてみてほしい。

そうすると何が起きるかというと、

プログラムがクラッシュする

実はこのプログラムをクラッシュさせることが大事な経験で、プログラムがクラッシュするとJavaのようなある程度の高級言語であればExceptionの内容がずらっとコンソールに表示されるようになっている。

これをみると

- クラッシュがどこで起きたのか

- どういう原因でクラッシュしたのか

がわかるようになっている。

これをしっかり読む習慣を見に付けて欲しい。

たとえばJavaであればnullしか入ってない変数に対して、関数を呼ぶなどのアクセスをしたときはNullPointerExceptionというExceptionがthrowされてプログラムがクラッシュする。

すると、コンソールに吐き出された内容を見ることで、どこでどの変数がnullで、その変数に何をしようとしたときにクラッシュしたのかがわかる。

次に、すぐにこの箇所にtry&catchやnullチェックを入れようとせず、なぜこの変数がnullになったのかを考えてみてほしい。

もしかして自分はこの変数がnullになることは想定していなかったかもしれない。

その変数は、サーバーのAPIから返されたデータかもしれないし、あるデバイスから返されたセンサーの値の一部かもしれない、または自分が作っていた別のUIコンポーネントから渡されるべきユーザーの情報の一部かもしれない。

この変数がもしnullになることを想定していなかったとしたら、次にじゃあなんでnullになったのだろうと考えてみよう。

サーバーのAPIの仕様で、その値はnullになることもある、ということを見逃していただけかもしれないが、サーバーのAPIの方にバグがあって、nullが入ってしまっていたなんてこともある。

デバイスのセンサーからnullが返ってくることもあるかもしれないが、もしかしたら、センサーからデータを読み取る方法が違っていただけかもしれない。

自分の作ったUIコンポーネントからnullが来ているようであればコンポーネントの方のコードを見直すことでnullを渡してこないような連携の仕組みを作れるかもしれない。

このような場合はこの変数がnullになるケースを根本的になくすような改善ができて、try&catchやnullチェックは引き続き入れなくて良いかもしれないのである。

このようにプログラムを少し書いては実行し、クラッシュさせ、原因をみて、なぜnullになったのか、errorがthrowされたのか、を1つ1つみて、その原因のほうを改善できないかを考えて行く。

それを繰り返してプログラムをあるところまで完成させると、

- ここはどうしてもnullが値として入ってくるケースがある

- ここはどうしても想定した値以上の値が来る場合があって、そのときは正常にハンドリングすることはできない

- ここはどうしても既存のライブラリがエラーをthrowするケースがある

という箇所がはっきりと見えてくる。

この時点で初めて、try&catchやnullチェックをいれて、nullの場合は自分がどうしたいのか、エラーがthrowされた場合はどうしたいのかを考えてエラーハンドリングの処理を記述するようにする。

ここまで原因分析をやってきた過程で、もう自分がエラーの場合はどうしたいのかということもはっきりと頭の中で見えているはずなので、エラーハンドリングの処理の書き方に迷うこともなくなっているはずである。

また原因分析で原因の方を改善することが積み重なることで製品の品質も自ずと上がってくる。

このやり方を習慣として常に継続していくと、最終的にはプログラムをクラッシュさせる前から、これは根本原因を潰しておけるものかどうか、どういうものだけtry&catchやnullチェックが不可避なのか、プログラムを書く時点で想像できるようになってくるのである。

若いときにこの"try&catchを極力書かない"方法を自分に課すようになったきっかけがあった。

プログラムを書いていたアルバイト先で、ある社員のコードを見たときに、nullチェックやtry/catchが至るところに張り巡らされているのをみて、その1つ1つを「なぜ、ここでこういうチェックをしているのですか?」と質問してみたことがあった。自分がnullチェックの必要性で悩んでいた時期であり、年上のプログラマーの人の考えを参考にしたいと思ったからだった。
しかしその人からもらった答えは「ここでnullになると困るから」、「ここでエラーがでると止まってしまうから」、という結果に関することばかりだった。
このとき、この人はプログラムが想定外の処理をする場合、どうしてそうなるのかが全くわかっていないんだ、と感じた。
この経験以降、自分はもっとしっかりと原因を理解したいと思うようになり、プログラムをあえて脆弱な状態で走らせて、現象を観察する習慣を身に着けていった。

僕の会社にくる若いエンジニアにも、私がアルバイト先で見たような、臭いものにとりあえず蓋をする、というプログラムを書くのではなく、プログラムを走らせたときの現象を観察して理解を深め、必要な対策を入れ、最後に必要なところだけエラー処理を書けるエンジニアになって欲しいなと思っている。

近年はGitHubフロー、あるいはGitフローをベースにした開発がある種日本的な解釈で浸透したことでPull Request単位で完璧なコードを納めないと行けないという文化が日本のソフトウェア開発の現場で醸造されつつある。
先日↓↓↓で書いたようなMal functioningを楽しむこと

がだんだん許されなくなっていて、
これは、try & catchやnullを省いてプログラムを実行して実験するということを若いエンジニアがやりにくくなっている、ということでもある。

うちの若手エンジニアにはとにかくプログラムを書いて走らせて実験して学んで、という一連のサイクルを経験してほしいので、GitHubフローに沿った開発をしつつも、このサイクルを阻害しないような環境を作ることをいつも考えている。

若い人も、いろいろ大変だと思うけど、try & catchは最後に、くらいの気持ちで、まずは実験して、変な実行結果を楽しんで、そこから学んでいってほしいなと思う。

つづく。





この記事が気に入ったらサポートをしてみませんか?