[ホームへ戻る] [前へ] [上へ] [次へ]

2.共通化・正規化

第二の基本は、「共通化」「正規化」です。

共通化は、同じものは一つにまとめることです。正規化とは、データの冗長性を排除し、データの一貫性と整合性を持ったデータ構造にする手法です。通常、データモデルにおいて用いられますが、ここでは便利な言葉なので、処理に対しても用いています。

なぜ、共通化が重要なのかというと、重複をなくすことができるからです。処理やデータに重複があるというのは、物事が整理されず、単純なものが複雑に見え、理解しづらくなります。一緒にしてしまえば一回追えばすむものを、両方を見なければならなくなります。

そして、1つにまとめられていれば、変更は一箇所で済みます。重複があると、複数直さなければならないのです。そして、もし重複があって、片方を直し忘れたりすることがあると、不整合が起きます。たとえば、生年月日を管理していてある箇所では西暦で保存し、別の箇所で同じものを和暦で保存していて、片方を修正してもう片方を修正し忘れると、整合性が取れなくなってしまうのです。

この辺の、重複をなくし、整合性を取る、ということを徹底して推し進めたものが、RDBの正規化の理論です。RDBは単純な表で構成されますが、その内容は奥深いものです。

その要点は、同じものは二度と書かない、ということです。情報の元のみを保存し、派生して導かれる情報も保存しないようにすることです。そのためには、情報を整理し、唯一のものに還元していくことです。また他と区別されるユニークなものを発見していくことが大切です。

RDBに格納するのは具体的な値なので、ソースの正規化というのは若干語弊があるかもしれませんが、同じぐらいの厳密さでソースを記述すると、無駄のないソースが書けるでしょう。

分類と共通化

分類は物事の違いを見出して区分すること、共通化は物事の同一性を見出してまとめることで、表裏一体の関係にあるともいえます。そして同一性を見出して、そこにラベルを貼ることが抽象化です。抽象化とはまとめることとも言えます。抽象化については次章で述べます。便宜上三つに分けていますが、これらは同じことということもできます。抽象化ができなければ、物事の違いを見出して部類することはできません。

共通化と差分

共通項を括り出した際、共通の部分と違いの部分(=差分)があります。差分は、共通のものに対して個々で異なる部分のことです。差分というのも重要です。例えば、共通化を行った結果、条件によって一部分だけ処理を変えたい場合が出てくきます。例えば、ソースのあちこちで使われている円周率を共通化して、3.14に統一したとしましょう。ところが、場合によっては、3.14以外を使いたいケースが出てきます。このとき、差分の考え方を導入する必要があります。

この共通化と差分、これをどのように作り上げていくかが、設計の肝と言えます。綺麗にできたプログラムは、この共通化と差分が適切に行われています。

逆によくないプログラムでは、あちこちに同じような処理があり、メソッドが異常に長くコピーアンドペーストが多用されたりします。同じ処理は共通化してまとめます。差分はどうするかというと、if文を使って条件の違いに応じて処理を分けます。ただこれだとあちこちにif文が存在することになりわかりにくくなります。オブジェクト指向を使うと、if文やswitch文は使わずに、継承を使ってサブクラスに実装するようにすることで、すっきりした形にします。もちろんその差分は、何の規約もなく機能を共通部分に追加したのでは統制が取れなくなるので、差分の部分を定型化します。共通化は継承で行い、差異化はポリモーフィズムで行うことになります。

共通化は、修正に強いのですが、共通化したものを使う側から共通部品への依存性が発生します。抽象化は、追加に強く、疎結合で依存性を弱くします。

1.メソッドの共通化

実際の実装では、各クラスで同じメソッドを作りたい場合、各クラスで別々に作るのではなく、別のクラスに一つだけそのメソッドを作り、各々のクラスすべてがそのメソッドを呼び出す形にします。もしそのメソッドが、同じ種類のクラスからのみ呼ばれる場合は、それらのクラスの親クラスに実装し、様々なクラスから使用する場合は、別個の独立したクラスに作ります。

2.定数の共通化

定数を別々に設定するのではなく、共通して設定し、皆同じものを読むようにします。その場合、親クラスに設定する方法と、全クラスに共通の定数クラスを作って設定する方法とがあります。

3.インターフェースの共通化

あるクラス群に対してアクセスするインターフェースを統一します。こうすることで、規格が統一され、外からは同じインターフェースでアクセスすればよくなります。これは、処理は異なっても、要求されるものが共通している場合に取る方法です。例えば、図形クラスがあって、どれも面積を返すメソッドを持つ場合、メソッド名をgetArea()として、統一するのです。これは1のメソッドの共通化とは逆に、共通化させてインターフェースを統一させるのです。

共通化部品

言語に付属のAPIには共通して使われるメソッド・クラス・パッケージが収められています。そういうAPIは、無償あるいは有償で他企業/団体が提供しているものもあるし、自社で作成したものもあるし、そのプロジェクトで作成したものもあります。共通化して使われる部品は、モジュール、ライブラリ、あるいはコンポーネントと呼ばれたりします。コンポーネントとは、いくつかのメソッドやクラスを集めてパッケージ化したもので、特に再利用を目的として作られます。JavaではBeanという名前でコンポーネントを提供します。Beanとは豆という意味ですが、小さい粒で部品を提供し、Beanをかき集めれば簡単にアプリケーションが作れてしまうという意図があります。

こういう部品を利用すると、新たに自分でロジックを組む必要がないため、工数の削減になります。また、プロジェクト内で同じものを使うことにより共通化を図ることができます。そして多くの人が利用していることからテスト済みで信頼性の高いものとなります。また、部品として切り離されているので、利用する側と疎結合となって、メンテナンス製にも優れています。

言語が登場した初期はライブラリが少ないので、当然あってもよさそうなユーティリティがなかったりするものです。そうするとそれを自作し、その後それを使いまわすことになります。しばらくすると言語のAPIに付属になったり、オープンコミュニティが洗練したものを公開したりして、自作のものは役目を終えます。有償で売り出していたとしても不要になります。

ただし、粒度が大きくなると、できることも多くなり、自分でコーディングする必要がなくなる一方、その使い方を覚えるのに時間を取られ、カスタマイズにも工数がかかります。いざそのコンポーネントの制約を超えようとすると、かなり遠回りなことをしたり、ソースを改変したりしてかえって時間がかかります。バグがあった場合にはさらに大変なことになります。この傾向は粒度が大きくなるほど大きくなるのです。





この内容についてご意見をください

 
   役に立った    まあまあ    つまらない    難しい    疑問がある

コメント(質問・指摘・要望なんでもどうぞ)
  
メールアドレス: 

  

Copyright Happie All rights reserved. Last Update: 2004.08.31