ソフトウェアの計量化
プログラミング評価
プログラムがある言語においてコーディングされた場合に,個々のモジュール内の複雑さを評価する尺度がある. すなわち,各モジュール内のプログラムが簡潔かつ適切に設計されていなければプログラムは複雑化し信頼性や保守性の向上にはつながらない.
このプログラムの簡潔さや適切さを表す尺度として複雑性尺度がある. プログラムの複雑さは,プログラムの作成,検査および保守の工数などに直接関係するため,適切に複雑さを見積もることや評価することは重要である.
プログラムの複雑さは次の3つの異なった観点から評価できる.
- 語彙的複雑性
特定の言語で記述されたプログラムにおけるプログラムを構成する語彙の複雑さである.
- 構造的複雑性
特定の言語で記述されたプログラムにおけるプログラム構造の形式的な複雑さである.
- 意味的複雑性
特定の言語で記述されたプログラムにおけるプログラムの意味的構造の複雑さである.
語彙的複雑性尺度
語彙的複雑さは,プログラムを構成する語彙の種類や数などに着目した尺度である.
構造的複雑性尺度
構造的複雑性尺度は,プログラムの制御構造に着目した複雑性の尺度である.
代表的な尺度には次のものがある.
- Cyclomatic数尺度
Cyclomatic数は,プログラムの制御の流れをグラフに表し,このグラフの構造を基に複雑さを表す方法である [McC76].
1つのプログラムに対して,1つの入口と1つの出口を持つ有向グラフ G = (V, E) を対応づける.グラフの各頂点 u ∈ V は制御がシーケンシャルに流れる連続したコードの集合 (ブロック) を表し,グラフの有向辺 (u, v) ∈ E は頂点 u から頂点 v への制御の流れを表す.グラフの辺が複数出る部分は制御の分岐を示している.
一般に,有向グラフ G が強連結 (どの頂点からも他の任意の頂点に到達可能) であれば,そのグラフに含まれる1次独立な閉路の数 V(G) は
V(G) = e - n + 1
で与えられる.ここで,e は辺の数,n は頂点の数である. プログラムの制御を示すグラフは一般に強連結ではないので,出口から入口に向う仮想的な辺を付け加えて強連結にする.このとき,グラフに含まれる1次独立な閉路の数 V(G) は
V(G) = e - n + 2
となり,これがCyclomatic数と呼ばれる尺度である. 構造化プログラムでは,この値はプログラム中の条件式の数+1であることが知られている.
Cyclomatic数は,モジュール分割の目安としても用いられており,経験的に10以下が望ましいと言われている.また,Cyclomatic数がプログラム内のパス数を表すことから,プログラムのテスト容易性や保守性を評価するのにも用いられる.
- Knot 数尺度
プログラムのブロックに相当する頂点を上から下の方に配置し,2頂点 u,v 間に制御の流れが存在するとき,その2頂点間に有向辺を引く.このようにして得られた制御流れグラフにおいて,辺の交差する数を Knot数尺度と定義する [Wood79].
Knot数は,プログラム内のGOTO文が非構造的に使われる場合のプログラムの複雑性を評価できる尺度である.
- 平均ネストレベル
プログラム内の分岐やループのネストの深さを実行文の数で正規化した尺度で,次の手順で求められる [Zol81].
- 最初の実行文をネストレベル 1 とする.
- ネストレベル n に実行文 A があり,実行文 B が実行文 A の次に連続して実行されるならば,実行文 B のネストレベルを n とする.
- ネストレベル n に実行文 A があり,実行文 B が実行文 A のループあるいは分岐に含まれるならば,実行文 B のネストレベルを n + 1 とする.
- 平均ネストレベル (ANL) を次式により求める.
ANL = Σ{i=1~S} NLi / S
ここで,NLi は実行文 i のネストレベルであり,S は実行文の数である.
複雑性尺度の特性
Weyukerはその論文において,プログラム P に対して |P| をプログラムの複雑さを表す尺度とするとき,この尺度が持つべき性質として以下の9つの特性を挙げている[Wey88].
- P1:(∃ P)(∃ Q) (|P| ≠ |Q|)
この特性は,尺度が意味のある測定量であることを示すものであり,異なる尺度を持つ少なくとも2つのプログラムが存在することを述べている.
- P2:c を正の数とするとき,尺度 c を持つプログラムは有限個存在し得る.
同じ尺度を持つプログラムは有限個しか存在しないことを示している.このことは,ある値の尺度を持つ任意の長さのプログラムは存在しないことを課している.
- P3:|P| = |Q| になるような異なるプログラム P と Q が存在する.
この特性は,尺度が意味のある測定量であることを示すものであり,同じ尺度を持つ複数のプログラムが存在することを述べている.
- P4:(∃ P)(∃ Q) (P ≡ Q and |P| ≠ |Q|)
この特性は,異なった尺度を持つ機能的に等価なプログラムが存在することを示すものである.
- P5:(∀ P)(∀ Q)(|P| ≦ |P ; Q| and |Q| ≦ |P; Q|)
この特性は,尺度の単調性を示すもので,あるプログラムに別のプログラムを付加したプログラムの尺度は,元の2つのプログラムのいずれの尺度よりも大きな値を持つことを表している.
- P6a:(∃ P)(∃ Q)(∃ R) (|P| = |Q| and |P; R| ≠ |Q; R|)
P6b:(∃ P)(∃ Q)(∃ R) (|P| = |Q| and |R; P| ≠ |R; Q|)
等しい尺度を持つ異なるプログラムを他のプログラムの前あるいは後ろにそれぞれ付加してもそれらのプログラムの尺度は同じにはならない.
- P7:Q を P のプログラムの文を入れ換えたプログラムとするとき,|P| ≠ |Q| になるようなプログラム P,Q が存在する.
プログラムの文を入れ換えることは,尺度の値を変える可能性があることを示している.
- P8:P を Q において変数名称を変えたプログラムとするとき,|P| = |Q| である.
変数名称を一様に変えてもプログラムの尺度に影響を与えないことを示すものである.
- P9:(∃ P)(∃ Q) (|P| + |Q| < |P; Q|)
2つのプログラムを結合したプログラムの尺度は,個々のプログラムの尺度の和よりも大きな値の尺度を持ち得る. 2つのプログラムを結合する時,それらの間の何らかのインタラクションが必要になることから尺度の値が増加することがあることを示している.
代表的な尺度について,Weyukerの特性との関係を示すと次の表のようになる.
評価尺度の特性
性質 |
LOC |
CN |
E |
DF |
P1 |
Yes |
Yes |
Yes |
Yes |
P2 |
Yes |
No |
Yes |
No |
P3 |
Yes |
Yes |
Yes |
Yes |
P4 |
Yes |
Yes |
Yes |
Yes |
P5 |
Yes |
Yes |
No |
No |
P6 |
No |
No |
Yes |
Yes |
P7 |
No |
No |
No |
Yes |
P8 |
Yes |
Yes |
Yes |
Yes |
P9 |
No |
No |
Yes |
Yes |
LOC : Statement Count / CN : Cyclomatic Number / E : Effort Measure / DF : Data Flow Complexity
Weyukerの複雑さ尺度が持つべき特性は,必要条件であり十分条件ではない[Che91].
また,これらの特性の中には同時には満足できない性質がある.例えば,性質P5はratio scaleを必要とする尺度を前提としているのに対し,性質P6はratio scaleを排除した尺度である. さらに,これらの特性の多くは従来の手続き的なプログラムに対して適用できるものであり,オブジェクト指向プログラムや人工知能プログラムなどの評価には別の特性を考慮する必要がある.