Personal tools
You are here: Home 原稿・資料 ワークス、アリエル共同勉強会 書籍「パーフェクトJava」輪講 特別講演
Document Actions

書籍「パーフェクトJava」輪講 特別講演

書籍「パーフェクトJava」の輪講をしている有志の勉強会向けの講演資料です。 (http://www.amazon.co.jp/dp/4774139904/)

目次

  • 「パーフェクトJava」読解
  • 書籍出版の裏話

第1部: 「パーフェクトJava」読解

「パーフェクトJava」で本当に伝えたいことは「良いコード」の書き方です

良いコードとは

色々な指標がありますが...

そもそも

「良いコード」以前に「プログラムそのものの価値」があるのも事実です

  • ユーザに与える価値
  • (ビジネスであれば)利益

極論すると

  • 「コードの良し悪しはどうでもいい」という理屈も真
  • しかし、そうすると話は終わるので

「コードの良し悪し」と「プログラムそのものの価値」は直交する前提で、前者に話を絞ります

改めて、良いコードとは

ありがちな指標

  • 高機能
  • 多機能
  • 高品質(バグが少ない)
  • 高速な動作
  • 低コスト
  • etc.

これらは、目的あるいは結果として達成される指標です

良いコードを書くために意識すべきこと

  • 可読性
  • 拡張性(変更容易性)

大前提

  • バグは必ずある
  • いずれ仕様は変わる

どうせコードは直すことになります

  • 「こんなコード、将来、誰もいじることは無いだろう」という幻想は捨てること

つまり

どんなコードでも

  • いつか必ず誰か(未来の自分も含む)が読んで
  • いつか必ず誰か(未来の自分も含む)が手を入れる

可読性

  • 読んで理解できるコードなら、機能を改善できる
  • 読んで理解できるコードなら、バグも直せる
  • 読んで理解できるコードなら、動作も速くできる

拡張性(変更容易性)

  • コード変更の影響範囲が明解(あるいは小さい)なら、機能を改善しやすい
  • コード変更の影響範囲が明解(あるいは小さい)なら、バグも直しやすい
  • コード変更の影響範囲が明解(あるいは小さい)なら、動作も速くしやすい

あえて、どちらが重要かと問われれば

迷わず「可読性」に軍配を上げます

  • コードの変更が多くの箇所に波及する「変更に弱いコード」だが、一応、読んで影響範囲が分かるコード
  • コードの変更の影響範囲がほとんどない「変更に強いコード」だが、その僅かの影響範囲が分かりづらいコード

であれば、前者の方がマシだから

と言っても

「可読性」の指標は、それほど自明ではありません

  • コードを読む人の経験や文化や慣れに依存

いったん、この議論は保留します

0x年代のスパゲッティコード

分割統治

  • モジュール化
  • データ中心設計
  • オブジェクト指向

の適用後、

  • 「長い関数や巨大なクラスの中にあった複雑さ」が「関係性や組み合わせの複雑さ」に移動

これではダメです

関係性や組み合わせが複雑だと

  • コードの変更の影響範囲が不明瞭
  • コードの変更の影響範囲が広い

要は「変更に弱いコード」になります

複雑さの制御

分割で複雑さを「関係性や組み合わせの複雑さ」に移動させないためには、

  • 「分割」するだけではなく
  • 「関係性」を制御する必要がある

関係性の制御

  • 依存性を明確にする(あるいは小さくする)
  • 境界を明確にする(あるいは小さくする)
  • 変化しやすい部分と変化しにくい部分を意識する
# 「小さくすること」は目安として役に立ちますが、重要なのは「明確にすること」

依存性

  • 依存性を明確にする一番容易な手段はレイヤ化 (注意:これだけが唯一の解ではありません)
  • 呼ぶ側(依存する側)と呼ばれる側(依存される側)を意識 (cf. コールバックによる依存性の反転)

技法

  • POJO(Plain Old Java Object)
  • DI(Dependency Injection)

なぜ依存性にそんなにこだわるのか?

変更の影響範囲がわからないと怖いから

境界

  • API(インターフェース)を意識
  • なるべく隠す

技法

  • スコープ管理
  • カプセル化

変化しやすい部分と変化しにくい部分

変化しにくい部分を意識的に作る

  • 不変オブジェクト
  • インターフェース
  • 関数型プログラミング(参照透明性)

変化の波及を最小限に抑える努力

  • DRY原則(Don't Repeat Yourself)
  • 防衛的なコード

変化しにくい部分に依存させる

  • レイヤ化で、変化しやすい部分を上位に追い出す
  • イベント(コールバック)で、変化しやすい部分をリスナ(オブザーバ)に追い出す
  • テンプレートメソッドパターンで、変化しやすい部分を具象(継承)クラスに追い出す

変化する部分を外に追い出す意味(外から与える)

実はミクロでは誰でもやっています

  • 関数のパラメータ(変数を外から与える)

たいていのプログラミングの技法は、この発想をマクロにやっているだけ

  • ストラテジパターン(実装を外から与える)
  • ジェネリックス(型を外から与える)

コールバック

なんちゃってイベントシステム(なんちゃってオブザーバパターン)を作らないために

  • 変わりにくい方をイベントソース、変わりやすい方を(イベント)リスナにするのが原則
  • イベントソースはリスナに依存してはいけない

この原理原則はレイヤ化も同じ

  • 変わりにくい方を下位層に
  • 下位層は上位層に依存しない(上位層の知識を持たない)

その他、意識しておくと良いこと

  • 名前付け(実は可読性に一番効く。しかし特効薬は無い)
  • 独立性(直交性、凝集性)
  • テスト容易性

実践的な話

心がけだけで良いコードが書けたら苦労しないので、明日からすぐ使える話など

どうでもいいことを頭から追い出すために

  • イディオムを知って、使う
  • デザインパターンを知って、(適切に)使う
  • コーディングスタイルを決める。守る
  • フレームワークを(適切に)使う

言語や標準クラスライブラリの理解を曖昧なままにしない

バグの多くは、APIの理解の甘さに起因します(経験則)

  • 曖昧な部分は実験コードで確認する癖をつける
  • 言語の落とし穴を知っておく(バッドノウハウであっても)

データ(状態)中心で考える

コードの複雑さは、多くの場合、状態管理に宿るので

  • オブジェクト生成とライフサイクル管理を意識して分離する、あるいは自分でやらない(cf. DIフレームワーク)
  • 「データと手続きの一体化」の(オブジェクト指向)教義にとらわれすぎない(データと処理クラスに分離して、処理の間を流す方が分かりやすいことも多い)

コンテナ(データベース)を自作しない。やるなら本気でやる

  • 「モノの集合の管理」は本質的に難しいことを知る
  • なので、分離して、そこは「モノの集合の管理」に専念する
  • 基本的に自分で書かない
  • どうしても書きたいなら、本気でやる(アプリケーション作成の片手間にやらない)
# とは言え、
# プログラマのキャリアの中できちんと勉強する期間も必要だと思います
# 「モノの集合の管理」にはプログラミングの本質があると思うので

メソッド設計の指針

  • 引数の変更は避ける(これに起因するバグは多い(経験則))
  • 問い合わせとコマンドの区別
  • デメテルの法則

どれもメソッド整理の目安程度には使えますが、教条的になりすぎないこと

ツールの活用

  • コンパイラにバグを見つけさせる
  • (javacの警告はぬるいので)FindBugsを使う
  • エディタを使いこなす
  • デバッガを使いこなす(コードの動的解析のため)

コードのコメント

初心者「可読性を高めるためコメントをたくさん書きました」
   やれやれ
原理主義者「コメントで説明するコードは絶対許しません」
   やれやれ

コメントは劇薬ですが、読み手へのメッセージとしてうまく利用すること

コードの全体像と位置感覚

コードをいじる時、全体の中のどの辺にいるかを意識すること

  • 同じコードにも複数の見立てがある

見立ての例

  • ストレージが一番下、UIが一番上のレイヤ構造的な見立て
  • WebアプリがMVCアーキテクチャに従っているなら、MVCでの見立て
  • Webアプリなら、リクエストを受けてからレスポンスを返すまでのシーケンス的な見立て

最後に。教条的になりすぎない

  • オブジェクト指向的であることがいつも良いとは限らない
  • デザインパターンがいつも良いとは限らない
  • 関数的であることがいつも良いとは限らない

未来の誰かが読んで書き換える時のことを想像するのが第一です。技法は手段です

第2部: 書籍出版の裏話

印税の話とか生々しいので非公開


Copyright(C) 2001 - 2006 Ariel Networks, Inc. All rights reserved.