Next.jsの設計をどうやるかドラフト版1

日々仕事の中でどうするのがあるべき姿か唸っているので一旦吐き出してみる。考えてばかりだと永遠にアウトプットしない気がするし
まだまだ試行錯誤途中なので、とりあえずドラフト版としてその 1 とする。色々と推敲不足なところがあると思います

現状で考えている設計案

ポイントととしては SOLID、KISS、YAGNI、そして DRY を適切に守り、Testable なものを作ることができれば理想ではないかと考えています

状態を一箇所で持つ

  • 状態が複数のコンポーネントにまたがっていると扱いづらいため、画面コンポーネントの根っこで持つのが望ましいと考える
  • fowardRef だったり Context API のような仕組みでアクセスすると状態の関係性が複雑化するので避けられるなら避ける
  • ただ状態がファットになってしまうという欠点もあり、ここをどう解決するかは課題

部品を細かくする

  • 単一責務の部品であれば UT は容易であるため
  • 基本的に SOLID 原則を守って作っていれば DI によるモックもでき、テストは容易になる
  • 但し部品が多い場合、認知負荷が上がる問題があり、ここをどう解決するかは課題

fowardRef は極力使わない

  • どこまでがコンポーネントの責務なのかわからなくなるため
    • 基本的にフローは親から子へ向かうべきで、子から親に向かうべきではない
  • .focus() を使いたいといった、どうしようもないときだけはあり
    • ただこれを使う時点で UX 的に微妙になっていないかを確認した方がいいと思う

型安全にする

  • any は使わず、unknown として TypeGuard を使い、型をアサーションすることで、論理的にも物理的にも型安全を確保する
  • これによってコーディングミスや予期せぬ結合不具合が減らせると考えている

型で縛れるところは型で縛る

  • 例えば次のコードは型で縛れない
    • キーに何が来るかわからないため
const foo: { [key: string]: string } = {
  foo: 'bar',
};
  • throw もよくわからないので利用を避け、return で管理するなどの検討も良いと思う(golangのように

変数は Immutable に

  • letuseRef は極力避け、constuseState といった Immutable なものを使う
    • 再代入を阻止することで予期せぬ値の変更によるバグを防ぐ目的
    • スコープが短ければ気にしなくていいと思うが…
    • オブジェクトの変更もプロパティ書き換えより作り直しのほうが理想的
    • 現実味は薄いが、参照引き回しによるバグは防げる

共通化しすぎない

DRY より KISS であれ

  • DRY 原則は少なくないプログラマーにとって絶対的だと考えています
    • 同じコードを書くことはナンセンスだと言う考えを持つ人は少なくないでしょう
  • 但しその時は偶々同じ処理でも、将来的に変わるかもしれません。次の考えが良い参考になると思います
  • 基本的には将来不変なものは共通化していいと思いますが、それ以外はしなくて良い気がしてます

余計なものは実装しない

YAGNI は KISS である

  • 今は使わないけど今後使うだろうというものは実装しない
    • 実装が不要に複雑になってしまう
    • 盲腸のような実装は結局使われないまま、削除のタイミングもなく放置されがち

作ってみた叩き台と課題感

Next.js-Architecture-Example

課題感としては次のような感じ

  • pages 配下の作りをどうするか
    • page には getStaticProps や getServerSideProps しか書かないのが正解な気がする
    • 問題は templates 配下
    • PageState と PageUseCase, PageView で分割しているがインターフェースと実装の依存が強すぎて微妙な気はする
    • 項目が増えれば増えるほど複雑化しファットになっていく