ケント・ベックさんのImplementation Patternsを読んだ読書感想文
ケント・ベックさんとは
ケント・ベックさんはアジャイルソフトウェア開発宣言を考えたエンジニアのなかのひとりで、テスト駆動開発(TDD)やエクストリームプログラミング(XP)で有名な方です。
ほかには、超著名なテストフレームワークであるJUnitの開発者としても知られています。
私はJUnitを利用した経験がありませんが、その影響を受けて開発されたPHPUnitを使った経験はあります。現代のソフトウェア開発に多大な貢献をしているお方ですね。
Implementation Patternsとは
ケント・ベックさんがソフトウェア開発をおこなうときに、こうしたらやりやすいんじゃないかなというパターンをたくさん教えてくれる本です。
とはいえ、同じアジャイルソフトウェア開発宣言で有名なマーティン・ファウラーさんのPatterns of Enterprise Application Architecture(この本は現在積読中です)のように重厚長大な書籍ではなく、150ページほどのコンパクトな本です。書籍のコードはケント・ベックさんの経験的にJavaを念頭においたものが多いですが、普段使っている言語がJavaでなくとも使えそうな点も多いと思います。
日本では実装パターンというタイトルで邦訳された書籍が出版されていました。
しかし出版社のいざこざによって絶版になっており、邦訳版は中古でも8000円と少し手が出ない値段です。
今回私が読んだのはその原著にあたる書籍です。informITというサイトで購入しました。
26ドルでeBook版を購入しました。円安の現在でも日本円にして4000円くらいです。邦訳版を買うよりもお買い得ですね。
そのためこの記事では邦訳版を参考にしていないのでニュアンスや訳の面で邦訳版と異なる可能性があります。その点ご了承ください。
余談ですが、このサイトは頻繁にバウチャー(30~50%OFF)を配布してくれるので急いでいなければそれらが配布されたときにまとめ買いをするのが通貨の安い国に住んでいる皆様にはおすすめです。
この本が示唆を与えてくれること
クラス(Class) どのようにクラスを作ったり、どのようにクラスにロジックを設計するか(原文では "patterns describing how and why you might create classes and how classes encode logic. " encodeを訳すのが難しいですね)
状態(State) 状態をどのように保持し、取り出すか
振る舞い(Bahavior) どのようにロジックを表現するか、特に代替的な手法(alternative paths)について
関数(Method) どのように関数を分解したり命名するか、そのコードを読んだ人がどのような結論を導くか
コレクション(Collection) どのようなコレクションを利用するか
フレームワークの発展(Evolving Frameworks) アプリケーションではなくフレームワークを開発するときにこれらのパターンがどうなるのか
3ページ、Tour Guideより引用
どれも多くのプログラマーが毎日であう者たちです。
ケントさんがこの本を通じてもっとも伝えたいであろうこと
ケント・ベックさんは5ページ冒頭で、多くのプログラムは以下の法則に従うと述べています
- プログラムは書かれるよりも読まれることが多い
- 完了するということはなく、プログラムは最初に書かれるときよりも変更するときにより多くの労力がかかる
- それら(多くのプログラム)は基本的な状態と制御フローの概念をつかって構成されている
- プログラムを読むときはその詳細と構想(in detail and in concept)を理解する必要があり、詳細から構想へ、構想から詳細へ行ったり来たりする
本書で述べられている多くの実装パターンは上記の法則によって起こりうる様々な問題をよりよく乗り越えるためにケント・ベックさんが考えたもので、この法則を念頭において読む必要がありそうです。
良いなと思った記述
本書には多くのパターンやケント・ベックさんの思考が書かれており一つ一つ書いているときりがないため、私がいいなと思った箇所をいくつか紹介したいです。
対称性(Symmetry)
この対称性をケント・ベックさんはよく使っています。前半に出てくるパターンではありますが、後半にもよく出てきます。
彼が最初に例に出したパターンとしてはadd()
というメソッドがある場合には remove()
というメソッドもあるべきというような意味の対称性です。
他にはこんな例もあります。
これは対称性の無いコードの例
void process() {
input();
count++;
output();
}
input()
やoutput()
に比べてcount++
はあまりに具体的すぎて対称性が無いためまずこう書き換えます。
void process() {
input();
incrementCount();
output();
}
具体的な値のインクリメントを関数に閉じ込め、これで対称性が揃ったように見えますが、ケント・ベックさんとしてはまだ不十分なようです。
input()
やoutput()
はその意図が名前に反映されていますが、incrementCount()
は意図ではなく実装の詳細が名前に出ています。そこでこう書き換えます。
void process() {
input();
tally();
output();
}
tally()
です。これで意味も揃っていい感じですね。
(でも、タリーというのは僕のような母語が英語ではない人にはなかなかすぐ思いつくのは難しさもありますね、タリーカウンターのことを考えるとき以外日本語では頭に浮かびにくい)
この対称性の箇所は取り組みやすさや、実際のコードを書くときも心に留めたいと思わせる有用さが良いと思いました。
15ページより
パラメーターオブジェクト(Parameter Object)
いくつかのパラメーターが一緒に多くの関数に渡される場合、それをオブジェクトにして関数に渡すことを検討しましょう。
本書ではこんな例が紹介されています。これはJavaのグラフィックライブラリに関するプログラムだそうです。
setOuterBounds(x, y, width, height);
setInnerBounds(x + 2, y + 2, width - 4, height - 4);
一見しただけでかなり読みにくいです。これらの4つの引数は同じ場面で同じ目的のために使われるため、一つのオブジェクトにします。
setOuterBounds(bounds);
setInnerBounds(bounds.expand(-2));
このパラメーターオブジェクトを導入することによって、コードが短くなるだけでなくどのような意図がこの引数にあるのかが名前をつけることで明確になります。また、このオブジェクトについているexpand()
関数のようなものがあるおかげでxを+2したらyやwidth、 heightの値を変更する必要があるというような修正へのミスが少なくなります。
また、パラメーターをオブジェクト化することによって、これら4つの値が強く関連づいているということも表現できます。
この箇所は、普段もよくやっているなと思わせるパターンだなと思いました。実際ケント・ベックさんが述べているようなメリットをよく感じています。
57ページより
感想
ともすれば「当たり前じゃん」とか「なんら新しいことはない」と思う方も多かろう内容の書籍ではあるのですがそれは当然の話で、この本が古典だからです。
本書で述べられている4つの基本原則は毎日の仕事で感じるところであります。実際、過去の自分が書いてしまったコードはよくわからないことも多いし、それが他者のコードであればなおさらのことです。
若干難しい箇所や、Java特有っぽいからいまの自分にはあまり関係ないかなと思うところもある(普段私はGoを使っています)のですが、簡単そうなところから取り入れられるのは本書のいいところだと思います。
今回は1ページめから順番に読みましたが手元においておいて困ったときになにかヒントがないかを探すような目的でも有用だと思います。
とりわけ、どのような意図でコードが書かれたのかを重視する姿勢は意識しようとしてもなかなか難しいところはありますが、ケント・ベックさんが何度も本書で強調しているところでもあり実際の仕事に大いに役立つはずです。
終わりに
この記事で紹介した内容は本書の一部に過ぎませんので、みなさまぜひ購入することをおすすめいたします。
また、翻訳や解釈の正確性も保証できません。ご了承ください。
Discussion