Clean Architecture の学習を目的とした、Node.js による バックエンドの実装例です。
- Node.js
- TypeScript
- GraphQL Code Generator (graphql-codegen)
- Apollo Server (w/Express)
- TypeORM
- Docker (MySQL)
- React.js, Next.js, Fluent UI React, formik, yup
- Jest, ESLint, Prettier
具体例として TODO アプリを提供しています。
- yarn を使用しています
- docker-compose と node.js が必要です
yarn
yarn setup
yarn fix
yarn test
- fix = typecheck(tsc) + lint(eslint) + format(prettier)
- test = all UnitTests + IntegrationTests
yarn docker:upd
yarn dev
- https://localhost:3000/graphql - backend (GraphQL Playground)
- https://localhost:7777/login - frontend (Next.js)
yarn rebuild
yarn docker:upd
yarn start
- https://localhost:3000/graphql - backend (GraphQL Playground)
- https://localhost:8888/login - frontend (Next.js)
Monorepo 構成になっており、役割ごとにプロジェクトを分けています。
明示的にプロジェクトを分けることによって、Clean Architecture を強制する意味合いを持たせています。
- common
- カスタムエラーオブジェクトなど、全プロジェクトから共通で利用されるもの
- schema
- .graphql ファイルにて、プロジェクト全体のスキーマおよび API 構成を記述
- graphql-codegen によって、graphql ファイルから DTO, schema, resolver の型情報を自動生成
- domain-model
- domain 層と usecase 層を実装
- 特定のバックエンド実装に依存しない、ビジネスロジックのみを記述
- backend
- interface 層と infrastructure 層を実装
- 永続化層の操作に TypeORM を使用、Web サーバとして GraphQL API を提供
- frontend (WIP)
- React(Next.js) でフロントエンドを実装しています
- 現在、login/logout・Done/Undone・CreateTodo のユースケースのみをサポートしています
GraphQL schema によって、フロントエンド・バックエンド間のコントラクトを規定しています。技術的には graphql ファイルにて、データ型(type, input, enum)や API(query, mutation)を規定しています。
graphql-codegen によって、graphql ファイルから TypeScript の型情報を出力しています。エンティティの型だけでなく、リゾルバの関数型情報なども出力しているため、高い型安全性を保ちながら開発が可能です。
またこのスキーマ情報をもとに、フロントエンド側に対しても Apollo Client に最適化した型情報を生成することができます。コード補完による DX 向上が期待できるほか、型情報に守られた高品質なサービス開発が期待できます。
プロジェクトのコアになるビジネスロジックを実装しており、そのための要素として value-object, entity, usecase などを実装しています。また、外側のレイヤ向けに、repository, presenter, usecase のインタフェースを公開しています。
ユースケースは domain-model 内で完結しており、外側のレイヤがなくてもユースケースが成り立つ実装になっています。実際のところ backend プロジェクトは、ビジネスロジックに対しては controller 経由で usecase を呼び出す実装しかしていません。
振る舞いの正しさの確認には、テストを使用しています。外側のレイヤ(repository, presenter)はモックを使い、usecase に期待するコアな状態遷移やバリデーションを中心に確認しています。
コアのビジネスロジックは domain-model 側が提供しているため、このプロジェクトの主な目的は外部レイヤとの連携になります。具体的には、GraphQL に対応したサーバ実装と、永続化層の提供をしています。
永続化層には MySQL(Docker)を使用し、TypeORM によるリポジトリパターンでの実装を行っています。TypeORM はリポジトリパターンを標準で提供しているため非常に Clean Architecture 向きです。蛇足ですが migration が優秀で、ORM コードと DB の差分を見て自動的にマイグレーションファイルを生成してくれるため、非常に楽です。