保守性指標の確立

COBOLアプリケーションの保守性指標の確立

保守性指数(MI)は、ソフトウェア品質測定において最も広く用いられている複合指標の一つです。コードのサイズ、複雑さ、ボリュームという3つの構造的特性を、コードの変更の難易度を予測する単一の数値スコアに集約します。現代のプログラミング言語では、計算式、閾値、ツールは確立されています。しかし、COBOLの場合は状況がより複雑で、多くのチームは汎用的な計算式をそのまま適用するか、あるいはスコアが開発者の実際の経験と一致しないように見えるため、定量的な測定を完全に放棄しています。

どちらのアプローチも誤解を招く結果を生み出します。COBOLの構文コンテキストにおける構成要素の動作を理解せずに標準的なMI式をCOBOLに適用すると、高品質なプログラムがぎりぎりのレベルで、低品質なプログラムが許容範囲内に見えてしまうような、体系的に偏ったスコアが生成されます。測定を完全に放棄すると、モダナイゼーションに関する意思決定は、ビジネス関係者に対して正当化できる定量的な根拠を欠き、数千ものプログラムからなるポートフォリオに対して改善作業の優先順位付けを行うことができません。

COBOLのメトリクス全体像を把握する

SMART TS XL COBOLプログラムを、複雑さ、ファンイン、およびJCL依存関係の深さに基づいて同時にランク付けします。

詳細情報

正しいアプローチは、MI式がCOBOLにおいて具体的に何を測定しているのか、品質を過小評価または過大評価する箇所はどこか、COBOL特有の盲点を補うための補助的な指標は何か、そして最新の言語コードベースから導き出された一般的なベンチマークではなく、実際のポートフォリオに基づいてしきい値を調整する方法を理解することです。このガイドでは、これら4つの項目すべてを網羅し、COBOL MIプログラムを実装するための十分な技術的深みと、近代化の意思決定に活用するための実践的なガイダンスを提供します。

具体的な仕組みに入る前に、最後に一点だけ補足しておきます。保守性指数(MI)は、様々な指標を組み合わせることで、プロジェクトの各セクションにおける相対的な保守負担を包括的に把握しようとするものです。COBOLポートフォリオにとって、このような包括的な視点が重要なのは、単一の指標では全体像を捉えきれないからです。MIは出発点であり、全てを網羅するものではありませんが、まさに適切な出発点と言えるでしょう。

COBOLにおいて保守性測定が現代言語よりも重要な理由

2年前に作成され、十分にテストされ、作成チームによって保守されているJavaまたはPythonコードベースの保守性を測定することは、有用な情報を提供するものの、緊急を要することはめったにありません。コードは作成者にとって読みやすく、ロジックは文書化されているか、テストから導き出すことができます。変更コストはチームの習熟度によって制限されます。

規制産業におけるCOBOLポートフォリオは、3つの点で異なっており、そのため定量的な保守性測定は品質管理の実践ではなく、運用上の必要性となる。

知識のギャップ。COBOLのほとんどには、正式に文書化されていないビジネスロジックが含まれています。数十年前に書かれたバッチジョブには、誰も覚えていないルールが記述されています。コードを流暢に読み、変更コストを正確に見積もることができる開発者は退職しつつあります。残っている開発者は、ポートフォリオの一部について部分的にしか知識がありません。定量的な指標がないため、変更コストの見積もりはどの開発者に尋ねるかに完全に依存しており、その見積もりの​​ばらつきが大きいため、プロジェクト計画は信頼できないものとなっています。

規模の問題。典型的なCOBOLポートフォリオには数千ものプログラムが含まれており、その多くは何年も手つかずの状態です。どのチームも、近代化プログラムを開始する前に数千ものプログラムを手作業で評価することは不可能です。ポートフォリオ全体にわたって数時間で自動的に計算できる指標を用いることで、何週間もかかっていた手作業によるレビューを置き換えることができます。

ビジネスケースの要件。近代化プログラムには投資の正当性を示す必要があります。数百万ドル規模の近代化予算を承認する経営幹部は、投資が妥当であることを示す定量的な証拠を求めています。MIスコア、MIから算出される技術的負債比率、MIの閾値を参照した変更コストの見積もりは、非技術系の関係者にも提示できる形で、こうした証拠を提供します。

MI式とそのCOBOL固有の構成要素

保守性指数を計算するために最も一般的に使用される式は次のとおりです。

MI = 171 - 5.2 × ln(Halstead Volume) - 0.23 × (Cyclomatic Complexity) - 16.2 × ln(Lines of Code)

