PHPのデザインパターン
デザインパターンは、プログラミングの思考法である。
開発に関するアドバイス、レディメイドのプラクティス、ベストプラクティス、洞察の数々を提供します。プログラミングパラダイムやタスクの種類によって、最適なデザインパターンが存在します。
メリット - なぜデザインパターンを使うのか?
プログラミングでは、ある種の問題を解くことは繰り返しになるので、その問題を解くために一つの方法を選び、その方法を繰り返し続けることは理にかなっています。
特にチーム開発では、全員がアプリケーションの開発方法(どのデザインパターンに従うか)を知っており、それを適用するだけなので、大きなメリットが生じます。そうすれば、変に書かれたコードをデバッグしたり、作者が意図した原理を理解しようとしたりする無駄な数十時間を省くことができるのです。
MVC - デザインパターンの使用例
私の好きなデザインパターンは「MVC」(「Model View Controller」から)です。これは、アプリケーションを3つの独立した層に分割し、互いに順次呼び出し、データを受け渡すというものです。
例えば、ページをレンダリングする際に、まずどのようなタイプのページなのかを判断し (例えば、カテゴリの詳細)、 CategoryController を detail メソッドで呼び出すように見えるかもしれない。
具体的な例(だいぶ簡略化しています)。
class CategoryController{public CategoryManager $categoryManager;public function actionDetail(string $id): void{$this->template->id = $id;$this->template->category = $this->categoryManager->getById($id);}}
注意:
これは、
MVCデザインパターンの原理を説明するためのサンプルコードに過ぎません。実際の実装では、例えば
CategoryManagerのインスタンスを取得して、それを property に渡す方法をさらに考えなければならないでしょう。一般的に、この種のタスクにはDependency injectionが使用されます。
カテゴリの詳細ページをレンダリングする前に、まず CategoryController が呼び出されて実際のリクエストを受け取り(つまり、ルータが URL などで取得した特定の ID のカテゴリ詳細をレンダリングします)、データを取得し(対応する Model に問い合わせ)、最終データをテンプレートに渡してレンダリングします。
この原則の大きな利点は、データの表現方法(テンプレート)に依存しないモデル(アプリケーションロジック)を数多く書くことができ、結果として再利用可能なコードを実現できることです。実際、別のプロジェクトで CategoryManager を使いたい場合、単に Controller を通して特定の方法でデータを渡せば、プロジェクト自身が定義したテンプレートに従ってレンダリングされます。アプリケーションロジックは同じままで、ソフトウェア層が合意したインターフェースと責任を果たしたので誰も気にしません。
実用上の注意事項
デザインパターン「MVC」は、Nette、Symfony、Laravelなど、最近のほとんどのフレームワークで採用されています。
モバイルアプリの開発などでは、データを取得して、ページやビューの種類に応じてテンプレートにレンダリングする必要があるため、「MVC」に遭遇することもあります。
Web開発における重要なデザインパターン
一般にプログラミングには、Web開発には適さないデザインパターンが多く存在します。このリストでは、私自身が使っている、そしてあなたが精通しているべき最も重要なパターンを説明しています。
全デザインパターンの一覧、使用例、詳しい解説は別ページで紹介しています。
- MVC** - アプリケーションをモデル(アプリケーションロジックとデータ)、ビュー(テンプレートとデータビュー)、コントローラ(モデルとビューをつなぐ)に分割する原理です。
- Dependency Injection - クラスインスタンスを作成する代わりに、自動的にインジェクトされたいわゆるサービスを定義します。コードはすべての依存関係を認め、個々のパーツを交換することができ、動的にアプリケーションを構築します。
- Singleton (シングルトン) - 各クラスは1つのインスタンスしか持たない (私は個人的にこれを
Dependency injectionと組み合わせて使っている。各サービスはアプリケーション全体で渡されるインスタンスを1つだけ持つ)。 - 遅延初期化(Delayed Initialization)** - 最初に必要なときにオブジェクトのインスタンスを作成する。
- Adapter - 互換性のない 2 つのクラス間で通信を行う必要がある場合、
Adapterはデータをある型から別の型に変換します (典型的には、PHP のネイティブデータ型からデータベースデータ型に変換し、またその逆を行います)。 - コマンド - 特定のタスクを直接実行するのではなく(例えば、メールを送信する)、それが起こるはずだったことを記憶しておくだけです。その後、別の、あるいは同じプロセスがその要求を拾って処理する。主な利点は、アプリケーションを遅延処理(したがって非常に高速)し、失敗したアクションを再試行し、呼び出しのパラメータを単純に保存することができることです。同時に、これによって、APIなどを介して、さまざまなクライアントからのリクエストを受けることができるようになります。送信されたアクションは、キューに入れ、優先順位をつけ、場合によっては評価前にキャンセルすることも可能です。
- 戦略** - ある種のアルゴリズムやオブジェクトをカプセル化し、クライアントにとって交換可能なように変更する。
デザインパターンは他にもたくさんありますが、これらは知っておくべき最も重要なものでした。
アンチパターン
プログラミングの開発手法の中には、デザインパターンと正反対の「アンチパターン」とされるものがあります。通常、簡単にデバッグやメンテナンスができない、「魔法のように」動作する奇妙なコードを生成するテクニックです。
典型的な例は、グローバル変数の使用である。