抽象化に関して

プログラムのコードを抽象化するという意味を考えてみる。まず、プログラムコードの構成要素として、以下の3つが存在する。

  • 表記(interface)
  • 実装(implementation)
  • 機能、意味(semantics)


抽象化するとは、表記が1つで、実装が複数(の可能性のあるよう)にするということである。別の言い方をすれば、表記を決めて、実装は何でもよくて、しかし、意味は「あるもの」を想定しているということである。


抽象化には、データの抽象化と処理の抽象化があるが、パターンが色々あり奥が深い。例えば、以下のものは、抽象化の例である。

・実体オブジェクトとポインタで指されたオブジェクトを同一扱い ⇒ 扱い方を実装で隠す
カプセル化 ⇒ 実装詳細を隠す
・物理モデルと仮想モデル ⇒ 物理モデルを複数想定し、扱いは仮想的に
・ラッパー ⇒ インタフェースを交換する(アダプタ)


また、例えば、Pythonなどの動的言語では、型が抽象化されているが、サプライヤ側の関数に渡す引数は、「ある意味を持つもの」が渡されることを想定している。
つまり、不正なデータが渡される可能性もある訳で、以下のように対処すべきだと分かる。


ある渡されたデータが、サプライヤ側の思惑として、不正だった場合、
①副作用なしで、言語側で自動的に例外を投げてくれる場合は、サプライヤ側の処理では何もしない。
②副作用があったり、例外が自動的に投げられない場合、サプライヤ側で、「うまく」対処する。

ここで、「うまく」と書いたのは、例外を投げたり、キャストしたり、ifなどで分岐したり、色々対処方法があるからだ。
例えば、以下の例を見てみよう。


def calc(a, b):
# cは、floatを想定
c = a / b
return c

print calc(5, 2) # 2となる(間違い!)

この場合、以下のようにすればOK。



def calc(a, b):
c = float(a) / b
return c

print calc(5, 2) # 2.5となる(OK!)

クライアントから不正なデータが渡されても例外を投げてくれないので、サプライヤ側で対処している。