クラス図を使ってロボットの構造を把握しよう
ロボットを動かす意図をプログラマーの頭からプログラムへ移す
では、どうしたら「(A)ロボットがラインの上にいないときは左に曲がり、ラインの上にいるときは右に曲がる」という意図をプログラムにも含めることができるでしょうか。コメントを書くという方法も、コードの意図がわかりやすくなるので良いでしょう。しかし、これではプログラムの全域において、
//左に曲がる
ecrobot_set_motor_speed(NXT_PORT_B, 50);
ecrobot_set_motor_speed(NXT_PORT_C, 0);
というコードを書くことを意味します。これで良いでしょうか?ここでもう少し工夫してみましょう。できればコメントではなく、「左に曲がる」と語りかけるコードが良いでしょう。例えば、次のように書いてみます。
turn_left();
いかがですか?このコードなら、関数の名前そのものが(A)の情報を持っていますし、コメントと違って修正の影響はコンパイラがチェックしてくれるので、動いているロボットをうまく左に向けてくれると思います。
turn_left関数の処理は次のようになります。実行効率を気にするのであれば、これをマクロで実現するという方法もあるでしょう。
void turn_left(void) {
ecrobot_set_motor_speed(NXT_PORT_B, 50);
ecrobot_set_motor_speed(NXT_PORT_C, 0);
}
プログラムの意図がコードだけで伝わるように工夫する
同様にして、光センサーの値を判断している次のコードを見てみましょう。
if(ecrobot_get_light_sensor(NXT_PORT_S3)
字面どおり読めば「(B)3番ポートのライトセンサーの値がしきい値より小さいときは明るいときで、Bポートのモーターを出力50で正回転させ、Cポートのモーターは停止する。しきい値以上のときは暗いときで、Bポートのモーターは停止し、Cポートのモーターを出力50で正回転させる。」となります。
しかし、このときロボットは、黒いラインの上なのかそうでないかを判定しているのですから、次のように書き換えてみたらどうでしょう。「!」は否定演算子です。「ラインの上にいるのでなければ……」と読んでみてください。
if( ! isOnline() ){ ...
このisOnline関数の処理は次のようになるでしょう。FALSE(0)とTRUE(1)は、nxtJSPが提供するtoppers_jsp/include/itron.hに定義してあります。
int isOnline(void) {
if(ecrobot_get_light_sensor(NXT_PORT_S3)
return FALSE;
}
return TRUE;
}
このような工夫をした結果、最初に示したライントレースのコードは、次のようなコードに変わるでしょう。わざとコメントを書かずにおきました。
if( ! isOnline() ){
turn_left();
}else{
turn_right();
}
「何だ、関数に分けただけじゃないか。」と思われるかも知れません。いえいえ、このコードにはそれ以上の価値があります。それは、「(A)ロボットがライン上にいないときは左に曲がり、ライン上にいるときは右に曲がる」という意図が、コードとして表現できているからです。
コメントがなくても、コードだけで意図が伝わってきます。ほかの人にもコードだけで意図が伝わるのです。なぜでしょうか。それは、関数名に(A)を、関数の中身に(B)を書くことで「私たちの頭の中」に構築してあった(A)と(B)の関係を、「プログラムが表現する知識」として見えるようにしたからなのです。