最近、Javaを勉強している。
一通り本を読んだ後、ネットで調べてみるとFizzBuzz問題というのがあるらしい。
この問題に挑戦してみることにした。
仕様は以下の通りだ。
- 1から順番に数を表示する。
- その数が3で割り切れるなら"Fizz"、5で割り切れるなら"Buzz"、両方で割り切れるなら"FizzBuzz"と表示する
プログラムをかじったことがある人だったら、どのようなロジックにすればよいか、頭に浮かぶのでないだろうか。
書いたコードをさらす。
public class FizzBuzz {
public static void main(String[] args){
int i;
final int NUMFIZ = 3;
final int NUMBUZ = 5;
final String STRFIZ = "Fizz";
final String STRBUZ = "Buzz";
for(i = 1; i <= 100; i++)
{
if(i % (NUMFIZ * NUMBUZ) == 0)
{
System.out.println(STRFIZ + STRBUZ);
}
else if( i % NUMFIZ == 0 )
{
System.out.println(STRFIZ);
}
else if(i % NUMBUZ == 0)
{
System.out.println(STRBUZ);
}
else
{
System.out.println(i);
}
}
}
}
ロジックよりも可読性、保守性を意識した。
工夫した点を以下に挙げる。
- マジックナンバーを少なくする。
- コメントを有効に使う。
- 仕様の変更に対応できるようにする。
作成者はマジックナンバー(コード中の具体的な数字)の意味を知っているが、他者が見る場合は、
コメントがないと何の数字かわからず、下手に手出しできなくなってしまう。したがってマジックナンバーは
できるだけ使わず、意味のある変数や定数にした方がいい。
コメントは他者がコードを見るとき、後日自分で見るとき、コード理解のヒントになる大事なもの。
処理が分かりずらい時や、変数の定義、クラスの説明などいろいろな部分に書き込む。
仕様通りに作るのは当然だが、要求が変わることはよくある。したがって将来的に変更がありそうな部分は、
変更がしやすいように書いておくと、コードの修正が楽になる。
今回、割り切れる数やそのときに表示する文章を定数として頭で宣言することで文中のマジックナンバーを減らし、
改修にも容易に対応できるようにした。
ifの分岐はどのような分岐なのかわかるように、分岐の中にコメントを挿入した。
自分としてはなかなか読みやすいコードになったと思い、友人(同レベルの)にコードレビューをしてもらった。
すると、自分で気づかなかったことや、ここはこうしておけばよかったなと反省するところが見つかった。
以下に挙げた意見や改善点がでてきた。
- 3でも5でも割り切れる分岐の条件を(i % NUMFIZ == 0) && (i % NUMBUZ == 0)にする。
- クラスの詳細(作成日や作成者、バージョン、入出力パラメータ)をヘッダーにコメントを書いた方が良い。
- ループ変数iはForループの中で宣言した方が良い。
- コメントは//よりも/*~*/の方が良い。
1番目は数学的には同じ条件だと思うが、もともとの条件だと分岐の順番を変えると不具合が発生してしまう。そこでより仕様に沿った条件を書いた方がいい。
2番目はクラスの情報が一目でわかるので、あると中身を全部読まなくても内容が読める。
3番目はスコープの問題だ。初めに宣言すると、宣言したクラス内どこでも変数が使えてしまう。変数は使用する部分以外では使えない方が不具合が減るので、使用時に宣言するのが良い。これはC言語と違う部分である。
4つ目はVBAに慣れてる僕には目から鱗だった。//だと一行全部がコメント部分になるが、/*~*/では書いてある部分だけがコメントになる。間違って改行していた場合なども意図せずコメントアウトすることがなくなるらしい。VBAでは基本的に複数行にまたがる条件やコードの書き方をしないので( _でできるが)すごく納得した。
後記
基本のプログラミングだったが、大変勉強になった。特に人に見てもらうのは説得力があり、理解もしやすい。こういった趣旨でコードを書いたと説明することも頭の中で自分のコードを反復するのに効果的だと思った。今後も定期的にコードを見てもらおうと思った。
はてな記法でコードを書く方法を教えていただいたthomさん、ありがとうございます。早速使ってみました。