本文へジャンプ

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む


お客様が developerWorks に初めてサインインすると、お客様のプロフィールが作成されます。プロフィールで選択した情報(名前、国/地域や会社名)は公開され、投稿するコンテンツと一緒に表示されますが、いつでもこれらの情報を更新できます。

送信されたすべての情報は安全です。

  • 閉じる [x]

developerWorks に初めてサインインするとプロフィールが作成されますので、その際にディスプレイ・ネームを選択する必要があります。ディスプレイ・ネームは、お客様が developerWorks に投稿するコンテンツと一緒に表示されます。

ディスプレイ・ネームは、3文字から31文字の範囲で指定し、かつ developerWorks コミュニティーでユニークである必要があります。また、プライバシー上の理由でお客様の電子メール・アドレスは使用しないでください。

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む


送信されたすべての情報は安全です。

  • 閉じる [x]

コード品質を追求する: 多弁なコードを黙らせるために

コードの冗長性を測るためのツールとメトリック

Andrew Glover (aglover@stelligent.com), CTO, Stelligent Incorporated
Andrew Gloverは合衆国ワシントン特別区にある、Vanward TechnologiesのCTO(最高技術責任者)です。Vanward Technologiesは自動化テスト・フレームワークの構築を専門としており、ソフトウェアのバグ発生数や統合時間やテスト時間の減少、また全体的なコード安定性改善に貢献しています。

概要: 開発者のなかには、壮大なコード・ブロックを遠目から眺めただけですくみあがってしまう人もいますが、これは当然のことです。。ほとんどの場合、多弁なコードは複雑さの証明であり、その結果、テストやメンテナンスが困難になります。。今月は、メソッドの長さ、クラスの長さ、そしてクラス内の結合を基準としてコードの複雑さを測定する、3つの重要な方法について説明します。今回の「コード品質を追求する」では、品質のエキスパートであるAndrew Glover が過剰なコードを見分けるためのヒントを説明し、次に、PMD やJavaNCSS などのツールを使って、さらに正確にコードの複雑さを見極める方法を紹介します。

日付:  2006年 6月 30日
レベル:  中級 この記事の原文:  英語
アクティビティー: 8706 ビュー
お気軽にご意見・ご感想をお寄せください: 


ためらわずに認めますが、私は複雑なコードのブロックを見ると本能的にすくみあがってしまいます。敢えて言うなら、私以外の人も長々としたメソッドや雑多なクラスに出くわすと、多少なりとも身震いするものだと確信しています。そんなとき、逃げ道を探してあたふたするのは人間として当然であるだけでなく、開発者の本能でもあります。あまりにも複雑なコードはテストやメンテナンスが難しいため、通常は問題が起こる確率も高くなります。

このシリーズの以前の記事で説明したように、厄介なコードの尺度として循環的複雑度 (cyclomatic complexity)が使われるようになっています。循環的複雑度が高いメソッドをテストすると、ほとんど間違いなく、簡単に出口が見つからない迷路に迷いこんだようになります。先月は、メソッド抽出パターンを使用して迷路からの逃げ道をリファクタリングする方法を説明しました。図1 に示すように、複雑なメソッドを小さく分けることによって、コードのテストやメンテナンスが簡単になります。


図 1. 複雑さの軽減によるコードのテストとメンテナンスの簡単化
複雑さの軽減によるコードのテストとメンテナンスの簡単化

循環的複雑度だけが、ハイリスクなコードを見極めるための測定値ではありません。クラスの長さ、メソッドの長さ、そしてクラス内の結合にも着目することができます。これらの測定値は相互に関連し、見分けるのも簡単です。今月は、この3 つがなぜ重要なのかを説明し、PMD と JavaNCSS を使って追跡する方法をご紹介しましょう。

過剰なコード

単純なコードと簡単なコードの違いを知ることは重要です。単純なコードは、必ずしも単純化されているわけでも、簡単で作成しやすいわけでもありません。単に理解しやすいだけです。単純なコードは、VisualBasic で書くのと同じぐらい簡単に C++ でも書くことができます。一方、どんな言語であってもコードを複雑にする最も簡単な方法は、一度にさくさんのコードを書くことです。

