はじめに
今回はフロントエンドアーキテクチャを中心にピックアップしてみました。後ほど紹介する記事のなかで「フロントエンドにおいても現代設計論が適応できる時代になっている」と言うことを知り、重点的に取り上げてみようと思いました。自分自身も将来はフロントエンドの設計が適切にできるようになりたいと感じました。
前回の記事↓
知識の露出・共有を適切にしてクリーンな設計をしよう
個人的まとめ
※個人的な解釈も含まれます。間違っていたらご指摘頂けると嬉しいです。
- クリーンな設計をしよう ≒ 技術的負債を少なくしよう
- 技術的負債とは「保守や機能追加が高コストになったシステム」
- 技術的負債が貯まる原因は密結合の範囲が広い。知識を露呈しすぎている
- 適切な広さの密結合はメリットも多いため、密結合と疎結合を使い分けることが重要
良くない例
- データを直接読み書きする
-> 読み書きするコードはデータ構造の知識を持っていることになるので、そのデータ構造が変更されたら、そのデータ構造にアクセスしているコードを探し出して変更する必要があるため改修が大変。 - 責務が複数存在している
-> 関数が複数の責務を持っていると言うことは、その分その関数を使っているコードが多く存在すると言うことになる。つまり、この関数を改修しようとすると、影響範囲が広くなるため改修コストが大きい。 - 関数に書かれたコードが知識として露出される
-> 関数に書かれたコードが知識として露出されていると、コピペなどによって技術負債が貯まる原因となる。実装されたコードを隠すためにインターフェースを用いて露出する知識と、そうではない知識を明確に分離する。 - 実装が使う側の知識を持っている
-> 実装が関数やクラスを使う側の知識を持っていると、改修した時に使う側が影響を受ける可能性があるため改修コストが高くなる。
良くない例のように知識が露呈してしまうと、密結合になり、モジュール同士が複雑に絡み合ったガチガチの状態でアプリが完成して改修が大変になってしまうため、知識を不必要に露呈しないように設計するのが重要だと感じました。
宣言的UIはReact Hooksで完成に至り、現代的設計論が必須の時代になる
個人的まとめ
※個人的な解釈を含みます。間違っていたらご指摘頂けると嬉しいです。
- React Hooksと宣言的UIによって大規模開発に用いられる設計論に対応できるようになり、技術的負債の抑制が可能になった(広範囲の密結合を防げる)
- ある程度以上の規模で開発するなら設計論をうまく使い設計しないと、技術的負債を抱え込む
- React Hooks以後の宣言的UIならば完全に設計論に対応できる
- 宣言的UIにより以前のDOMの状態にアクセスする必要性が無くなった
-> 状態管理とDOMが切り離された - 状態管理とDOMが切り離されたことによって、状態管理に設計論を適応できるようになった。代表例がFlux
-> 「このDOMにアクセスして状態を更新して」といったようなことをしなくて良い。つまり状態に関する実装が特定のUI、DOMに依存せずに実装することが可能になった。状態の更新に関する処理は特定のDOMに依存しないため、使い回すことができる。 - Hooksによりローカルの状態を持つ関数をできるようになった
-> Hooks以前はローカルの状態(フォームの値など)に関する処理は特定のコンポーネントに依存する形でしか記述ができなかった。HOCなどを用いれば切り離せるが、Reactのシンプルさを失う。Hooksという解決方法が登場したことによって、UIとローカルの状態管理が綺麗に分離されたため、設計論を適応できるようになった。
Clean Architecture for React
個人的まとめ
SOLIDの原則
- SOLIDの原則はモジュール間の接続に関する設計原則。SOLIDの原則を満たしていることは、Clean Architectureを実現する上で重要
- 単一責任の原則(SRP): モジュールはたった一つのアクターに対して責務を負うべきである(DRYの原則を適応するときは、アクターが同じかを確認するべき)
- オープン・クローズドの原則(OCP): 機能追加などの拡張の際に既存のコードを修正する必要がなく(オープン)、修正する際に他のモジュールに影響がない(クローズド)べき
- リスコフの置換原則(LSP): SがTの派⽣ならば、Tが使われている箇所をSに置き換えても同じ振る舞いをするべき
- インターフェース分離の原則(ISP): 一つのインターフェースに全てを詰め込むのではなく、クライアントが必要とする機能のみを提供するべき
- 依存関係逆転の原則(DIP): ソースコードの依存関係が(具象ではなく)抽象だけを参照するべき
- 補足: 下の図1上の円の内側の安定なコードから外側の不安定なコードに依存すると、依存している内側まで不安定になってしまうため、依存関係を逆転するべきという考え
Clean Architecture
- 核となるビジネスドメインを他の依存からいかに守るかを重視する
- エンティティ: 企業全体の最重要ビジネスルールをカプセル化したもの。その企業が取り組んでいるビジネスのルールを表す
- ユースケース: アプリケーション固有のビジネスルールを扱う。エンティティを操作しながらアプリケーションが必要とする処理を行う
- DIP違反をする箇所はメインコンポーネント(main関数など)にまとめる
Dependency Injection
- DIコンテナなどを使わずにDIを行うと、DIする度に具象クラスをインスタンス化する必要があるため、結局依存することになる(具象クラスをimport箇所が依存している箇所)
- DIコンテナを使うと、依存する箇所を一箇所にまとめることができる
- TypeScriptにはInversifyJS、TSyringeなどのDIライブラリがある
SPA
- Viewは変更されやすい(不安定な)ためClean Architectureにおいて円の一番外側に位置する
- SPAはViewに相当する
- SPAには複雑な設計が求められるようになってきたため、本来プロダクト全体を設計する手法であるClearn Architectureのような現代的な設計論を適用する余地が生まれた
- SPAにおける円の中心はビューモデル。ビューモデルはエンティティを表示のために変換したもの
- ユースケースはビューモデルを操作しながら表示に必要な処理を行う
ぼくのかんがえたフロントエンドアーキテクチャ
kichionさんが考案した実際に現代的設計論を適用したフロントエンドアーキテクチャです。
僕自身もフロントエンドアーキテクチャを少し考えたりしています。今後の記事で書こうと思っているので頑張って完成させたいと思います💪