開発メモ

開発関係のメモをいろいろと。たぶん。

Effective Java 第2版

Effective Java 第2版

Effective Java 第2版_a

種類 情報
著者 ジョシュア・ブロック
柴田芳樹
発行日 2001年11月30日 初版第1刷発行
2008年11月25日 第2版第1刷発行
2011年1月10日 第2版第7刷発行
発行 ピアソン桐原

感想

※以下、第2版の感想です

ある程度Javaを使いこなしてる人を対象に、Javaを使う上で知っておいたほうが良い知識・注意した方がいいテクニックを紹介した本。最近の(?)JDKで追加になった新しい機能についても、便利なものを中心に紹介してある。

対象となるJavaのバージョンはJDK 1.6。


項目名だけ見ると「○○する」って形で方針が書かれてるのが多いけど、その内容は「○○する場合には、こんな所に気をつけるべき」ってのが多い。項目名だけ見て判断しないで、すべての項目に1度は目を通しておくべき。

ただ・・・ すべての項目にしっかり目を通そうと思ったら、そこそこJavaを使い込んでる人でも、かなり時間がかかりそう。それぐらい内容が濃い。まぁ、あきらめて読むしか無いんだけど。実は、「そんなの当たり前だろ」って項目も多いんだけど。


書かれてる内容は間違ってないんだけど、筆者の好みを読者に押し付けようとする部分が多すぎ。プログラムなんて世の中に星の数ほどあって、それぞれのプログラムで最適の解法も違ってくるはずなのに「○○が最適です」って言い切られてもねぇ。

この本に書かれてることをすべて守ってたら、Javaで開発するのが嫌いになりそう。どのテクニックをどういう場面で使うかは、それぞれのプログラマーが自分で判断するべき。


Javaで開発をしてる人間なら、一度は目を通しておくべき本。

おすすめ指数:☆☆☆☆☆

(2013/07/11 読了)

Effective Java 第2版 (The Java Series)

Effective Java 第2版 (The Java Series)

Amazon

項目別の感想

それぞれの項目別で、気になったところの感想。省略した項目は、いちいち突っ込むまでもなく当たり前の話って事で。

第2章 オブジェクトの生成と消滅

項目1 コンストラクタの代わりに static ファクトリーメソッドを検討する

デザインパターンのファクトリーメソッドではない」ってわざわざ書いてあるけど、説明されてる内容はファクトリーメソッドそのもの。たまにこのパターンが便利なこともあるけど、常に考えるようなテクニックではない。

項目2 数多くのコンストラクタパラメータに直面した時にはビルダーを検討する

確かに利点もあるかもしれないけど、ここまでやる必要が有ることはめったにない。もしくは、元々のクラス設計が間違えてる。かなり、自己満足の世界。

項目3 private のコンストラクタか enum 型でシングルトン特性を強制する

確かに便利な方法だけど、そもそも、シングルトンモデルをシリアライズしないといけないパターンがどれだけあるのか? そこまで考慮する必要があるのか?

項目4 private のコンストラクタでインスタンス化不可能を強制する

そもそも、インスタンス化を不可能にする必要が有るのか? これも、かなり自己満足の世界。

項目5 不必要なオブジェクトの生成を避ける

例に出てるような問題は、本来なら、コンパイラが勝手に最適化するべき。いちいち、プログラマーに意識させる時点でおかしい。Javaに残ってる問題点の1つだな。

項目6 廃れたオブジェクト参照を取り除く

言ってることは当たり前の事。そうそう、問題になることは無いと思うけど。ただ、キャッシュにデータが残るのは、メモリリークとは言えないのでは?

第3章 すべてのオブジェクトに共通のメソッド

この章の内容は、どっちかというとJavaと言う言語の弱点をプログラマーに押し付ける話。どれも、もっと簡単にオーバーライド出来るように、言語のレベルで設計しておくべきだった。C++から複雑な部分を取り除いたはずが、結果的に、もっと複雑になってる部分でもある。

それぞれ「○○する」って項目名になってるけど、書かれてる内容はオーバーライドする場合の注意点。

項目8 equalsをオーバーライドする時は一般契約に従う

ものすごく基本的なことなんだけど、ちゃんと理解してないと分かりにくいかな。

項目10 toStringを常にオーバーライドする

