2020-11-06

コード共通化するな

プログラミングできる気になった自称中級者は、ソースコード共通パターンが現れると決まって、その処理を関数などに共通化したがる。

しかに、そうすることでソースコードは短くなるし、一見して保守性が上がったような気になるのだが、それは間違った作法から止めろ。

かいこと言っても伝わらない自称プログラマが読んでることを想定して、先に結論簡単に書いておく。

お前は絶対コード共通化するな。

共通化してはいけない理由

なぜコード共通化するのがいけないのか。理由簡単だ。要するに、コードが似ているのは単なる偶然であって、それらは別の処理だからだ。

別の処理だから共通化するのはおかしいし、もし共通化した処理の一方のみ仕様が変わった場合、その修正は他方にも影響してしまう。つまり保守性が下がっている。

たとえば、同じプロジェクトの中に、10%の消費税を加える処理と、10%の金利を加える処理があったとする。この2つの処理はともに元の金額を1.1倍する処理であり、全く同じ処理であるが、共通化してはいけない。

これらを共通化してしまうと、たとえば金利が8%に変更になったとき金利計算の処理だけではなく、消費税計算している箇所すべてを変更しなければならなくなる。

実際のアプリケーションでやりがちなのは複数の処理の「事前処理」「事後処理」などを1つの関数にして、呼び出し毎に細かい挙動引数制御するようなパターンだ。

これは結局、改修を重ねる度に「事前処理」「事後処理」の内容が使用箇所によって全く異なるものとなり、それに対応するために

といった悲惨設計に陥る。

他にも、GUIアプリユーザーの応答を待つDialogクラスなんてものを作って、使用箇所ごとにメッセージボタンに割り当てる処理などを切り替えることがある。

これも間違いなく、プログラムが成長するにつれて破綻する。たとえば、ある場所ダイアログは、表示するメッセージテキスト形式のみではなくなり、脇に画像を表示するかどうかのフラグコンストラクタに渡したり、Dialog継承させて表組みを表示するTableDialogサブクラスを作ったりすることになる。ボタンが「OK」と「キャンセル」の2種類の場合じゃなくなって、表示するボタンの数をコンストラクタに渡したり、ボタンに割り当てる処理をリスト形式で渡したりし出す。

こうして、最初は良い設計に見えたDialogクラスはどんどん複雑になる。こうなった原因は明らかで、本来は異なるもの共通化したからだ。おかしな色気を出さずに、素直に別々に実装しておけばよかったのである

処理に名前をつけろ

プログラミングをする上で「コード共通化する」なんてことは意識しなくていい。それよりもプログラマがすべきことは、処理に適切な名前をつけることだ。そのプログラムにおいて「単なる変数操作」を超えた意味のある処理には名前をつけろ。そして、同じ意味の処理なら同じ関数を使うし、違う処理なら違う関数を使う。それだけだ。コード共通化できるかどうかなんて全く関係ない。

変数関数クラス名前空間等が再利用のための機構だという先入観は一旦捨てろ。それらの真の意義は、「関心の分離」にある。つまり実装隠蔽し、その意図抽象するために存在する。たまに勘違いしてる奴がいるが、別に1回しか使われない関数とか、1行しかない関数はあってもいい。というか、この原則にしたがって設計すると、ほとんどの関数(or メソッド)は数行になる。

上の消費税の例で言えば、「消費税を加える」「金利を加える」処理は、明らかに単なる算術演算以上の意味のある操作から関数化する。そして、それぞれの実装は当初の仕様では奇しくも全く同じになる。消費税を加える箇所では前者の関数を呼ぶし、金利を加える箇所では後者関数を呼ぶ。

これはこう言い換えることもできる。消費税を加える関数を変更するのは、消費税計算処理が変わったときのみであり、金利を加える関数を変更するのは、金利計算処理が変わったときのみである。つまり、すべての関数は、それを変更する理由がただ1つになるように設計しろということだ。

こういうアプローチプログラムを書くと、ソースコードはあたかもそのアプリケーションドメイン特化言語で書かれたかのような見た目になる。

また、一つ一つの関数は小さく、理解やすく、テストデバッグも容易になる。そして、結果として再利用もしやすくなるし、プログラムの変更も容易になる。

  • へー、そうなんだ。

  • 意外とちゃんとした説明でしっくりきた

  • 本当に共通化すべきなのは、もっと小さな単位の処理ということでは。

  • タイトル詐欺乙。共通化を悪いみたいにいうな。 つか、ほぼクラス設計の話をしない時点でおかしい。 なんで関数単位での話しかないの? 継承 と 移譲 の分別、依存の方向などの話を...

  • 共通化が嫌ならアセンブラでも使えば?

記事への反応(ブックマークコメント)

ログイン ユーザー登録
ようこそ ゲスト さん