!より良い開発をすべく日々奮闘しているプログラマーのブログです。設計に興味があります。はじめに今回はSymfonyフレームワークにおいて、どのようにデザインパターンが使われているかについてのお話します。Editionをベースに解説しています。Symfony4系でもコードベースはそれほど変わっていないと思います。これまでにデザインパターンをなんとなく勉強したことはあるけど、実務で活かせた経験がないない。メリットがいまいち分からなかった。いった方が「なるほど。いう使い方をするのか」と気づいてもらえればうれしいです。それでは本題StrategyパターンStrategyパターンはオープンクローズドの原則に則っていて、ロジック(ここではStragetyと呼んでいます)の切り替えや追加を簡単に行えるようするデザインパターンです。GofのStrategyパターンは、最も有名なデザインパターンがの1つではないかと思います。通常フレームワークでは利用する「ロジックを簡単に切り替え」たり、「拡張点があらかじめ提供」してくれています。「ロジックの切り替えとは?」と思った方もいるかもしれませんが、例えばMySQLやPostgreSQLといった自分が使いたいデータベースを自由に選択することができます。他にもキャッシュの保存先、セッションの保存先など実装者はFWが用意してくれた多くの選択肢の中から自由に選ぶことができます。1つの選択肢しか取れないとなると非常に困りますよね。Symfonyにも勿論このような機能が提供されています。configファイルに記述することで簡単にロジック(ストラテジー)を選択できるようになっています。いった、ロジックの切り替えを行う機能を提供するのにうってつけのパターンが「ストラテジーパターン」になります。ここでは直接触れませんが自分の要望に合うものがなければ自作のストラテジーを用意して追加することもできます。説明が長すぎても伝わらないと思うので、実際にコードを見ていきましょう。例に取り上げるのはSessionHandlerです。自体はPHPで標準に提供されています。ManualそしてSymfonyにおける抽象クラスの定義がこちら。doDestroy($sessionId);}各サブクラスではこれらの抽象メソッドが実装していくこととなります。愚直にコードを書くと以下のような利用イメージとなります。各ストラテジーとなっており実装者は自由に選択することができます。用いた例ですが、Symfonyでは下記の通りconfigを設定することで利用できます。}ここまで見てきて分かることは、実際のところこのSessionクラスにおいては1つのストラテジーのみが利用できることとなっています。Symofnyにはコンパイルフェイズ(Bundleの起動)があり、選択された1つのSessionHandlerがDIコンテナによって注入されることになります。このSessionHandlerはアプリケーションの実行時に変える必要がないため、configの設定に応じた唯一のSessionHnaderだけが注入されているのは理にかなっていると思います。実務で書くStrategyパターンは実行時(ランタイム)で決まることが多いと思います。実行時に使うストラテジーを変更したい場合には、下記記事が参考になりますので見てみるとよいと思います。Methodパターンと見ることもできます。いったサブクラスで実装されています。パターンは単に継承を活用しただけなので、それほど難しいパターンではなく実は無意識のうちにわりと書いていたりするのではないかと思います。できるようにする設計パターンです。個人的にとても好きなデザインパターンの1つです。以前、別の記事でSymofnyのコントローラーの実行時間の計測にはDecoratorパターンが利用されていると紹介したことがあります。今回は別の箇所で、Decoratorが利用されている部分を見てみましょう。Cache機能を付け加えたのがAppCacheクラスです。メソッドがそのまま使え既存のコードには影響がありません。Cacheの機能が追加されただけとなっています。Cacheの仕組み自体はここでは解説しませんので、以下ご参照ください。symfony.comDecoratorパターンが素晴らしいのは、もし仮に独自拡張のMyKernelクラスを作りたくなったとしても、MyKernelがKernelインタフェースさえ実装していれば、いくらでもクラスを重ねることができ、機能の追加だけを行うことができます。$kernel->handle($request);非常にエレガントです。ObjectパターンはStrategyパターンの応用と考えてよいと思います。同一インタフェースを実装した何も仕事をしないオブジェクト(Strategyクラス)に差し替えることで、利用側のコードを変えることなく機能を無効化することができるデザインパターンとなります。使われていたりします。いうものもありますね。メリットとしては最初に書いた通り、こういったクラスに差し替えることでtest環境ではメールを送信しない、ログを記録しないといったことが行なえます。return;}というガード節を書かなくてはならずあまりいい感じはしないですね。Objectパターンが利用されているケースを紹介したいと思います。Swift_Mailerクラスをみてください。いうインタフェースにのみ依存しています。クラスをみてください。sendメソッドは実際のメール送信は行わないダミーメソッドとなっています。使われるようになります。オブジェクトは、動作とそれに伴うパラメータをカプセル化したパターンCommandパターンのメリットは2点あります。Methodパターンの派生でより目的特化したものと考えることもできます。メソッドに実装します。Symofnyのどこで使われているかですが、もちろんCommadクラス(Consoleコンポーネント)ですね。実装するように書かれているのであまり意識したことはないとは思います。Commandクラスのコードを見てみましょう。}}実はexecute()メソッドはabstractメソッドではないので、厳密にはCommandパターンとは呼べないかもしれません。Commandコンポーネント開発者の意図としてはこのデザインパターン通りだと思います。Commandコンポーネントの場合、実質configure()メソッドの実装もほぼ必須だと思います。okaponコマンド自体が分離しているので、以下のドキュメントのようにあるコマンドから別のコマンドを呼び出すというようなことも簡単に行なえます。あるCompositeパターンの例では、ディレクトリ構造たどっていくサンプルコードがありますが、このFormObjectもまさにそのような構造をとっています。まとめSymfonyではここでは挙げきれないほどの様々なデザインパターンが活用されています。Symfonyのコードリーディングをすることで、拡張性の考えられた設計、デザインパターンの活用どころがわかるようになります。Symfonyのコードリーディングにチャレンジしてみてください。