- for (int theElementIndex = 0; theElementIndex < numberOfElements; theElementIndex++) {
- elementArray[theElementIndex] = theElementIndex;
- }
- if (check(c)) ...
- if (!(blockId < bottomBlockId) || !(blockId >= topBlockId))
- ...
- int x = ...;
- if (x & MASK == BITS)
- ...
- x += (xp = (2 * k < (n-m) ? c[k+1] : d[k--]));
- subkey = subkey >> (bitoff - ((bitoff >> 3) << 3));
- str[i++] = str[i++] = ' ';
- boolean = true;
- if (month == FEB) {
- if (year%4 == 0)
- if (day > 29)
- legal = false;
- else
- if (day > 28)
- legal = false;
- }
- int i = 0;
- while (i <= n-1)
- a[i++] = 1;
- for (int i = 0; i < n; )
- a[i++] = 1;
- for (int i = n; --i >= 0; )
- a[i] = 1;
- boolean leap = false;
- if (y % 4 == 0)
- if (y % 100 != 0)
- leap = true;
- else if (y % 400 == 0)
- leap = true;
- fac = lim / 20; /* スケールファクターをセット */
- if (fac < 1)
- fac = 1;
- /* ヒストグラムを生成 */
- for (int i = 0, col = 0; i < 27; i++, j++) {
- col += 3;
- k = 21 - (let[i] / fac);
- star = (let[i] == 0) ? ' ' : '*';
- for (int j = k; j < 22; j++)
- dwar(j, col, star);
- }
- draw(23, 2, ' '); /* x軸のラベル */
- for (int i = 'A'; i <= 'Z'; i++)
- drawLabel(i);
- char c = ...;
- if (c >= 65 && c <= 90)
- int arg(int[] a) {
- int sum = 0;
- for (int i = 0; i < a.length; i++) {
- sum += a[i];
- }
- return sum / a.length;
- }
- int i1, i2, i3;
- long l1;
- ...
- i3 = (i1 > 10) ? i2 : l1;
- void func(long n) {
- for (int i = 0; i < n; i++) {
- ...
- }
- }
- if (var1 == 0) {
- ...
- } else if (0 < var1) {
- ...
- }
- switch (var1) {
- case 0:
- ...
- break;
- case 1:
- ...
- break;
- }
- int[] a = ...;
- for (int i = 0; i != a.length; i++) {
- ...
- }
- int i;
- for (i = 0; i < MAX; i++) {
- data[i] = i;
- }
- if (min > max) {
- i = max;
- max = min;
- min = i;
- }
- for (int i = 0; i < MAX; j++) {
- ...
- i++;
- }
- for (i = 0; ループの継続条件1; i++) {
- ...
- if (終了条件1) {
- break;
- }
- if (終了条件2) {
- break;
- }
- if (継続条件2) {
- continue;
- }
- ...
- }
- switch (var1) {
- case 0:
- sig = ZERO;
- case 1:
- sig = PLUS;
- default:
- sig = MINUS;
- }
CheckStyle プラグイン(*) | Javaソースコードのコーディング・スタイルの検査 |
---|---|
com.atlassw.tools.eclipse.checkstyle_4.1.1-bin.zip | |
http://eclipse-cs.sourceforge.net/ | |
FindBungs プラグイン(*) | Javaバイトコードの静的解析 |
de.tobject.findbugs_0.0.14.zip | |
http://sourceforge.net/project/showfiles.php?group_id=96405&package_id=118233 | |
ステップカウンタ | stepcounter1_13.zip |
https://sourceforge.jp/projects/amateras/files/?release_id=16538 | |
Metrics プラグイン(*) | メトリクス計測 |
com.teaminabox.eclipse.metrics_2.7.0.zip ... Eclipse3.0用 | |
http://sourceforge.net/project/showfiles.php?group_id=128057 | |
Test & Performance Tools Platform | tptp.runtime-TPTP-4.0.1-200510031151.zip |
http://www.eclipse.org/tptp/home/downloads/drops/TPTP-4.0.1.html |
[エディッターで右クリック] - [ソース] - [フォーマット]
図 ソース上のメッセージ
- public class FindBugsSample01 {
- public static Counter count = new Counter();
- public static void main(String[] args) {
- String aString = "bob";
- aString.replace('b', 'p');
- if (aString.equals("pop")) {
- System.out.println("true");
- }
- String bString = null;
- if (isBound() && isBound()) {
- bString = " Hello! ";
- }
- aString = bString.trim();
- System.out.println("true");
- if (aString == bString) {
- System.out.println("same string");
- }
- }
- public static boolean isBound() {
- return count.countup() == 10;
- }
- }
- class Counter {
- int count;
- public int countup() {
- return count++;
- }
- public boolean isUnBound() {
- return !new FindBugsSample01().isBound();
- }
- }
図 ソース上のメッセージ
図 「問題」タグのリスト
図 「問題」の詳細
記号 | 意味 | 内容 |
---|---|---|
CC | マッケーブの循環的複雑度 (McCabe's cyclomatic complexity) | プログラムの複雑さを測る指標のひとつで、値が大きいほどテストや保守が難しいことを意味します。「ソフトウェア開発の定量化手法―生産性と品質の向上をめざして 」という書籍の中では、5 以下のプログラムは単純、10 以下でもそれほど難しくはない、20 以上は複雑さが高い、50 以上になるとテスト不可能と指摘しています。 |
Ce | Efferent Couplings | 外部パッケージへの依存度 |
LOCM-CK | Lack of Cohesion in Methods | クラス中のメソッドどうしの関連の度合いを示す指標。共有している変数が多いほど値が大きくなります。これはメソッドどうしが強く関連しており、望ましいカプセル化が行われていることを表します。逆に、値が小さいものは、メソッドどうしがあまり関連しておらず、さらにクラス分割できることを示唆します。 |
LOCM | Lines of Code in Method | メソッド中のコードの行数 |
NOF | フィールド数 | |
NOL | メソッド中の入れ子の深さ | |
NOP | メソッドのパラメータ数 | |
NOS | メソッドのステートメント数 | LOC は空白行やコメントなども計測するのでコーディングスタイルの影響がありますが、この値はステートメント数だけをカウントするのであまり影響がありません。 |
WMC | Weighted Methods Per Class | あるクラス中のメソッドの複雑さの総和 |
図 ソース上のメッセージ
図 ホームページ
図 パッケージ内行数
図 パッケージ内サイクロマチック数
図 パッケージ内サイクロマチック数の詳細
- for (int i = 0; i < elem.length; i++) {
- elem[i] = i;
- }
- if (hasError(c)) ...
- if (!((blockId >= bottomBlockId) && (blockId < topBlockId)))
- ...
- int x = ...;
- if ((x & MASK) == BITS)
- ...
- if (2*k < n-m) {
- xp = c[k+1];
- } else {
- xp = d[k--];
- }
- x += xp;
- subkey >>= bitoff & 0x7;
- str[i++] = ' ';
- str[i++] = ' ';
- boolean = true;
- if (month == FEB) {
- if (year%4 == 0) {
- if (day > 29) {
- legal = false;
- }
- } else if (day > 28) {
- legal = false;
- }
- }
- for (int i = 0; i < a.length; i++) {
- a[i] = 1;
- }
ただ、この程度であれば、つぎのように論理演算子を使ったほうがわかりやすい場合もあります。
- boolean leap = false;
- if (y % 400 == 0) {
- leap = true;
- } else if(y % 100 == 0) {
- /* DO NOTHING */
- } else if(y % 4 == 0) {
- leap = true;
- } else {
- /* DO NOTHING */
- }
さらに、boolean 型の変数に値を代入しているのであれば、つぎのようにすることもできます。
- boolean leap = false;
- if ((y % 400 == 0) || ((y % 100 != 0) && (y % 4 == 0))) {
- leap = true;
- }
- boolean leap = (y % 400 == 0) || ((y % 100 != 0) && (y % 4 == 0));
- final int MINROW = 1; /* 上端 */
- final int MINCOL = 1; /* 左端 */
- final int MAXROW = 24; /* 下端(<=) */
- final int MAXCOL = 80; /* 右端(<=) */
- final int LABELROW = 1; /* ラベル位置 */
- final int NLET = 1; /* アルファベットの数 */
- final int HEIGHT = MAXROW - 4; /* バーの高さ */
- final int WIDTH = (MAXCOL-1)/NLET; /* バーの幅 */
- fac = (lim + HEIGHT - 1) / HEIGHT; /* スケールファクターをセット */
- if (fac < 1)
- fac = 1;
- /* ヒストグラムを生成 */
- for (int i = 0; i < NLET; i++) {
- if (let[i] == 0)
- continue;
- for (int j = HEIGHT - let[i]/fac; j++)
- dwar(j+1+LABELROW, (i+1)*WIDTH, '*');
- }
- draw(MAXROW-1, MINCOL+1, ' '); /* x軸のラベル */
- for (int i = 'A'; i <= 'Z'; i++)
- drawLabel(i);
ただし、上記もお勧めできません。以下のようにすべきです。
- char c = ...;
- if (c >= 'A' && c <= 'Z')
システムの用意しているライブラリーを使おう
- char c = ...;
- Character.isUpperCase(c)
または、Exception をスローします。
- int arg(double[] a) {
- int sum = 0;
- for (int i = 0; i < a.length; i++) {
- sum += a[i];
- }
- return a.length <= 0 ? 0 : sum / a.length;
- }
- int arg(double[] a) throws Exception {
- if (a.length <= 0) throw new Exception();
- int sum = 0;
- for (int i = 0; i < a.length; i++) {
- sum += a[i];
- }
- return sum / a.length;
- }
この場合、可能であればキャストではなく、すべての型を long にした方がいい場合が多いです。
- int i1, i2, i3;
- long l1;
- ...
- i3 = (i1 > 10) ? i2 : (int) l1;
- long i1, i2, i3;
- long l1;
- ...
- i3 = (i1 > 10) ? i2 : (int) l1;
- void func(long n) {
- for (long i = 0; i < n; i++) {
- ...
- }
- }
- if (var1 == 0) {
- ...
- } else if (0 < var1) {
- ...
- } else {
- 例外処理 または コメント
- }
- switch (var1) {
- case 0:
- ...
- break;
- case 1:
- ...
- break;
- default:
- 例外処理 または コメント
- break;
- }
- int[] a = ...;
- for (int i = 0; i < a.length; i++) {
- ...
- }
- for (int i = 0; i < MAX; i++) {
- data[i] = i;
- }
- if (min > max) {
- int work = max;
- max = min;
- min = work;
- }
- for (int i =0; i < MAX; i++) {
- ...
- j++;
- }
- for (i = 0; ループの継続条件; i++) {
- ...
- if (終了条件1 || 終了条件2) {
- break;
- }
- if (!継続条件2) {
- ...
- }
- }
- switch (var1) {
- case 0:
- sig = ZERO;
- break;
- case 1:
- sig = PLUS;
- break;
- default:
- sig = MINUS;
- break;
- }