ほとんどの商用ツールで使用されているマイクロソフトの境界付きバリアントは、これを0~100のスケールにマッピングします。

MI (bounded) = max(0, (171 - 5.2 × ln(HV) - 0.23 × CC - 16.2 × ln(LOC)) × 100 / 171)

各コンポーネントには、COBOLに関連する特有の考慮事項があります。

COBOLのコード行数

COBOLソースファイルは、IDENTIFICATION、ENVIRONMENT、DATA、PROCEDUREの4つの部門で構成されています。IDENTIFICATION部門はプログラムを識別し、ENVIRONMENT部門は実行環境を記述し、DATA部門はデータ構造を定義します。実行可能なステートメントはPROCEDURE部門のみに記述されます。

測定上の疑問点: LOCは4つの部門すべての行数をカウントすべきか、それとも手続き部門のステートメントのみをカウントすべきか?

管理情報の観点から、すべての行(データ宣言を含む)をカウントすると、実行の複雑さが増すことなく、LOCが大幅に増加します。レコードレイアウトを定義する400行のDATA DIVISIONと100行のPROCEDURE DIVISIONを持つCOBOLプログラムは、100行のDATA DIVISIONと400行のPROCEDURE DIVISIONを持つプログラムとは保守性の特性が異なりますが、LOCだけでは両者を同じように扱います。

ベストプラクティス: COBOL MIの計算には、ソースコードの総行数ではなく、PROCEDURE DIVISIONステートメントのカウント(空白行、コメント行、およびセクション/段落ヘッダーを除く)を使用してください。これにより、実行可能コードの複雑さにより近いLOC値が得られます。

COPYメンバーの問題: COPY文はコンパイル時に外部ソースメンバーを取り込みます。200行のデータ定義に展開されるCOPY文は、ソースファイルには1行しか追加されませんが、コンパイルされたプログラムには200行が追加されます。ツールによっては論理LOC(コピー後の展開)をカウントするものもあれば、物理的なソース行数をカウントするものもあります。COPYを多用するプログラムでは、この差は桁違いになることがあります。

注意: MIツールが物理的なソース行数をカウントする場合、COPYを多用するプログラムは実際よりも小さく、保守しやすいと表示されることがあります。ツールのLOCがコピー展開前か後かを必ず確認してください。

COBOLにおける循環的複雑度

循環的複雑度とは、コード内の独立したパスの数を測定することで、コードの理解しやすさと保守性を評価するコード品質指標です。COBOLでは、独立したパスを生成する決定構造には以下が含まれます。

COBOL構文循環的複雑性の影響
IF ... END-IFIFごとに+1
IF ... ELSE ... END-IFIF文ごとに+1(ELSE文では別のパスは追加されない)
EVALUATE ... WHENWHEN句ごとに+1
PERFORM UNTIL conditionUNTIL条件ごとに+1
PERFORM VARYING ... WITH TEST BEFORE/AFTER変動ごとに+1
AT END READに関する条項+1
ON EXCEPTION / NOT ON EXCEPTION例外ハンドラーごとに+1
ON OVERFLOW / NOT ON OVERFLOWオーバーフローハンドラーごとに+1
ON SIZE ERRORサイズエラーハンドラーごとに+1

88レベルの盲点: COBOLの88レベルの条件名は、IF文やEVALUATE文に現れる論理条件を作成しますが、定義はDATA DIVISIONで行われます。複数の決定構造でそれぞれ参照される20個の88レベル条件を持つプログラムは、PROCEDURE DIVISIONの文数から推測されるよりもはるかに複雑な動作をします。循環的複雑度は決定点の数を数えますが、88レベルの名前とそれらをテストするロジックとの間の意味的な関係を捉えることはできません。

暗黙の複雑性を通してパフォーマンスを実現する: PERFORM SECTION-A THRU SECTION-Z SECTION-A と SECTION-Z の間のすべての段落を実行します。段落の数と、その中の決定構造はすべて PERFORM ステートメントの実効的な複雑さの一部ですが、ステートメント レベルで計算された CC は、 PERFORM THRU 間に何があっても、それは単一の道筋として捉えられる。

COBOLにおけるハルステッドボリューム

ハルステッドボリュームは、演算子とオペランドの数に基づいてプログラムのサイズと複雑さを測定する指標です。COBOLでは次のようになります。

演算子は、COBOL の動詞とキーワードです。例えば、MOVE、ADD、SUBTRACT、MULTIPLY、DIVIDE、COMPUTE、IF、PERFORM、READ、WRITE、OPEN、CLOSE、CALL、GO TO、EVALUATE、WHEN などです。