「常に」は言いすぎ。オーバーライドしておいたほうが便利なこともあるぐらいに覚えておけば十分。

第4章 クラスとインタフェース

この章の内容は、どれも、筆者の趣味を読者に押し付けるような内容になってる。「○○は駄目! ××を使うべき!」って話が延々と続く。

けど、実際にはそれぞれに長所・短所があるわけで、どっちを使うべきかは開発している状況で変わってくる。プログラマーが柔軟に判断するのが一番正しいやり方であって、勝手に個人の趣味を押し付けるのは気持ち悪い。

項目13 クラスとメンバーへのアクセス可能性を最小限にする

ものすごく当たり前の話。ただ、書かれてる内容はやりすぎ。

インスタンスフィールドは、決してpublicにするべきではありません」なんて、もはや宗教のレベル。もっと考え方を柔軟にしていい。

項目14 public のクラスでは、public のフィールドではなく、アクセッサーメソッドを使う

これも言い過ぎ。「クラスがそのデータフィールドを公開したとすると、その表現形式を変更するという望みは全て失われることになります」とか、まるで、筆者が世界の支配者であるかのような言い方が気持ち悪い。

publicのフィールドでも、変えたほうがいいなら変えれば良い。そのクラスを使ってるプログラムが世の中に溢れてるとしても、変えたくなったら変えればいいだけの話。

利点と欠点を考えて、状況に応じて使い分けられるのが普通のプログラマー。「アクセサーを使わないのは悪いプログラム」なんて思い込んでるのは・・・ 言っちゃ悪いけど、典型的な駄目プログラマーかと。

項目15 可変性を最小限にする

言ってることは正しいけど、不変クラスに夢を見過ぎ。不変クラスにした場合のメリットと、不変クラスにするための作業量を、ちゃんと自分で考えよう。

項目16 継承よりコンポジションを選ぶ

もはや、言ってる内容が個人の趣味のレベル。実装するにあたって、便利な方を選べば良い。

そもそも、無駄なコンポジションは「明瞭性(clarity)」に反してるんだけど、そこは無視なんだろうか?

項目17 継承のために設計および文書化する、でなければ継承を禁止する

文書化するのは継承と関係なく当たり前の話。継承を禁止するかどうかは、設計者がクラスの使われ方を想定して決めれば良い。どっちも、ものすごく当たり前の話。

項目18 抽象クラスよりインタフェースを選ぶ

どちらがいいかを場合に応じてちゃんと判断するべき。勝手に方針を決めるような問題ではない。

項目19 型を定義するためだけにインタフェースを使用する

普通にプログラムを作ってれば、自然に、インターフェースが型になるはず。逆に、型のためだけにインターフェースを使うようであれば、それはプログラムの設計がまずいということ。

定数インターフェースパターンをわざわざ否定してるけど、そんな発言は無視するべき。現場の判断は臨機応変。勝手に決め付けるのが一番たちが悪い。

項目20 タグ付クラスよりクラス階層を選ぶ

これも言い過ぎ。どっちがいいかはプログラマーが柔軟に判断するべき。

項目21 戦略を表現するために関数オブジェクトを使用する

関数オブジェクトの基本的な使い方の話。実は、Javaって言語の問題点の1つでもある。

項目22 非 static のメンバークラスより static のメンバークラスを選ぶ

常にstaticのメンバークラスに出来るとは限らないんだから、柔軟に選べば良い。

第5章 ジェネリック

JDK 1.5で追加になった、ジェネリック関係の基本的な話。

項目23 新たなコードで原型を使用しない

ちゃんとした形でジェネリックを使えってこと。当たり前の話。

項目24 無検査警告を取り除く

普通のプログラマーなら無意識にやってるかと。

項目25 配列よりリストを選ぶ

それぞれに長所・短所があるんだから、柔軟に判断するべき。

項目26 ジェネリック型を使用する

ジェネリックを使って、自分でクラスを作るときの話。

項目27 ジェネリックメソッドを使用する

ジェネリックを使って、自分でメソッドを作るときの話。

項目28 APIの柔軟性向上のために境界ワイルドカードを使用する

ジェネリックで型を指定するときの基本的な話。

項目29 型安全な異種コンテナーを検討する

ジェネリックで型の情報を使う時の話。

第6章 enumアノテーション

