Hatena::ブログ(Diary)

低学歴エンジニアの戯言。

2010-07-07

よろしい。ならばソースコードリーディングだ。

| 15:45

こんにちわ。世間は七夕です。


短冊に願いことを書けといわれたら真っ先に


性的なお付き合いを前提としてあずにゃんと結婚したいです。

もっと技術力がほしいです。明日にも食っていけなくなりそうなんです。


と、ガチで書いてしまいそうな俺です。


単純に技術力とをつける…言っても様々ですが、個人的に一番力がつくのはソースを読むことではないかと思っております。


自分はメインプロダクトがJavaなのでヒマなときはよくJava関連のソースをよく読んでいます。

Javaは元々OSSの毛色が強いので色々あります。

Webフレームワークに興味のある人はStrutsあたりを読むとServletの扱いやTemplate Methodパターンについて理解できるかもしれません。

DIやAOPに興味のある人はSeaser2をオススメします。

書いているのが日本人なので几帳面なソースの書き方をされています。

GAE/Jに興味があるなら同じくひがさんの作ったSlim3

こちらはSeaser2ほど大きくもないので結構さくさく読めたりします。

特にbigtableを理解したいならSlim3はマジオススメです。Slim3DataStoreマジbigtable


でもー…。これらのソースって正直それなりに前提の知識がないと中々読めなかったりします。

事実、自分もSeaser2のソースを読みながら口から魂が抜けていきそうに何度もなりました。


そこでオススメなのがJava標準APIのソースです。


今更感漂うんですが、これがホントにイイ。

元々使い慣れているのでインターフェースも仕様も解っているしソースも結構綺麗に書かれています。

初心者のときは単純に力をつけるのに役に立ちますし、ある程度慣れてくると最初は意味が解らなかったところも設計思想を読み取って「なるほど!」と思えたり。


読むときのコツなんてものを教えれるほど自分は技術ありませんがこんなことに気をつけて読んでいます。

・使ったことないメソッドを調べるより良く使うメソッドを調べる。

・行数の少ないメソッドだと尚可。

・何故そういう風になっているんだろう?っていつも思いながら読む。




例えば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


あと、もしJavaAPIを読むならあわせてこの本も読むといいと思います。


amazon:Effective Java 第2版 (The Java Series)


さらにマニアックな楽しみ方として読んだソースの書き換えなんかしてみても楽しいですね。

同じような結果になるようにリファクタリング*4してみるんです。

実際コンパイルして動かしてみると意外と元のメソッドよりパフォーマンスでたりして。


そんな感じでゆるゆる〜っとソースコードリーディングを楽しみましょう!

*1:Stringクラスってはかなり傑作なAPIじゃないかなーと自分の中では思っております。

*2:なでことも性的なお付き合いを前提として結婚したいです。なでなで。

*3:しー抜きでいや、死ぬ気でがんばりましょう。

*4:自分にはequalsメソッドをリファクタリングするような度胸も技術もないですが…orz

akiradeveloperakiradeveloper 2010/07/23 05:59 最初のifのIDを評価してるのは, 自明な場合に処理を打ち切るためのガードで,
while(n-- != 0)はなんだろうね. 整数は0との評価の方が速いとかいう話ですか?

Crimson_AppleCrimson_Apple 2010/07/23 15:41 >>akiradeveloper さん
ようこそ。
最初のif (this == anObject)はJavaはすべて参照渡しであるということを利用したガードですね。

whileはコストの低減だと思っています。
forよりwhileの方がコストが低いのは明らかなので恐らくwhile使ってます。
n--なのは恐らく、そっちのほうが効率がいいんでしょう。
個人的にはこっちのがコスト低くない?と思ってみたんですが
while (i < count) {
if (v1[i++] != v2[j++]){
return false;
}
}
変数offsetや変数countの役割を考えると少し微妙です(バグがあるかもしれない)。
また、明示的に0:intを指定出来るのでこの部分は定数化されますし。

小さなことですが、何分いろんなところから膨大な回数呼ばれるメソッドなのでカリカリにチューニングしてあるんじゃないかなー…と。
あとコードが妙なのは下位互換を残しているという点も見逃せません。

まぁコレは正解かどうかわかりません。自分の予想なので…。