さあ今度は最初からオブジェクト指向♪

「オブジェクト指向入門」では、従来の手続き型のプログラムをオブジェクト指に直していくアプローチで、オブジェクト指向というのはどんなもんなんだということをご紹介しました。
伝統的なフローチャートから、徐々にオブジェクト指向ぽい図にしていった結果、特に身構えるほどのものではないような感じを受けられたのではないでしょうか…受けられてるといいなあ(^^;

この「オブジェクト指向入門2」では、最初から全体のフローチャートなどはあまり考えずに、それぞれのオブジェクトの関連を探すことからはじめます。
やはり身構える必要はありません。やはりこれも、どおってことないアプローチなんです。

作業の流れ

さて、オブジェクト指向でシステムを考えるときの手法は数多くあり、またそのどれもが「これが最高」というようなものではありません。
一長一短…というか、ケースバイケースで最適な手法は変わります。
私も、もちろんすべての手法をマスターしているはずはありません。
これから実際に作業していきますが、もちろん私が採用している手法が最適とも限りません。一つの例としてご覧ください。

オブジェクト指向のシステム(プログラム)開発の手順として、以下のようなものがあります。

  1. 作る範囲(スコープ)を決める
  2. 実際の動きのパターン(ユースケース)を調べてみる
  3. オブジェクトを探し出して図にする(概念図)
  4. 「人間」と「システム」の動きや係わり合いを明らかにする(システムシーケンス図)
  5. プログラムを考えてユースケースを定義する
  6. プログラムにすることを考えてお互いの振る舞いを定義する(協調図)
  7. プログラムにすることを考えて図にしなおす(クラス図)
  8. 実際にプログラムにする(コード化)
こう書くと面倒くさそうな気もします…。
それは事実でもあります(^^;
やはり開発というのは、プログラムを作るだけではなくて、それに関する準備、そして後始末に手間がかかります。
しかし手順の一つ一つはそう難しいものではありません。

スコープの決定

まず、どの機能までつくるかというようなことを決めます。
スコープデフィニッションとか、あるいは要件定義などと呼ばれる工程です。
どんなことを決めるかというと、じつはシステムによって、あるいは開発者によってある程度の幅があります。
しかし、おおむね、以下のことを決めているようです。
項目 説明
概要 どんなシステムなのか
ターゲット 誰を対象としているのか、どこの会社で使うつもりなのか
目標 このシステムで達成すべき目標はなにか
機能 このシステムの機能はどんなものが必要か
属性 機能に対する必要な属性はなにか

今回、「オブジェクト指向入門」でつかったPOSシステムをそのまま当てはめてみます。
そうすると…


Scopeの定義
概要 とてもプリミティブなPOSシステムの作成
ターゲット 練習用のため特になし
目標 迅速で正確な代金計算を行い、取引の記録を行う
機能 別記
属性 別記
基本的な機能
番号 機能 カテゴリ
R1.1 現在の取引を記録する(購入された商品を記録する) 明白
R1.2 現在の取引の合計金額を、税金も含めて計算する 明白
R1.3 スキャナでバーコードから購入商品の情報を得るか、商品コードを手作業で入力する 明白
R1.4 取引が完了(確定)したら、取引内容を保存する 内部的
R1.5 オペレータはIDとパスワードでログインする 明白
R1.6 ディスクを使用する 内部的
R1.7 商品の説明と価格を表示する 明白
機能における属性
番号 機能 カテゴリ 属性 詳細・制約 カテゴリ

画面形式 クールな画面デザイン 目標
R1.7 商品の説明と価格を表示する 明白 応答時間 最大0.4秒 必須
機能の表の番号と、属性の表の番号は対応しています。
また、機能は一見だぶったものでもとりあえず列挙し、あとでまとめるようにします。

実際には、この「スコープの決定」というのは非常に時間と手間がかかる工程です。
とくに大掛かりなシステムになればなるほど、この工程を入念にやっておかないと後々泣きを見ます。
今回はこんなふうにさらさらっとやってきましたが、実際は、スコープ定義が、欲しいシステムを表しているかを確かめる話し合い(レビューといいます)を何度も行って、スコープを洗練させていきます。

ユースケース

スコープを定義したら、ユースケースというものを調べます。ユースケースは「Use Case」と書き、そのまま「使う、場合」というような意味です…つまり、そのシステムを使うのはどんな場合か、というのをいちいち調べ、そのときにそれぞれのパーツ(あとでオブジェクトになるんですが)はどんな風に振舞うのか、ということを考えるのが、この「ユースケース」という工程です。
ユースケースには、「ハイレベルユースケース」という、非常に基本的な動作を記述したものと、「拡張ユースケース」というある程度詳細までそれをブレイクダウンしたものがあります。

ハイレベルユースケース

ユースケースには一定の書式があります。今回を例にとってみましょう。
Buy Items (商品を購入する)
Actor お客さん、操作員
分類 プライマリ
説明 お客さんは購入しようとする商品をもってレジに行く。
操作員は購入される商品を記録し、支払いを受け取る。
終わったら、お客さんは商品をもってその場を去る。
なーんだ、という声が聞こえてきそうです。そう、あたりまえのことを書いてるだけですよね。
Actorというのは、このユースケースに登場する人物(とは限らないんですが)です。
分類は、補助的なものか、主なものか、あと本質的なものかなどを書きます。ここでは、今回扱うPOSレジではこのユースケースこそが中心ですから、プライマリとしてあるわけです。 これをもう少し詳しくしたのが、拡張ユースケースです。

拡張ユースケース

Buy Items (商品を購入する)というのをもう少し詳しく分析してみましょう。また、購入するために現金と引換えますので、ここでは「Buy Items with Cash (商品を現金で購入する)」ということを定義してみます。
Buy Items with Cash(商品を現金で購入する)
Actor お客さん、操作員
概要 お客さんは購入しようとする商品をもってレジに行く。
操作員は購入される商品を記録し、支払いを受け取る。
終わったら、お客さんは商品をもってその場を去る。
─イベントの順番─
Actorの行動 システムの応答
1 お客さんがレジへ商品を持ってくる。商品は複数ある場合もある。
2 操作員は商品の識別情報を記録する。
同じ商品がある時は、操作員は個数を入力できる。
3 商品の価格を判別し、現在の取引トランザクションに商品情報を追加する。商品の説明を表示し、価格を表示する。
4 商品入力が終了すると操作員はレジに商品入力の完了を通知する。 5 販売金額の合計を計算し、表示する。
6 操作員はお客さんに合計金額を知らせる
7 お客さんは合計金額を現金で支払う。お釣が必要な場合もある。
8 操作員は現金を受け取り、その額を記録する。 9 お客さんへのお釣の金額を表示する。レシートを出力する。
10 操作員はお釣の分の現金を取出す。操作員はお釣とレシートをお客さんへ渡す。 11 完了した取引を保存する。
12 お客さんは購入した商品を持って去る

こんな風に、ハイレベルユースケースでは文章だけで大雑把に記述していたものを、細かく分析するのに使われるのが、この拡張ユースケースです。
これは全部のユースケースに対して必要なわけではなく、特に重要なものや、複雑なものをこのように拡張ユースケースまで分析するのが一般的です。

概念図

概念図というのは、概念モデルを図化したものです。
概念モデルの目的は、取り扱う問題を個別のオブジェクトに、つまり私たちが知っているモノやコトに分類することです。
まずは概念を列挙しましょう。このでいう「概念」は本や分析法によっては「エンティティ」と呼ばれたりします。
いくつかガイドラインがあるのですが、そのうちの一つ、概念のカテゴリリストを紹介します。
うわー、うんざりする。
ええまあそうでしょう。ですからもっと簡単な方法を挙げましょう。
それは「ユースケース内の名詞を列挙する」ということです。
ただ、名詞=概念、という機械的な変換はできません。
ですから、名詞を列挙した後、カテゴリリストと組み合わせて、注意深く、どれを「概念」と取り上げるべきか考えます。
もっとも、概念図の段階では、取り残しがあるよりは多すぎるほうがいいという傾向にありますので、それほど神経質になる必要はないかもしれません。

そうそう、忘れてはいけないのは「概念図」はプログラムの設計図ではないという面です。
これらは現実世界のモノやコトを整理し説明するためのものです。こういう工程を「分析フェーズ」と呼びます。
ですから、プログラムに関係ないと思うことも列挙します。

概念図1:概念だけ

で、上記にしたがってユースケースの中の概念っぽいものを列挙してみましょう。
さてこれを、「概念」としてふさわしいものはなにか、とか、あるいは「これとこれは同じものを含んでいる」とか「これにこれが含まれるな」とか分析します。
この分析は分析者によって多少違いますから、皆さんの考えと私の考えは違うかもしれません。
で、整理した後がこんな感じです。
統合したものもあれば、新しく入れたものもあります。最後の「レジに入力した商品」は新しく追加してみました。
ユースケースで「商品の識別情報を入力する」とありますが、入力された識別情報のリストがこの文章に隠れていますね。
ですのでこの分析で出しました。
商品に関する個々の概念は商品情報に属するとします。
さあこれを、いよいよ概念図(その1:まずは概念のみ)にしてみましょう!

あ、なんですかその沈黙は。
いま、ちょっとむっとしましたね?
でも、ほんとうにここから始めるんです、概念図。
これに、リレーションとか、属性とかをつけていきます。
ちなみにこれはUMLという表現形式で、最近のオブジェクト指向の表現ではかなりポピュラーなものです。
進んでいくにつれ、より「UML」らしい形式になっていきます。
もしかしたら、途中で、UML入門を割り込ませる(別コーナーだろうと思われるので)かもしれません。

概念図2:リレーション

さて、非常に単純な概念図でしたが、それぞれの四角形(オブジェクトといったり、エンティティといったりします。分析手法の違いによります。概念図の段階ではエンティティとしたほうが一般的かもしれません)同士の関係を考えてみましょう。
システムというのは、なんであれ、「何かが何かに働きかけて」動作するものです。これはコンピュータシステムに限らず、すべての「システム=系」と呼ばれるものがそうなっていると思います。
つまり、このオブジェクト間の関係を明確にするということは、現実の世界を、この図にモデル化するということに他なりません。
で、この関係のことを「リレーション」と呼びます。(っていうか、まんま英語です)。
リレーションには、「典型的なもの」と「独自なもの」があります。
典型的なものは、おおむね以下のとおりです。 まあこんなものでしょう。
これらは(概念を拾い上げるときもそうですが)「正解」というものはありません。正しいかどうかというのは、それぞれの視点によって変わってしまうからです。
ですから、「同じ視点で考える」ということが大事です。
また、問題になるのは「正しいかどうか」ではなく「便利かどうか」です。
いくつでもリレーションはかけますし、またいくつでもエンティティを書くこともできます。
どのくらいまでが分析に便利なのかなと考えながら作っていきましょう。

もちろん上であげた関連が全て必要になるわけでもありません。(あ、ちょっと安心しました?(^^;)
概念図を書くに当たって、重要なのは「AはBの一部」と「AはBの中」、そして「AはBに記録される」くらいです。
また、関係を探すより概念を探すほうが重要です。関連を探すのはなかなか面白い作業ですが、できるだけ概念を探すほうに力を傾けてください。
実用性の少ないリレーションで図を覆ってしまうと見難くなりますので、その点も注意してください。
関連には「役割(ロール)」というものが含まれていて、「関連の名前」「多重度」「誘導可能性」というのがあるのですが、とりあえず多重度は文脈によってどんどん変わりますし、誘導可能性とかいう良くわからないものもおいといて、さしあたっては「関連の名前」に気をつけていきましょう。

リレーションの名前

リレーションの名前は、名詞(エンティティ)─リレーション名─名詞(エンティティ)となったときに読みやすいものをつけるのが普通です。
この感じからおわかりになるように、リレーション名は一般的に動詞句になります。
もともとの考案者が英語圏の人たち(高名な人たちですのでUMLを検索すればきっとすぐに出てきます)なので、これは英文の文法をちょっと取り入れています。
このためリレーション名は一般的に英語で(日本のシステムでも!)して、動詞で、頭文字を大文字、二語(toとかwithとかbyとかつくことが多い)以上の場合はハイフン(-)で繋ぎます。
一般的に、図において「上から下に」「左から右に」読まれます。だから、図の上でエンティティをどこに置くかによって、動詞が受身形になったりします。

図が見たいんだよ図が

まあごたくはこの辺にしておきまして、とりあえずいってみましょうか。
えい。

あ、なんだか高度なことしてるっぽい図になってきました。
何度も言うように、こういった図に「絶対の正解」はありません。
見方が違えば図も違います。
また、全ての関連を書く必要はありません。
たとえば「操作員」と「お客さん」は「商品をわたす」とか「挨拶する」とか「顔見知り」とか「初対面」とか「好意を抱いてる」…とか、いろいろな関係を書くこともできますが、あえて入れていません。それをこの図に入れても便利ではないからです。
あと、図の左下、「入力商品」と「商品」の関係が「売ったものを記録(Record-seles-of)↓」となっています。
この矢印はつけてもつけなくてもいいのですが、「商品」が左かつ下にあるような配置になっているので、「受身にすべきかどうか」で悩まないように、つけてもいいことになっています。

概念図3:属性

属性は、ユースケース上のエンティティの「個性」を決めるものだ、といっていいんではないでしょうか。
オブジェクト指向言語に慣れ親しんだ人なら「クラスのデータメンバだろ」と即座に切って棄てるかもしれませんが、それは正しい認識ではありません。(結果として同じことになってもです)。
繰り返しますが、概念図は現実世界のモノやコトを整理したものであり、ソフトウェア上の設計に直接関与するものではないんです。
だから、たとえば、操作員を管理するための操作員番号などはここでは出てきません。
どのくらい多くの属性を探せばいいんだ、という問いの答えには「ユースケースを詳しく説明するために必要なだけの属性」を探してください、という答えが適している…と思います。

単純なほうがいい

属性というのは、基本的に単純であるほうが望ましいといえます。
できるだけ簡単な「型」で構成されるように整理してください。
複雑な「型」や「モノゴト」を属性にするのは(正しくないとまではいいませんが)不便です。
そういう場合は、その属性もエンティティと捉え、属性にするのではなくリレーションで表現したほうがよくないか検討すべきです。

たとえば上のリレーションの時に作った図で言えば、「売上取引」は「入力商品」を属性として持つこともできます。
でも、そうしていないのは、「入力商品」のような複雑であることを暗示させるようなものは、属性として扱うと不便だからです。

属性の型として単純なのは、おおむね以下のとおりです。

で、これ以外のは全部エンティティ…にするとあまりにも概念が多くなり煩雑だったりしてやはり理解するのに不便になるので、一般的に属性としていいんじゃないかという型もあげます。
その他があるんなら何でもありじゃん、とか思う人たくさんいそうです(^^;
が、複雑な概念(=エンティティとなるべきもの)を属性として扱うのは大変に不便です。
その「属性」の型を考えたときに、複雑なデータ構造になるものは「エンティティ」にするべきです。

それってER図と違うの?

エンティティがあり、属性がある。あ、データベース設計におけるER図(エンティティリレーションシップ図)に似ていますね。
でも、違います。
何度でも言います(コピーペースト)が、概念図は現実世界のモノやコトを整理したものであり、ソフトウェア上の設計に直接関与するものではないです。
つまり、概念図におけるエンティティは、外部エンティティーへのキーを持っていません。ER図でいうフォーリンキーは含まれていないことに注意してください。
外部エンティティへのキーを属性として持っているのではなく、外部エンティティとリレーションしているのです。

で、具体的に今回の属性って何

はいはい。まず今回のシステムで、各々のエンティティとして何を把握しなければならないのかを整理してみましょう。
エンティティ 把握する対象
現金支払
  • お釣りを計算するのに、金額が必要です。
釣り
  • 釣りを表現するのに、金額が必要です。
商品情報
  • 画面やレシートに商品名を表示するために、商品名が必要です。
  • 入力商品を元に検索するために商品コードが必要です。
  • 販売した金額の合計を計算するために価格が必要です。
(税金情報はあえて無視します。無税のいい国家だと思ってください…(笑))
売上取引
  • レシートに印字するため、日付と時間が必要です。
入力商品
  • 販売した金額の合計を計算するために個々の量が必要です。

図に記入してみる


まあ大体おわかりかと思いますが、ちょっとだけ説明を。
エンティティが、ただの四角から、線が入った四角、になってます。
これは線の下が属性を意味してます。で「属性名:型」となっています。

もちろん他にも探せば属性はたくさん出てくるでしょう。
でも、「このシステムで必要な属性」はこんなところだと思います。

システムシーケンス図

概念図で取り扱ったのは、エンティティ間の関係、そしてエンティティが何を持っているか、つまり、静的な──タイミングを考慮しないという意味ですが──モノやコトの記述をしてきました。
システムシーケンス図というのは、そのエンティティの振る舞いを定義するもので、動的な──タイミングを考慮した記述になります。
ただの「シーケンス図」ではなく、わざわざ「システムシーケンス図」としていることに注意してください。
その名が示すとおり、これは、「システム」と、「その他のなにか」のやりとりを図にしたものなのです。
分析フェーズの終盤(ほんとはさらに「契約」や「辞書登録」などがありますが今回は割愛します)に位置するこのシステムシーケンス図では、「システムが何をするのか」で「システムと対話するのは誰なのか」が明らかになります。

図を見たほうが早い


というわけでさっさと図にしました。

矢印が、「どっちがどっちに働きかけるか」という方向を表します。(この場合は操作員がシステムに働きかけてます)

矢印の上にある文字は、その働きかけに名前を付けています。そのうしろにあるカッコの中は、働きかけに使われるデータです。このデータは、必須ではありません。

点線は、必須ではないのですがシステム境界です。これより右側はシステムだということを明示したいときに使います。

人形みたいなのが「アクター(Actor)」といいます。じつはこの用語、ユースケースのところで何にも説明しないで話をしてきてます。
考え方としてはそのシナリオの「登場人物」だと思っていただければいいのではないでしょうか。

ユースケースがでてきたところで、上の図の左側にある文章。どこかで見たことがありませんか。
そう、これは拡張ユースケースの文章そのまま持ってきてみました。
ピンときたかたもいらっしゃるかもしれませんが、システムシーケンス図というのは、拡張ユースケースを図にしたものといえます。
だから、当然このシステムシーケンス図を書くには、ユースケースが必須です。
もっとも、ユースケースは全ての基本ですから、この手法でシステム開発を行う際は、何はともあれ(スコープと)ユースケースがありきです。
…でも、それなら、ユースケースだけで構わず、システムシーケンス図なんて書かなくてもいいのではないかと考える方もいらっしゃるでしょう。
そういう考え方もあります。ですが、図を良く見てください。ユースケースの全てが図になっているわけではありません。
システムシーケンス図というのは、アクターとシステムとの対話をあらわしたもので、つまり、システムと対話するものしか登場しないのです。
ここで、システムとしては何をしなければならないのかが判ります。判るように記述します。
反面、どうやって、それをするのか、ということは記述されないのが普通です。

今回はわざと左側にユースケースのテキストを持ってきてみましたが、必ずこれをしなければならないというわけではありません。
むしろシンプルに補足情報を記述したほうがわかりやすい場合が多いです。
#ユースケースから抜き出して記述するということも、もちろんあります。

さあここまでで、とりあえず分析フェーズはひとまず終了としましょう。
次からは設計のフェーズ。
次は、またユースケースです。同じモノやコトを、プログラムを考慮してユースケースにします。
それは「現実的」ユースケースと呼ばれます。ちなみに、最初のユースケースは「本質的」と呼ばれます。
#上のほうで出てきている「手順」、少しづつ変更しています。
#あしからずご了承ください。


設計フェーズへ
Copyright (c) 2000 - 2002 Takao Tamura