Web MVCがもたらす速度低下をどう回避するか
プログラマの不注意をアーキテクチャで予防する
イワモトです。2019年9月から10月にかけ、ベルトラの速度改善に取り組みました。サーバ側の平均応答速度が2割ほど改善され満足なのですが、とある速度低下の遠因がフレームワークのWeb MVCアーキテクチャにあると気づき、モヤモヤしています。本稿で掘り下げてみます。
速度低下とその原因
本稿で掘り下げたいのは「コントローラからビューテンプレートに対して不要なデータを渡していることにより速度が低下している」状況です。
速度を重視するのであれば、無駄な処理は避けるべきです。不要なデータなら、わざわざ参照したり受け渡したりする必要はありません。なぜ、そのような無駄が生まれるのでしょうか。
考えられる原因
今回の速度改善の経験から、不要なデータがビューテンプレートに渡される原因は下記の2つに大別できると考えます。
- あるコンテンツの表示が不要となり、ビューテンプレートから削除されたが、コントローラには手が入れられなかった
- あるコンテンツの表示/非表示が、ビューテンプレート側のロジックで決まっている
1つめは「書籍詳細ページから売上ランキングの表示を削除した」ような場合です。売上ランキングデータはもはや参照不要ですが、コントローラから参照処理を削除し忘れることが往々にしてあるようなのです。
2つめは「書籍の概要文が1000文字未満の場合のみ売上ランキングを表示する」ような場合です。概要文が1000文字以上の書籍なら、売上ランキングデータを参照しなくてよいはずです。
Web MVCアーキテクチャの問題点
上記のような問題が発生する遠因は、フレームワークのWeb MVCアーキテクチャにあるのではないか、というのがぼくの見立てです。以下、詳述します。
まず、多くのWeb MVCフレームワークは、コントローラがモデルのデータを参照し、ビューテンプレートに渡すよう設計されています。そのため、データの設定箇所と使用箇所が離れることとなります。
もし両者が離れていなければ、使用箇所のみを削除して設定箇所の削除を忘れることは少ないはずです。また、特定の条件下でのみ使用されるデータを無条件に参照することも減るでしょう。
つまり、Web MVCアーキテクチャが前提としている「ビューテンプレートで使われるデータをコントローラが知っていなければならない」という制約こそが、速度低下を招く遠因なのではないかと思うわけです。
回避策1:コントローラの責務を減らす
一般的なWeb MVCフレームワークでは、3つの責務がコントローラに任されています。
- リクエストに応じて、モデルを参照/更新する
- ビューテンプレートを決定する
- ビューテンプレートにデータを渡してレンダリングする
しかし、ビューテンプレートで使われるデータを本当にコントローラが知っていなければならないのでしょうか。ぼくにはビューテンプレートが必要としているデータの参照はビューテンプレート自身に任せるのが自然な気がします。
もし、データ参照をビューテンプレートに任せられるならば、コントローラの責務は下記のようにすっきりします。
- リクエストに応じて、モデルを更新する(POST、PUT等の場合)
- ビューテンプレートを決定するために必要なモデルを参照する
- ビューテンプレートをレンダリングする
また、データの設定箇所と使用箇所がビューテンプレートのみに集中するので、懸案の問題も解消すると考えられます。
回避策2:サーバサイドをAPIに専念させる
ビューテンプレートからモデルを参照するのに抵抗感を抱く方も多いかもしれません。他の回避策として、サーバサイドをAPIの提供に専念させる方法が考えられます。サーバサイドをM、フロントエンドをVおよびCとするアーキテクチャです。
フロントエンドは門外漢ですが、Vue.jsを少し触った印象では「データの設定箇所と使用箇所が離れる」問題が起こりにくい気がします。仮に離れたとしても、無駄なデータ参照、つまり無駄なAPIコールを放置する状況にはなりにくいはずです。
したがって、この方法でも懸案の問題が軽減できると期待できます。
まとめ
本稿では、Web MVCアーキテクチャに起因する速度低下の問題と、その回避策について検討しました。
1つめの回避策は、コントローラの責務軽減でした。ビューテンプレートが必要とするデータはビューテンプレートだけが知っていればよいという発想の転換です。
2つめの回避策は、サーバサイドをAPIに専念させるアーキテクチャへの移行でした。フロントエンドのほうが問題が起きにくいと考えられます。なお、このアーキテクチャにはテストが書きやすくなる優位性もあります。新規開発では採用を積極的に検討すべきではないでしょうか。