歴史を学ぼう
今更ながらContainer/PresentationalPatternに触れる機会がありまして、実際に触れていく中で色々とお気持ちなどなどを語りたく、記事にしてみました。
今更ながら学ぶContainer/Presentational Pattern
業務の中で、Container/Presentational Patternのデザインパターンで実装をしていたのですが、そもそもこのパターンが何なのか、何をモチベーションで使われているのかがいまいち理解できなかったのでちゃんと学んでみました。
Container/Presentational Patternとは何か
1行で説明すると、UI/ロジックの関心の分離をすることを目標にしたデザインパターンです。
UIを担うPresentational、UIを表示するために必要な要素を渡すためのContainerを置くことで、それぞれの関心を少なくすることができます。
詳しく説明していきましょう。
Presentational
UIに関わるものに対しての機能を持ちます。
UIに関わらないことについては何も持ちません。データも自身では持たず、Propsで値をもらい、その値を加工することなく表示します。
※UIに関する状態、例えば開閉状態などであれば持つこともあります。
Container
コンテナはアプリケーションのロジックを担当して、最終的にPresentationalコンポーネントで描画するためのデータを渡すことを目標にしています。
- APIの呼び出し
- 状態管理、例えばstoreへのアクセスなど
- Presentational層で使いやすいデータへの加工
などなど、ロジックに関わることであれば全てこの層で行います。
一方でUIについては何もしません。Presentationalコンポーネントをレンダリングするのみで、Containerではスタイルを含めてUIに関係するものを何も持ちません。
Container/Presentational Patternは結局何を解決したのか
Container/Presentational Patternが解決したのは責務を完全に切り分けるというところです。
FEで使われるフレームワークではUIとロジックを同一のファイルに配置することが可能です。
1ファイルでUI/ロジックについて書くことができる利便性がある一方、どちらも書けてしまうことで混沌としたコンポーネントともなりえます。
責務を完全に分けることで、デザイン面の修正であればPresentationalをいじれば良い、かつ、ロジックを含まないため誰でも変えうることができる。
ロジックであればContainerを修正すればよいとはっきりと責務が分かれることで実装などがスッキリします。
また、PresentationalはUIだけを示すので、再利用性も高めやすい(ロジックがContainerに依存するので、同様のUIであればContainerがデータを加工することで対応ができる)のも嬉しいです。
個人的に感じたポイント
ここからは個人的に感じたポイントについてお話しします。
PresentationalとContainerを1対1にするべきかと言う問題
PresentationalとContainerを1つのコンポーネントに対して両方とも作るか、それともどちらかの分類とするかが難しいと思っています。
ロジックを綺麗に剥がせるのが1つ目のパターンです。そのUIに依存するロジックや状態がContainerを配置することで必ず全て剥がせるようになります。
ですが半端なContainerが生まれるため、UI層に当たるPresenterの再利用性は低まります。
では後者のコンポーネントを分類する方はどうかとなりますが、こちらはこちらでHooksがなければContainerがPresentationalに完全依存する実装を複数することになってしまったり、また、そもそも分類するのが難しいといった問題もあります。
Hooksとの取り回しをどうするか
そもそも前提としてContainer/Presentational PatternはHooks前に生まれたパターンなのですが、HooksでもロジックとUIの関心の分離はできます。
ので、モチベーションがロジックとUIの関心の分離であればContainerはいらず、このデザインパターンにする必要はないです(とりわけ個人でやるプロジェクトなど小さい場合はファイル数を肥大させるだけかもしれないです)。
HooksでロジックとPrensentationalコンポーネントを分けることができるようになった一方で、HooksをPresentationalコンポーネントで呼び出すと、UIの再利用性が下がります(Propsとして受け取る方が再利用性が高まるので)。
うまい塩梅を考えないと、HooksとPresentationalコンポーネントが乱立し、ひたすらファイル数が肥大化する危険性もあります。
まとめ
個人的には現代のFE、例えばReact/NextであればHooks、Vue/NuxtであればComposableのようにロジックの切り出し、再利用をできる状況なので、このパターンに囚われすぎる必要はないのかなと思っています。
(提唱者も「このパターンに固執するな」と言及していたりします。)
ですが、再利用性や疎結合といった概念を考えると、このデザインパターン自体はうまく使えば非常に優れる作りにできそうだなと思います。
最後に
こちらはTLB Enjoy Developers Advent Calendar 2022の17日目の記事になります。
明日は@magatakoheiさんの記事になります。