はじめに
Angular を学習しだして現在1ヶ月ほど。すでに作成されているアプリケーションに機能追加をするためにコード理解を進めているが、その中で**「HTTP によるバックエンドとの通信において、サービスにはどこまで処理をさせるべきなのか」**という疑問がわいた。調査してもあまり理解しきれなかったため、Angular Japan User Group で質問したところとても丁寧に回答してもらえ、自分なりに納得できたためそれらをまとめる。ちなみに実際にした質問のリンクはこちら。
Angular Japan User Group には、質問をした当日に丁寧な回答をくださる方がたくさんいらっしゃり非常に助かったので、Angular でお困りのことがある人はぜひ相談してみるとよいと思います。
疑問
詳細に関してはこちらの一連の流れを見てもらうこととし、疑問に関して簡単に説明する。
API からデータを取得するサービスにおいて、レスポンスの処理には以下2つのパターンが想定される。
- サービスは HTTP リクエストを送って返ってきたレスポンスを渡すまでとし、レスポンスの処理はコンポーネントで行う
- サービスは HTTP リクエストを送り、返ってきたレスポンスの処理までサービスが行う(コンポーネントは処理後のデータを受け取る)
私が読んでいたコードは上記 1 に相当しており、「1 は複数のコンポーネントで同一サービスを使用する際、似たような処理をそれぞれのコンポーネントで行う必要があるため冗長ではないか?2 の方が適切ではないか?」というのが私がもった疑問である。自分で軽く調査したり考えてみたものの、1 のパターンが肯定されるケース(1 のメリット)や 2 のパターンが否定されるケース(2 のデメリット)が自分で思いつかなかったため、Angular コミュニティに相談した、というのが一連の流れである。
ちなみに Angular 日本語ドキュメンテーション - サービスの追加では、以下記述があったことも疑問を強くした要因の一つである。
コンポーネント内では直接データの取得や保存を行うべきではありません。もちろん、故意に仮のデータを渡してもいけません。 コンポーネントはデータの受け渡しに集中し、その他の処理はサービスクラスへ委譲するべきです。
結論
結論としては**「サービスで処理をすべき(※ただし複数考慮すべき点あり)」**である。誤解を多く招くと思うので、考慮すべき点というのを以下で述べる。
共通処理かどうか
「そのサービスの処理が各コンポーネントに対して共通処理であるか」を確認し、**共通であればサービス内で処理を行う。**たとえば、バックエンドから以下のようなデータ配列を取得する UserService
というサービスを考えてみる。
[
user1: { age: 20, hobby: soccer },
user2: { age: 55, hobby: traveling },
...
]
このとき、ユーザ一覧コンポーネントであれば欲しいデータは [user1, user2, ...]
のようなユーザ一覧であり、ユーザ詳細コンポーネントであれば欲しいデータは { age: 20, hobby: soccer }
のような(あるユーザの)ユーザ詳細となる。この場合、サービスは共通処理とならないため、サービスでデータ加工などの処理まではすべきでない。(だからといって各コンポーネントで処理するのではなく、サービスの分割によって別サービスとしてそれらの処理を行う方が望ましいと考える。詳細は後述。)
サービス名と責務の対応関係
「サービス名から想像がつく処理かどうか」を確認し、名前と責務が乖離していた場合は**対応するようにサービスを分離する。**上記の UserService
の例だと、このサービスからユーザ一覧が得られるのか、それとも各ユーザの詳細情報が得られるのか、はたまたユーザデータ全体を得られるのかといったことが名前からわからない。もしユーザ一覧とユーザ詳細の2パターンの処理を行うのであれば、1つのサービスで処理すべきでなく、責務が名前からわかるようなサービスに分割する。たとえば、ユーザ一覧取得サービス UserListService
とユーザ詳細取得サービス UserDetailsService
のように分割して、それぞれのサービス内で処理をする。
またこの際、各サービスにて HTTP 通信の部分は共通するため、この部分はさらに UserApiService
ようなサービスに分割してあげるとより見通しがよくなる。
おわりに
サービスの処理に関して、Angular コミュニティにて質問した内容をまとめた。自力で調べたり考えたりする力はもちろん必要だが、このようなコミュニティの有識者の方に尋ねるとより高い視点からの意見をいただけるので、物怖じせずどんどん聞いていこうと思う。