Web サービスにおけるバッチ処理には例えば以下のようなものがある。
- 売上レポートの集計
- 決済整合性の定期チェック
- 不正利用者の検出
- リソースの定期加工
- ...... etc
いつ処理が落ちても大丈夫なようにトランザクションを貼ったり, 繰り返し実行できる冪等性の担保とかクエリの最適化とか API でも気にするようなところを同じように色々気をつけて実装する必要があって, サービスに依存してるバッチ処理なのでビジネスロジックも絡んでくる。
ビジネスロジックは切り分けたいし, トランザクションの境界はハッキリさせたい。インターフェースによる依存の定義で外部サービスをいつでも切り替えれるようにしたい。テストを効率良く書きたい ... etc その辺を考慮するとクリーン(レイヤード)アーキテクチャがマッチしてるかな〜と考えて実践してみた。
すでに似た事を実践してる記事はあり, 全力でこの記事に乗っかってる。
「Clean Architectureで実装するバッチ処理」についての勉強 - tsuchinaga
アーキテクチャとしてはこんな感じ
- utils は struct 操作とか文字列操作とか時間操作とかとかレイヤーに依存しない実装置き場
- adapter は, API では「URLに対応してて, リクエストを受け取ってレスポンスを返す」層
- 今回バッチ処理という事で「入力を受け取って, 出力を返す」というところでサブコマンドをおいてみた
- usecase は「○○する」みたいなのを書くところ, トランザクションを貼る, 通知処理する, データを更新するみたいな実処理を書いてる service を複数呼ぶところ
- domain は entity を起点に entity に CRUD する repository と entity, repository を扱って実際のビジネスロジックを実現させる service をおいてる
- repository は interface, entity は struct とか const