2010-07-07
よろしい。ならばソースコードリーディングだ。
Java |
こんにちわ。世間は七夕です。
短冊に願いことを書けといわれたら真っ先に
性的なお付き合いを前提としてあずにゃんと結婚したいです。
もっと技術力がほしいです。明日にも食っていけなくなりそうなんです。
と、ガチで書いてしまいそうな俺です。
単純に技術力とをつける…言っても様々ですが、個人的に一番力がつくのはソースを読むことではないかと思っております。
自分はメインプロダクトがJavaなのでヒマなときはよくJava関連のソースをよく読んでいます。
Webフレームワークに興味のある人はStrutsあたりを読むとServletの扱いやTemplate Methodパターンについて理解できるかもしれません。
DIやAOPに興味のある人はSeaser2をオススメします。
書いているのが日本人なので几帳面なソースの書き方をされています。
GAE/Jに興味があるなら同じくひがさんの作ったSlim3。
こちらはSeaser2ほど大きくもないので結構さくさく読めたりします。
特にbigtableを理解したいならSlim3はマジオススメです。Slim3DataStoreマジbigtable。
でもー…。これらのソースって正直それなりに前提の知識がないと中々読めなかったりします。
事実、自分もSeaser2のソースを読みながら口から魂が抜けていきそうに何度もなりました。
今更感漂うんですが、これがホントにイイ。
元々使い慣れているのでインターフェースも仕様も解っているしソースも結構綺麗に書かれています。
初心者のときは単純に力をつけるのに役に立ちますし、ある程度慣れてくると最初は意味が解らなかったところも設計思想を読み取って「なるほど!」と思えたり。
読むときのコツなんてものを教えれるほど自分は技術ありませんがこんなことに気をつけて読んでいます。
・使ったことないメソッドを調べるより良く使うメソッドを調べる。
・行数の少ないメソッドだと尚可。
・何故そういう風になっているんだろう?っていつも思いながら読む。
例えばString#equals(Object anObject)*1。
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = count;
if (n == anotherString.count) {
char v1[] = value;
char v2[] = anotherString.value;
int i = offset;
int j = anotherString.offset;
while (n-- != 0) {
if (v1[i++] != v2[j++])
return false;
}
return true;
}
}
return false;
}
20行もないメソッドですが書かれている内容はプログラムのエッセンスに富んでいます。
例えば
if (this == anObject) { return true; }
ってなってますけど、普通なら「オブジェクト同士の比較ならequals使うんじゃね?なんで==使ってんだろ?」とか
while (n-- != 0) { if (v1[i++] != v2[j++]) return false; }
「普通for文で回すよね?なんでn--にしてんだろ?」とか。
そういう小さい疑問の積み重ねを一つ一つ解決してチリも積もればやまとなでしこ*2技術力になっていくわけですね。*3
あと、もしJavaのAPIを読むならあわせてこの本も読むといいと思います。
amazon:Effective Java 第2版 (The Java Series)
さらにマニアックな楽しみ方として読んだソースの書き換えなんかしてみても楽しいですね。
同じような結果になるようにリファクタリング*4してみるんです。
実際コンパイルして動かしてみると意外と元のメソッドよりパフォーマンスでたりして。
while(n-- != 0)はなんだろうね. 整数は0との評価の方が速いとかいう話ですか?
ようこそ。
最初のif (this == anObject)はJavaはすべて参照渡しであるということを利用したガードですね。
whileはコストの低減だと思っています。
forよりwhileの方がコストが低いのは明らかなので恐らくwhile使ってます。
n--なのは恐らく、そっちのほうが効率がいいんでしょう。
個人的にはこっちのがコスト低くない?と思ってみたんですが
while (i < count) {
if (v1[i++] != v2[j++]){
return false;
}
}
変数offsetや変数countの役割を考えると少し微妙です(バグがあるかもしれない)。
また、明示的に0:intを指定出来るのでこの部分は定数化されますし。
小さなことですが、何分いろんなところから膨大な回数呼ばれるメソッドなのでカリカリにチューニングしてあるんじゃないかなー…と。
あとコードが妙なのは下位互換を残しているという点も見逃せません。
まぁコレは正解かどうかわかりません。自分の予想なので…。