ソースコードの可読性というのは、SEにとって間違いなく重要なポイントの一つであると考えられます。
しかし可読性と一言にいっても可読性が高いコードというのは定義が難しく、主観も混じる話であるため、なかなか決着が付かない話題でもあります。
それでも明らかに万人に見づらいコードというものはあると思い、自分の主観交じりではあるものの、
どういったコードが可読性が低いのか、またそういったコードを書かないためにはどうすればいいのかを書いていきたいと思います。
今回は例としてjavaのソースを見ていきますが、そこまで深い話ではないので他言語にも適用できると思います。
この記事を書くことになったきっかけ
ついこの間、このようなことがありました。
今携わっている案件で、以前作成したロジックと同じような書き方で実装できそうな処理がありました。
なのでコピペして一部書き換えようとしたところ、自分で書いたにも関わらず何をしているのかが見ただけでは読み取れず、結局デバッグモードで一行ずつ追いかけてようやく処理内容を理解することができました。
単純に自分のスキル的な問題もあるかもしれませんが、さすがに去年自分が書いたコードが読み取れないのは書き方に問題があると思い、自分への戒めのためこの記事の執筆に至りました。
わかりにくい原因
まず件のソースの何が問題だったかを紐解いていこうと思います。
なお、具体的なソースは守秘義務的に出すことはできないため、この記事に載せるソースは特徴だけ捉えた適当なサンプルになります。
・原因1 コメントの不足
より正確に言うと、コメント量自体は特に不足していたわけではないのですが、
最終的な処理結果のみが端的に書かれているだけで具体的な処理内容に関するコメントが不足していました。
if文の場合、条件分岐の条件が書かれているだけで結局どういった処理をしているかが書かれていませんでした。
・原因2 変数名がいまいち
次に変数名のわかりにくさがあげられます。
変数名が一般的な命名からずれたつけ方をしていたため、何を格納している変数なのかがぱっと見でわからないようになっていました。
例:数学のテストの点数をIntegerの配列に追加し、点数を比較して高い点数を表示する処理
//数学の点数
String mathematics = "70";
int imathematics = Integer.parseInt(mathematics);
List<Integer> imlist = new ArrayList<Integer>();
imlist.add(imathematics);
String mathematics2 = "75";
int imathematics2 =Integer.parseInt(mathematics2);
imlist.add(imathematics2);
//点数を比較
if(imlist.get(0)>imlist.get(1)){
int top = imlist.get(0);
System.out.print("このクラスの最高得点は"+top+"点です");
}
else{
int top = imlist.get(1);
System.out.print("このクラスの最高得点は"+top+"点です");
}
imlistとだけ聞いて"数学の点数をIntegerに変換したものの配列"であるとぱっとわかる人はなかなかいないのではないでしょうか。
ちなみにこの記事を書く際に、変数の付け方について少し調べたのですが、名称を短縮しすぎるのはよくないらしいです。
これはまさにその典型的な例に当たるかと思います。
なぜこのようなコードを書いてしまうのか
このあたりから特に個々人の問題になるとは思いますが、自分の場合はとりあえず動かすところまで作ってしまいたいという気持ちがあったために起きたことだと考えています。
いったん動けばいいだろうと考え、仮として雑に決めた変数名を結局そのまま使用してしまいました。
コメントについても同様で、明日の自分がわかる程度に書いておいて後で書き直そうと思い、結局そのままにしていました。
どうすれば回避できるか
原因から考えると、全体像や処理イメージを固める前に部分的に作っていることが問題と考えられます。
そのためまずコメントやメソッド、変数のみ作成して、具体的な処理内容はそのあと書いていくという二段階に分けるのがよいのではないかと考えました。
これならある程度具体的かつわかりやすく書かないと成り立たなくなるため、コードありきで考えることができなくなります。
コードより先にコメントを書く手法自体は無意識でやっている人もいるかもしれませんが、おそらくそれは複雑な処理を書く際にやると思います。
しかし処理の整理という意味では、変数やコメントをきれいに整えることにも役立つのではないでしょうか。
そもそもいい変数名ってどうすればいいんだというのはおそらく先人たちがたくさん考えてくれているので、グーグル先生にお伺いしてください。
実際にこの手法で上記のサンプルを作ってみましょう。
//数学の点数一つ目
String mathematicalScoreStr;
//mathematicalScoreStrをintに変換
int mathematicalScore;
//点数を格納するIntegerのlist
List<Integer> mathematicalScorelList = new ArrayList<Integer>();
//mathematicalScoreをmathematicalScoreListに追加
//数学の点数二つ目
String mathematicalScoreStr2;
//mathematicalScoreStr2をintに変換
int mathematicalScore2;
//mathematicalScore2をmathematicalScorelListに追加
//一つ目の点数と2つ目の点数を比較
//大きい方を最高得点として表示
まずコメントで記述
冗長な印象はありますがとりあえずこのまま続けましょう。
処理を書いてみます。
//数学の点数一つ目
String mathematicalScoreStr = "70";
//mathematicalScoreStrをintに変換
int mathematicalScore = Integer.parseInt(mathematicalScoreStr);
//点数を格納するIntegerのlist
List<Integer> mathematicalScoreList = new ArrayList<Integer>();
//mathematicalScoreをmathematicalScoreListに追加
mathematicalScoreList.add(mathematicalScore);
//数学の点数二つ目
String mathematicalScoreStr2 = "75";
//mathematicalScoreStr2をintに変換
int mathematicalScore2 = Integer.parseInt(mathematicalScoreStr2);
//mathematicalScore2をmathematicalScorelListに追加
mathematicalScoreList.add(mathematicalScore2);
//一つ目の点数と二つ目の点数を比較
if(mathematicalScoreList.get(0) > mathematicalScoreList.get(1)){
int top = mathematicalScoreList.get(0);
//大きい方を最高得点として表示
System.out.print("このクラスの最高得点は"+topScore+"点です");
}
else{
int topScore = mathematicalScoreList.get(1);
//大きい方を最高得点として表示
System.out.print("このクラスの最高得点は"+topScore+"点です");
}
何をやっているのかわからないということはなくなってきたのではないでしょうか。
ただここまでコメントが多いとくどい印象です。整理してみましょう。
//点数を格納するIntegerのlist
List<Integer> mathematicalScoreList = new ArrayList<Integer>();
//数学の点数一つ目
String mathematicalScoreStr = "70";
int mathematicalScore = Integer.parseInt(mathematicalScoreStr);
mathematicalScoreList.add(mathematicalScore);
//数学の点数二つ目
String mathematicalScoreStr2 = "75";
int mathematicalScore2 = Integer.parseInt(mathematicalScoreStr2);
mathematicalScoreList.add(mathematicalScore2);
//一つ目の点数と二つ目の点数を比較し、大きい方を最高得点として表示
if(mathematicalScoreList.get(0) > mathematicalScoreList.get(1)){
int topScore = mathematicalScoreList.get(0);
System.out.print("このクラスの最高得点は"+topScore+"点です");
}
else{
int topScore = mathematicalScoreList.get(1);
System.out.print("このクラスの最高得点は"+topScore+"点です");
}
少なくとも一番最初のサンプルよりは見やすくなったかと思います。
正直これくらいなら一発で書ける人はざらにいると思いますが、雰囲気としてはこのようにしていくというのが伝わったでしょうか。
まとめ
長々と書いてきましたが、要するに「面倒なことを後回しにするな」というあんまりプログラムと関係ない結論にたどり着いてしまった感が若干否めません・・・
ただ今回のような例であれば、特別知識等も必要なく意識するだけで改善が見込めると思われます。
少しでも参考になるところがあったら幸いです。