PoEAA に学ぶデザインパターン系の書籍の読み方
PoEAA から始めるパターン集
2年ほど積読していた PoEAA を手に取ってみると、これが意外と面白い。PoEAA は20年ほど前の書籍であるものの現代でも通用するところがある。というより、PoEAA は当時の実装パターン集であるため、現代でも活かせることがあるのは当然とも言える。
それは、パターンが現場で直面する課題に対して、繰り返し活用できる解決方法だからだ。 ソフトウェアがデータベースにアクセスしたり、オブジェクトのコレクションを扱ったり、同じインターフェースを備えた複数のオブジェクトを差し替えて動き方を変えることは20年以上前から今に至るまで変わらない。これからも同じことを相変わらず行うだろう。
ただ、厄介なことに PoEAA の実装コードは古くなっている。 本書の序文によると、著者であるマーティン・ファウラーが書籍内のパターンに出会ったのは80年代後半から90年代初頭であり、それらはSmalltalk、C++、CORBA などで書かれていたとのことだから当然だ。
書籍内のコードは Java で記述されているため今でも読めないこともない。 ただし、そのコードをそのまま実務で記述してもコードレビューは通らないだろう。設計が過剰である上にコードが冗長という指摘を受けるに違いない。また、現代ではメジャーな MVC フレームワークの備えている機能を活用すれば十分な箇所もある。
しかし、それでも PoEAA は現代でも読むべき価値のある書籍だと痛感している。なぜなら、この書籍のおかげでバックエンドエンジニアとのコミュニケーションがスムーズになり、さらに自分が前から持っていた 「DDD 忌避症」が解消されたからだ。 PoEAA を読むことで、DDD の半分はパターン集であり、そのパターンも PoEAA が執筆された当時のものを参考にしているとわかったためだ。
本記事では PoEAA を例に、パターン集を読むための私見を紹介する。ここでいうパターン集は PoEAA の他に、GoFのデザインパターン、リファクタリング、Domain Driven Design、 SQLアンチパターンあたりを想定している。
パターン集を読む時に注意していること
パターン集を読む際、個人的に注意していることは「現代では通用しない箇所を差し引きつつ、場所と時を超えて普遍的なことを頭に入れておく」ことだ。
実装詳細は差し引いて読む
まず、差し引いて読むところはどこか。それは実装詳細だ。 例えば、PoEAA に出てくる JAVA のコードも、Kotlin で書き直すともっと洗練されたコードになるだろう。「リファクタリング」は初版のサンプルコードは Java だったが、第2版で JavaScript に変えられたので読みやすくなった。ただし、このようにコードが書き直されることは稀である。
実装は、その本が書かれた時に流行しているプログラミング言語や当時のベストプラクティスによって変わる。このため、パターン集を読むにあたって実装を鵜呑みにしないことが重要だ。
普遍的な記述に注目する
反対に、頭に入れるべきは現代でも通用する普遍的な箇所だ。 もちろん、あるパターン集の記述の全部が今でも活用できる知識ではない。このため、深い洞察がある記述を探すのもパターン集を読む醍醐味の一つである。
PoEAA は2部構成であり、第2部では様々な実装パターンのカタログだ。さらに実装パターンの紹介も「パターンの定義」「動作方法」「使用するタイミング」「実装例」という一種のパターンになっている。そして、「パターンの定義」「動作方法」「使用するタイミング」 には普遍的な内容が書かれている可能性が高い。
パターンはその定義と使うタイミングを覚えておく
特にパターンの定義とそれを使用するタイミングを覚えておくと良い。 すると、そのパターンが解決する課題に直面した時(使用するタイミング)に、パターン名の実装方法を検索できるからである。検索方法は、書籍内の PoEAA の該当の記述でも良いし Google でも良い。 もちろん、人とのコミュニケーションに役立つ。 CTO やテックリードに聞いたりや Stack Overflow で質問しても良い。
その際、「このパターンが適用できそうなのですが、そもそも今回の課題に当てはまりますか。また、そうであればこの言語・フレームワークだとどう実装するのがいいでしょうか」と尋ねることができる。質問された方もそのパターンを知っていると「ああ、あれね」とコミュニケーションがスムーズになる。 メジャーなパターンはコミュニケーションの共通言語になるのだ。
特に PoEAA では、現代の開発者にとって当たり前の単語がパターンとして解説されている。 このため、プログラミングの基礎を学び終え、綺麗なコードを書こうとするプログラマにとって重宝する。「アクティブレコード」「レポジトリ」「サービスレイヤー」「ドメインモデル(今では一般的にドメインオブジェクトと呼ばれている)」「データ・トランスファー・オブジェクト(DTO)」「データ・アクセス・オブジェクト(DAO)」「トランザクションスクリプト」「クエリーオブジェクト」などという単語を理解しておくとこの先もずっと使える知識となる。
そして、パターン名とそれを使うケースを読んでおくと、「目の前の課題を解決するためのとっかかり」が頭の中にできる。すると、目の前にある課題があったとき、その文脈・背景を知っている自分、もしくはチームが、普遍的な課題解決策であるパターンの視点から課題を捉え直すことができる。
パターンの注意点
ただし、パターンは銀の弾丸ではない。このため、書籍にあるようなパターンは大抵そのまま適用できない。
このため、パターン集において、その実装は鵜呑みにしてはならない。それよりも、パターンの定義とそれを活用する場面、コンテキストを頭に入れておくこと。 これは PoEAA だけではなく、もちろん GoF のデザインパターンにも当てはまる。
また、何でもマイクロサービス化しようとしたり何でも DDDを適用しようとする態度も、結局それらは一種のパターンだという観点が抜け落ちている。 マイクロサービスは数あるアーキテクチャパターンの一つに過ぎず(その他のパターンは「ソフトウェアアーキテクチャの基礎」に数多く掲載されている)、DDD もその半分は実装パターン集である。
ソフトウェアアーキテクチャであれ、アプリケーションアーキテクチャであれ、パターンの活用原則通りに、そのパターンが課題に対する適切な解決策になっているか、コンテキストを考慮しながら慎重に判断する必要がある。
簡単にまとめると以下のようになる。
パターン学習の原則
- パターンの定義を理解する
- 実装詳細より、パターンのユースケースを重視する
- パターンは専門家の共通言語である
パターンを適用する原則
- パターンは、課題解決の出発点である
- パターンは、教科書通りに適用できるとは限らない
- パターンは、無理に適用するものではなく、後から発見するものである
読書を楽しむ
この記事では、技術書のパターン集の読み方を解説してきた。色々書いてきたが、古いパターン集だから役に立たないだろうし読みにくそうと避けずに、まずは手に取ってみて読書そのものを楽しむことだ。
普遍的な記述の箇所だけに価値があるのではない。古くなっている記述は、当時の技術の流行や雰囲気を今に伝えている。パターン集は古典である。古典を読んだ後は、視点が相対化され、同じものを見ていても昨日と今日で捉え方が変わる。古典と向き合うことは、まさに自分の世界を広げることに繋がるのだ。
最後に、田中ひさてるさんの 「GoF デザインパターン チートシート」 を紹介する。この記事にはデザインパターンの乱用について釘を刺すベテランならではのアドバイスが書かれている。
Happy Coding 🎉