WEBマガジン

「ソースコード品質評価を契機にした品質改善」

2011.04.05 オージス総研  田邉 浩之

1. はじめに

 現在、組み込みソフトウェア開発に関わる多くの現場で、ソースコードの品質評価を実施していただいています。しかし、品質評価した結果をいざ改善に活かそうという際に、うまく進められない現場が多いようです。
 そこで、本稿では品質評価結果を改善に活かす際の考え方を紹介します。
 最初に、問題が混入した開発工程を捉えることの重要性に触れます。
 次に、改善効果が表れる時期を捉えることの重要性について、改善の実例を交えながら説明します。
 最後に、上記2点を明らかにすることで、改善の見通しがつきやすくなることを説明します。

2. 問題が混入した開発工程を捉える

 ソースコード品質評価を実施することで、様々な品質上の問題が明らかになります。
 例えば、ソースコード品質評価ツール「Adqua」では、5つの品質特性(信頼性、効率性、保守性、移植性、再利用性)ごとに評価しますので、どんな品質特性にどんな問題があるかがわかります。従って、プロジェクトが重視する品質特性と評価結果を照らし合わせることで、対処する問題の優先順位を決めることが容易になります。
 しかし、取り組むべき問題がわかっても、その要因がわからなければ根本的な改善はできません。そこで、問題が混入した開発工程を捉える必要が生じます。「ソースコード品質評価でわかる問題なのだから、要因は実装にあるのでは?」と思われる読者の方もいらっしゃるかもしれませんが、実装だけが要因とは限りません。問題によって、要因となる開発工程は異なります。
 それでは、Adquaで明らかになる問題を題材として、問題が混入した開発工程がどのように異なっているかを具体的に見てみましょう。

 Adquaで信頼性の問題として指摘される「値が未設定の自動変数の利用数」というメトリックがあります。これは、関数内で宣言した自動変数に対して初期化や値の代入が行われていない状態(不定値の状態)で利用されている件数を表すものです。宣言時に自動変数を初期化することは、プロジェクトのコーディング規約で定めていることがほとんどです。これは、このメトリックが設計(※本稿では、設計に「方式設計」と「詳細設計」を含むこととします)ではなく実装時にケアすべきものであることを示唆しています。つまり、この問題が表出した場合、その要因は実装にあるといえます。
 次に、Adquaで保守性の問題として指摘される「他クラスから呼ばれる(自クラスの)関数の率」というメトリックがあります。これは、あるクラスのメンバ関数のうち、別のクラスから使用される関数の割合を示すものです。この値が大きいほど、他クラスへの影響度が大きいと判断できます。このようなクラス同士の関係やメンバ関数の可視性は、一般的に設計時に検討されるものです。従って、この問題は、設計時に混入する可能性が高いです。一方、設計で定義していない関係を実装時に追加してしまうことで生じる可能性もあります。つまり、この問題が表出した場合は、設計と実装のどちらか、もしくは両方に要因を求めることができます。問題の中身と設計を比べることで、要因を絞り込んでいくことになります。

 このように、問題の要因が実装のものと設計等の上流工程のものがあることがわかります。そして、実装が要因の問題は、実装の修正のみで改善できる一方、上流工程が要因の問題はその工程以降全てに見直しをかける必要があります。そのため、実装の修正で改善できる場合は改善にかかる時間コストと影響範囲が小さく、上流工程から改善する場合には時間コストと影響範囲が大きくなります。

3. 改善の時間軸を捉える

 ここで、改善前に押さえておくべきもう一つのポイントを紹介します。それは、「改善の時間軸」です。
 一般に改善というと、「今存在する問題に対して今対応する」ことを想定すると思いますが、開発の最中に全ての問題に対応できるとは限りません。だからといって、対応しきれない問題を未来永劫放置して良いわけではありません。そこで、「次の開発プロジェクトで同じ問題を出さないようにする」という将来を見据えた改善が別の選択肢として挙がってきます。
 問題に対して今のプロジェクトで改善することと次以降のプロジェクトで同じ問題を出さないようにすることは、効き目が表れる時間軸が異なるばかりか、その中身も異なります。従って、両者を区別しておくことが重要です。

