補足

なんというか、先日書いたデザインパターン批判のようなことに対してつっこみをいただいたので補足をして見たい。
言いたかったことは、デザインパターンそのものに対する批判ではなくて、パターンを見つけたときに、どう対処すべきかを考えてみようということ。(ちなみに、デザインパターンに対するこのような意見や考察は、当然新しいものではなく、色々なところで見聞きしたものを言い直しているだけです。)

まず、プログラミングという作業において、繰り返しは「悪」だということ。(DRY原則参照)
そして、パターンというものは本質的に繰り返すものであり、もし人間がプログラミングにおいてパターンを繰り返していることが分かったら、なんらかの抽象化手段(例えば関数、モジュール、ライブラリ、マクロ)を使って、人間がパターンを繰り返さなくても済むように努力するべきではないか、ということである。
パターンというものは、明白に現れる場合と、そうでない場合がある。
例えば、毎日同じパターンでコマンドライン上でlsしてgrepしてcpしているなぁ、よし、シェルスクリプトを書こう!というような場合や、
同じ処理をいろいろなところに書いてしまっているので、サブルーチンとしてまとめよう!という場合は、比較的パターンがわかりやすい例だといえるだろう。
で、すこしだけパターンがわかりにくくなった例として、畳み込み関数を挙げたい。
 整数のリストに対して、すべての和をとる関数と、すべての積をとる関数を別々に書くことを考える。ここではあえて再帰を使わず代入を使って命令的にPythonで書いてみる。

>>> def sum(xs):
	a = 0
	for x in xs:
		a = a + x
	return a

>>> def product(xs):
	a = 1
	for x in xs:
		a = a * x
	return a

>>> sum([1,2,3,4])
10
>>> product([1,2,3,4])
24

上記のsumとproductの定義を見比べると、やはりパターンが見出せる。sumとproductの定義の違いを探すと、
a = "1" OR a = "0"
a "*" x OR a "+" x
であることはすぐわかる。ひとつめの違いは、単純に整数の値としての違いなので、簡単に引数にすることができる。二つ目の違いは、演算子の違いである。もし、演算子を引数として渡すことができる関数の仕組みがあれば、このパターンを関数にすることができる。関数にしてしまえば、同じパターンを人間が何度も書く必要はなくなる。かわりに計算機がおなじ関数を繰り返し実行することになるが、当然計算機が繰り返してくれる分にははOKだ。
で、Pythonでは残念ながら演算子そのものを引数として関数に渡すことはできない。しかし、代わりに関数を引数とすることができる。それを使ってパターンを関数にしてみる。

>>> def myreduce(i, f, xs):
	a = i
	for x in xs:
		a = f(a, x)
	return a

>>> def sum(xs):
	return myreduce(0, lambda x,y:x + y, xs)

>>> def product(xs):
	return myreduce(1, lambda x,y:x * y, xs)

演算子が渡せないので、

>>> def sum(xs):
	return myreduce(0, +, xs)

このように書くことはできない。lambda x,y:x + yと書くのは冗長、つまり
lambda x,y:x * yに対してパターンがみられるのであまり好ましくないが、例えばHaskellだと

foldr op k [] = k
foldr op k (a:x) = op a (foldr op k x)

sum = foldr (+) 0
product = foldr (*) 1

Prelude> sum [1..5]
15
Prelude> product [1..5]
120

こんな感じに書ける。Lisp演算子と関数の区別が無いのでやはり簡潔に書ける。
で、演算子も関数も、ユーザ定義オブジェクトも関数に渡せない言語の例として、具体的な言語の例が思いつかないので、マクロも関数ポインタも使えないc言語のサブセットを仮にc--としよう。このc--言語では、sumとproductに似たようなパターンがあらわれていることに気付いたとしても、それをデザインパターンとして扱い、毎度毎度そのパターンにそってコードを人間が書くことを繰り返さなくてはならないだろう。
つまり、パターンがあらわれたとき、それをうまく抽象化できるかどうかは、使用している言語や、プログラミング手法・パラダイムなどに依存するということだ。逆に、もしパターンが見出されて、そのパターンにそって毎度毎度プログラムを書く以外の方法が無さそうに見えたとしても、そこであきらめるのではなく、どうしたらそのパターンを抽象化することができるか、を模索するべきだと思う。
頻出するパターンを見つけた時は、新しい関数を作るか、新しいライブラリを作るか、新しいフレームワークを作るか、新しいパラダイムとその実装としての言語を作るか、新しいアプリケーションソフトを作ることを考えるべき時だと思う。(フレームワークはいまいちだが。)