オブジェクト指向開発:C++プログラミングケース1:仕様の変化


個人開発をしていても、なかなかC++オブジェクト指向パラダイムから恩恵を得ている感覚が湧いてこないかもしれません。
そんなあなたに1つ具体的なケースをご紹介しましょう。

イントロ

システムの中に、何かを制御するような機能があったとしましょう。
クラス図で表現すると以下のようなイメージです。

クラスの責務は、それぞれノートに記載している通りです。
 A:制御指示を出したり、制御情報を管理したりする
 B:対象物を制御している
 C:対象物の状態を取得する
 D:制御対象に出力を指示する
 E:制御情報をユーザーに公開する(GUIとかその辺)

だいぶ抽象化してしまっているので、イメージが湧かないかもしれません。
電気ポットをイメージしてみましょう。
あ、ネーミングがイマイチ・・・
 TemperatureOperator:温度情報を管理する
 TemperatureController:水の温度を制御する
 TemperatureAccessor:温度センサから水の温度を取得する
 Heater:ヒーターにかける電圧を指示する
 TemperatureInformation:水の温度を何度にしているかディスプレイに表示する

仕様の変化

仕様とは常に変化していくものです。
それに応じてソフトウェアも変化していきます。

例えば「温度センサから取得するデータは、10secの単純移動平均にしてほしい」と要求されたとしましょう。
この場合どのような対応が求められるでしょうか?

そうですね、温度センサから取得してTemperatureControllerに温度データを渡す前に、内部で10secの単純移動平均をかけるようなクラスがあればいいですね。
既にTemperatureControllerが温度データを取得するためのI/Fクラスが存在するわけですから
、その派生クラス(実現クラス、具象クラス)としてnewすればいいことになります。

TemperatureController.cpp
    // Instantiate. 
    temperatureAccessor_ = new TemperatureSimpleMovingAverage;

    // get temperature data. 
    if(NULL != temperatureAccessor_)
    {
        currentTemperature_ = temperatureAccessor_->getTemperature();
    }
TemperatureController.h
private:
    ITemperatureAccessor* temperatureAccessor_;

TemperatureControllerからすれば、取得した温度データが移動平均をかけたものかどうかなんて知りません。
温度センサから取得した温度に3度(3°C)足したデータをTemperatureControllerが知らずに取得しているかも知れません。

仕様の変化がこれくらいであれば、生成されるインスタンスのクラスが変わるだけです。
I/Fクラスの派生クラスとしては、以下が存在していて、newする箇所だけ変更すればいいですね。
 TemperatureAccessor
 TemperatureSimpleMovingAverage
 TemperatureKatteniHosei

インスタンス生成時に、どのクラスのインスタンスなのかconfigurationファイルで設定できるようにすれば、コードの変更すらありません。
いやー、ありがたい。

というわけで、変化に強いソフトウェアを開発するためにオブジェクト指向が有効なんですね。
まだまだ責務がどうだとか話に出せていないので、具体的なケースをもとにまた執筆します。

※「こういう考え方だぞ、間違えんなよ」とか「クラス図イケてないよ」とかコメント大歓迎!