JAVA WORLD という雑誌がある。私が毎月購入している雑誌は、現在2誌しかない。 そのうちの1つだ。
Jugem でいろいろメモっている内容をご覧の方は想像できていると思うが、 私のJavaのスキルは高くない。 今までのコーディング量は行数でいえば1万行〜10万行あたりだと思う。 このレベルだと、業務スキルとしてはよくても中級あたりではないかと思われる。
2004年12月号の特集に「Javaプログラミングの正しい作法」というのがあった。 いろいろな指針、教訓、ポリシーが出てきて、 プログラマーなら、 ビジネス本みたいな感じで読めば結構役に立つと思う。 こういう記事は好きだ。 ちなみに私はこれを「さくほう」と読んだのだが、 もしかすると「さほう」なのかもしれない。 読み方はどうでもいいとして、 その中で一番面白かったのは「オタク系」の記事だ。 指針というのは、例えばこんな感じ。
わずかな高速化のために、 コードの可読性や保守性を犠牲にしない
これは最近の流行だ。 リソースがふんだんに使えるようになったら、 ケチって大損するというパターンにハマることは多い。 叩き台になっているプログラムは、行列の加算と乗算を行うクラスである。 こんな感じだ。
public class Matrix {
private int m; // 行
private int n; // 列
private double[][] values;
public Matrix(int m, int n) {
this.m = m;
this.n = n;
values = new double[m][n];
}
// 途中略
public int rowCount() {
return values.length;
}
public int columnCount() {
return values[0].length;
}
}
紹介したのは掲載されているリストからの引用ではなく、 こんな感じのコードがあった、という話で、 類似のコードをエッセンスだけ書いてみたものだ。 興味のある人は、ぜひ JAVA WORLD を買って比べてみて欲しい。
さて、どこが叩かれるかというと、まず、mとnという変数名。 何だか分からないという。 そりゃいえる。 これに対して、おたくプログラマー(今後、O氏と書く)は、 行列においてmとnという名前が何を意味するかは常識だと反論する。
※昔ある仮名漢字変換のプログラムで、「ん」を「n」で入力するか「nn」で入力するかを表す「n」という名前のグローバル変数があったというのが伝説。
まあそれも一理ある訳だが、 これに対して叩き屋の…えーと、誰?…X氏と呼ぶことにしよう。 X氏も「それも一理あるが」と簡単に片付けていて、 mやnという名前にそんなに明確な意味があるのなら、 なぜnCountとかmCountではなくて、 rowCountとかcolumnCountというメソッド名を付けたのだ、 と突っ込むのを忘れている。
まあそれもどうでもよくて、 X氏、このmとnという変数がクラス内から直接参照されているのが気になるらしく、 getter 使えばどうだと突っ込んでいる。 これに対してO氏は、 getter 使うと遅くなる罠、 と反論する訳だ。
まあgetter使えば遅くなるというのは微妙な話かもしれないが、 それも一理ありそうな気がしないでもない。 しかし、 そういう速度の話を言うのなら、 どうしてこういう書き方をしないのだろうか?
public int rowCount() {
return m;
}
public int columnCount() {
return n;
}
}
このクラス、
コンストラクタを呼んだところで配列のサイズは固定されてしまって、
後で変更しようがないのである。
そのサイズがmとnに入っているのだから、
それを直接返せばいいだけだと思うが、
もしかして、最近のJava だと、
return m;
よりも
return values.length;
の方が効率がいいのかもしれないけど、
私はJavaに関してはアバターに到達していないので、
そういう所がよく分からないのだ。
というのはまあどうでもいい話。 余談はおいといて、 そろそろ本題に入らせていただくが、 こういう指針もある。
あまり特殊なテクニックは使わない
これ自体は激しく同意。 さて、その叩き台となっているのが、 別のクラスのこういうメソッドである。
public double getValue(int i, int j) {
return i == j ? 1.0 : 0.0;
}
(JAVA WORLD 2004年12月号、p.074、右段より引用)
これに対して、このメソッドの処理内容を一瞥で理解した人は、 かなりの手練れだ というのである。
ハァ?
どう見ても一瞬で理解できるような気がするのだが、 かなりの手練れといわれては、 やはり何か見落としてしまったのか、 と不安になるしかない。 慎重に見直すが、何も不審な所とか、トリッキーな所は思いつかない。 あ、本文を読むと、ヒントが書いてあった。
この1行のコードで行っているのと同じ処理を、if文を使えばもっとわかりやすいかたちで書けるということです。
(同誌、p.074 より引用)
謎。
この処理を、これより分かりやすく書くというのは、 一体どういうマジックを使えばいいのだろうか? ギブアップだ。 プログラマーになって二十数年、 これほど冷や汗をかくのも珍しい…こともないか。 最近、薄氷を踏むようなプログラムばかり書いているような気もするし、 いやどーも済みません。修行がまだ足りないです。 教えてクレー。 という訳で、指針を適用して改善したというプログラムのコードを見てみた。
public double getValue(int i, int j) {
return i == j ? 1.0 : 0.0;
}
(同誌、p.079)
ハァ(゚Д゚)?
私はきっと悪い子で、どうしても王様が裸に見えるのですが、それってトリビアになりませんか? いや、何かあるはずだ、校正するつもりで熟読してみると。
これまでに指摘してきた問題をどのように回避しているのかがおわかりいただけるはずです。
(同誌 p.078)
うぐぅ…
そこまで言い切られてしまうと、 うぐぅの声しか出ない私なのであった。