フロントエンドのコンポーネント設計について

2020年2月7日

はじめに

4月よりフロントエンドエンジニアとして活動開始して、約3か月がたちました。
ちなみにAngularを使っています。
その間にフロントエンド開発において、コンポーネント指向での設計やら、実装などを経験したものをつらつらとまとめていきます。

コンポーネントとは

フロントエンドにおける、Component(コンポーネント)とは、画面表示に責任を持った部品、または部品を集めて作成したページみたいなイメージです。
このComponent部分は、設計によりどの程度の大きさになるのか変わってくる部分になるかと思います。
現在では「Atomic Design」を参考にコンポーネントの設計をすることが多いようです。
ただ、私は初めてComponent指向での開発を行っていて、正直Atomic Designによる実装を行っても無駄が増えるだけだと思ったので、真逆のいったん大きいページベースのコンポーネントを作成して、そこから共通部品切り出してコンポーネント化する、といった形で開発進めています。
※Atomicデザインの場合は、button や labelなどの最小単位の部品(Atom)をコンポーネント化して、それを組み合わせてページを作成していくらしいです。
詳しくはこちらから

Presentational ComponentとContainer Component

AngularでComponent指向で実装する際に、Presentational ComponentとContainer Componentとでそれぞれ役割を分けるといいらしい、とよく記事に書かれているのですが、最初はどのように実装すればいいのかイメージがつきませんでした。

Presentational Componentは画面表示のみに責務を持っていて、
Container Componentは入力に対する処理と結果に責務を持つ

らしいのですが、まず第一にContainer Component っていう名称がわかりづらい
役割を分けたいっていうのはわかるのですが、Containerってなんやねん、、、ていう状態でした。
Presentationalはわかる。
表現とかいう意味だし、見た目を意味してるんだなーってわかるし、そしたら画面表示だけするって言われても納得。
けどContainerはわからん。
和訳すれば、容器とか、入れ物って意味だけど、それがなんでロジック側と結びつくの????って感じでした。

もうそれがわかりづらすぎて、合っているのかわからないけど、Angularで使う際には画面表示するための動的な変数とか用意したり、または必要な部品を取りまとめて一つのページを作ったりする部分で使っていたので、
Container Componentはページ単位での処理を扱うコンポーネントとして、チーム内ではPage Componentと名称を変えて使っています。
Page Component内に、Presentational Componentを配置して、@Inputと@Outputを活用して画面表示と入力に紐づく処理とで責務を分断するようにしています。
なんでContainerになったのかわからないですが、きっとデータを取りまとめる一つの箱みたいなイメージのコンポーネントだからなんですかね。。。?
それにしてはContainer Componentって色々な処理持ちすぎてますよね。
ここももっと分割していく必要があるのかな。。。
また困ったら考えてみようと思います。

NgRxも実装してみました

正直Reduxとか聞くのも初めてでしたが、今後のページ数が膨大になることなどを考えると、状態管理する個所は一つにまとめておくべきだ、という結論になったので、 NgRxも実装してみました。

これもまた難易度が高い、、、理解するのにとても時間がかかりました。(今でも完全に理解しているわけではない)
ただ書いていて思ったのは、それぞれの処理がものすごく疎になるなぁという感じでした。
通常であればコンポーネントで発生したイベントと、そこに紐づくデータ取得の処理ってメソッドの呼び出しなどで実装するから、少なからず結びつくと思うんですよ。

けど NgRxってそこを疎結合にするみたいで、
コンポーネントでイベントが発生すると、コンポーネントでは「こんなアクションが発生したぞー!」って声を上げるだけ。
そのあとデータ受け取りとかは一切気にしない。
そんで NgRx側は、そのアクションの受け取り口があって、そこからアクションに応じてReducerが処理を始めて、Storeに結果を反映するだけ。
コンポーネントの状態とか、どのコンポーネントがイベント発生させたのか一切気にしない。
後はObservaerさんがよしなに処理してくれて、値が書き換わったらAngularさんが変更検知して画面の表示変えてくれる。
めっちゃ便利。

けど書き方がすごく抽象的なので、難しい。
保守とかでちゃんとこの部分理解する人がいる前提ならがしがし入れちゃっていいかもって思うけど、技術的に期待できない場合には、入れないほうがいいかもと思いました。
私は今フリーランスとして案件の開発に入らせてもらってるけど、開発が終わったら別のところいく可能性が大きいし、後のことを考えておくと、どこまでやっていいのか、、、と悩みどころですね。

今の所は全ページで状態管理しているであろう最低限の情報のみstoreに格納して、そのほかはServiceに持たせちゃってます。
これも状態管理している箇所が複数になっているから、 NgRx入れる意味ないんじゃないの?って感じなんですけどね。。。
今の所はプロトタイプなので、作りながら必要であればすべて NgRxで実装して、不要と判断できたら、現在 NgRx実装している箇所は全て排除して、状態はserviceに持たせて管理させて行こうと思います。