コードの品質向上

最も急を要する質問に対する答えは、Andrew のディスカッション・フォーラムを参照してください。

この法則がメソッドとクラスにどのように当てはまるかを考えてみてください。ほとんどの人はクレジット・カードの番号を記憶するのに苦労します。その理由は単純で、私たちが一度に覚えられるデータは7 つ (プラスマイナス 2) のみだからです。このことを念頭に置けば、過剰な条件文を理解するのは困難で、そのためにテストやメンテナンスがしにくくなることもわかります。これと同じ原理が論理ブロックにも適用されます。

コード本体には通常、同じ目標に向けて動作するグループ化されたステートメントが含まれます。例えば、コレクションを作成し、そこに項目を追加するなどの目標です。ただし、たくさんの論理ブロックをグループ化して1 つの長いメソッドにすると、メソッドの意図全体があっと言う間に不透明になってしまいます。そのような大規模なデータ・セットを効率的に扱える人はほとんどいないからです。この弱点こそが、コード・ベースにおけるメンテナンスの問題を引き起こします。巨大なメソッドを効率的に構文解析できる人は数限られているため、巨大なメソッドは不具合の温床と言えます。長いメソッドはたくさん作業をしてくれるだけでなく、理解するのにもたくさんの作業が必要になります。

長いメソッドが開発者を混乱させるように、冗長なクラスにも同じことが言えます。これと同じ議論はコード全体にも当てはまります。長々としたクラスはたくさん作業をしすぎるため、責任も過多になります。

何が余分なのか?

長いメソッドや長いクラスは、当然どこか主観的な構成になっています。目安として、コメントを除いたコードが100 行を超えるメソッドは長すぎると言えるでしょう。この数字には無論、個人差があります。私にとっての限界は、50行のコードですが、別の開発者はスクロールダウンしないとメソッドの本体全体が見えなければ、そのメソッドは長すぎると言うかもしれません。この基準を決めるのは、あなた自身です。

同様に、クラスの適切なサイズを決めるのにも個人の判断が必要です。大多数が主張する目安は、1つのクラスにつき 1,000 行のコードで、これより多くの行を持つクラスは大きすぎるとされます。一方、500行のコードであれば、耐えられるという人もいます。


クラス内の結合

あるオブジェクトが別のオブジェクトと関係を持つようになる場合、複雑さを増加させるパターンは繰り返されます。外部依存関係をたくさんインポートするクラスや、public メソッドを多く持つクラスを理解するのは難しいだけでなく、それによってクラスの責任の負担が増えるため、クラスが脆弱になります。

まず、依存関係から説明しましょう。オブジェクトが 80 を超える外部クラスをインポートする場合(標準 JavaTM システム・ライブラリーを除く)、そのクラスの遠心性結合の値は高いことになります。つまり、インポートされたクラスを変更すると、クラス自体に影響が出ます。最悪の場合、具体的なクラスがインポートされ、それぞれの動作が変更されると、インポートを行うクラス自体が壊れてしまいます。(遠心性結合について詳しくは、参考文献を参照してください。)

脆弱性を予測するための有効な手段はインポートするオブジェクトの数に注意することですが、パッケージ全体が.* 表記でインポートされている場合 (例えば、com.acme.user.*) は誤解を招くおそれがあります。正確を期すには、オブジェクトが所有する固有の型の数に注意を払うことです(これは、import 文ではなく、コードを構文解析することによって行います)。固有の型のメトリックは、アプリケーションのパッケージ構造が、少数のパッケージに多くのクラスを組み込めるように大まかにレイアウトされている場合にも役立ちます。

多くの public メソッドが含まれるクラスも、インポートの数が多くなりがちです。このようなクラスは通常、ファサードまたはユーティリティー・クラスのいずれかとして、コード・ベースの中心になります。この責任(多数の public メソッドによって公開される) により、このようなクラスは高い求心性結合を持つとされます。高い求心性結合も、逆の脆弱性につながります。これらのクラスのいずれかが変更されると、関連性のないように見えるアプリケーションのさまざまな部分が壊れてしまう可能性があります。


複雑さの相関関係

