coding
コーディングスタイル

よくあるコーディングスタイル改善パターン

C やそれに類する構文を持つ命令型言語用。

If-else 条件の逆転 (1)

If 節の中身が else 節の中身より長い場合、条件と if/else の中身を逆にした方が普通は読みやすい。

// いまいちな例
if (foo) {
    doSomething1();
    doSomething2();
    // やたら長い正常系処理...
    doSomethingN();
} else {
    logError("..."); // 短い異常系処理
}
// マシになった例
if (!foo) {
    logError("..."); // 短い異常系処理
} else {
    doSomething1();
    doSomething2();
    // やたら長い正常系処理...
    doSomethingN();
}

If-else 条件の逆転 (2)

Else 節の中身が return, break, continue, goto で終わるが if 節はそうでない場合、条件と if/else の中身を逆にした方が普通は読みやすい。

// いまいちな例
if (foo) {
    doSomething1();
} else {
    doSomething2();
    return;
}
doSomething3();
// マシになった例
if (!foo) {
    doSomething2();
    return;
} else {
    doSomething1();
}
doSomething3();

さらにこの後、以下の「Else 節からの取り出し (1)」を適用することができる。

// さらにマシになった例
if (!foo) {
    doSomething2();
    return;
}
doSomething1();
doSomething3();

Else 節からの取り出し (1)

If 節の中身が return, break, continue, goto で終わるときは、else 節の中身を if-else 文の外に出すことでインデントを減らすことができる。

// いまいちな例
if (foo) {
    doSomethingX();
    return;
} else {
    doSomethingElse1();
    doSomethingElse2();
    // やたら長い else の中身...
    doSomethingElseN();
}
// 改善例
if (foo) {
    doSomethingX();
    return;
}
doSomethingElse1();
doSomethingElse2();
// やたら長い else の中身...
doSomethingElseN();

Else 節からの取り出し (2)

If-else 文の直後に return, break, continue, goto がある場合は、それを if 節の最後にも置くことで同様に else 節の中身を外に出すことができる。

// いまいちな例
if (!foo) {
    logError("..."); // 短い異常系処理
} else {
    doSomething1();
    doSomething2();
    // やたら長い正常系処理...
    doSomethingN();
}
return;
// 改善例
if (!foo) {
    logError("..."); // 短い異常系処理
    return;
}
doSomething1();
doSomething2();
// やたら長い正常系処理...
doSomethingN();
return;

関数の末尾の if 文

関数の末尾に else 節のない if 文がある場合は、条件を逆にして return することで if 文の中身を if 文の外に出してインデントを減らすことができる。

// いまいちな例
void foo() {
    ...
    if (bar) {
        doSomething1();
        doSomething2();
        // やたら長い処理...
        doSomethingN();
    }
}
// 改善例
void foo() {
    ...
    if (!bar) {
        return;
    }
    doSomething1();
    doSomething2();
    // やたら長い処理...
    doSomethingN();
}

一致個所の共通化

If 節と else 節の中身がほとんど同じ場合は、違うところだけを if-else 文内に残して、後は外に出す。コードを読む人に人力で diff を取らせるべからず。

// いまいちな例
if (foo) {
    this.listView.bounds = newBounds(top, right, bottom + normalMargin, left);
} else {
    this.listView.bounds = newBounds(top, right, bottom + wideMargin, left);
}
// 改善例
float bottomMargin;
if (foo) {
    bottomMargin = normalMargin;
} else {
    bottomMargin = wideMargin;
}
this.listView.bounds = newBounds(top, right, bottom + bottomMargin, left);
// さらに if 文をやめて ? : 演算子にすると
float bottomMargin = foo ? normalMargin : wideMargin;
this.listView.bounds = newBounds(top, right, bottom + bottomMargin, left);

Do-while ではなく while や for を使う

ループの先頭にループの条件が書かれている方が、普通は読みやすい。「ループが 1 回以上回ることは最初からわかっているから」という理由だけで for や while ではなく do-while を使うのはやめよう。