VSS で管理しているのにソースの修正部分の差分をコメントとして残す。というのが未だに多いのですが、VSS で差分管理できるということを知らないとかいうオチですか? その会社の伝統や風習みたいなものでしょうか。皆さんの周りではどうでしょうか?
手動でソースコードをマージする時 (いくつかの外注に発注する時) に指示することはあっても良いと思いますが、いつまでもずっと残っているのですよね。10 年物の修正履歴になると、コメントアウトされている量が異常に多くなるので可読性が著しく低下します。
何より「差分」で残すため、に腐った制御構造を壊せずどんどん処理や条件が増えていきます。そうなると平然と 10 インデント以上もの行が存在しうる (実際に 13 インデントを発見した) ので弊害が大きいです。たとえば、条件に「ガード句」を使っているソースであればさほど問題になりませんが、「関数の最後のみで必ず return する」なんていう規約が存在していると大変です。
たとえば、条件に「ガード句」を使っているソースであればさほど問題になりませんが、「関数の最後のみで必ず return する」なんていう規約が存在していると大変です。実際そういった規約のあるソースの修正や仕様追加が進むと平然と 10 ネスト、10 インデント以上もの行が存在しうる状況になりかねないです。実際、私は最近「魔の 13 ネスト」という洗礼を受けました。(もう受けたくも請けたくもない...)
「ガード句を使って return する場合」と「関数の最後のみで必ず return する規約がある場合」を比べてみましょう。
ガード句を使って return する場合
if (! 条件1()) {
return FALSE;
}
if (! 条件2()) {
return FALSE;
}
if (! 条件3()) {
return FALSE;
}
if (! 条件4()) {
return FALSE;
}
if (! 条件5()) {
return FALSE;
}
条件を満たせばできる処理();
上記であれば条件が増えても修正は容易ですね。制御構造が単純化されているので修正によるミスも少ないです。
関数の最後のみで必ず return する規約がある場合
BOOL bRet = FALSE;
if (条件1()) {
if (条件2()) {
if (条件3()) {
if (条件4()) {
if (条件5()) {
条件を満たせばできる処理();
bRet = TRUE;
}
}
}
}
}
return bRet;
上記のように仕様が追加されればされるほどネストが深くなります。
上記は簡単な例を示すためこうなりましたが、実際にはこの間にはとんでもない行の処理が含まれていたり else の分岐もあったりします。そうなると、対応している if と else の区別がつきにくい (if に対応する終了ブラケット } が数千行も差があるので追えるわけがない) です。そうなると修正が容易ではなくなります。対応するブラケットを確認するだけでも大変な目に遭うことさえあります。
関数でまとめれば解決すると思うのは甘いです。これらを関数で表現していくと関数の呼び出しが連鎖的になって構造がわかりにくくなります。いずれにしても修正は容易ではなくなるということです。
2008/06/05 9:34 ・・・ 追記しておきます。
これらの問題 (というか、規約をすり抜けるために) 空の while や for を使って break でガード句に対応する方がいますが、制御構造の基本を無視している (つまり、トリッキーな実装になる) のでやめた方が良いです。何人が見ても理解しやすいコードにするために存在するルールが本末転倒になっています。それなら素直にウォータフォールな goto を使って頂いた方が良いです。(特に VB7.1 以前は Continue がないので案外見かけます)
goto が使えない、ガード句を使ってはいけないのであれば... もう、しょうがないんだよねw これはさw フフッハwww するしかないです。
2008/06/05 10:01 ・・・ さらに追記しておきます。
この記事の本題ですが「ソースの修正履歴を残さないといけないがために制御構造を壊す変更ができない」のを問題視しています。『制御構造を壊すような変更なんて怖いのでしてはいけないのでは?』という意見もありますが、上記に書かれたような場合でもそう言えますでしょうか。「制御構造を壊せないがために修正が容易でなくなり、かえって間違いが多くなる」という可能性を考える必要があります。
ということです。