4. 改善の実例

 ここで、「改善の時間軸」が異なる実装改善プロジェクトの実例を2つ紹介します。
 1つ目のプロジェクトは、現在開発中のソースコード(C++)を品質評価し、実装のみの修正で改善できる問題に対応するものです。問題に対する改善案は以下の通りです。


 <問題のあるコード片(コメントで問題を記述しています)>
001: Msg* pMsg = 0;
002: pMsg = getMessage();
003: int number;  // 自動変数を初期化していないため値が不定値
004: if(pMsg->id == QID) {  // pMsgが0の場合、NULLポインタへの参照となる
005:   number = getQidNumber();
006: }
007: return number;  // numberの値が不定値の状態で返す可能性がある

<提示した改善案>
 ・numberを安全な値で初期化する
 ・pMsgはNULLの可能性があるため、L004の前にNULLでないこと確認する

<改善後のコード片(コメントで改善内容を記述しています)>
001: Msg* pMsg = 0;
002: pMsg = getMessage();
003: int number = 0;  // 自動変数を安全な値で初期化
004: if(pMsg != 0) {  // pMsgを参照前にNULLでないことを確認
005:   if(pMsg->id == QID) {
006:     number = getQidNumber();
007:   }
008: }
009: return number;

 2つ目のプロジェクトは、過去に開発したソースコードを品質評価し、判明した問題の発生を抑えるためにコーディング規約を作るというものです。これにより、過去のプロジェクトをベースに開発する今後のプロジェクトで、過去と同じ問題が生じることを防ぐことが狙いです。
 上記コードのような問題に対しては、以下のような内容をコーディング規約に盛り込むことで、同じ問題の発生を将来のプロジェクトで抑制する効果を期待できます。
 ・自動変数は宣言時に安全な値で初期化する
 ・ポインタを参照するときは、事前にNULLでないことを確認する
 さらに、コーディング規約をチェックリスト化し、実装後にセルフレビューを実施することで、規約をより徹底する運用をお勧めします。

 このように、同じ実装改善プロジェクトであっても「改善の時間軸」が異なれば、改善の中身も異なります。

5. 「問題が混入した開発工程」と「改善の時間軸」による改善施策のまとめ

 以上の内容を踏まえ、「問題が混入した開発工程」と「改善の時間軸」の組み合わせに応じた施策例と特徴をまとめると、以下のようになります。

表 1 「問題が混入した開発工程」と「改善の時間軸」の組み合わせごとの施策例
「問題が混入した開発工程」と「改善の時間軸」の組み合わせごとの施策例果<

 このように、「問題が混入した開発工程」と「改善の時間軸」の組み合わせによって、改善施策は大きく異なります。品質改善に取り組む上で正しい施策を選択するために、「問題が混入した開発工程」と「改善の時間軸」を明確にすることをお勧めします。

6. まとめ

 本記事では、ソースコード品質評価を契機にしたソフトウェア品質改善に取り組む際の考え方を紹介しました。問題が明確になれば、すぐに改善したくなるのがエンジニアの性かもしれませんが、即座に改善するべき問題ばかりとは限りません。また、ソースコードの問題だからソースコードだけを直せば良いとも限りません。
 「問題が混入した開発工程」と、いつ改善させるかという「改善の時間軸」で問題を整理することで、今後の品質改善に見通しをつけてから取り組むことをお勧めします。

*本Webマガジンの内容は執筆者個人の見解に基づいており、株式会社オージス総研およびさくら情報システム株式会社、株式会社宇部情報システムのいずれの見解を示すものでもありません。

『WEBマガジン』に関しては下記よりお気軽にお問い合わせください。