CHILLNNのビジョンを実現するためのアーキテクチャに関して

株式会社CHILLNNのCTOをしています。永田と申します。

一昨日サービスのリリースを出した時に少し触れたシステム設計に関して、備忘録がてら少し書いておきます。
一応下にリリースのリンクを貼っておきます。

簡潔にまとめると、今回のシステム設計に求められるのは、流動的な販売チャネルを自由に増やしていくことができる、可用性の高いアーキテクチャでした。

自分は、大学在学中の前職時、受託開発の現場で高速にたくさんのアプリケーションのプロトタイピングを行っていました。(常に2〜3個くらいパラで作ってました。)そのため、0→1を高速に作れるアーキテクチャには経験があり、よく開発時のコード生成の自動化などを行っていました。

一方で保守性の高いシステムに関しては、前職から独立した時点でほぼ無知で、この学習と試行錯誤に1年をかけました。結果的に今の形に落ち着き、変更に対して開いており、修正に関して閉じているアーキテクチャーを現時点で実現できている気がして満足しています。そのアーキテクチャについて少し語っておこうかと思います。

とはいえ、辿り着いたのは、基本に忠実なものになったとおもいますので、特に新しい発見はないかもしれません。(Clean Architectureの超具体的な実装方法に関しては参考になるかも、、、。ただ、そもそも僕はあまりチーム開発をしてきていない独学の野良エンジニアだったので、業界では常識なのか、、、?)という一抹の不安を抱えながらスタートします。

画像1

上で引用させていただいたのはAncle Bobの有名なClean Architectureの概念図です。本も含めて、ちょっと、抽象度が高すぎないですか?自分はマジでまったく具体的な実装イメージが湧きませんでした。

ネット上に落ちている多くの評価が高い記事を読んでも、具体的な実装はピンとこず、何回かプロトタイピングをしてみたのですが、あまりClean Architectureのメリットを享受できていない気がして何度か作りなおしました。

結果的にはとりあえず「結合度を下げて、凝集性をあげて、依存関係を逆転させる」という基本に忠実に実装することにしました。ただし、とにかく徹底的に。

具体的には各レイヤーをプロジェクトベースで全て完全に切り分けました。言語はTypeScriptを使うことにしていたので、各レイヤーをそれぞれnpmパッケージとしました。この際、データのI/Oはレイヤーの中心にインターフェース(Repository パターン)のみ定義し、最も外側のレイヤーから実装を流し込むことにしました。

このようにすることで、package.jsonのdependenciesが明確にレイヤードアーキテクチャとなっていることを保証してくれます。また、サーバーとフロントで実行するビジネスロジックを完全に共通化することができます。

結果的には、内部レイヤーの外部ライブラリとの依存はなく、レイヤーの一番外に位置するサーバー(AWS Lambda)やフロント(Nuxt)で書いたのは、(多少、サーバーにはセキュリティーを考慮してロジックを書き足しましたが)viewロジックとRepositoryの実装のみになりました。

この時点でTypeScriptを使った利点は享受していましたが、さらに良かったのは、APIの仕様としてGraphQLを用いたことと、DBにNoSQLを採用したことです。

今回、CHILLNNでは、流動的に販売チャネルを追加できるようにしたかったので、単純に実装すると今後ビジネスロジックが肥大化していきます。
コアロジックが複雑になると、テストとかもう本当にマジでめっちゃめんどくさかったので、中心のビジネスロジックを二層のレイヤーに分離しました。具体的には、もっともコアなビジネスロジック(共通リソースのふるまいと、各アプリケーションに共通のユーザーのふるまい)のみを中心に置き、そのnpmパッケージを継承する形で各販売チャネルのアプリケーションのビジネスロジックをそれぞれパッケージとして実装するようにしました。(外側のビジネスロジックのレイヤーは販売チャネルの数だけ並列に複数あることになります。)このとき、GraphQLのtypeを継承することで、コアロジックを引き継いだまま、各販売チャネルに合わせたshemaの自由な拡張を表現できました。NoSQLのおかげでDBスキーマの変更も必要ありませんでした。

もともと僕は大変なことと、めんどくさいことは後に回してしまう質なので、テストをあまり書きたくないのですが、上記のような構成にすることで、内部レイヤーほど重要度が高くなることがわかるので、ちゃんとテストを書くようになりました。

結果的には、プロジェクト構成自体が大きなレイヤードアーキテクチャになっているシステムを構成できました。ビジネスロジックにはインフラやフレームワークに対する依存が一切ないので今後の修正も、機能の拡張も非常に見通しがいいです。

チーム開発においても、そもそも触っているソースコードが分離されているので、個々人の習熟度に応じて、触れるソースコードのレイヤーを変えることができ、比較的初学者もコードレビューのコストを低く保ったまま実戦投入できるような体制が整いました。

あとは、serverless frameworkをつかって全てサーバーレスで構築し、コアなロジックに関わらない部分は、SNSとSQSを使って、実行するサーバーごと切り分けたので、分析基盤の構築や、外部サービスとの連携も綺麗にできたかなという感じです。

以上です。
インフラはもう本当にAWS様様といった感じです。本当にありがとうございます!!!

さてさて、自分の頭を整理できたのでそろそろ寝ます。おやすみなさい。


この記事が気に入ったらサポートをしてみませんか?