ソフトウエアの再利用

第8回 ソフトウエアの再利用
オブジェクト指向プログラミング(7)
動的分析(1)
状態(現実)
①信号は「赤である」「青である」という状態
と
その変化があります。
②自動車も「停止中」「前進中」という状態の
変化があります。
③中には、一見まったく変化がなく、状態な
どないように見えるものもあります。
状態(プログラム)
①通常のC言語のプログラミングで考えると、
関数の処理がどのような結果になるか。多
くの場合は、その関数に渡す引数の値に
よって決まります。
状態(オブジェクト指向)
①メンバ関数がどのように動作するかは、引
数だけでなく、その時のインスタンスが
持っているデータメンバにどんな値を格納
するかによって大きく変わります。
状態(結論)
①クラスの場合は、メンバ関数に同じ引数を
与えてコールしても、そのときそのときでメ
ンバデータの値が違えば、それによって結
果が変わる。
状態の管理
状態を管理する方法
「状態遷移図」といいます。
ハレル図ともいいます。
状態の管理
①状態遷移図(例:CDプレーヤー)
再生ボタン
停止中
一時停止ボタン
再生中
停止ボタン
一時停止中
一時停止ボタン
停止ボタン
状態の管理
<図の説明>
①まず最初はCDプレーヤーは停止していま
す。
②そして、再生ボタンを押されるとCDの再生
が始まり、CDプレーヤーは再生中になり
ます。
③再生中で反応するボタンは停止ボタンと
一時停止ボタンです。
状態の管理
④一時停止ボタンが押されると、再生を中断
し、CDプレーヤーは一時停止状態になり
ます。
⑤もう一度、一時停止ボタンを押すと、一時
停止が解除され、再び再生中になります。
⑥一時停止ボタンではなく、停止ボタンを押
すと、再生状態には戻らずに、CDプレー
ヤーは停止します。
状態の管理
状態とは何か
図のそれぞれの四角はCDプレーヤーの1
つの状態を示しています。1つの状態には
必ずその状態に存在している時間があり
ます。逆に、状態から別の状態への移行
には時間がかかりません。
状態の管理
ある出来事をきっかけに、ある状態から別
の状態に移行します。これを「状態が遷移
する」といいます。また、そのきっかけにな
る出来事を「イベント(事象)」といいます。
状態の管理
これが状態遷移図とそれを利用した状態
の管理です。
これによって、あるものの状態が、何をきっ
かけに、どのように移り変わっていくかとい
うことを分析することができます。
状態遷移図のプログラムへの応用
状態の分析は、動的分析の一部です。
主に.cppファイルのプログラムの実際に
動きに反映されます。
クラスがどのような状態を持つか、というこ
とについては、それはクラス自体の静的な
成り立ちに関係してくるので、.hファイル
にも影響があります。
状態遷移図のプログラムへの応用
オブジェクト指向開発では、クラスの内部
の変化を状態としてとらえます。
状態図があるとないのとでは、コーディン
グ、デバッグにかかる時間がまったく違い
ます。
状態遷移図のプログラムへの応用
図では、状態が3つに分かれています。
「停止中」「再生中」「一時停止中」
これをプログラムコードで表すと、そのクラ
スが今どの状態かを示す、1つのデータメ
ンバになります。
状態遷移図のプログラムへの応用
LIST9-1:状態のデータメンバでの実現
#define
#define
#define
STOP
PLAY
PAUSE
0
1
2
class CD_Player // CDプレーヤークラス
{
int state ; // CDプレーヤーの状態を管理しているデータメンバ
// 0:停止中
// 1:再生中
// 2:一時停止中
public:
:
:
};
状態遷移図のプログラムへの応用
次は、イベントです。これはメンバ関数です。
状態遷移図のプログラムへの応用
LIST9-2:状態のメンバ関数での実現
#define
#define
#define
STOP
PLAY
PAUSE
0
1
2
class CD_Player // CDプレーヤークラス
{
int state ; // CDプレーヤーの状態を管理しているデータメンバ
public:
virtual int stop () ;
// 停止ボタン押下メンバ関数
virtual int play () ;
// 再生ボタン押下メンバ関数
virtual int pause () ;
// 一時停止ボタン押下メンバ関数
};
プログラム部の定義
「停止ボタン」例に状態とプログラムのか
かわりを理解する。
注目するべきは、図の中にでてくる「停止
ボタン」のイベントの数、そして位置です。
プログラム部の定義
1つ状態図の中に同じイベントが複数登場
することは非常によくある。
その状態図に記述されている複数の状態
のうち、いくつの状態がそのイベントを受け
ることができるか。
プログラム部の定義
IST9-3:プログラム内での状態エラーのチェック
// 停止イベントが起こったときによばれるメンバ関数
int CD_Player :: stop ()
{
if ( state == STOP )
{
// 停止中に停止ボタンが押された
return -1 ; // エラーコードを返す
}
else
{
// 正常系の処理
:
:
状態の変化の実装
状態の変化をどのように実装するか。
この際に注目するべきことは、イベントに
よって状態が遷移する先、そして、遷移の
元の状態です。
状態の変化の実装
LIST9-4:状態の変化のプログラム内での記述
// 停止イベントが起こったときに呼ばれるメンバ関数
int CD_Player :: stop ()
{
:
// 停止処理を行って成功した場合
:
state = STOP ;
// 状態を停止状態にする
:
:
複雑な状態変化の実現
LIST9-5:複雑な状態変化の実現
// 一時停止ボタンイベントが起こったときに呼ばれるメンバ関数
int CD_Player :: pause ()
{
if ( state == PLAY )
// ボタンが押されたときに
{
// 状態が再生中だったら
:
// 一時停止処理
:
state = PAUSE ;
// 状態を一時停止に
}
else
{
if ( state == PAUSE ) // 状態が一時停止状態だったら
{
:
// 再生処理
:
state = PLAY ;
// 状態を再生に
}
:
:
状態のまとめ
状態図が十分に整備されていればそれを探し当
てるのが容易である。(バグ発生する「状態」を探
し当てること)
分析時に、「状態の数」「イベントの種類」そして、
「そのイベントがどの状態で発生してどの状態に
遷移するか」を把握していれば、状態をプログラ
ムに実装する際に、それは極めてシステマティッ
クに行い、機械的、直接的にプログラムコードに
変換することができます。
状態のまとめ
「再現性がないバグ」が発生する可能性自
体が激減する。