Architectureはおなじみのアーキテクトとして親しまれるようになりました。Architectureを導入し、メリットを享受できます。Architectureを導入する手順を、実際にコードを追いながら紹介していきます。実際のコード実際に書いたコードはこちらのGithubに公開しています。データを外部から取得するフローを表現するために、node.jsで実装されたモックサーバーも用意しました。Architectureでおなじみの図と共に前提知識を簡単に紹介します。詳しい説明はここでは割愛しますが、基本的に外側のレイヤーから内側のレイヤーへ依存するよう設計していきます。一方で内側から外側へと依存する場合は、依存性逆転の原則に則り、インターフェースを通じて抽象に依存する必要があります。今回はフレームワークにReact.jsを用いていますが、それぞれ次のように実装しました。Architectureを導入するメリットは、各レイヤーが疎結合になり、特定のフレームワークやライブラリへの依存関係が減らせることなどが挙げられますが、とりわけ個人的に強く感じるのはテスタビリティが高まることです。あるレイヤーが別のレイヤーのクラスを参照する場合、それが実装ではなくinterfaceであればテストの際にモックを差し込むことで、単体テストを容易に書けるようになります。APIリクエストのように実際には通信が発生してしまう場合でも、規定の値を返すモックを挿入すれば、Repository層のテストにも対応できます。具体的にどのようにテストを書けば良いのかは後述しているので、そちらを参照してみて下さい。Objectに近く、DDDに慣れ親しんだ人からすればEntityという言葉に違和感を覚えるかもしれません。Domainを利用してはいけないわけではありません。(ドメインモデル)それでは実際にTypeScript+React.jsを使った実装内容を見ていきましょう。今回はサーバーから記事情報を取得し、それを描画する処理を行います。ドメインモデルとしてArticle、それに付随してAuthorを定義しています。Objectパターンのようにプリミティブ型ではなく、ユーザー定義クラスを活用し、それぞれに振る舞いを持たせます。不変オブジェクトとなるよう、readonly属性を付与しています。}}UseCaseドメインモデルを使ってビジネス手順を記載していきます。UseCase自体にビジネスロジックは記載せず、ロジックが発生する場合はEntity層に寄せ、ここではあくまで手順のみを記述します。}}UseCaseが呼ぶRepositoryは、レイヤーでいう内から外へと依存性が逆転しています。そのため依存性逆転の原則から、UseCaseはRepositoryの実装ではなく、インターフェースを参照する必要があります。初期化時にRepositoryのインターフェースを実装したインスタンスを注入することになりますが、それが実際に何であるかをUseCaseは関知しません。Repository外部と内部をつなぐレイヤーとしてRepository層を定義します。外部から取得したデータは、内部で扱うためにデータをアプリケーション固有のドメインモデルに変換しますが、それをRepositoryが担っています。}}先ほどのUseCaseと同様にここでもRepositoryからDriverと、内から外へと依存性の逆転が生じているので、インターフェースを参照しています。DriverDriver層では実際に外部からデータを取得します。外部から来るデータはJSON形式ですが、ここではドメインモデルへの変換は行わず、結果をそのまま返しています。}}ここまでデータのやり取りにフォーカスしてきましたが、実際にUIに反映させるようPresenter層を記述していきましょう。(React.js)Presenter層は内側から受け取ったデータを、外側であるUIへ反映させます。PresenterはUseCaseに依存し、ここでは必要な記事情報(Articles)の取得を試みます。App;PresenterからUseCaseへの依存は逆転が生じていませんが、インターフェースを通じてやり取りすることでPresenter層の単体テストも書きやすくなる利点があります。エントリーポイントエントリーポイントでは必要な依存性を注入し、ブート処理を担います。今回はPresenterに値を渡すことで、描画を開始しました。アプリケーションの開始が目的で、最小限の手順のみであることが望まれます。document.getElementById("app"));各レイヤーはinterfaceを参照しているので、実際に注入された値が何であるかを知りません。インターフェースが同一であれば、実際に注入された値が変更されたとしても、アプリケーションへの破壊的な変更を避けることができます。Architectureのメリットとしてテスタビリティの向上を挙げましたが、実際にテストコードを書きながら、その恩恵を見ていきましょう。テストフレームワークにはjestを使用しています。Architectureに限らずですが、単体テストの際は各レイヤーの責務にフォーカスし、レイヤーを越えた先の動作はモックすることで、テスト対象の動作のみにフォーカスすることができます。今回UseCaseではRepositoryから受け取った記事情報をそのまま返していますが、テストの際はRepositoryの動作をモックし、UseCase自体が適切な処理を行っているかを検証します。});});UseCaseが依存するRepositoryは、テスト時にインターフェースを実装した仮のオブジェクトを実装します。その上でspyOnを使うことで返り値を規定すると共に、それが実際に呼び出されたかどうかを検証しています。少々冗長な内容に感じられるかもしれませんが、以上からUseCaseがRepositoryのfindAllを呼び出したこと、Repositoryからの結果をそのまま返していることを確認しています。このように外部サーバーとの通信が発生する部分でも、モックを活用すれば容易にテストを書くことができます。RepositoryのテストDriverから受け取ったプリミティブな値を、アプリケーション固有のモデルに変換するRepositoryの動きを検証します。本来Driverでは外部との通信が発生しますが、それをモックすることでクライアントのみで完結してテストすることができます。});});以上でDriverから渡ってきた値をもとに、適切にドメインモデルに変換できることが検証できました。今回は単に値を詰めただけですが、null時に規定の初期値を与える場合、不正な文字列が渡ってきた場合の対応、特定の値同士を掛け合わせるといった要件も発生しうるので、それらに応じてテストを追加していくことになります。Architectureをフロントエンドに適用する例を紹介してきました。Architectureを厳密に適用することは費用対効果に見合わないと思われるかもしれません。Architectureを導入するコストの方が大きく出ることがあるでしょう。一方で要件がある程度明確な中、チーム開発で継続的にアップデートを続ける場合にはコストを上回るメリットを享受できるはずです。Architectureを導入したいと思っている方の参考になれば幸いです。実際のコードはGithubに公開しています。requestStockLike23@ttiger55以前はRoRやiOS開発→最近はGolangがメイン。個人的に今後やりたいのはTerraform、gRPCなど。学習したいのはオブジェクト指向のアーキテクチャ、コンピュータサイエンスなど。学生時代はボクシングをやっていて、社会人では一時期マスターズ陸上で年代別の日本記録を持っていたことがあります。upLoginユーザーは見つかりませんでした。