これまでの説明で、貪欲なコード (長いメソッド、多すぎる公開メソッド、過剰な条件文とインポートなど)は理解し難く、テストやメンテナンスの容易性も損なわれるというパターンが見えてきました。このパターン自体がさまざまなメトリックで繰り返されるため、メトリックはすべて相関する傾向にあります。例えば、図2 に示すように、長いメソッドでは通常循環的複雑度が高くなります。


図 2. 長いメソッドと循環的複雑度の相関関係
長いメソッドと循環的複雑度の相関関係

相関関係はこれだけにとどまりません。過剰なインポートを持つクラスには、固有の型がたくさんあります。そのようなクラスは一般的にかなり大きくなります。大きなクラスは通常長いメソッドを持ち、さらに、長いメソッドが高い循環的複雑度を持つことは珍しくありません。図3 に、複雑度のメトリックがどのように相関しているかを示します。


図 3. 複雑度のメトリックの相関関係
複雑度のメトリックの相関関係

PMD と JavaNCSS

PMD と (それほどではないにしろ) JavaNCSS では、冗長なコードを簡単に見分けられます。この2 つのツールはどちらも、Ant や Maven などのビルド・プラットフォームに簡単に組み込むことができます。

PMD はいわばルールに基づいたエンジンで、ソース・コードを分析してルールに違反しているインスタンスを報告します。PMDは現在、メソッドの長さ、クラスの長さ、固有の型、および public メソッドの数それぞれに対する固有のルールを200 近く定義しています。カスタム・ルールを定義したり、既存のルールを (例えば、ドメインの必要性に合わせて)変更することもできます。

PMD のカスタマイズ

例えば、長いメソッドを見つけるには PMD の ExcessiveMethodLength ルールを使います。このルールでは、メソッド長のしきい値のデフォルトは100 (スキャンしたメソッドの長さが 100 行を超えていると、PMD がルール違反を報告します)ですが、このしきい値は必要に合わせて小さい値にすることができます。

PMD ルールではプロパティーを定義できます。PMD 開発チームの優れた先見の明により、定義したプロパティーは実行時にルール・セット・ファイルを使っててオーバーライドすることができます。ExcessiveMethodLengthルールのデフォルト値 100 を 50 にするには、properties 要素をルール定義に追加して、プロパティーの名前を参照するだけで済みます。リスト1 では、minimum という名前のプロパティーが PMD の rule の定義に追加されています。


リスト 1. ExcessiveMethodLength ルールのカスタマイズ
                
<rule ref="rulesets/codesize.xml/ExcessiveMethodLength">
 <properties>
  <property name="minimum" value="50"/>
 </properties>
</rule> 

Ant のカスタム・ルール・セット・ファイルで PMD を呼び出すには、リスト 2に示すように、PMD タスクの rulesetfiles 属性を使用して、そのカスタム・ファイルのパスを指定する必要があります。


リスト 2. カスタム・ルール・セット・ファイルの参照
                
<pmd rulesetfiles="./tools/pmd/rules-pmd.xml">
 <formatter type="xml" toFile="${defaulttargetdir}/pmd_report.xml"/>
 <formatter type="html" toFile="${defaulttargetdir}/pmd_report.html"/>
 <fileset dir="./src/java">
  <include name="**/*.java"/>
 </fileset>
</pmd>

図 4 に示すように、PMD はソース・ファイルごとに違反を報告します。この例では、ソースコードが50 行を超えているメソッドがいくつか見つかっています。


図 4. PMD Ant レポートの例
PMD Ant レポートの例

長いクラスに対しては、PMD には ExcessiveClassLength ルールがあり、デフォルトで1,000 行のコードに設定されています。ExcessiveMethodLength ルールと同様に、このデフォルト値はより適切な値で簡単にオーバーラオイドできます。さらに、PMDには CouplingBetweenObjects と名付けられた固有の型の数に対するルールがあります。インポートの数については、ExcessiveImportsルールを調べてください。どちらのルールも構成が可能です。

JavaNCSS による冗長性の測定

