maybe daily dev notes

私の開発日誌

帰納的プログラミング

定義

プログラムに変更Xを加えるとき、類似の機能A,B,Cの実装を確認し、その共通部分から、変更Xに必要な実装を導くことがあります。

この一連の作業を、この記事では帰納的プログラミングと呼びます。

帰納(きのう、英: Induction、希: επαγωγή(エパゴーゲー))とは、個別的・特殊的な事例から一般的・普遍的な規則・法則を見出そうとする論理的推論の方法のこと。 出典: Wikipedia

帰納的プログラミングの例

このコミット帰納的プログラミングにより作成されました。

github.com

帰納する際は、次のコミットを参考にしています。

MDEV-28007 Deprecate Spider plugin variables regarding statistics per… · MariaDB/server@f31642e · GitHub

MDEV-28297 Deprecate spider_internal_offset · MariaDB/server@1866fb0 · GitHub

MDEV-27981 Deprecate spider_internal_limit · MariaDB/server@e87c710 · GitHub

帰納的プログラミングの良いところ

帰納的プログラミングを用いることで、開発者は対象のシステム・コードベースに対する知識をほとんど持たない場合でも正しそうな実装をすることができます。そして、知識を取得するコストを掛ける必要がないので、作業スピードも比較的速いです。

これはYAGNI原則に従っていると言えるかもしれません。ある作業が実際に必要になるまでは実行を遅延させることで、将来の不確定さに対するコストを最適化する考え方です。

上の例で言えば、作業者はMariaDBに関する周辺知識を習得するコストを将来に遅延させ、必要最小限のコストでPRを作成したのです。今回は間違いなく良く機能した例でしょう。

一方で、私の過去を振り返ると、必ずしもこれに頼りすぎるのは良くないと思うことがあります。次のセクションでまとめます。

帰納的プログラミングの欠点

帰納的プログラミングが悪く機能する場合も考えられます。この方法の最大の欠点は、既存のコードのパターンから抜け出せないということです。

すべての機能が、帰納プログラミングで既存のコードをコピペしたようなパターンで実装されていったとしましょう。この時、実はこの繰り返しパターンは抽出して共通化すべきだったかもしれません。DRY原則を常に実践する必要は一般的にありませんが、メンテナンス性やコードのアーキテクチャを考えると共通化すべき場面はやはり存在します。帰納的プログラミングを行使して他の方法を検討する手間を省いている場合、このような可能性を見逃すことになります。

あるいは、ある日既存のコードを大規模にリファクタすることになったとしましょう。全体最適なリファクタをするためには、変更対象の箇所に関する知識のみならず、コードベースに対する広範な知識が求められることがしばしばです。 これまで帰納的プログラミングを行使して必要以上の知識習得を遅延してきた場合、この局面になって初めて多くの知識を習得する必要が生じるのです。そうなると、果たして今回のリファクタタスクはいつものスピードで達成可能でしょうか。

帰納的プログラミングに過度に頼ることは、上記のようなリスクをはらんでいます。

欠点を回避するために

帰納的プログラミングで素早くタスクを終えられるのは良いことです。一方で、いつも必要最小限の知識を学ぶだけだと、今後のより高度なタスクに立ち向かえないリスクもあります。

このリスクを回避するためには、その時のタスク遂行には必要ではない周辺知識を学ぶ時間を意識して確保すると良いでしょう。チリも積もれば山になります。個々のタスクで積み上げた知識は、いずれより難しいタスクに立ち向かうときに効果を発揮するに違いありません。

あるいはタスクの割り振り方が非常に優れている場合は、常にタスク遂行に最小限の知識を学んでいるだけでも、順当にステップアップできる場合があります。信頼できるメンターがいる場合は、これに乗っかってしまうのも良いでしょう。*1

まとめ

帰納的プログラミングという言葉を定義し、その良し悪しを考えました。 簡単なタスクだからといってすぐに完了させてしまうよりは、あえて寄り道してみるのも大事かもしれません。

*1:今回のMariaDBのケースもこれに当てはまる気がしています。