はじめに
この記事は2020年の RevComm アドベントカレンダー24日目の記事です。
前日は @zoetaka38 さんの「Serverless/FlaskでSwagger付きサーバレスAPIを作る」でした。
RevComm でリードエンジニアをしています @qii-purine です。
普段はちょっとした機能を作るところからコードレビュー、プロダクトマネジメントまで幅広く MiiTel の開発に携わっています。
さて、みなさんは開発においてどういうアーキテクチャを使っていますか?
その選択においてどんなことを考えましたか?
今回はとある場面におけるアプリケーションアーキテクチャを考えていけたらと思います。
アーキテクチャって?
アーキテクチャと言われてどんなものを連想しますか?
MVC やレイヤードアーキテクチャ、クリーンアーキテクチャ、VIPER色々ありますね。
広義にすると DDD や DI、CQRS、オブジェクト指向、アスペクト指向、デザインパターンまで広がります。
どれにしても、開発運用時の課題を楽に解決するために考案され様々なシステムで利用されています。
※この記事では各アーキテクチャに関する具体的な説明は行いません。
選択における条件は
さて、さっとアーキテクチャを考えるとはいいましたが、プロダクトに応じて様々に条件があると思います。
今回の条件はこんな感じ。
- 言語は python。
- フレームワークは django (drf)。
- 作成するのは Restful API で、html を返すようなものはない。
- UnitTest はやる。
- 10人以上が変更を加える。
候補
今回は大枠の候補として
drf の ModelViewSet を使うパターン、レイヤードアーキテクチャ、クリーンアーキテクチャの3つを考えてみましょう。
drf の ModelViewSet
参考にするのはここ。
https://www.django-rest-framework.org/api-guide/viewsets/#modelviewset
複雑なロジックを組む場合は次の レイヤードアーキテクチャ の仕組みを部分的に導入する形になるでしょう。
- 作成するコード
- ViewSet
- Serializer
- Model
- メリット
- コード量は少なくて済む。
- デメリット
- ロジック部分を drf が隠蔽しすぎて処理順が一見してわからない。
- 複雑なロジックが増えると Fat Controller, Fat Model で苦しむことが予想できる。
レイヤードアーキテクチャ
ModelViewSet の Base Class となる ViewSet を使います。
https://www.django-rest-framework.org/api-guide/viewsets/#viewset-actions
- 作成するコード
- ViewSet (Application層)
- Serializer (Application層)
- UseCase (Domain層)
- Model (Infrastructure層)
- メリット
- レイヤごとに疎結合に実装できる。
- デメリット
- UseCase が肥大化する。(行数ではなくクラス数的な意味で)
- テストがしづらい。
クリーンアーキテクチャ
ここ数年よく耳にするアーキテクチャですね。
DI をうまく使うことでインフラ部分の依存関係を逆転させることができます。
- 作成するコード
- ViewSet
- Serializer
- Entity
- UseCase
- Repository
- Model
- メリット
- テスタブル。
- インフラの変更にも耐えられる。
- デメリット
- UseCase が肥大化する。(行数ではなくクラス数的な意味で)
- コード量多すぎ。
mock によって解決すること
python の mock はそこそこ強力で、グローバルな変数のモックができます。
これはクリーンアーキテクチャのように依存関係を逆転させずとも DB などのインフラ部分に依存させずテストができるようになります。
考えないこと
遭遇確率の低そうなフレームワークやインフラの変更は考えなくていいでしょう。
また、チーム内で共通の認識を作るのは何をするにしても必要なことです。難解過ぎなければ払うコストはほとんど同じです。
Minimum Viable
いずれを選ぶにしても一長一短ありますが、コード量的にはレイヤードアーキテクチャが良さそうです。
テストがしづらいというデメリットも mock によって解決できます。
それから DI は実装箇所によっては欲しい機構なので使えるようにしておきましょう。
まとめると、こんなでしょうか。
- 作成するコード
- ViewSet
- Serializer
- UseCase
- Model
- メリット
- レイヤごとに疎結合に実装できる。
- テスタブル。(mock の恩恵)
- デメリット
- UseCase が肥大化する。(行数ではなくクラス数的な意味で)
おわりに
いかがでしょうか。
今回は レイヤードアーキテクチャ + DI の形に収まりましたが、プロダクトの規模やチーム体制、開発期間によっても取捨選択が変わると思います。
少数精鋭で全員が drf に精通している場合は ModelViewSet で必要十分かもしれません。あるいは、十分に時間があり長期に渡り運用していく場合にはクリーンアーキテクチャが適しているかもしれません。
自分たちにあったアーキテクチャの選択をおこないましょう。
明日は最終日。@zomaphoneさんの記事です。
よろしくおねがいします。