CSD研修を通してGoFのデザインパターンの奥深さを感じ再学習の機会が訪れてる話
この記事は1年以上前に投稿されました。情報が古い可能性がありますので、ご注意ください。
本記事の狙い
こんにちは、モバイルアプリエンジニアの内田です。
先日6/27-30の4日間、Certified Scrum Developer(以下CSD)研修を受講しました。講師は『レガシーコードからの脱却』の著者David Bernstein氏です。
オンライン認定スクラムデベロッパー研修 by David Bernstein
O'Reilly Japan - レガシーコードからの脱却
僕は研修を通して特に、Gang of Four(以下GoF)のデザインパターンに対する認識が大きく変わりました。今回の研修を受講したことで何を学び、考え方がどのように変わったのか、そしてCSD研修はどのような方におすすめだと感じたかを紹介します。
なぜDavid氏の研修を選んだか
テスト駆動開発やリファクタリングといったXPのプラクティス、オブジェクト指向設計を書籍で学んできました。しかし、独学であるため適切に実践できているかという不安がありました。また様々な技術情報の中で、アジャイル開発、スクラムチームにおける開発者として必要なコアな技術面のスキルはどんなものか、なんとなくの感覚はあるものの確信までは至っていませんでした。
CSD研修を受講することで自信をつけ、組織に技術を広める活動に活かせることを期待していました。
講師のDavid氏については、研修以前に著書を読んだことがありました。またRSGT 2023の基調講演でも話を聞き、その情熱あふれる人柄を感じていました。過去の受講者からの勧めも受けていました。
そのため刺激に溢れ、ソフトウェア開発へのエネルギーが沸き起こるような研修になるだろうと考え受講を決めました。
研修内容
研修はHPにもある通り4日間で、
- スクラムフレームワーク開発者エッセンシャル (ScrumFramework Developer Essentials)
- デザインパターン開発者エッセンシャル (Design Pattern Essentials for Developers)
の2パートと、さらに細かいスクラム・分析・デザイン・開発の4セッションに分かれて学びます。スクラムとデザインパターンのどちらも、初めて学ぶ人がついて来れるような丁寧な導入から始まり、グループワークや講師からの問いを通して実践の難しさや奥深さを感じられるところまで進む、振り幅のある内容でした。
またDavid氏は研修の意図として
「資料を通して様々な知識を提示するが、それらは氷山の一角に触れるだけ。研修後も資料をガイドとして活用し、各自が必要だと感じたものを現場で実践し深掘りして欲しい」
とも話しており、さらなる探究のための書籍も複数紹介されました。
特に刺激を受けたGoFのデザインパターンについての話
GoFのデザインパターンは全部で23種類ありますが、研修ではその内の12種類を扱いました。
デザインパターン (ソフトウェア) - Wikipedia
研修ではまず次のような導入がありました。
デザインパターンとは一般的に「コンテキストの中に繰り返し見られる問題に対する一般的な解決策」ですが、それにとどまりません。各デザインパターンにはUMLやコードには現れない意図、つまりそのデザインパターンが達成しようとしているものがあります。その意図を理解することこそが重要です。
Big Design Up Frontでデザインパターンを見出すことは難しいため、問題に加わっている力を見極めていきながら、適切なタイミングで適切な箇所でコードを切り分けデザインパターンを用いることが重要です。各デザインパターンの意図を学ぶことで、どのような時にデザインパターンが現れるか識別するのに役立つのです。
導入に続いてGoFのデザインパターンそれぞれの
- 意図
- カプセル化しているもの
- 適用例
- 適用によって得たもの・失ったもの
を学んで行きました。また複数のデザインパターンを学び進める中で、似ているデザインパターンの違いを問いとして投げかけられるなど、デザインパターン同士の意図の違いにフォーカスした内容でした。
研修受講前のGoFのデザインパターンへの理解
僕は研修受講前
- 数年前に『Java言語で学ぶデザインパターン入門』でGoFのデザインパターンを一度学んでいた
- 『パターン指向リファクタリング入門』を読んだり、fukabori.fmでのt-wadaさんが出演されたGoFのデザインパターン回を聞いてた。そのため「デザインパターンは最初に全て見出すものではなく、イテレーティブに開発を進める中で見出すもの。リファクタリングに方向性を与えるもの」という理解はあった
という状態で大体分かったような気持ちでいました。
またGoFのデザインパターンの一部は特定の言語が抱える事情に由来していたり、継承を用いるものもあります。しかし言語が進化したり、継承の弊害もあるため、現代では使わなくなったデザインパターンも存在するという話を聞いていました。この話を拡大解釈して捉えており、継承を用いるデザインパターンは使うべきではなく、言語によって不要なデザインパターンもある。そのため、学ぶことの重要性は現代においてそれほど高くないと考えていました。
増補改訂版Java言語で学ぶデザインパターン入門 | SBクリエイティブ
パターン指向リファクタリング入門~ソフトウエア設計を改善する27の作法
48. GoFデザインパターンとDI (前編) w/ twada | fukabori.fm
49. GoFデザインパターンとDI + リファクタリング (後編) w/ twada | fukabori.fm
しかし、研修直前にDavid氏から紹介された『Head Firstデザインパターン』を事前学習として読み、さらに研修本編を受講することで、これまでの認識は適切ではなく、またGoFのデザインパターンへの理解が浅かったことを実感しました。感じたことは大きく3点あります。
O'Reilly Japan - Head Firstデザインパターン 第2版
1. 設計原則との繋がりを意識したことがなかった
『Head Firstデザインパターン』でも研修でもいくつかの設計原則を紹介し、GoFのデザインパターンにそれらの設計原則がどのように適用されているか解説されていました。
特に印象に残っているのは
- 『Head Firstデザインパターン』: オープン・クローズド原則(以下OCP)を用いて、各デザインパターンがどのような拡張に開いていて、どのような変更に閉じることで問題を解決しているかを説明
- 研修: カプセル化を用いて各デザインパターンが何をカプセル化しているのか、意図を説明
という2点です。
僕はこれまで各デザインパターンを理解する時、DRY原則を主軸としていました。そのため実務でデザインパターンを適用する流れとして
- 機能追加の設計をする(フローチャート作成)→既存の設計と比較し重複部分を見つける
- 機能追加の実装をする→重複コードを見つける
と、まず具体的に考えてから重複を発見することがスタート地点でした。そのため、デザインパターンへ向かい始めるまでが比較的重めのプロセスだったと感じます。
しかしOCPの考え方を用いると、検討中の機能追加は何を拡張したいのか、何は変更したくないのか早い段階から抽象的に考えることができそうだと感じます。そして既存コードとの良い抽象化に気づいたら、まずリファクタリングで拡張のためのスペースを空け、その後に拡張するというDavid氏の教えをより実践しやすそうだとも考えています。
またこの気づきの大元は、僕の各設計原則への理解が浅かったことだと思います。設計原則を説明する文章を読んでおおよその雰囲気は分かっていても、それを常に実装に落とし込めるレベルまでの理解には至っていなかったことに気づきました。設計原則を通してGoFのデザインパターンを学ぶことで、GoFのデザインパターン自体の理解のみならず、設計原則の理解も促進されると感じたのです。
2. 実装例の形に囚われ意図を意識したことがなかった
GoFのデザインパターンについて過去に一度学んだ際、本に出てくる例や、それまでの自分自身の経験で各デザインパターンを適用できそうなものをイメージして理解していました。つまり各デザインパターンの意図ではなく1〜2個の実装例を理解するのみでした。
しかし研修を通して、意図を満たしていれば実装方法が異なっていても同じデザインパターンだと言えることを学びました。実装例のみの理解では狭く、しかも不正確な理解になることさえあると気づいたのです。
典型的だったのはTemplate MethodとStrategyの違いです。僕は
- Template Method: 継承によって拡張を実現する
- Strategy: 委譲によって拡張を実現する
という違いがあると理解していました。しかし実際には
- Template Method: アルゴリズムの手順の変更に対して閉じ、手順の一部の拡張に対して開いている
- Strategy: あるアルゴリズムの拡張に対して開き、他のアルゴリズムの変更に対して閉じている
という意図であり、その実装方法が継承か委譲なのかは本質ではないことを学びました。
Template Method パターン - Wikipedia
Strategy パターン - Wikipedia
その他にもクラス図は同じ形でも意図が違うデザインパターンが存在すること、クラス図は同じ形でも意図を満たしておらずデザインパターンには当てはまらない実装も存在することを学び、意図を学ぶ重要性を感じました。
3. デザインパターン間の繋がりを意識したことがなかった
『Head Firstデザインパターン』でも研修でも、似ているデザインパターンの比較、繋がりへの言及がありました。構造・振る舞い・生成というGoFのカテゴリー分類が同じもの、例えば同じ生成に属するBuilderとFactoryが似ていたり、同じ構造に属するAdapterとFaçadeが似ているのはすぐに想像がつきます。しかし似ている全く考えたことがなかったケースがいくつもありました。
例えばDecoratorとChain of Responsibilityはその筆頭です。GoFのカテゴリー分類ではDecoratorは構造、Chain of Responsibilityは振る舞いに属しています※。しかし、「複数の処理を連続して実行する」という点で共通しており、「処理をどのタイミングで終了するか」が異なるという見方をすると似たものとして見えてきます。この違いはデザインパターンの意図の違いが現れているのであり、やはり実装例だけではなく意図を理解することが大事だと再認識できた瞬間でもありました。
Decorator パターン - Wikipedia
Chain of Responsibility パターン - Wikipedia
このように、全く異なると思っていたデザインパターンも似て見えてくるものがあります。また実務で問題の中にデザインパターンを見出そうとしてたときに、それまで気づかなかった共通性に気づくことがあるのではないかと考えています。GoFのデザインパターンの奥深さを垣間見て、より深く学んでいきたいと感じました。
※もっとも『Head Firstデザインパターン』でも言及されていましたが、GoFのカテゴリー分類は必ずしもしっくりくるものばかりではなく、別のカテゴリーに属するのではと感じる人は少なくないようです。
研修を通してどう認識が変わったか
役立つデザインパターンは想像していたより多そう
現代では不要なデザインパターンが存在するという話を過剰に受け取っていました。しかし、現代でも使用機会があり役立つデザインパターンは想像より多そうだという認識に変わりました。深く学ばずにいる言い訳として飛びついていたと反省中です。
GoFのデザインパターンを学ぶことは良い設計のための訓練である
設計原則を通してGoFのデザインパターンを学ぶことで、GoFのデザインパターン自体の理解のみならず、設計原則の理解も促進されると感じたと述べました。これは、GoFのデザインパターンは設計原則を用いて適切に抽象化している例だからだと思います。
GoFのデザインパターンは、クラス図は同じでも意図が異なるデザインパターンが存在するなど、それなりに頭を使って理解する必要があるものが多く存在しています。GoFのデザインパターンを通してカプセル化やOCPなどの設計原則を適用するバリエーションを学び、頭を柔らかくしておくことで、実際の問題に取り組む訓練になると感じました。
また本当に重要なのは各デザインパターンそのもの以外のところにあるのではないのではないかとも感じました。様々なデザインパターンカタログに触れ自身の手数を増やすことはとても価値があると思います。しかし、より価値があるのは設計原則の適用方法を学ぶことです。David氏の言葉を借りると、問題には力が働いています。設計原則の適用方法を学ぶことで、その問題に働いている力を見極める能力が高まり、新たなデザインパターンを見出し適切な箇所で切り分けられるようになると感じました。
人に説明することで深い理解に至る
扱った中でも特に難しかったのがBridgeでした。GoFのデザインパターンの中でも最も難しく、一番大まかに理解している自覚は元々ありましたが、やはり研修で説明を受けても理解しきれません。それだけでなく、何がわかっていないのかわからず質問もできませんでした。
Bridge パターン - Wikipedia
David氏や研修スタッフの方からも、難しく理解に時間がかかったと聞きました。それでもとても悔しく、翌日の研修までに質問できるレベルまでは理解しようと試行錯誤していました。
翌日の研修時、David氏がBridgeを理解するに至ったきっかけを聞いてみると「人に話す・説明する経験を経て噛み砕くことができた」とのこと。
確かに言われてみると、今回のデザインパターンへの理解が揺さぶられたのはDavid氏からの問いをきっかけに自分の言葉で説明しようと考えた瞬間です。人に説明しようとすると同じように自分の理解の言語化を試みるので、それが深い理解に至る方法なのだと、今後の勉強における1つの指針を得ることができました。
Discordを活かした学び
参加者や研修スタッフの方々と、研修本編の時間以外も含めDiscordで様々な話をして様々な学びが得られました。
上記のBridgeでの試行錯誤時はあれこれ質問させていただきました。研修直後には感想戦、研修中にもあれこれチャットで
- Smart Reference ProxyはTest DoubleのSpyのことなのではないか?けれどDecoratorにもかなり近い気がする。ということはDecoratorとProxyも似てるんじゃないか?
- Cache Proxyはモバイル文脈でのRepositoryそのものだと感じる
- Chain of Responsibilityでポーカーの役判定を作ったという話が研修で出たけれど、麻雀の場合は各役を加算するのでDecoratorだと思う
→二盃口と七対子は配の形が同じだけど、二盃口が優先されるので、そこだけはChain of Responsibilityが必要そう - Abstract Factoryは本によって実装例が色々あり、入り組んだ例だとパッとAbstract Factoryだと気づきづらいことがある
などなど、デザインパターンを様々な角度から眺め楽しく理解を深めることができました。
一緒にお付き合いいただいたみなさん、理解を深めるためにとてもいい時間になりました。ありがとうございました。
今後の学習
まずはGoFのデザインパターンをより深く理解することを目指したいと思っています。具体的には、David氏に勧められた『オブジェクト指向のこころ』を読んでみるつもりです。『Head Firstデザインパターン』では扱ってないデザインパターンについても触れているそうなので、楽しみです。
オブジェクト指向のこころ - 丸善出版 理工・医学・人文社会科学の専門書出版社
またずっと避けてきた原典にも触れてみようと思います。David氏によると、本の最初に書かれているGoFのアドバイスは後ろに続くデザインパターンと行き来しないと理解することは難しいそうです。研修のおかげで理解しやすくなっていることを願いたいです。
オブジェクト指向における再利用のためのデザインパターン(改訂版) | SBクリエイティブ
さらに、2009年にGoFメンバーによって再整理されたデザインパターンの記事を読んでみて、デザインパターンへのより現代的な目線を学んでみたいと思っています。
Design Patterns 15 Years Later: An Interview with Erich Gamma, Richard Helm, and Ralph Johnson | InformIT
そして理解するだけでなく、人に説明することで自分の理解を深めていきたいと思います。まずは自分の理解を人に説明するまとめ資料、特にデザインパターン同士の比較表などを作っていきたいと思います。
また、より実践的な学習の機会としてAdvanced Certified Scrum Developer研修の受講も検討していきたいと思っています。
まとめ
GoFのデザインパターンはそれ単体で設計の手数として知っておく価値がある例ですが、適切に設計原則を適用し抽象化された例でもあります。そのため、設計原則と合わせて学ぶことで設計原則の理解が深まり、実際の問題に取り組む訓練になると感じます。問題に働いている力を見極める能力も高まり、新たなデザインパターンを見出し適切な箇所でコードを切り分けられるようになると感じました。
そのため現代のスクラムチームの開発者でもGoFのデザインパターンを学ぶ価値があると思います。
その他の印象に残ったこと: まずは設計が最初なのではないか
CSD研修でデザインパターンの話が割合として多い話は噂で聞いていました。しかし実際受講すると、テスト駆動開発やリファクタリングといったXPの技術プラクティスを実践する時間がないことに少し驚きました。良いソフトウェアを作る上で重要なプラクティスであるけれど、誤った使い方をすると悪い結果になり得るから気をつける必要があるという説明はありましたが、実践の時間はなかったのです。
これについては研修後スタッフの方とも話したのですが、良い設計についての知識がなければリファクタリングの際にどの方向に向かえばいいか迷ってしまうかもしれない、なのでまず良い設計をデザインパターンを通して学んだのではないかという結論になりました。実践についてはAdvanced Certified Scrum Developer研修の中で時間が取られるそうです。
僕自身これまでテスト駆動開発をチームに広めようとした時に、テスト駆動開発の作法そのものは理解したけれど、実務で実践する際にどうやらまずどんなオブジェクト・メソッドから始めるかが壁の1つになっていそうだと感じたことがあります。そのためまず設計知識、そして次にレガシーコードに対していかに自動テストの接合部を作るかの知識が必要になるのではないかという仮説を持っています。
研修の構成から、David氏も同じように設計知識を身につけるのが最初だと考えているのではないかと推測しました。
CSD研修をどんな人に勧めたいと感じたか
アジャイル開発や設計をこれから学ぶ人にも、すでにある程度知っているけれどその意図を深く理解したい人にも勧めたいと感じました。
これから学ぶ人は、スクラムチームの開発者として必要な幅広い知識の全体像に触れ、歩み出す入り口まで連れて行ってもらえそうだと感じます。
すでにある程度知っている人でも、ここまで書いてきたようにより深い理解、学び直しの機会になることを実感しました。