コードを2つに分けて書く - 一つは自分のため、もう一つは顧客のために
はじめに
この記事は、身近なプログラマー仲間に向けて書かれたまとめです。 私的な、身内向けの解説文ではあるのですが、 仕事でプログラムを組む人全般に通じるように書く、つもりです。
主張
私は基本的に Perl プログラマーです。ですが仕事では、 Perl で 1ファイルで全部書けるような小さな案件でも、
のように、2つのプログラムに分けて書いたほうが良いと考えています。 この記事ではその理由を解説します。(この考えは Perl と Zsh の組み合わせ以外にも、応用できます)
どんなコード量・規模を想定した話か分からないと納得できない人もいると思うので、 参考として、この考えに基づいて書いた昔のコードを載せておきます。 (コードの解説はありません。要望があれば書きます) github.com
仕事のコードを2つの層に分けるメリット
1. 適材適所
一つの理由は、言語毎の得意領域の違いです。 例えばファイル名操作やプロセスの単純な起動とデータのやり取りは、少なくとも私にとっては、 Perl よりも Zsh の方が短時間で書け、 かつ動作検証もコマンド行で出来て楽である、といった風に。
ですが、理由はそれだけではありません。
2. 汎用を目指すコードと、汚れ役になるコードをファイル単位で隔離できる
もっと大きな理由は、ファイルを分けることにより、プログラマーとしての自分を納得させるためのコーディングと、 顧客第一でオーバーエンジニアリングを避けるコーディング、 2つのコーディング方針を使い分けることが出来るからです。
言うまでもないことですが、仕事のコードは顧客・案件に特化した定数 (ファイル名・ディレクトリ名・アカウント名・サーバー名…)を扱う必要が有ります。 汎用的なプログラムを書きたいなら、こうした定数を何らかの形で プログラムの外部に追い出す必要が有ります。
早くからプログラムをファイルとして2つに分けておくことにより、
- 『汎用性があるよう、キレイに書きたいコードを入れるファイル』
- プログラマーが納得できる抽象度のコードを書くためのファイル
- 『定数をハードコードして良い、 汚れ役 ファイル』(雑事吸収層 と呼んでいます)
という風に、2つのプログラムで別々のゴール・価値基準を追求できるようになる、という考えです。 一つのプログラムで満たそうとすると無理が出るので、別々のプログラムに分ける、ということです。
脱線しますと、私がこの方針に至った背景には、よく知られたフレーズの一つ↓の影響が大きいように思います。2つの直交した問題領域を扱うなら、間にマッピングをかまさないと、片方に漏れ歪みが出るのは自然な現象ですよね。
『計算機科学のあらゆる問題は別のレベルのインダイレクション(間接参照)で解決できる』
好き>
— hkoba (@hkoba) 2018年3月14日
"All problems in computer science can be solved by another level of indirection," is a famous quote attributed to Butler Lampson, the scientist who in 1972 envisioned the modern personal computer.
Beautiful Code: Another Level of Indirection https://t.co/hRLxSe3HYv
この記事によれば誰が言い出したのかは諸説あるぽいですね>
設定ファイルは無限に拡張され、半端なプログラミング言語に成り果てる。なら最初から…
ここで、定数のハードコードを避けたいだけなら、 yaml や ini, json などの設定ファイルの読み込み機能を提供するだけで十分ではないか? プログラムをもう一つ用意するほどではないのでは?と疑問に思う人も多いかもしれません(要出典)。 これに対する私の意見は、(例え設定ファイル読み込み機能を提供する場合でも) ユーザーに渡す汚れ役プログラムを別途作成したほうが、費用対効果が良い、というものです。
その理由は、
- 本来、設定ファイルは定数を書くためのもの。ロジック・ダイナミックな値を書くために設計されたものではない。
- 顧客の事情にもロジックはあるし、ダイナミックな値を使って記述したいことは沢山有る
- 共通の値(変数にしたい)、条件式と分岐、繰り返し、ワイルドカード・パターン…
- 故に、設定ファイルで無理にロジックを表現しようとすると、あちこちに Ad-Hoc な eval を行う拡張ルールを定める必要が出る。
- それは実質的に、不完全なプログラミング言語を作っているようなもの
- その拡張?が延々と続く…
ここでもう一つの名フレーズが思い出されます。
「十分に複雑なCまたはFortranの プログラムは全て、後付けで、正式な仕様がなく、バグがてんこもりの、 遅い、CommonLispの半分の実装を含んでいる」
(訳はこちらの脚注より)
Greenspun's tenth rule - Wikipedia
http://practical-scheme.net/wiliki/wiliki.cgi/Lisp:GreenspunsTenthRule
あくまで私の解釈ですが、このフレーズが言う後付の出来損ない common lisp というのは、 設定ファイル機能の成れの果てを指しているのではないか、と思うのです。
いずれそうなる定めなら、最初から(チューリング完全な)プログラミング言語を持ち出したほうが良いのでは、と。
最後に
ここまで読んで下さりありがとうございました。
文章を書くのって、本当に時間がかかりますね…