抽象化のメリット、デメリット

プログラムの良し悪しを決める構成要素としては、以下のものが考えられる。


パフォーマンス(スピード)、メモリ、可読性、汎用性(再利用性)、修正しやすさ、などである。


他にもあるかもしれないが、とりあえず、以上のもので考えてみる。また、パフォーマンスとメモリに関しては、奥が深いし、低レベルな階層の議論になりがちなので、ここでは考えないことにする。


抽象化のメリットとしては、(場合によって)可読性が上がる、汎用性が増す、修正しやすくなるなどである。
デメリットとしては、(場合によって)可読性が下がるということである。


まず、デメリットを考えてみるが、例えば、Pythonのような動的言語で、以下のものを考えてみる。


a = b = [] # リストで初期化
a.append('test') # aに'test'という文字列を追加
print a, b # => ['test'] ['test']

一行目で、aとbを空のリストで初期化している。しかし、aにデータを追加すると、bにも影響が出てしまう。これは、aもbもリファレンス(ポインタ)として扱われていて、同じオブジェクトを指しているからだ。しかし、以下の例、


a = b = 5
a = 3
print a, b # => 3 5

では、aとbが別ものになっている。これは、aとbがリファレンスとしてでなく、値として扱われたからだ。このように、C#で言うところの、「値型」と「参照型」のように、内部の実装を抽象化することにより、同一扱いできるのだが、動作をきちんと理解しないと分かりづらいものになっている。このことから、可読性が下がったと言える。


また、Rubyイテレータのような、以下の例、


a = [1, 2, 3, 4]
a.each { |num|
print num, ' ' # => 1 2 3 4
}

では、慣れれば問題ないが、コードブロックの意味(役割)は、メソッドにより異なるので、内部に実装がかくれていて、分かりづらいと言える。


逆にメリットの方は、ライブラリのメリットなどを考えてもらえば分かるように、可読性や汎用性はもちろん上がる。また、インタフェースをうまく使えば、コードを修正、追加しても既存のコードに影響を与えないようにもできる。
抽象化は、ある意味プログラミング言語の進化の歴史でもあるので、作るものにもよるが、最重要な概念であることは間違いないと思われる。