ObjectSquare [2001 年 3 月号]

[技術情報]


コンサルタントの考えるソフトウェア開発のベストプラクティス


株式会社 オージス総研
オブジェクトテクノロジー・ソリューション部
畑 伸樹



私は普段、主に組み込みシステムを対象にオブジェクト指向によるソフトウェア開発のコンサルティングを行っています。このページでは私のコンサルティングの経験から、私の考える大規模ソフトウェア開発のベストプラクティス(最良の実行原則)を紹介します。



開発方法論(モデリング記法、開発プロセス)

大規模開発を行う際、開発方法論に従って開発を進めることはその導入コストを補ってあまりある効果をもたらします。
OMGでは開発方法論=モデリング記法+開発プロセスと定義しています。

UML

UMLはモデリング記法です。ただし、UMLを用いることで、おのずとある手法による開発を行うことになります。UMLを導入することで、以下のような利点があります。

UMLの参考書籍は

などがあります。

弊社でもUML技術者認定制度を行っています。かんたんUMLを読んだらブロンズレベル、モデリングに慣れたらシルバーレベル試験を受験してみてはいかがでしょう。


RUP(ラショナル統一プロセス)

プロジェクトにおいてソフトウェアシステム(以降、システム)を開発する際には開発プロセスに基づいて行うのが良いでしょう。開発プロセスに基づいて開発を行うことで、先人のソフトウェア開発に対する知恵を利用することができます。また、開発プロセス自体を改善していくことも可能になります。

オブジェクト指向言語を用いて、企業で大規模なソフトウェア開発を行うなら、RUP(ラショナル統一プロセス)をおすすめします。

RUP採用の長所をあげます。

短所は、

RUPの参考書籍は

などがあります。

開発プロセスに関しては、上述した「UMLモデリングのエッセンス」でファウラーさんの知見が述べられていますので参照するとよいでしょう。
オブジェクトの広場でも、過去(2000年2月)にファウラーさん特集を行いました。ぜひ参照してみてください。


XP(エクストリーム・プログラミング)

XPは少人数で行う開発にしか向いていません。大規模なソフトウェア開発には不向きです。しかも経験豊かなで優秀な技術者が過半数を占めていないとうまくいきません。しかし私は、XPはソフトウェア開発プロセスについて革命的ともいえる提案をいくつもしていると思います。RUPで行うプロジェクトにもXPの考え方を取り入れることができると思います。有効に活用しましょう。



〜繰り返し型開発での各作業の紹介〜
以下では繰り返し型開発で行う典型的な作業を紹介します。

設計に入る前に行う作業

要求分析

設計を始める前に、プロジェクトで「何を作るのか」をはっきりさせます。このために、ユースケースを使って要求分析を行います。ユースケースを使うことで、システムに要求される事項をマクロに捕らえることができます。「かんたんUML」などにもユースケースが紹介されていますが、ユースケースの作成は自由度が高すぎるため、実務へ適用する場合に迷うことも少なくありません。

詳しい解説書としては以下のものがあります。


問題領域(ドメイン)の分析

要求分析と並行して、問題領域(ドメイン)を理解するために、概念モデリングと呼ばれる作業を行います。概念モデリングでは、システムが扱う概念をあげていき、それをクラス図で表現してドメインに対する理解を深めます。
このクラス図が設計局面でのクラス図に発展すると主張している書物もあるかも知れませんが、大規模開発においては、クラス設計はアーキテクチャ設計の後に行われるので、私は設計時には概念モデルは参考資料的に使用しています。

概念モデルは以下の本を参考にすると良いでしょう。

概念モデリングもユースケースモデリングと同様に自由度が高い作業であり、どこで作業を完了とするか、などに難しさがあります。だからといってそのような作業を行わない、というのではなく、落しどころを自分なりに考えて、開発に活用するようにしましょう。


ビジネスモデリング

システムの設計に入る前に、ビジネスフローの再設計(Business Process Reengineering)や開発する製品がユーザに求めるワークフローを再設計するのが望ましい場合が多々あります。ユーザや情報システム部やプロセス技術者などのユーザに近い部門と協力して、アクティビティ図などを使って、それらを再検討します。これは大変な作業ですが、作ったシステムが求められているものと違う、ということを避けるために、マンパワーを投入します。



アーキテクチャ設計

アーキテクチャ設計は少数精鋭で行います。この間、アーキテクチャ設計を行わないメンバが手待ちになるようなら、要求仕様をユースケースをもとに詳細化したり、開発標準(開発規則、ガイドライン)などを作成させます。

ユースケースの選択

システムの設計を行う際、まずアーキテクチャの設計を行います。アーキテクチャを設計する際には、まずはアーキテクチャに大きく関わってきそうなユースケースを選択してそれを実現することを目標にアーキテクチャを設計します。
このあたりのことはRUPの本を参照してください。


サブシステム構成の設計

まず、サブシステム構成を設計します。サブシステムとは外部に対してインタフェース(CORBAやCOMのインタフェースやJavaのインタフェースクラスと同義です)を持つソフトウェアシステムの下位部品(モジュール)です。
サブシステム、インタフェースなどの定義はUMLに含まれています。「UMLガイドブック」などを参照してください。

