学生の頃「計算数学」という講義を受けていました。この講義には毎回プログラミングの課題がありました。
数値計算(ニュートン法とか、LU分解とか、SOR法とか、非定常反復法とか)をやるわけです。うちの学科では、基本的に課題はJavaで書くことになっていました。当時の僕は、数ヶ月前から、今勤めている会社でバイトをしていて、そこでもJavaを使っていました。また、中学生の頃からプログラミングをやっていたので、それなりに自信もありましたし、「Effective Java」や「軽快なJava」といった本を読んで感動し、デザインパターンなども、かじり始めていた頃でした。
そんな時、急にコードの書き方が分からなくなったのです。何故かというと、
- 本に書いてあること
- 今まで自分が書いていたこと
- 会社で先輩たちが書き、自分もそれを真似していること
- 大学で助手の先生が指導すること
全てが異なっているからです。
同じJavaと言っても書き方は用途によって、また、現場の微妙な判断によっては180度異なります。「これが正解」というものはないのです。しかし、当時の僕は知りませんでした。本は、いかにもそれが正式であるように見えます。先生や会社のコードは一貫性を貫いてぶれないので、それもなんだか正しいように見えます。
僕自身はいろんな書き方を試して来ました。まだ、自分の書き方というものが確立していませんでした。本を一冊読むたびに書き方を今までの自分のコードが恥ずかしくなり、全部書き換えてやり直したりを繰り返していました。
当時の僕は、ニュートン法やSOR法を実装するため、あるいは別の授業でSimplex法を実装するために、ベースに壮大な数値計算フレームワークを作り上げていました(笑)
さらにもう一つ厄介なことがあります。大学の数値計算の授業ともなると、まずは、数学的理論から始まります。数学の世界では、例えば、「二次元配列のi行とj行を入れ替える」「ある行をn倍する」という意味を示すために、基本行列というものを使います。こんな感じです。
http://ja.wikipedia.org/wiki/%E8%A1%8C%E5%88%97%E3%81%AE%E5%9F%BA%E6%9C%AC%E5%A4%89%E5%BD%A2
なので、教科書に書いてある理論をそのまま実装すると、こんな実装になります。
Matrix x = new Matrix(data);
Matrix a = Matrix.exchangeMatrix(x.rows, i,j);
x = x.multiply(a)
おおおお!!たった3行で配列のi行とj行が入れ替わりましたwwwwwしかし、普通はこう書きます。
double[] tmp = data[i];
data[i] = data[j];
data[j] = tmp;
見た目は変わらないかもしれませんが、前者は煮ても焼いても食えないダメコードです。行数は3行ですが、裏では行列のサイズをnとすると、nの3乗回の掛け算と、同じ回数の足し算が必要です。メモリも消費します。誤差も発生します。
でも、講義の先生は真剣に、行列計算でアルゴリズムを示されるのですよ。それはタテマエとは知りつつ、次の時間、助手の先生は、下のような実装を示すわけです。
ちなみに、数値計算の世界では、変数はaとか、xとか一文字で受けるのが基本です。数式が複雑になるので、業務プログラミングの世界では常識な、長い変数名を使うと、かえって読みにくくなります。
そんなわけで、当時、いっぱい勉強していた僕の脳はパンクし、徹夜明けで意識が朦朧とする中、講義の先生と助手の先生と、TAの方が集まっているところで、こう聴きました。
「先生、プログラムの書き方が分からなくなりました。どう書いたらいいのでしょう?」
数値計算の課題で、デザインパターン使い過ぎなオーバースペックなコードを提出する僕は既に目をつけられていたみたいなので、彼らは驚かれた様子で、やがて助手の先生がこう答えられました。
「問題が解ければ良い」
「ハヤク解ければもっと良い」
ここまで読んでくださった方にはこんな落ちでゴメンナサイ。
しかし、この言葉を僕は未だに大事にしています。この言葉を聞いたことがきっかけで、書き方で悩む日々を抜け出すことができたのですから。
今、書き方に悩んだときは、与えられている条件と、容易に想像しうる範囲の未来をちょっと見据えて、形に拘らずコードを書くことにしています。正解ではないかもしれませんが、あとで問題に気づいたときも、正直に向きあって、本当に問題ならば修正することにしています。勤務先の会社が、リファクタリングに積極的だということも、幸いなのかもしれません。
では、いろんな書き方が氾濫し、一度にたくさんの情報を与えられた入門プログラマーはどのように乗り越えていけばいいのでしょうか。考えてみたことを書いてみます。
とにかく徹底的にまねをする
郷に入れば郷に従え、その場所でその書き方が取られているのは、長年の経験に基づく理由があるはずです。
間違っても、「大学のセンセイなんて、頭は良くてもパソコンの使い方はわかってなくて、コードなんて古い書き方だ」というように失礼なことを考えてしまってはいけません。たしかに、大学の先生は時に、プログラミングの本に書いてあることと180度違うことをおっしゃいます。
例:「配列をreturnするメソッドは作ってはいけない」
しかし、どんなに違和感を感じても今まで読んできた理論とは違っても、それは、その方の研究範囲内で特化したやり方である可能性があります。まずは許容してください。そして、その書き方を極めましょう。
別の流儀を持ち込む
ある程度そこでの書き方に慣れたところで、数値計算のアルゴリズムをJUnitでテスト可能にしてみるとか、別の流儀の書き方を持ち込んでみましょう。多くの人が関わる開発でそれを行うといろいろまずいので、例えばちょっとした使い捨てのバッチとか、自分専用ツールとかを作るときにそれを適用しましょう。
とは言っても、デザインパターンが要求される規模のプログラミングを行う経験はなかなかありません。そこで、多少オーバースペックでも一度は強引に体験してしまいましょう。そして、多分、痛い目に遭います。そしたら、なぜそれは良くなかったのかを考え、チャンスがあったら、先輩や先生、上司に質問できるうちに沢山質問してしまいましょう。
自分の書き方を確立する
それぞれの書き方のいい点、悪い点を見つけたら、今までの経験に基づいて、今自分が取り組んでいる範囲で最適な書き方を見つけましょう。この期間は、あまり本は読まないほうが良いかもしれません。
本一冊くらいでは微動だにされないくらいの自信が付くまで本を封印するくらいで良いと思います。技術書を休んで、むしろ、文芸書でも読んでいましょう。司馬遼太郎などはいいんじゃないでしょうか?ゴメンナサイ適当に言いました!
いつも同じ書き方をする。時々ブラッシュアップする。
あとは、ミッションが継続している間はなるべく一つの書き方を変えないようにしましょう。しかし、本や他人のコードをシャットアウトはしないで、むしろ積極的に読みましょう。自分と書き方が違う場合は、なぜそうなのか?このコードを書いた人と、自分とはターゲットが違うのか?それとも自分が単に未熟なのか考えてみましょう。
僕が今まで読んできた本を紹介します
流行っているらしいんので……w
Effective Java
言わずと知れたEffective Javaです。初めて呼んだときは感動しました。この本は、Javaを極めようとしている人、フレームワークやライブラリをつくろうとしている人、大規模案件のアーキテクトを担当する人は必読です。しかし、僕の経験では、対象のプログラムが小規模だったり、Webサイトのようにフットワークの軽い開発を求められる場合は、この本のとおりにすると結構痛い目に遭いました。ですが、そのことを語るにはこの本を最低限読んでいることが必須です。Javaプログラマーは必ず一度は読んだほうが良いと思います。
少し古くてゴメンナサイ。読んでいた当時は知らなかったんですが、後のヌーラボの方々なんですね!Effective Javaを読む前の一冊に良いかもしれません。残念ながらJDK1.4ベースです。最新の状況を踏まえて改訂してくれたら、教育用にすごく良さそうなので、惜しいです。
書いてる人がかなりのC頭ですので、CからJavaに来た人にも、生粋のJavaの人にもいい刺激になるかもしれません。VMやGCの仕組みを軽く触ることができます。これも、Javaの古いバージョンベースですが、エッセンスとしては、役立つと思います。
いろんなソースを読むのにはうってつけです。和書の技術書ではなかなかここまで触れられないレベルのことが盛り込まれています。
まさに、「書き方」を体系化した本です。Kent Beck先生が極められた、一つの体系として非常に参考になります。
おまけ
新婚の頃、妻が一生懸命料理を勉強してくれていたとき、
「料理の作り方がわからない」
と言っていました。話を聞くと、色んなことを言う人や書く人がいて、どうしたらいいのか分からないというのです。どこかで聞いた話ですね。間違っても
「食えれば良い!」
「早く(そして速く)食えればなおさら良い!」
そんなことを言ったら、二度と料理作ってくれなくなったでしょう(^^