kmizuの日記

プログラミングや形式言語に関係のあることを書いたり書かなかったり。

動的型付き言語は素早くプロジェクトを立ち上げるのに向いており、静的型付き言語は長期間の保守にむいているという仮説

 :誤解されないように最初にこの記事の意図を書いておくと、古典的な静的型付き言語VS.動的型付き言語の論争をするつもりはありません。これまで色々なプロジェクトを観察(風聞も含む)して来たところ、そういう傾向があるのではないかという仮説です。それと、文脈として主にWebアプリケーション開発する時のことを想定しており、それ以外のケースはいったん脇に置いています。WebアプリケーションだとPHP(動的型付き言語)の方が圧倒的に事例多いのではという感想もありそうですが、その辺りを考え出すと話がこんがらがるので、これもいったん脇においています。

 たとえば、色々な事例を見聞きするに、スタートアップ企業において動的型付き言語であるRubyのWebアプリケーションフレームワークであるRuby on RailsRoR)は好まれる傾向にあります。近年のPythonの動向はさておき、未だにRoRの求人がかなり多いのも間違いない。で、何故だろうと考えた時に色々な人から聞くのが「とにかく最低限のアプリケーションを素早く作ることができる」ということなんですね。RoRが出た当初にあった、テンプレートエンジンとの手軽な連携というメリットが今どのくらいあるかはともかく、Webアプリケーションを立ち上げる時、ほとんどのプロジェクトはまずRDBを使うでしょうから、ActiveRecordが標準で備わっているRoRには独特の強みがあるように思います。

 そして、ActiveRecordのような、一見メソッド呼び出しに見えるものがDBアクセスになるような柔軟なライブラリを作りやすいのは、メタプログラミングが容易という部分があるにせよ、動的な型付き言語ならでは(あるいは静的な型が「ない」から)というのがあります。実際、ActiveRecordガリガリに使われたRubyコードに静的な型をつけようとしても(たとえば、Ruby 3のRBSにのっとった型注釈を使っても)かなり苦しい。他にも色々ありますが、静的な型がない言語というよりそれを前提に作られたライブラリやフレームワークは、「短期間にとりあえず成果物を作る」ことに向いているように思えます。

 また、特にそういうプロジェクトの立ち上げ期にはありがちですが、非常に短期間の試行錯誤が必要とされるので、その度に型が変わっていたら(少なくとも現状の(強力な)静的型システムを持つ言語では、都度都度違う型を割り当てる必要がある場面もある)面倒くさくて仕方がない。また、静的型付き言語では実行前に型チェックが走る以上、(傾向として)「ちょっと変えて再実行」はより時間がかかります。つまり、試行錯誤の回数が滅茶苦茶多いような状況では、静的型付き言語は時間がかかりがちと言えそうです。もちろん、立ち上げ期でも静的型付き言語の方が向いている事例(たとえば、金銭のような「厳密な扱い」がとりわけ重要視されるものをよく扱う場合とか、そもそも最初期でもそこまで試行錯誤しなくていい場合は、妙な計算をあらかじめはじくことが出来る静的型付き言語の方が向いている)もあります。

 というわけで、(あくまでも仮説ですが)動的型付き言語は素早く最低限の成果物を作るという点においては静的型付き言語よりは向いているのではないかと。もちろん、プロジェクトメンバーのスキルセットが違ったり、あらかじめ問題の性質がわかっているとか、状況によって揺らぐ部分はいくらでもありますが。

 しかし、RoRを採用した事例で同時に聞くのが「保守するのがとても辛い」という声です。もちろん、どんなプロジェクトであろうとコードを長期間保守するのはしんどいものですが、自分が見たコードでも、「長期間の保守のしんどさ」はRoRを採用した事例でとても多い。繰り返しますが、あくまで例でRoRが悪いといったことを書きたいわけではありません。

 で、なんでRoRのプロジェクトを長期間保守するのがしんどいかと言うと、自分が見た事例も含めると「とにかく、コードを読む手掛かりが少ない」んですよ。たとえば、これは一見メソッド呼び出しに見えるけど、実はDBアクセスじゃないだろうか、とか、このメソッドは状況からするとクラスAのものぽいけど、実は無関係のクラスBのものを呼び出していた、とか、とにかくコードをぱっと見しただけだと手がかりが非常に少ない。

 こういう時に「ドキュメントをきちんと書くべきである」とか「テストをきちんと書くべきである」という反論をよく耳にします。確かに正論ですし、苦しい状況に陥った現場での解決策としては、それしかないとも思います。

 しかし、優秀なプログラマですら納期などの時間制約があればドキュメントをさぼったりあるいは書いても最低限なことはあります。テストだって「きちんとしたテスト」を常に書けるほど人間は完璧じゃないはずです。テスト駆動開発はそういう事を回避するための方法論かもしれませんが、じゃあ「きっちり」テスト駆動開発を実行し続けることは果たして可能なのだろうかと言う疑問は持ちます。テスト駆動開発が悪いといかいう話ではなくて、やっぱり人間はそこまで完璧ではない。

 一方、静的型付き言語であれば*1、少なくとも「引数の型と返り値の型」は明記しなければなりません。もしサボろうものならそもそもプログラムを実行できませんから、いわば「最低限のドキュメント」を強制的に書かされることに近い。この「最低限のドキュメント」がどのくらい役に立つかは立ち位置によって別れると思いますが、DropboxがPythonにほぼ100%型注釈をつけた事例などを考えると、現実的には役に立つと考えざるを得ない。ちなみに、このようなことが可能だったのは、型注釈が機械によってチェックされるという性質によるものであって、「書いた型が間違っている可能性が高い」状況では到底達成ができなかったのではと感じます。

 以上、私の経験に基づく仮説にはなりますが、動的型付き言語はすばやい立ち上げに向くが長期間の保守に向いておらず、静的型付き言語はすばやい立ち上げには向かないものの、長期間の保守にむいているように思えます。

 ただ、くどくはなりますが、論じたいのはあくまで傾向の話です。Rubyを採用している現場でもテストやドキュメントを「きっちり」書いた結果として、保守性の問題が起こっていない現場はあるでしょうし、Javaを採用している現場でもメンバーのスキルセットや性格の問題で「型があるからテストもドキュメントもテキトーでいいや」とばかりに、テストや(型以外の)ドキュメント書きを軽視した結果、悲惨なことになった現場は山ほどあるはずです。個別の言語戦争を煽るのは意図していないことは改めて書いておきます*2

 しかし、人間は本来的に面倒くさい作業を後回しにしがちだし、(本来の意味で)怠惰な人が多いという現実を踏まえると、「素早くプロジェクトを立ち上げたい」時は「型を頻繁に変える」作業は面倒くさいから、結果として動的型付き言語の方が楽な部分はある一方で、その後にきっちりとしたドキュメントを書く必要性が生じても「緊急じゃないしなあ」と面倒くさがるものじゃないかなと。そういう「面倒くさがりな人間の現実」を踏まえて言語を選定することが必要ではないか、と最近は思うようになりました。

 ちなみに、そういう現実を踏まえた時に思うのが、最初から「言語をいずれ置き換える」ことを見越すことです。ただ、「一度作った資産を放棄する」のはやはり人間心理として難しいものです(サンクコストバイアスによるものと言えるかも)。そういった現実まで考えると、「最初は型をつけない」けど「徐々に型をつけることができる」漸進的型付け*3というアプローチはより重要になってくるのかもしれません。特に、サーバーサイド用言語としては「最初から漸進的型付け」な言語はほぼ無い状況ですが、TypeScriptとはまた違った「漸進的型付け」な言語を作るのがいい解のようにも思えます(TypeScriptはJavaScriptとの互換性をある程度維持しなければいけないという制限がある故にデザインがやや歪になってますが、一から設計するのならもっと良い漸進的型付けの言語が作れそうです)。

