どうもこたにんです。
同僚とプログラミングについて話している中で、共通化の話題になった。
彼曰く「自分はプログラミングする上で帰納的な作り方をする」とのこと。
なんだかあの会話が忘れられなくて、自分なりに掘り下げて考えてみることにする。
帰納的プログラミング
帰納とは
少しは耳にしたことがある言葉かもしれません。
帰納とはすなわち、いくつかの事例・事実をもとに規則・法則を作ることです。
Wikipediaに良い例えがあるので引用します。
「ネコaはネズミを追いかける」「ネコbはネズミを追いかける」「ネコcはネズミを追いかける」という事例が幾つかあるので、「全てのネコはネズミを追いかける」と結論を下すとしよう。
このように、いくつかのサンプルをもとに、共通の法則を作ります。
帰納は共通化しやすい
これがプログラミングにおいて力を発揮するのが、共通化をしたいとき。
何かの実装をしていく中で、いきなり共通ロジックを組むことってあまりないと思います。
(よっぽど先見の明があるか、強い経験値を持っていない限り)
そうなると、帰納的な作り方をすると、プログラミングはしやすいのかもしれない。
複数のメソッドを書く中で、なんだか似たような処理を書くことが多い。
そうなったときにはじめて、共通化したメソッドを立てる。
これが、帰納的な作り方をするということ。
帰納は蓋然的
ただそこには、落とし穴があります。
帰納法とは、蓋然的なのです。
先述したネコの例え「全てのネコはネズミを追いかける」というもの。
観測されていないだけで、もしかしたらネズミを追いかけないネコもいるかもしれない。
帰納的に導いた法則というものには、例外がはらんでいます。
その完全ではない確からしさ、蓋然的な部分がどうしてもあります。
プログラミングにおいても、それが等しく問題になりえます。
いくつかのメソッドのために共通化しても、新たに生まれたメソッドでは適用できない。
パラメータを増やしたり、処理を増やしたり、しなければいけないかもしれない。
帰納は無駄がない
その蓋然性があってもなお、共通化において無駄がないことが帰納の良いところ。
それが同僚のプログラミングスタイルにもなっているわけで。
たしかに納得だし、スマートだし、リーンだと思う。
演繹的プログラミング
演繹とは
帰納に比べると耳馴染みないかもしれませんが、帰納の反義語です。
演繹とは、前提が正しければ結果は絶対的に正しい、という法則の見出し方。
こちらもWikipediaの例え、というか演繹ですごく有名な例えをば。
このように、前提をつなぎ合わせて、結論づけます。
演繹はインターフェース
演繹とは強く意識してプログラミングに適用することはあまりないと思います。
が、適用できるとしたらインターフェースの部分かなって思う。
間違いなく正しい所作を決めておく。
そこから波及したメソッドは必ず正しい動きを実現する。
そういって正しさを数珠つなぎにしていくことが、演繹たる強みな気がする。
演繹は絶対的
演繹とは、絶対的なものです。
確実に正しい、ということを証明されるものです。
先述したソクラテスの三段論法においても。
「人は必ず死ぬ」「ソクラテスは人である」のどちらの前提も正しいことありきです。
どちらかの前提が破綻してしまえば、途端に結論も破綻してしまいます。
その確実に正しいというところが、演繹で重要になる部分です。
プログラミングにおいても、それが等しく問題になりえます。
いくらインターフェースを書いたところで、それの正しさはどこで担保するのか。
TDDなのかもしれないし、もっと泥臭い手法なのかもしれない。
演繹はスピードが出る
ただしその正しさが本当に担保できているのであれば、演繹はスピードを生む。
それは繋がれた先の物事の見通しが立てやすいから。
ただそこには、それが実は無駄なのか間違ってるのか判断する存在が必要。
というのをアンケート取ってみたんだ
こういった考えの整理ついでに、アンケートを取ってみた。
実装力で絶大な信頼をしている同僚と「共通化する上で必要なのは『帰納』『演繹』どちらなのか」って話をした。帰納的に作るのが無駄なくていいよね。でも演繹的に考えることができるとスピードはでるよね。どっちがいいんだろう?
— こたにん@エンジニア採用など (@Kotanin0) August 17, 2019
約半数には、そもそもこいつが何を言っているのか、が伝わらなかったらしい。
その人達にも、少しでも伝わればいいな。
帰納的プログラミングと演繹的プログラミング。
普段考えることのない軸だと思いますが、考えながら実装してみるのもいいかもです。