プログラミングが上達すると、コードの共通部分をプロシージャに切り出すことを覚える。
コードを共通化すれば、共通部分に変更が発生した場合に、修正は一か所で済むので効率的だとされる。
はたして本当にそうだろうか?
私もつい最近まで、コードの共通化は善だと信じていた。
しかし、最近いくつかの機能を備えたプログラムを書く機会があり、この考えに疑念を抱くようになった。
例えば下図のように機能Aと機能Bがそれぞれ別のモジュールに存在し、それぞれ3つのプロシージャで構成されているとしよう。
そして、ProcA-2とProcB-2が多くの点で共通しており、うまくすればひとつのプロシージャに纏めることができる状況を想像してみて欲しい。
実際にまとめるとこのようになる。
以前の私なら、このコードは変更に強くなったと考えていた。
しかし実際にこのような状況を経験してみて、その考えは浅はかだったと反省することになった。
例えば機能Aを変更したいとき、それに合わせて共通プロシージャProcAB-2も変更する必要が生じたとする。
しかしProcAB-2を変更するには、機能Bに悪影響が無いよう慎重に整合性を保つ必要が出てくる。
複数の機能から依存された共通プロシージャは、おいそれと変更できなくなる。
また、これまで単一モジュールで完結していた機能が複数モジュールにまたがることで、モジュールの独立性が弱まり、別プロジェクトへの移植も困難になる。
DLL地獄というのを聞いたことがあるだろうか。様々なアプリケーションが共通DLLに依存しており、ソフトウェアによって依存しているDLLバージョンが異なることで発生するトラブルである。コードの共通化はまさにこれと同じトラブルを招く危険性がある。
私は最近、過度のコード共通化でプロジェクトのあちこちに依存が発生し、そのVBプロジェクトを破綻させてしまった。
今、最初からやり直しているが、心がけていることは極力モジュールの単体完結性を維持することである。ひとつの機能をうまく成し遂げるためにモジュールを作る。モジュール間でコードの重複があっても気にしないこと。それは必要な冗長性だ。
ここまでコード共通化のデメリットを書いてきたが、もちろん正しい共通化にはメリットがある。
私が問題だと思うのは、共通化は善であり、共通化可能だという単純な理由で依存性やプロシージャの独立性を考慮せずに共通化するケースである。
真に汎用的なプロシージャが、たまたま機能Aと機能Bから参照される場合は問題ないと思う。