明確なルールを定義してソース・コードを分析する PMD とは対象的に、JavaNCSSはコード・ベースを分析して、クラス・サイズ、メソッド・サイズ、そしてクラス内で検出されたメソッド数などコード長に関するすべての項目を報告します。JavaNCSSでは、しきい値は関係ありません。検出されたすべてのファイルをカウントし、サイズに無関係にその値を報告します。PMDと比べ、この種のデータはありきたり (で冗長) にも見えますが、事実からかけ離れたものにはなりません。

JavaNCSS ではすべてのファイル・サイズが報告されるため、相対値を理解することができます。これは、PDMではなかなか困難です。例えば、PMD は違反が含まれるファイルのみを報告するため、コード・ベースの一部に関するデータしか理解できませんが、JavaNCSSではコンテキストにおけるコード長データが提供されます。図 5 を参照してください。


図 5. JavaNCSS Ant レポートの例
JavaNCSS Ant レポートの例

まとめ

開発チームが空白の IDE コンソールを起点として、見事で簡潔なコードを入力するグリーンフィールド開発は、ソフトウェア・アプリケーションの生涯においては非常に小さな部分です。今日、世界中の多数の組織では、いまだにCOBOL をベースとしたアプリケーションを実行しています。これは開発者の側からすると、大昔の見知らぬ人が書いたコードと格闘するということです。

そんな怪物に直面して嫌気が差すのは当然のことですが、何日も続けて病欠の電話をすることしかできません。ある時点で、その巨大なコード・ブロックと対決し、征服しなければなりません。敵を知る最初のステップは、クラスの長さ、メソッドの長さ、そしてクラス内の結合(つまり、オブジェクトのインポートと固有の型) に対する複雑度メトリックを用いることです。まず始めにクラスとメソッドのサイズに関する目安を知り、PMDおよび JavaNCSS などのツールを使って詳細に焦点を合わせてください。

長年使われたコード・ベースで複雑度メトリックを始めて使うと、非常に多くのことが分かりますが、そこで終わらせてはなりません。複雑度メトリックを引き続き監視することで、長期にわたってコード・ベースを拡張およびメンテナンスすると同時に、より賢い判断を下してリスクを低減させることができます。


参考文献

学ぶために

製品や技術を入手するために

  • PMD: Java コードをスキャンして問題を見つけます。

  • JavaNCSS: ソース・コード・メトリックを測定する単純なユーティリティーです。

議論するために

著者について

Andrew Glover

Andrew Gloverは合衆国ワシントン特別区にある、Vanward TechnologiesのCTO(最高技術責任者)です。Vanward Technologiesは自動化テスト・フレームワークの構築を専門としており、ソフトウェアのバグ発生数や統合時間やテスト時間の減少、また全体的なコード安定性改善に貢献しています。

不正使用の報告のヘルプ

不正使用の報告

ありがとうございます。 このエントリーは、モデレーターの注目フラグが設定されました。


不正使用の報告のヘルプ

不正使用の報告

不正使用の報告の送信に失敗しました。


developerWorks: サイン・イン


IBM ID が必要ですか?
IBM IDをお忘れですか?


パスワードをお忘れですか?
パスワードの変更

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 利用条件

 


お客様が developerWorks に初めてサインインすると、プロフィールが作成されます。 プロフィールで選択した情報は公開されますが、いつでもその情報を編集できます。 お客様の姓名(非表示設定にしていない限り)とディスプレイ・ネームは、投稿するコンテンツと一緒に表示されます。

表示名をお選びください

developerWorks に初めてサインインするとプロフィールが作成されますので、その際にディスプレイ・ネームを選択する必要があります。ディスプレイ・ネームは、お客様が developerWorks に投稿するコンテンツと一緒に表示されます。

ディスプレイ・ネームは、3文字から31文字の範囲で指定し、かつ developerWorks コミュニティーでユニークである必要があります。また、プライバシー上の理由でお客様の電子メール・アドレスは使用しないでください。

(半角英数字で3文字以上31文字以下にする必要があります)


「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 利用条件

 


この記事を評価する

コメント

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=60
Zone=Java technology
ArticleID=219444
ArticleTitle=コード品質を追求する: 多弁なコードを黙らせるために
publish-date=06302006
author1-email=aglover@stelligent.com
author1-email-cc=