オペランドは、データ名、リテラル、および記号定数です。DATA DIVISIONで定義されたデータ項目、数値リテラルと文字列リテラル、およびCOBOLの記号定数(SPACES、ZEROS、HIGH-VALUES、LOW-VALUES)が含まれます。

冗長性要因: COBOLは、同等のロジックを表現する現代の言語と比べて、はるかに冗長です。Java式 total = quantity * unitPrice * (1 - discount) これは、4つの演算子と4つの被演算子を含む1行のコードです。COBOLでの同等のコードは次のとおりです。

COBOL

       COMPUTE WS-TOTAL = WS-QUANTITY * WS-UNIT-PRICE
                        * (1 - WS-DISCOUNT)

これは演算子と被演算子の数ではほぼ同等ですが、Javaでは3行で済むような複雑な計算を考えてみましょう。COBOLでは、式の連鎖がないことと、中間作業用記憶領域を使用する必要があるため、5行以上必要になる場合があります。COBOLでは同じ計算をより多くの言語トークンで表現するため、同等のJavaよりもHalstead Volumeは高くなります。

実務上の結果として、COBOLプログラムは同等の論理を持つ現代言語プログラムよりもハルステッドボリュームが高くなります。ハルステッドボリュームが高いほどMIは低下します。したがって、COBOLプログラムは、保守が難しいからではなく、構文的に冗長であるため、同等の複雑さを持つ現代言語プログラムよりもMIスコアが体系的に低くなります。

標準MIがCOBOLに対して不十分な点:4つの盲点

標準のMI式は正しく計算されていても、COBOLの保守性に関する4つの側面を見落としており、これらは実際の変更コストに大きな影響を与える。

1. コピーメンバーの結合

300個のプログラムにインクルードされているCOBOLコピーブックは、変更が加えられると300個すべてのプログラムに影響を与える保守依存関係です。この依存関係はMI式のどの構成要素にも現れません。20個のコピーブックを含むプログラムには300個の暗黙的な依存関係が存在しますが、MIはこれをコピーブックを含まないプログラムと同等として扱います。

補足指標:コピーメンバ依存度カウント。これは、プログラムのDATA DIVISIONにおける固有のCOPYステートメントの数です。COPY結合度が高いプログラムでは、変更を行う前に影響分析を行い、どのプログラムが同じコピーブック定義を共有しているかを把握する必要があります。

2. ファンイン(カウントによる呼び出し)

150個の他のプログラムから呼び出されるCOBOLサブルーチンは、MIスコアに関係なく、変更リスクの高い対象となります。150個のプログラムから呼び出される保守性の高いサブルーチン(MI = 85)は、誰も呼び出していない保守性の低いユーティリティ(MI = 45)よりも、安全に変更するのが困難です。MIの計算式は、プログラムの使用頻度を考慮していません。

補足指標:ファンインとは、CALLまたは動的ディスパッチを介して特定のプログラムを呼び出す個別のプログラムの数です。ファンインは、サブプログラムの内部的な複雑さに関係なく、サブプログラムの変更リスクの主要な要因となります。

3. JCLの依存関係の深さ

JCLジョブによって呼び出されるCOBOLプログラムは、そのプログラムより後に実行され、その出力に依存する15個の下流依存ジョブを持つため、MIの範囲外の運用リスクを伴います。MI=55のスタンドアロンで実行されるプログラムは、複雑なバッチ依存チェーンの中心に位置するMI=80のプログラムよりも、変更時のリスクが低くなります。

補足指標: JCL依存深度。これは、JCLジョブネットワークにおける下流の依存関係チェーンの深さを示します。JCL依存深度が高いプログラムは、内部MIスコアに関わらず、変更を行う際に、より広範なテスト範囲が必要となります。

4. デッドコードインフレ

デッドパラグラフやデッドセクション、つまり定義はされているもののどの実行パスからも呼び出されないCOBOLコードは、稼働中のコードの保守負担を増やすことなく、LOC(行数)とハルステッドボリュームを増大させます。デッドコードが600行、稼働中のコードが200行のプログラムの場合、デッドコードは変更コストとは無関係であるにもかかわらず、MI(管理指標)はデッドコードに対してペナルティを課します。

補足指標:デッドコード率。これは、本番実行パスから到達不可能なプロシージャ部ステートメントの割合です。デッドコード率が高い場合、MIで算出されたLOC(行番号)とHalsteadボリュームが大幅に過大評価されていることを示します。

完全なCOBOLメトリクススイート

COBOLの保守性を完全に把握できる単一の指標はありません。以下の指標群を組み合わせることで、全体像を把握できます。

