役割ではなく、それを実行するための状態を考える#
クラスを定義する際にはユーザからの業務要件が基になりますが、それはシステムあるいはプログラム、つまりオブジェクト指向で言えばクラスの役割を規定しているだけです。役割を規定しただけではモノを決められないことは前述の通りです。私たち開発者は、その役割を実現出来るモノはどういう状態であるべきかを考える必要があります。状態はデータ構造によって規定されます。
繰り返しますが、その内部の状態がどうなっているかはクラスを利用する側からはあまり重要ではありません。利用する側からは「何をしてくれるのか?」が重要だからです。
しかし、「それをするためにはどういうデータが必要か?」をクラスの設計者は考える必要があります。
クラスには境界がある#
クラスを設計する際に必要なのはデータ構造を考えることです。データ構造というのは「ひとかたまりとして扱いたい情報」です。AクラスとBクラスを異なるクラスとして定義するということは、Aの情報のかたまりとBの情報のかたまりとの間に境界があるということです。境界がなければ同じクラスでも構わないからです。境界線を引いた上で、境界線の内側にある情報(属性)同士が同じクラスとして扱われるべきです。

処理に着目してクラスを定義すると、上記のような境界線は見つかりません。2つの処理がある場合、それを1つのクラスにしても2つに分けたとしてもいずれでも実装出来てきてしまいます。2つの処理に明確な境界線は引けないからです。
しかしデータ構造の場合は人が認識出来る境界線が上記の図のように必ずあります。
クラスにしてはいけないもの#
実際の設計をする上でクラスを考える際、「何をクラスにすべきか」よりも「何をクラスにしてはいけないのか」を考える方が近道です。クラスにしてはいけないのは次のようなものです。- ファイル送信クラス
- データ受信クラス
- ログ制御クラス
- メッセージ表示クラス
- 従業員管理クラス
動詞になる名詞を持つということはすなわち処理に着目して定義されています。つまりそれは処理を共通化しようとしてクラス化されており、誤っています。オブジェクト指向において共通化すべきなのは処理ではなくデータ構造なのです。
上記の延長線上として、英語の動詞に'er'を付けた名前のクラスも誤りであることが多々あります。
- Controller
- Sender
- Receiver
物と結果がクラス#
それではクラスにすべきものは何でしょうか? システム要件の中に出てくる、- 物
- 結果
【物クラス】#
この種類に分類されるクラスは、実際に存在する物として人間が認識出来るものです。データベースのマスタデータとして分類されるものを多く含みます。- 商品
- 組織
- 顧客
- 発注先会社
- 通貨
- 日付
- 氏名
- 画面上の座標
【結果クラス】#
この種類に分類されるクラスは、人間やシステムが行った結果を記録したものです。商用のシステムの場合は「取引」の結果が中心となります。紙の伝票として書いてあったものは全てこの種類のクラスです。その他に、システムが行った通信の結果を記録したもの(ログ)などもこれに分類されます。データベースのトランザクションデータとして分類されるものを多く含みます。
- 受注伝票
- 発注伝票
- 経理仕訳
- アクセスログ
- 金額
受注伝票で考えてみる#
商品を受注した時の伝票を考えてみます。(受注時のオブジェクト図)
上記図中のオブジェクトをまとめると次のクラス図が考えられます。

このクラス図中では、
- 金額クラスは商品単価の金額値を持つクラス
- 商品単価は「ある特定の日の商品の売り値(金額)」として定義される
- 日付クラスは、受注伝票クラスでも商品単価クラスでも利用される
ところがこのクラス図には問題となる部分があります。商品が受注個数を持つようになっていますが、受注個数は受注のたびに変わるため、商品の一部としてこれを持つのは無理です。正しくは、
- 「商品/受注個数/商品単価」の組合せとなる結果クラスが必要

さらに問題があります。上記クラス図では商品単価を特定できていません(商品単価が複数あり得る)。商品単価は、
- 商品
- 日付
order_classes3.png
アプリケーションクラス#
上記の「物」と「結果」に加えて、アプリケーションプログラムそのものを具現化するクラスが必要です。次の3つがあります。- レイアウトクラス
- プログラムクラス
- メインクラス
【レイアウトクラス】#
- 画面レイアウトクラス
- 帳票レイアウトクラス
帳票レイアウトは出力メディアが様々なのでその時々で異なります。例えばExcelやPDF用のクラスを作成する必要があります。
これらのクラスは「情報の配置図(レイアウト)」であり、「物クラス」の性質を持ちます。
【プログラムクラス】#
- 画面プログラムクラス
- 帳票プログラムクラス
- バッチプログラムクラス
例えば入荷実績登録画面上で登録ボタンが押されると、
- 入荷実績登録プログラムクラスの登録メソッドが呼ばれる
- 画面レイアウトクラスが持つ入力情報を受け取る
- 入荷商品ごとに在庫商品の数量を増加させる
- 入荷予定を消し込む
プログラムクラスはプログラム自身を具現化したものなので、
- プログラムID
- プログラム名称
【メインメクラス】#
アプリケーションが起動される入り口のクラスです。このクラスはメイン関数(メソッド)を持っているだけです。メインは関数にならざるを得ないため、この中での処理はログ出力やエラー時の対応など最低限にとどめ、プログラムクラスのインスタンスに早く委譲するようにすべきです。
メインクラスはアプリケーションプログラム個別に作成する場合と汎用的に一つだけ持つ場合があり得ます。
アプリケーションのクラス構成#
上記で説明したクラスを受注伝票登録画面のアプリケーションとして仕上げる場合、次のような構成になります。
まとめ#
- 中心となるクラスは「物」と「結果」
- 動詞のクラスを作ってはいけない
- クラスを抽出する前にオブジェクト図でまず考えてみる
コラム#
「処理がクラスだ」と思っている開発者が大勢います。そう思っていなくても結果的にそういう実装になっている人も多いのです。クラスを設計する際は、
- どんな情報が必要か?
- どんな状態を持つ必要があるか?
それが出来るようになればきれいな設計に自然に近づきます。
次: 小物クラス
添付ファイルの追加
ログイン済のユーザのみが添付ファイルをアップロード出来ます。
添付ファイル一覧
Kind | Attachment Name | Size | Version | Date Modified | Author | Change note |
---|---|---|---|---|---|---|
png |
amount_class.png | 3.4 kB | 3 | 24-2-2011 00:45 | ytp | |
png |
boader.png | 9.7 kB | 1 | 03-2-2011 01:37 | ytp | |
png |
order_classes.png | 6.6 kB | 5 | 31-12-2011 19:19 | ytp | |
png |
order_classes2.png | 6.9 kB | 4 | 31-12-2011 19:20 | ytp | |
png |
order_classes4.png | 9.9 kB | 2 | 31-12-2011 19:39 | ytp | |
png |
order_objects.png | 11.7 kB | 1 | 21-2-2011 23:06 | ytp |
«
This particular version was published on 09-8-2011 01:55 by ytp.