*1:明示的な型注釈が重要である、がより正確ですが、引数や返り値の型をほぼ完璧に推論してくれる言語であっても、推論結果をファイルに出力する事は可能なので、脇に置いておきます

*2:私も過去にそういう言語戦争に参加していたのだろうという批判はあるでしょう。私が未熟であった故としか言えないですが、今はそういう立場ではないとだけ書いておきます

*3:追記:TSは漸進的型付き言語のひとつですし、Pythonにおけるmypyも広義にはそう言えます。PHPのtype hintがそう言えるかはやや微妙ですが、「漸進的型付けっぽい」くらいは言えるかもしれません。なんでこれを追記したかというと、メジャーな動的型付き言語は部分的に静的型を追加していて既に漸進的型付けに近いアプローチを採用しているというのを当然の前提としてたのですが、多くの人にとって普通の前提ではないことに気づいたからです。なお、Ruby 3に限って言えば漸進的型付けの方向かはやや微妙です。というのは、.rbsという形で型シグネチャを別ファイルに分離する、つまり.rbには変更を加えないという路線がまずあって、その上にsoutaroさん作のsteepのように.rbsとか見て漸進的型付けをするツールがあり、他方でmameさんの型プロファイラのような独特なアプローチもある感じだからです。個人的に型プロファイラがどうなるかは興味深く見守っていますが他の動的型付き言語とは違う方向に舵を切っているのは確かなようです