設計を型にエンコードするということ
動的型付け vs 静的型漬けのアレでもんにょりしてたのをついったーに放出して会話してたらなんとなく自分なりの考えがまとまったので貼っておく。
……(ファントムタイプとか型安全ビルダーパターンとかで、型レベルにロジックをエンコードした結果、ライブラリ利用者がテストを書くまでもなく適切にライブラリを利用できるようになる、という意味での「静的型でコンパイラは最強のテスティングフレームワーク」という視点があると思う)
— 蒸発プログラマさん (@yuroyoro) 2013年3月11日
@yuroyoro 最初のメジャーなテスティングフレームワークがJUnitなので違和感を感じます。
— ぎゃばんぱみゅぱみゅさん (@ledsun) 2013年3月11日
@ledsun メジャーかそうでないかで言われると反論しようがないですが、捉え方というか視点として、ビジネスロジックを型レベルにエンコードして、テストの手前(コンパイラ)でチェックしようという思想があるという話です。
— 蒸発プログラマさん (@yuroyoro) 2013年3月11日
@ledsun @ledsun 例えば、型安全ビルダーパターンを使えば、ビルダーパターンでのメソッド呼び出し順を型レベルでチェックさせることができるので、そのビルダーを利用者が適切な順序で呼び出しているかコンパイラにチェックさせることができます。
— 蒸発プログラマさん (@yuroyoro) 2013年3月11日
@ledsun さきほどのビルダーパターンの例では、利用者がテストを書いて確認するところを、一足前にコンパイラがチェックしてくれるので、ライブラリの使い方を間違ってしまう心配がなくなります。実例として、ScalaでのMongoDBライブラリのRogueがこのようなことをしています
— 蒸発プログラマさん (@yuroyoro) 2013年3月11日
@yuroyoro なるほどそんな考え方があるんですね。ビルダーパターンはライブラリーやフレームワーク作る人からするとすごくありがたい機能に思えます。一方、すべてのアプリケーションプログラマが使いこなすのは難しそうなので、流行るのかどうか心配です。
— ぎゃばんぱみゅぱみゅさん (@ledsun) 2013年3月11日
@ledsun 現時点では、このような手法はなかなか受け入れられる環境ではないと思いますが、言語やツールが進化して敷居がさがればいいなーと思います。例えば、多相型(Generics)などは色々な言語に取り入れられ認知もされつつあり、この方向での言語の進化は確かにあると感じます
— 蒸発プログラマさん (@yuroyoro) 2013年3月11日
「最後にこの言葉を送る。
guud rack【グッドラック】
俺の好きな言葉だ。」
— 蒸発プログラマさん (@yuroyoro) 2013年3月11日
まとめると
- コンパイラがテストしてくれるように型を書きたい
- 型に対して、データ型のラベル以上の意味(設計の意図とか)を持たせたい
- そうすると、自分以外の人が自分が書いたコードを使うときに、正しい使い方を自分やドキュメントに代わって、コンパイラが教えてくれるようになる
- そういうことが簡単にできるように言語とか進化するといいよね
現実的になんでもかんでもコンパイラにやらせようとすると難しいところもあると思う。
「アカデミックだ」「現場では使えない」とか単に否定するのは簡単だ。
静的な型漬けの言語でコード書いたからって、上記のようにすべてのロジックを型レベルにエンコードすることなど不可能だし、制約が強すぎると感じるかも知れないし、この制約が逆に足かせになる性質のプロダクトがあることもわかっている。
でも、型推論とかGenericsとかは、アカデミックな研究と実用のニーズが相まって、
現実のプログラミング言語に取り入れられつつあるし、
静的な型漬けを好む人達が見据えているプログラミング言語の進化の方向性として、こういう考え方がありますよ、って知って欲しい。