Viewに依存する処理はHooks層に、依存しない処理はUseCase層に書く
責務の似たUseCaseとHooksの関係について
イメージとしては、殆どUseCase == Hooksという立ち位置
UseCase層が2つあるイメージ
ただし、Reactをやっている以上、Hooksは必須であり、UseCaseはoptionalとなる
UseCaseがある場合は、Hooks→UseCase→Repositoryとやり取りをする
UseCaseを省略した場合は、Hooks→Repositoryとやり取りをする
毎回UseCaseを省略せずに書いてもよいが、そうすると
以下のようなただ受け流すだけの関数が乱立して無意味なので省略している
code:usecases.ts
import * as Repository from 'repositories.ts'
export const getPost = (postId: PostId) => {
return Repository.getPost(postId);
}
UseCaseに書くか?Hooksに書くか?
結論としては、
Viewに依存するならHooks層に書く
他のhooksに依存するならHooks層に書く
そうでないならできるだけUseCase層に書く
UseCaseに書けるならできるだけUseCaseに書きたい
ただ、外部libraryのhooksに依存している処理はHooks層に書くしかない
例えば、
react-queryのuseQuery
reduxのuseSelectorやuseDispath
react-hook-formのuseForm
Next.jsのuseRouter
react-navigationのuseNavigation
etc.
理想的には、Viewのlibraryが変わってもUseCaseには影響しないようにする
例えば、同じドメインを扱うweb(React)とmobile(RN)の実装がある場合、
この辺は同じになる
Type
Entity
Usecase
Repository
この辺は同じだったり変わったりする
Hooks
この辺はけっこう変わる
View
というイメージ
例えば、web/RNのroutingを見た時
webのNext.jsではuseRouter
RNのreact-navigationではuseNavigation
と言ったように、routingに使用するhooksは異なるものになる
ここの変化を吸収するのがHooks層になる
UseCaseやRepositoryには影響しない
例えば、webではpaging、RNではinfinite scrollにしたい場合、
webではuseQuery
RNではuseInfiniteQuery
にするだけで良い
UseCaseやRepositoryには影響しない
今までswrを使っていたが、今後はreact-queryにする、のような方針転換があった時
Viewにも依存せず、Hooks層のみの変更で済む
ViewやUseCaseやRepositoryには影響しない
例えば、formのlibraryを変える時
今まではredux-formを使っていたが、今後はreact-hook-formにする、のような方針転換があった時
HooksとViewの変更だけに留められることを目指す
UseCaseやRepositoryには影響しない
理想的には、ReactからVueに変わった時も、ViewとHooksを変えるだけで済ましたい
たぶん完全には無理だけど、何も考えずに実装しているよりはマシなはずmrsekut.icon
Hooksはある程度、Viewの都合に合わせた粒度になる
同じ機能は凝集させるが、それでもViewに依存して分けることも多い
例えば、会員登録フォームに(username, email, password)の3つがある時、
デザインによって、以下のようなことが考えられる
これら3つを1ページに表示する
1ページ1フォームにして、3ページで表示する
場合にも依るけど、前者は1つのhooks、後者は3つのhooksにもなり得る
凝集させる目線では後者も1つにしたいが、formを作るlibraryなどにもよって異なる
折衷案として、1file内に、3つのhooksを定義する感じになると思われる