今日、拘束14時間、約12時間のペアプログラミングをしました。嫌い嫌い大好きXPって感じです。
端で見ているから他人のミスに気づくという側面もありますが、辛口ながら、ミスの多さは偶然では無いと思いました。以下、少し愚痴っぽい話ですが、プログラミングの基本的な部分を含んでいるので書きます。
# 以下の例で命名が甘いですが、そこは論点では無いので無視してください。
「データ構造」と言っても、高度な話ではありません。非常に基本的な話です。
簡単に言うと、Cで書くと
struct foo_t {
int x;
int y;
} foo[N];
のようなデータ構造であるべきものを、次のように書いていました。
int arr_x[N];
int arr_y[N];
要は、構造体の配列であるべきところが、複数の配列になっています。
配列arr_xと配列arr_yが(暗黙に)関係しています。結果として、これらを参照するコードは次のようになります。
for (i = 0; i < N; i++) {
int x = arr_x[i];
int y = arr_y[i];
// xとyはペアで使われる
}
以前、プロのプログラマ歴20年以上の人がこんなコードを書いたので、速攻で直させました。例え、動いたとしても、こんなコードは、存在そのものが許せません。
今日は諸般の事情により放置されました... (言語がPerlだったというのも理由のひとつです。Cだったら10分で書き直すのですが、Perlのリファレンスとハッシュのコードを10分で書き直す自信がありませんでした。会社に戻ったら、隣の凄い人にバカにされそうです)
フラグ変数が多すぎる、という問題もありますが、実はぼく自身もフラグ変数を結構使うのであまり人のことは言えません。
しかし、フラグの直交性には気を使います。ここでのフラグの直交性を簡単に説明すると、次のような話です。フラグ変数a,b,cと3つあった時、フラグcに「aかつb」の意味しか無い時、フラグ変数cの存在を許してはいけません。途中でフラグの意味が変わって、気づいたらフラグ変数cの意味がそうなっていた時も、即刻フラグ変数cを削除すべきです。
cの部分の記述性を明示したいなら、ぼくなら、次のようなマクロでCの部分の記述性を明確化します(Perlなら、まあ関数にでもするのでしょう)。
#define IS_C(conf) ((conf)->is_a && (conf)->is_b)
「呼ぶ-呼ばれる関係」はぼくの用語ですが、雰囲気で察してください。
コードに問題がある時、呼ぶ側の問題なのか呼ばれる側の問題なのかの区別をすることは重要です。この区別を素早く行うためには、呼ぶ側と呼ばれる側を切り離す「感覚」が必要です。
今日のペアプログラミングで、呼び出す外部コマンドが未実装、という状況でした。切り離す感覚があれば、とりあえず何もしない(キックされたことだけが分かる)ダミーの外部コマンドを用意して、あると仮定してテストはできます。外部コマンドでも関数呼び出しでも同じようなものです。今風のモックオブジェクトという用語もありますが、頭での理解より、切り離すと言うか突き放すと言うか、そういう感覚が先です。
このような切り離す感覚があれば、呼ばれる側だけの単体テスト、呼ぶ側だけの単体テスト、と小さな部品ごとの動作確認の意識にもつながります。今風にユニットテストと言う用語もありますが、これも頭での理解の前に、区切って隔離するとでも言うべき、感覚の方が先です。
- その他
- printfデバッグもバカにしたものではありません
- 1分でprintfが書けるなら、コードを見てなぜ動かないのか考えているより、たぶん解決は速いです。
- 気になることはコードに書いておきます
- コードを見ていると、気になる部分が見つかります。一瞬で直せれば直しますが、後で良さそうなものは、コードにコメントでメモっておきます。BSD系の伝統に従い、ぼくはXXXコメントと呼んでいます。気になる部分の多いコードだと、あちこちにXXXマークがつきます。本を読んでいて、気になるページにしおりをはさんだり、メモを書いたりする感覚に近いです。
ペアプログラミングにもメリットはあるんでしょうが、ペアプログラミングだけは、やりたくない・・・と思います。理由は、人に見られながら、コードを書くのが耐えられないということと、仕事で書くコードは個人のものではないし、いずれ自分以外の人がメンテナンスしていったりするものですが、書いてるそのときぐらいは自分のコードだと思いたいから・・・かな。下手なコードでも。