メトリック測定対象COBOL固有の注記主な用途
保守性指数総合的なメンテナンスの容易さ(複合材)PROCEDURE DIVISIONステートメントに適用し、COPY処理を確認する。ベースライン品質スコア、ポートフォリオランキング
循環的複雑性独立した実行パスの数EVALUATE WHEN、PERFORM UNTIL、AT END、ON EXCEPTION を含めるプログラムごとの変更作業量、テストケース数の見積もり
ハルステッド巻計算負荷(演算子+被演算子)同等の現代語学プログラムよりも高い価値を期待してください。MIの一部。COBOLポートフォリオ内でのプログラム間比較。
メンバー数をコピー共有定義による依存性結合COPYメンバーが15名を超えるプログラムでは、変更を行う前に影響分析を実施する必要があります。変更リスク分類
ファンイン(コールドバイ)このプログラムは何件ありますか?サブプログラムにおける変更リスクの主な要因移行の順序付け、変更承認のしきい値
デッドコード %到達不能な手順コードの割合除外されていない場合はLOC/HVを膨張させる。変換範囲から除外する。近代化のための範囲縮小
JCL依存関係の深さ下流バッチジョブチェーンの深さCOBOLソースコードだけでは計算できません。JCL解析が必要です。運用変更リスク、テスト範囲
ネストされたPERFORMの深さPERFORM呼び出しの最大ネストレベル深い入れ子構造は、CCでは捉えきれない構造的複雑さを示している。リファクタリングの優先順位

COBOLのしきい値校正

標準のMIしきい値は、最新の言語コードベースに基づいており、COBOLに直接適用できるものではありません。以下の表は、標準のしきい値とCOBOLに適した同等の値とを比較し、調整の根拠を説明しています。

スコアの範囲標準的な解釈COBOL解釈理由
85-100メンテナンス性が非常に高い保守性が非常に高い(一貫性がある)この範囲の最高のCOBOLプログラムは、構造が明確で、適切なサイズです。
65-84中程度のメンテナンス性保守性は中程度で、COPYカップリングとファンインをレビューしてください。標準的な閾値は有効だが、ここでは補足的な指標がより重要となる。
50-64不十分、リファクタリングが必要限界的、文脈の中で評価する多くの構造化されたCOBOLプログラムは、冗長性だけで高得点を獲得します。CCとファンインを使用して、実際の問題と構文上のアーティファクトを区別してください。
25-49非常に貧しい不良、おそらく高CCおよび/または過剰なLOCこの範囲のプログラムは、COBOLの冗長性だけでなく、構造的な問題を確実に示している。
0-24重要な、大規模なリファクタリング重要事項であり、修復または廃止の最優先事項である。標準的な解釈と一致する

重要なキャリブレーションのガイダンス:プログラム固有のしきい値を設定する前に、COBOLポートフォリオ全体でMIを実行します。ポートフォリオの中央値と四分位範囲を計算します。「注意が必要」なしきい値は、Javaプログラムから導き出されたしきい値を下回るプログラムではなく、ポートフォリオの25パーセンタイル、つまり特定のコードベースの下位四分位にあるプログラムに設定します。このアプローチは自己調整型であり、COBOL特有の冗長性の影響を考慮しています。

近代化の意思決定にMIを活用する

MIスコアは、具体的な業務上の意思決定に役立つ場合に最も価値を発揮します。主な用途は以下のとおりです。

移行ウェーブの順序付け。MIスコアが高いプログラム(適切に保守され、複雑性が低いプログラム)は、早期移行ウェーブの最適な候補です。これらのプログラムは検証が容易で、文書化されていないエッジケースが含まれる可能性が低く、移行後の環境で予期しない動作が発生するリスクも低くなります。MIスコアが低いプログラムは、チームが経験と自信を積み、ビジネスロジックを徹底的に抽出した後、後のウェーブで移行する必要があります。

保守の優先順位付け。MIが25パーセンタイル未満で、かつファンイン(多くのプログラムから呼び出される)が多い、またはJCL依存度が高いプログラムは、最もリスクの高い組み合わせです。つまり、構造的に複雑で、他の多くのプログラムが依存しているプログラムです。これらのプログラムは、変更関連の欠陥が発生する可能性が最も高く、発生した場合の修復コストも最も高くなります。そのため、技術的負債削減プログラムの最初の対象とすべきです。

構築か購入かの判断。COBOLプログラムを長期的に維持するか、SaaSや最新の代替手段に置き換えるかを評価する際、MIスコアと変更コスト履歴は、構築か購入かの計算の定量的な根拠となります。MI=30で、過去3年間に15回変更され、各変更に予想よりも大幅に時間がかかったプログラムの場合、保守コストが文書化されているため、置き換えコストと比較することができます。

