null安全を誤解している人達へのメッセージ http://qiita.com/omochimetaru/items/ee29d4c6eb0d78f02b15 を読み、自分の考えとややずれがあったので、せっかくなので久しぶりに記事を書いてみることにします。
私個人としてはnull安全どころかさらに強力な型システムがあったほうが嬉しいですが、記事としては中立のつもりで書きます。
はじめに+まとめ
最も重要な点として、null安全というのは型チェックの延長線上にあるということです。
言ってみればジェネリクスと同じようなもので、型チェックでできることが少し広がって記述が少しだけ煩雑になる代わりにより多くのミスが防げるようになるという機能です。
ただ、null安全は継承やジェネリクスや型クラスなどの型システムの機能の中ではかなり単純な割にメリットが大きいので型チェックが好きな人は学んでおくのが良いと思います。
Go言語ユーザーには「ジェネリクス欲しい」という人と「ジェネリクス不要、このままでいい」という人がいます。
特に、型チェックのためじゃなく速度のためにGoやC++を使っているんだという人にとっては言語機能は少ないほうがよいと考えるのも不思議ではないでしょう。
null安全についても好みの問題ということでいいのではないでしょうか。
PHPやRuby, JavaScript等をそのまま利用する「型チェック自体が不要」だという人にとっては、null安全などどうでもよいことです。というかnullだけ防いだところで何だという感じです。
型好きな人たちがなんかいっとるわーと適当にスルーするのが良いと思います。
参照先の記事の意見に対する自分の考え
意見: Null Object Patternによってnullにまつわる問題は解決する。
きっと「null安全」という言葉がミスリードしてしまったのでしょう。Option
型と呼んだ方がわかりやすいと思います。
この機能の目的は「必ず、あるUserが存在する状況」と「Userは存在するかもしれないし、存在しないかもしれない状況」を区別したいということです。
ヌルぽで死ぬのを避けるのが目的ではないんです。
意見: null安全があっても、ちゃんとやるのを忘れているかもしれないのでは
参照記事の通りですが、ありえないです。うっかりint
に文字列を代入しちゃったぜってくらいありえないことです。
ただ後で触れますが、既存資産との連携でちゃんとやるのをミスるのはあり得る話です。
意見: 文法が難しそう、例えばデフォルト値を書くのはめんどくさそう
意見: Swiftで実用的なWebアプリケーションは作れない。null安全は実用的ではない。
意見: null安全にするためには型推論が必要らしいが、これはコンパイル待ち時間を増やす。生産性が下がるだけだ。
意見: 新しい機能を導入すると理解しない人によって新しいパターンのバグが生み出されるだけだ。null安全には意味がない。
意見: null安全がそんなに素晴らしいなら、その反面高いコストがあるはずだ。生産性が下がるはずだ。
コストに見合わないという意見ですね。わかります。
もしScalaやRustのようにライブラリも含めてnull安全を試せるという環境であれば、間違いなくメリットを感じることでしょう。「もう型チェックなしでは生きられない」と言うプログラマがいるようにもしかしたら「もうnull安全なしには生きられない」という意見に変わるかもしれません。試してみては?
TypeScriptやKotlinのようにnull安全を考慮してないコードと連携するすることが多い環境だと、確かに面倒さが勝るかもしれません。前にKotlinでAndroidアプリを書いたときは結構苦しんだ覚えがあります。
(Kotlinではnon-nullに代入した箇所で動的にnullチェックされるため、引数の?
を付け忘れると実行時に死ぬ)
SwiftでもObjective-Cで書かれたサードパーティーのライブラリをガンガン利用して、自分の書くコードはあまりない状況だとメリットを感じにくいような気がします。
言語の型システムの外の話ですが、静的解析ツールを用いてnullチェックするという話は、本当に好きな人や必要に迫られてる人だけがやればいいと思います。
意見: nullになりうるポインタ変数はよく扱う。私はその変数がnullになる場所、ならない場所を考慮できるし、assertionを書いているからバグもすぐに発見できる。今更特に何も便利にならない。
意見: テストコードを書けばバグはカバーできる。null安全をありがたがっているのは、テストコードが書けない無能プログラマだ。
意見: nullに関してバグがあっても、ちゃんと動作チェックすれば発見して直せる。それに、製品の網羅的な動作チェックはどっちにしたって必要なことだ。null安全には意味がない。
そのまま型チェック必要・不要論とほぼ一緒だと思われます。
好みの問題ですね。
意見: ?.のような機能はRubyにも&.がある。Rubyはnull安全に分類されるはずだ。
型チェックのない言語は比較対象ではありません。
意見: null安全がそんなに素晴らしいなら、すでに普及しているはずだ。普及していないのだから、大したものではないはずだ。
おかげさまで、最近作られた言語はだいたいnull安全なのではないかと思います。
一方で、既存の言語にライブラリの互換性を保ちながら、新しい機能を導入するというのは本当に大変なんです。
JavaやC#では後からジェネリクスが追加されたためイケてないところがあったりしますし、
PHPなんかだと標準ライブラリ内にエラー値を返すものと例外を投げるものが混在していたりします。
意見: Javaがnullを代入できるようにしたのには、理由があるはずだ。だから正しいはずだ。
理由があるのと正しいのは別です。C言語にポインタがあるのも、Javaではポインタがなくなったのも理由があります。たいていはトレードオフでしょう。
Javaは、すべての型が内部的に0
の初期値を持つという設計になってます。
例えばもしnullがないとJavaで new User[100]
とやったときにどうなるでしょう。C++はコンストラクタが100回走りますが、Java設計者はきっとそれを避けたかったでしょう。
今設計しなおすなら配列はプリミティブ型とObject?
だけで他はArrayList<T>
を使うという方針になるのでしょうか。