JDK 1.5で追加になったenumアノテーションに関する話。基本的に「どっちも便利なんだから絶対に使うべき」って論調だけど、「分かりにくい」ってデメリットは無視されてる。

コンパイラは知りません」って説明が多用されてるのが面白い。もともと、何でもObjectで誤魔化すのがJavaでは王道だったのにね。

項目30 int定数の代わりにenumを使用する

enumが使えるようになってよかったね」って話。Javaenumの欠点は、拡張性があるってことだったりするけど。

項目31 序数の代わりにインスタンスフィールドを使用する

Javaenumの基礎知識。知っておくと便利かなぁ。

項目32 ビットフィールドの代わりにEnumSetを使用する

Javaenumの基礎知識。分かりやすいようで分かりにくい。

項目33 序数インデックスの代わりにEnumMapを使用する

Javaenumの基礎知識。これも、分かりやすいようで分かりにくい。

項目34 拡張可能なenumをインタフェースで模倣する

本当に必要なテクニックなのか? これこそ、タグ付けクラスで良いのでは?

項目35 命名パターンよりアノテーションを選ぶ

結局、アノテーションに関する文書化が必要になるのは変わらないわけで。好きな方を選べばいい。「命名パターンを使用するのは論外です」とまで言い切る精神は気持ち悪い。

項目36 常にOverrideアノテーションを使用する

今時のIDEなら、ほっといても怪しいオーバーライドは警告を出せるでしょ? ほとんど、自己満足の世界。

項目37 型を定義するためにマーカーインタフェースを使用する

この項目に対する反論は「項目19」と同じ。これも、自己満足の世界。

第7章 メソッド

メソッド設計に関する話。

項目38 パラメータの正当性を検査する

言ってることはものすごく当たり前の話。ただ、本当に検査が必要かどうかは、その都度判断するべき。

項目39 必要な場合には、防御的にコピーする

好きにすれば良い。Javaの世界では、完全に防御することは不可能なんだし。

項目43 nullではなく、空配列か空コレクションを返す

nullを返したほうが良いパターンも有る。柔軟に判断するべき。

項目44 すべての公開 API 要素に対してドキュメントコメントを書く

言うまでもなく、当たり前の話。あえて「ドキュメントを書かない」という選択肢もあるけど。

第8章 プログラミング一般

ほとんどの項目が、言うまでもなく当たり前の話。

項目52 インタフェースでオブジェクトを参照する

現実問題として、インターフェースはそのままで、クラスだけ入れ替えるのが有効なケースってどれだけあるだろうか? プログラマーとして3回生まれ変わって、1回あるかないかぐらい?

第9章 例外

項目62 各メソッドがスローするすべての例外を文書化する

そうした方がいい。面倒だけどね。

項目64 エラーアトミック性に努める

ただの理想論。

項目65 例外を無視しない

例外を無視すること自体が目的の場合もある。柔軟に判断するべき。

第10章 並行性

マルチスレッドプログラミング関係の話。

項目68 スレッドよりエグゼキューターとタスクを選ぶ

JDK 1.5で追加になったExecutorの話。これから、Javaでマルチスレッド関係の開発をやるなら知っておくべき。

項目69 waitとnotifyよりコンカレンシーユーティリティを選ぶ

JDK 1.5で追加になった同期ユーティリティの話。これも、知っておいたほうがいい知識。

項目70 スレッド安全性を文書化する

基本的な話だけど、面倒。

項目71 遅延初期化を注意して使用する

「必要でなければするな」の一言で終わってる。

項目72 スレッドスケジューラに依存しない

基本的な話。1回痛い目にあうまで、実感することはないんだろうけど。

項目73 スレッドグループを避ける

とっとと非推奨にするべき。そろそろなってるのかな?

第11章 シリアライズ

項目75 カスタムシリアライズ形式の使用を検討する

使い捨て実装から逃げるなんて簡単なんだけど、どうしてそんなに怖がるのかは謎。

項目77 インスタンス制御に対しては、readResolve より enum 型を選ぶ

かなり自己満足の世界。個人的には、シリアライズが必要なら、シングルトンパターンを使わないほうが好み。わざわざenumを使うのは、「明瞭性(clarity)」に反してないか?

項目78 シリアライズされたインスタンスの代わりに、シリアライズ・プロキシを検討する

運が悪ければ、この知識が役に立つ場合もあるかも?