変更承認のしきい値。一部の組織では、MIスコアを使用して必要な変更承認レベルを決定します。特定のMIしきい値を下回るプログラムでは、本番環境への展開前に、より厳格なレビュー、独立したテスト、および追加の承認が必要となります。これにより、すべての変更を手動で評価することなく、品質を重視した変更管理プロセスが構築されます。

MI(管理指標)でできないことが一つあります。それは、変更がビジネスに与える影響を予測することです。MIが85のプログラムで、規制資本の計算を行う場合、MIが40のプログラムで、リスクの低い報告機能を実行する場合と同等以上のテストと検証が必要になります。MIは変更にかかる労力を測定するものであり、変更による影響を測定するものではありません。リスク評価を包括的に行うには、両方の側面を考慮する必要があります。

認定条件 SMART TS XL COBOLの保守性指標を確立し、追跡する

単一のCOBOLプログラムのMI(管理指標)を計算するのは簡単です。しかし、数千ものプログラムからなるポートフォリオに対して、COPY拡張を考慮し、デッドコードを特定し、MIが見落としている追加の指標で補完しながら、正確にMIを計算するには、大規模な自動分析が必要です。

SMART TS XLさん 静的コード分析 このガイドで説明されている COBOL メトリックスイート全体をポートフォリオ全体で同時に計算します。MI は、ソース行の総数ではなく PROCEDURE DIVISION ステートメント数を使用して計算され、共有データ定義が正しく割り当てられるように、分析の前に COPY 展開が実行されます。サイクロマティック複雑度は、IF ステートメントだけでなく、EVALUATE WHEN 句、PERFORM UNTIL 条件、および例外ハンドラ分岐を考慮します。Halstead Volume は、PROCEDURE DIVISION 内の COBOL 動詞とデータオペランドから計算されます。

重要なのは、 SMART TS XL MIは、数式で不足している指標を補完します。 アプリケーション依存関係マッピング ポートフォリオ内のすべてのプログラムについて、ファンイン値、呼び出し回数を生成し、MIスコアに関係なく高リスクのプログラムを特定します。 JCLの拡張 この機能は、すべてのプログラムに対してJCLの依存関係の深さを提供し、COBOLレベルのMI分析を、JCL分析でしか明らかにできない運用リスクのコンテキストに接続します。

影響分析機能によるデッドコード識別機能は、インバウンド実行パスのない段落やセクションにフラグを立て、MI計算からデッドコードを除外することを可能にするとともに、プログラムの低いMIスコアが真の複雑さを反映しているのか、それともLOCが水増しされているのかを判断するデッドコード率の指標を提供する。

エンタープライズ検索機能により、メトリクスデータセット全体をクエリ可能になります。数百万行に及ぶCOBOLコードの中から、MIが40未満、ファンインが20を超えるすべてのプログラムを、JCL依存関係の深さでソートし、ポートフォリオ内で最も優先度の高い修復対象として、単一のクエリで検索できます。このクエリ可能なメトリクスインベントリは、前述の保守優先順位付け、移行シーケンス、および変更承認アプリケーションの基盤となります。

最後に、MI(改善指標)を経時的に追跡し、重要な変更サイクルごとに再計算することで、プログラムが改善しているか悪化しているかが明らかになります。 SMART TS XLの分析は、キャッシュされたスナップショットではなく、最新のソースコードに対して実行されるため、メトリクスは、分析が行われた時点でのコードベースの実際の状態を反映し、時代遅れになる可能性のあるある時点での評価を反映することはありません。

言語に合った指標

保守性指数(MI)は、COBOLポートフォリオにとって有効かつ有用な指標ですが、COBOLの構文特性とコンポーネントとの相互作用を理解した上で適用した場合に限ります。COBOLプログラムに一般的な閾値を適用すると、誤解を招く結果となります。MIに不足しているCOPY結合度、ファンイン、JCL依存度、デッドコード率などの指標を追加することで、開発者がCOBOLポートフォリオで実際に経験する状況に即した状況を把握できます。

これらの指標を効果的に活用している組織は、それらをプログラムの品質に関する最終的な判断基準としてではなく、情報に基づいた議論の出発点として捉えています。MIスコアはシグナルです。このシグナルは注目に値するものであり、変更にコストがかかり、修正にリスクがあり、近代化を開始する前に対応すべきプログラムを一貫して示しています。MIができないことは、コードを読む開発者の判断に取って代わること、あるいは単一の指標では捉えきれない依存関係やビジネスロジックを明らかにする構造分析に取って代わることです。