Edited at

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

More than 1 year has passed since last update.

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 を使うのはやめよう。