【技術】MVVMになじめなかった理由を考えてみた
初めに
アプリの構造を考えたときに、MVCかMVVMかどちらにするか悩むことがあると思います。私はこれまでJavaのSpringBootの業務アプリばかり作ってきましたので、MVCにはなじみがあり理解しているつもりですが、MVVMは実務で触ったことがなく、あまりなじめずにいました。
ただ、最近フロントエンド開発にも関わりだし、Reactを触る機会がありました。その中でなぜMVVMがよくわかっていなかったのかつかめたので、忘れないうちにまとめておこうと思います。同じようなことで悩まれている方の参考にあれば幸いです。
MVCとは
MVCとは、Model/View/Controllerの3要素で成り立つアーキテクチャです。Modelはビジネスロジックを、Viewは画面表示を、ControllerはModelとViewの仲介役を務めます。
MVVMとは
MVVMとは、Model/View/ViewModelの3要素で成り立つアーキテクチャです。Model、ViewはMVCと同じ、ControllerにあたるのがViewModelになりまります。ViewModelのキーになる考え方がデータバインディングで、ViewまたはModelのどちらかでデータの変更が発生した場合に、相互にView/Modelでデータの更新が発生します。
なぜなじめなかったか
私は同期通信主体のアプリしか作ったことがなかったので、Ajax通信を使うのは検索ポップアップ画面を作る時くらい、という状態でした。なので、「Viewでの変更とModelでの変更を相互に反映する」という「データバインディング」の考え方が理解できずにいました。ただ、Reactなどの宣言的なUIを前提としたFWを触り、PropsやStateといった概念を把握することで、データバインディングの考え方が理解できました。
PropsやStateというのはReactにおいて内部的に表示するデータを管理する方法のことで、あらかじめ定義したデータ更新用の関数を使うことで、Viewの更新をModel側に反映するという考え方をしています。私は無意識に同期通信を前提に処理を考えていたので、ViewModelがControllerの代替としか思えず、どう違うのか?がわからずにいたのです。
ではなぜ最近になって腹落ちしたかというと、最近Typescriptを触る機会があり、非同期通信を前提とした記述になじむことができました。その中で、非同期通信として処理をするということは、Viewから送信された情報をModelに渡し、Modelから帰ってくる情報をViewに渡す、という流れを一組で実装しなくてよいと理解できたのです(非同期通信なので当たり前なのですが)。
MVCとMVVMの決定的な違い
MVCとMVVMは、同期通信になじむのか、非同期通信になじむのか、という考え方の違いがあるのではないかと思います。つまり、通信の考え方が一方通行なのか、双方向なのかということです。
- MVCの場合 : 通信は、V->C->M->C->Vで画面から画面までの通信が一組で実装される。(C->M->Cの部分は一対一対応し、呼び出し元のCとデータを返す際のCのメソッドは一緒になる。)
- MVVMの場合 : 通信は、V->VM->Mと、M->VM->Vの二組に分割されて実装される。(VM->MとM->VMのVM部分は異なるメソッドで実現され、Callbackに後者を指定することで結び付けられる。)
上記の差によって、MVCの場合はVが必ず処理の起点になります(一方通行)が、MVVMの場合はVからVMを、MからVMを呼び出す処理がそれぞれ実装されるので、VとMそれぞれが起点の処理になる(双方向)のです(つまりこれがデータバインディングの考え方のキーなのです)。ここが腹落ちした時点でやっとデータバインディングという考え方を表層的な意味以上に理解できた気がします。
終わりに
今回はMVVMとMVCアーキテクチャの違いについて、自分なりに理解した内容をまとめてみました。あくまで個人の見解のため、間違っている点があればご容赦ください。