オーソドックスな方法ではサブシステム構成を考える際にはまずレイヤ構成を考え、各レイヤにサブシステムを配置します。
ネットワークのOSIモデル(TCP/IPなどもこのモデルに基づいて設計されている)やWindowsDNAのプレゼンテーション層、ビジネスロジック層、データベース層などもこの考えに基づいています。
それぞれの層が上の層に対して何を隠蔽するかを考えるとうまくレイヤ構成が決められます。例えば、インタフェース層、アプリケーションロジック層(アプリケーションサービス層)、ハードウェア層などが考えられます。

レイヤに対して、垂直分割をパーティションと呼びます。COMやOLEのアーキテクチャブロック図がこの例です。パーティションを設けることで、横方向の不必要な結合を防止してメンテナンス性の高い部品を作ります。

参考文献としては、ランボーさんの「OMT」などがありますが、日本語版は残念ながらトッパンが出版事業をやめたので、現在絶版です。RUPの解説書でもこのあたりについて少し解説されています。
「ソフトウェアアーキテクチャ」にもアーキテクチャパターンが紹介されています。

ツールとしてはRoseなどが使えます。


サブシステムのインタフェース設計

サブシステム構成がだいたい決まったら、サブシステムのインタフェースを設計します。設計したインタフェースで選択したユースケースが実現できるかどうかをシーケンス図を書いて検討します。
シーケンス図はUMLで定義されているので、UMLの入門書などを見てください。


技術課題のクリア(アーキテクチャメカニズム設計)

サブシステム設計に先立って、採用するアーキテクチャが抱える技術的課題の解決を行っておきます。技術的に優れたメンバーが担当します。これを行うことで、サブシステムの担当者に高度な技術が要求されないようにします。サブシステムのインタフェース設計をつめるのと並行して行うと良いでしょう。



サブシステム設計

アーキテクチャ設計で決定されたインタフェースを実現するようにサブシステム内を設計します。この作業は開発メンバーに割り当てると良いでしょう。

クラス設計

クラス設計の最大の目標は、変更に対する強さ(保守性)です。
ヤコブソンさんは「OOSE」の中で、バウンダリ(境界)クラス、コントロール(制御)クラス、エンティティクラスで設計を行うことで保守性が向上できると主張しています。バウンダリクラス(層)がサブシステム外部に対する変更、拡張を担当します。エンティティクラスは現実世界の物や概念が投影されたクラスです。初期のオブジェクト指向(ナイーブなオブジェクト指向)でクラスとして捕らえられていたクラスやER図でのエンティティに相当します。コントロールクラスはエンティティクラスに持たせることができないロジックを保持します。複数のエンティティクラスを扱うアプリケーションロジックなどもここに置くことになるでしょう。コントロールクラスを多重階層にすることも考えられます。

「OOSE」は残念ながらトッパンが出版事業をやめたので、現在絶版です。

保守性に優れたクラス設計を行う際にはバウンダリクラス、コントロールクラス、エンティティクラスだけにこだわることなく、「デザインパターン」なども参考にすると良いと思います。

ややこしい状態を持つクラスに対しては状態図を書いて、設計を行います。状態図は単体テストなどでも使えます。このようなクラスにはStateパターンを使って、それぞれの状態をクラスとして状態の拡張に備えることもできます。
Roseのようなモデリングツールを使えば、モデルからコード生成が行え、さらに、コードとモデルを常に一致させておくことも可能です。


実装

「実装(コーディング)は誰にでもできる。設計(モデリング)こそが大事。」という意見もありますが、「設計だけでは詳細を詰めることはできない。実装も大事だ」、ということがリファクタリングやXPによって指摘されています。「リファクタリング」の2章の中の「リファクタリングの原則−リファクトリングと設計」などで記述されています。

「リファクタリング」では実装と設計を行き来します。

C++の実装スキルの向上には「Effective C++」のような定番本があります。


単体テスト

「リファクタリング」の第4章に実践的な単体テストの入門が書かれています。リファクタリングではリスク主導で、危なそうなところからテストすることが薦められています。テストを自動化し、クラスを修正した時には、繰り返しテストを実施するようにします。(回帰テスト)

より詳しい単体テスト技法は「オブジェクト指向ソフトウェアテスト技法」に書かれています。



システムテスト(ユーザレベルでのテスト)

ユースケースに対してイベントフロー(メインフロー、サブフロー)を作成しますが、これに対して、制御フローテストを実施することができます。システムテストについては、「実践的プログラムテスト入門」などを参照してください。

システムテストで不具合が見つかった場合は、単体テストをすり抜けるバグがあったということなので、単体テストを追加して類似のバグを防止することを「リファクタリング」では薦めています。


まとめ

私の考えるソフトウェア開発のベストプラクティスを紹介しました。特に大規模開発においては開発プロセスは重要になります。大規模開発においては開発の停滞や混乱は大きなコスト増となってしまいます。プロジェクト管理者や開発リーダを務める方は、日々難しい決断を迫られていると思います。先人の知恵や最新のトレンドを知ることは決断を助ける羅針盤として役に立つと思います。




アンケートにご協力お願いいたします
記事の内容を5点満点で評価してください。
1点 2点 3点 4点 5点

© 2001 OGIS-RI Co., Ltd.
HOME HOME TOP オブジェクトの広場 TOP