テストという言葉の定義はどこにあるのか?人によって、関わる仕事によってPHPerの中でもテストという言葉の認識のズレがあるなーと感じている今日この頃です。 人によってはモンキーテストと呼ばれる懐かしい物をさす人がいる。また、受け入れテストを想像する人もいるだろう。イケてるエンジニアの人々にはユニットテストを想像する人もいるかと思います。
MVC(MVC2的なMVC)におけるモデルにも同じ事が起きていることにみんな気づいているだろうか?
僕は最近このモデルの認識のズレがあるような気がします。まあ、モデルとは一口にいってもいろいろなモデルがある訳で、それぞれが違っている意味合いになってくるので仕方ない事でもある気がします。
ただその違いがうまく認識できないと、コミュニケーションの齟齬というか、そういったことが起きる。
そもそもMVCとは?
今回はWEBアプリケーション(PHP)界隈で言われるMVCにおけるモデルについて考えてみたいと思う。
PHP界隈におけるフレームワークで超絶人気なCakePHPでのモデルについて見てみましょう。
モデル(Model)
モデル層はビジネスロジックを実装するアプリケーションの部品を表します。これはデータの検索、アプリケーションに意味のある形への変換、また処理、検証(validating)、関連(associating)、そしてデータを扱うことに関する様々なタスクに責任をもつことを意味します。
一見して、モデルオブジェクトはアプリケーションに使用しているであろうデータベースとやりとりする最初の層と見ることができるでしょう。 しかし、一般的にこれはアプリケーションを実装するものの主要な概念を表します。
ソーシャルネットワークのケースでは、モデル層はユーザのデータを保存する、友人の繋がりを保存する、ユーザの写真を保存または検索する、新しい友人の提案を検索する、等々のタスクを引き受けることでしょう。 このとき、モデルオブジェクトは「友達(Friend)」、「ユーザ(User)」、「コメント(Comment)」、「写真(Photo)」と考えることができます。
※引用元: MVC(Model-View-Controller)を理解する
「モデル層はビジネスロジックを実装するアプリケーションの部品を表します。」
たしかにその通りだと思う。しかしこの後の記述されている以下の内容は本当に良い事なのだろうか?
「これはデータの検索、アプリケーションに意味のある形への変換、また処理、検証(validating)、関連(associating)、そしてデータを扱うことに関する様々なタスクに責任をもつことを意味します。」
これはいいのか?
少なくとも僕は違和感を感じている。
オブジェクト指向設計原則の単一責任の原則を考えてみてもらいたい。
単一責任の原則とは?
クラスを変更する理由は1つ以上存在してはならない。
この原則では「役割(責任)=変更理由」と定義している。 クラスの変更理由が2つ以上ある場合、クラスの役割も2つ以上あると考えることができる。基本的に、1つのクラスに割り当てられる役割は1つになるようにする。
※引用元アジャイル設計と5つの原則
あれCakePHPのモデルの責任が多過ぎるのは僕だけでしょうか?
- データの検索
- アプリケーションに意味のある形への変換、または処理
- 検証(validating)
- 関連(associating)
責任が多過ぎる。 よく「CakePHPのモデルはActive Recordを含んでて…」的な話はあることだし、あの有名なスライドにも「 ActiveRecord やORM,DAOだけでは無いということ。」書かれている。
確かにActive Recordを含んだモデルになっている。 ただし、データソースは別オブジェクトに委譲されているのはわかる。結局ところCakePHPはデータを扱うことの たしかにwebアプリケーションはデータベースとのやり取りが中心なシステムが多いし、CakePHPみたいなアプローチも十分ありなアプローチだとは思う。 あと誰にでも扱いやすいというメリットもある。
あとモデルというかロジックを書くところをモデルクラスの中で固定してしまえば、誰でもロジックをモデルの中に書くので分散しなくて済む。 しかし、それは良い事なのだろうか?
僕は絶対にダメだとも言えないし、絶対に正しいとも言えない。 ただ、Active Recordを含んでるからこそDBのテーブル間の関連が無いモデルの連携がやりにく。(まあ僕はLibとかbehaviorsを活用するわけですが…
Symfony2から見るモデル
まさしくここに書かれている通りだと思う。
Symfony2による実践的アプリケーション開発
業務の知識を組み込む場所と捉えるのが正しいのではないのかなぁと思います。
もちろんデータも扱うし。ただし、そのオブジェクトが一つのクラスとして実装されてなくてもいいのでは?って感じもします。
エンティティ、リポジトリ、サービス、ファクトリーだとかそれぞれ役割を持たせたクラスが連携し合う事が重要ですね。
そもそもMVCとはなにか見直してみる。
わりと今日一番の衝撃を受けたのが、以下の記事
Reenskaug博士を知っていますか?
MVCは人間とそのメンタルモデルに関するものであり、オブザーバーパターンに関するものではない。
本当に心に刺さったというか、衝撃を受けたわけです。 単にソースコードをM、V、Cに分割するだけのテクニック的に捉えれた僕としては衝撃というかなんというか、自分が恥ずかしくなってくるわけです。
結論
モデルの使い方とかモデルクラスとかにとらわれずにアプリケーションを作る際になにが最適なのかってことを常に考えなければ行けないと反省しました。 それから、全力でもっとオブジェクト指向やDDDについて勉強しないとダメだということも自覚しました。がんばります。 おしまい。