Don't panic!!
この言葉があることは十分に承知しています。
しかし、Golang標準ライブラリでも使っている箇所があります。
しかも、1ヶ所、2ヶ所では無いです。
(一番下にリンクした記事では、ざっくりgrepで、4000ヶ所らしいです。テストが含まれている気がして、正確性には疑問がありますが。。)
おそらく使うべき状況というものが存在するのだと思います。
(そもそも、絶対ダメなら言語仕様に無いはずです。)
なので、十分に見切って使う分には、使ったほうが良いと思うのです。
余談ですが、僕のことを好意的に思っているエンジニアでも、この話をすると引かれることが多いです。。。
使っちゃ駄目なパターン
Golang の defer 文と panic/recover 機構について
上記記事の引用:
- 外部に公開する API はエラーを伝える手段として panic() を使ってはいけない
- 多値の返り値 w/ error インターフェースを使うこと
- panic() はパッケージをまたいで伝搬させることがないようにする
- panic/recover 機構はスタックが深くなるような呼び出しをする際に有用
- 使用することで可読性を向上させることができる
つまり、外部にエラーを伝える手段としては error インターフェースを使うのが正式なやり方で、panic/recover はあくまで内部的に用いるべきもの、ということらしい。
Golangは全体的にエラーを返すやり方で記述されています。
なので、とあるライブラリだけ、panicを使って外部にエラーを返すのは、迷惑すぎるということだと思います。
逆に言えば、内部で使用する分には問題ないということです。
タイトルのWebサーバで階層型アーキテクチャの場合、階層分の if error
が無くなって良いと思うのです。
メリットについて
色々とメリットが多いです。
- エラー時にstacktraceの詳細なものが、必ず取れる
- Golang書いてびっくりしたのが、stacktrace頑張らないと出ないんですよね。。
-
if err != null
の記述が大幅に無くなるので、見通しが良くなる - メソッドチェインが出来るようになる
- エラーのreturn忘れが無くなる
- 1値返すメソッドか?、2値返すメソッドか?、あまり考えなくて良くなる
- 考えることが減るのと、コーディング量が減るので開発が速くなる
- どんなエラーが発生しても、必ず捉えられ後処理を実行できる
- データベースのTransaction、Rollbackとか
エラーのreturn忘れですが、知り合いのエンジニアからLinter使うでしょ?的な話がありました。
( staticcheck などのLinterを使えば指摘してくれます)
ですが、Linter無いと危なくて書けないとか、言語として間違っていると思います。
Golangはおそらく、Webサーバ用に作ってないのでしょうが、panic使えば回避出来るとか、例外的状況にも対応出来る言語だなぁと思います。
システム開発時に重要だと思うこと
僕はシステムは、結果を出してなんぼだと思っています。
大きな会社に居た時に、すごいメンバーがサービスを作って、売上出ないからクローズというのを、よく見かけました。
さらに最近の世の中は、変化が速く、変化よりも速い速度で製品を出せないと、出す頃には古くなっているという自体が起きます。
なので、システム開発に重要なのは、下記の2点になると思います。
* 正しく動作すること
* 速く開発が出来ること
これを考えると、
- Golang
- Webサーバ
- 階層型アーキテクチャ
- panic解禁
というのは、かなり良い構成じゃないかなぁと。
人手不足で納期も短い世の中とあっては、プラクティスは気にしつつも、
結果が出るほうを優先するのが良いと思いますが、どうですかね?
開発に銀の弾丸は無い
よく銀の弾丸は無いと言われます。
そうであれば、
ベストプラクティスも存在しないのでは?
と思います。
現時点で書いたコードは、一年後にエンジニアとしてレベルが上がっているのであれば、レガシーコードに映るはずです。
どうせレガシーになるなら、現時点でチームが納得のいく、ベストを尽くすまでなのかなぁと思います。
(駄目だった場合の責任取るのもチームですし。)
完全に余談ですが、コードレビューの時に自分のコードが指摘されると、腹が立つという人が居るみたいです。
チームのレギュレーションに沿って、機械的にレビューするなら、そんなことにはならないと思うのですが、どうなんですかね?
Javaとかのtry-catch機構に近い
悪手も状況が違えば、善手になりうると思います。
Javaのtry catchは、強制されるのがイケてないだけで、
コードがシンプルになるという意味では、エラー機構として優れていると思います。
そして、それはGolangでも出来ます。
Webサーバのような、DBなどの外部APIの待ち時間が支配的な状況下においては、実行速度の低下も気にもなりませんし。
まとめ
韓国のエンジニアに見せてもらったGolangの本では、堂々と使おうと書いてあるみたいです。
日本の記事を見てみると書いている人がいないので、書いてみました。
(もしかしたら、日本の場合、強烈なマサカリが飛んでくるので怖くて書けないだけかもしれませんが。。)
システム開発は、トレードオフの連続で、記述的に正しいよりは、結果が出るのかどうか?を軸に考えたほうが良いと思います。
2人しかいないチームで実際にpanic使って書いていますが、かなり良くなったと思っています。
もしかしたら後で後悔することになるかもしれないですが、今の所、その兆候は全く無いですし、そんときはそんときで書き直せば良いのだと思います。
ちゃんとテスト書いているから、なんとかなります。
最後に、英語の記事ですが、下記はサンプルコードもありますので、時間があるときにでも見てみてください。