DDD及びその周辺の自分の現在地と勝手な想い(ポエム)

この投稿は[ZOZOテクノロジーズ #4 Advent Calendar 2020](https://qiita.com/advent-calendar/2020/zozo_tech4) 13日目の投稿です。

昨日は[@hmsnakr](https://qiita.com/hmsnakr)さんの[Taurusを用いてJMeterのレポートを作成する
](https://qiita.com/hmsnakr/items/a64507c31d1365dd6bb0)でした。
JMeterまだまだ現役ですね。こういうサポートツールが出てきて使い勝手が良くなってる気がします（そういえば、あのUIも現役ですよね。）

# はじめに
今回の投稿では、年の瀬ということで、DDD周りの自分の今の気持ちを素直に書き綴ろうかと想います。自分の立ち位置を改めて振り返り、来年に繋げたいと思います。ポエムです。

# DDDに対する今の自分の想い
## 改めてなぜDDDなのか
自分自身、DDDを採用したプロジェクトを新規での開発から3年以上の運用まで経験してきた中で思うなぜDDDなのかという答えの全ては　**プロダクトのために** ということです。

ソースが動いた瞬間からそれは始まり、サービス開始、その後の運用、監視、改修、新サービス企画、検討、設計、追加・・・プロダクトに関する全てが含まれます。
それらをどうスムーズに行うか？

その答えの一つが **ソースコードで業務を理解しやすい形で表現する** こと、ということだったのだろうと理解しています。

サービスの成長に必要なのは、改修や機能追加という実作業だけではないということ。
日々の運用や監視、企画や設計などにもDDDで実装されたソースコードは役に立つはずというのが今の考えです。

例えば、
- 500エラーが検出された。ログから該当の箇所をすぐに見つけられるか？
- 関連サービスが止まった。影響範囲をすぐに判断できるか？
- 顧客から問い合わせが来た。今の仕様をすぐに答えられるか？
- 新しい顧客には特別な対応をしたい。可能かどうかすぐに判断できるか？
などなど、
業務の知識がわかりやすい形でソースコードに反映してされていればこれらのリクエストには答えやすいのではないだろうかと思うわけです。

## 自分のDDDの現在地
今自分自身、自分の携わっているプロダクトではどこまで実現できているか？
というと、まだまだだなという感じ。
だが、実現不可能かと言われるとそうでもない気がします。

ということで、今やってみていることは一旦俯瞰的にモデルを見てみるということ。
日々の運用や、改修はあるがやはりそういう時は森ではなく木を見てしまいます。

そこから離れて森を見る。そこで見えてくるものは何か？
答えは全部出ていないが途中経過として [前回の投稿](https://qiita.com/YasuhiroKimesawa/items/bac3eea2bfc3f6d68458) を上げてみました。
まだまだ良くするための策はありそうなので折を見てまた記事にしてみたいです。

# DDDの周辺技術
話は変わって、DDDに関わる周辺の技術についても振り返っておきます。

## アーキテクチャ周り
伝統？のレイヤーアーキテクチャからはじまり、オニオンアーキテクチャ、クリーンアーキテクチャなど、まあ色々話題になりますが、今の自分の気持ちは、 **「モデルさえ分離されてればなんとかなる」** ということ。
最悪DIなど使わなくてもモデルさえ他のレイヤーに依存していなければ案外なんとかなるというのが大元の考えです。

その前提で、レイヤーをどうするか？レスポンスをどうするか？永続化をどうするか？DTOを使うのか、DIを使うのかなどを考えていけばよいでしょう。
採用している言語にも依るし、使ってるフレームワークによってもここら辺は変わってくると思います。

## CQRS/EventSourcing

最近までここまでしなくてもいいのでは派だったのが変わりつつあるのがCQRS/EventSourcing。

コマンドとクエリはまあ違うモデルを要求されることが多い。**特にクエリは本当わがまま**。
この顧客には別の形式で返して欲しいだの、このレスポンスが欲しいだのというのが本当に多い。
これらをコマンドのモデルと混ざってしまうとモデルが大きくなりすぎて見えづらくなってしまいます。

それに今では簡単に実現できる下地もできてきたと思う。AWSで言えばDynamoDBストリームやSQSなんかを使えば比較的容易に実装できそう。もちろん他にも選択肢はある。
EventSourcingについてはおそらくセット。コマンドのモデルにはEventが本当に扱いやすい。これも先の技術を使えばできるし、イベントを永続化しておくとなにかと後から便利。保守運用の手助けにもなります。

## マイクロサービス
**モノリスは辛い。実感しています。**
では簡単にマイクロサービス化できるかというとなかなかまだまだ難しい印象。
そもそもどうやって分ける問題が。当初とにかく細かく分ければいいんじゃない？という考えがあったが、今は**サービスを利用する部署や利用者によって分けるといいかもと考えています。**
例えばサポートが使う機能、A部署が使う機能、バックヤードチームが使う機能・・・みたいな感じ。
部署間の業務やデータのやりとりそのままにサービスを分けるとうまくいきそうな気がしている。

パッケージやAggregatesの分離もまた大事。この辺ができてないと実現できない気がしています。
あとはコアドメインを見つけるのにもこの分け方がいいと思っています。どの部署のどの業務が売り上げに直結しているのか？を考えるきっかけになりそう。

## Unitテスト
書いてないと怒られるので書いてる。というのは置いておいて、**Unitテストが容易に書けないコードは設計がまずい。**
特にモデル、サービスのテストでローカル変数にモックが必要なケースだったり、privateメソッドのテストがしたくなったりしたら設計に問題があるはずなので見直すきっかけになれば。

それから、コントローラはそもそもテストしずらい。なのでここのテストがしたくなったらそれはそれで設計がまずい。モデルやレポジトリに移動するべき。そしてそれらの呼び出しはサービスからするべきです。

一番テストが必要なのは言うまでもなくモデル。
テストがモデルの使用例みたく書かれてるのが理想。
それはモデルの役割が非常に明確になってる証です。

また意外とテストが必要なのは、**変換層。腐敗防止層やDTOを使ってればデータの詰め替えをしてる箇所**。
なぜなら間違いやすい、人的ミスが多いところだから。ここは重点的に書いたほうがいいです。書いてあると追加や変更もしやすくなります。これ確かEvans本にも書いてあったと思います。

# モデル
一番重要だが、一番語られることが少ない。アーキテクチャや、CQRSやマイクロサービスの話はみんな大好きだけど、モデルをいかに構築するかの話は、、、多分したいけどしずらいのだと思います。
業務の秘密なところの気遣いもあるし、携わってるサービスによっても異なるので話しずらい。
でも自分的にはモデルの話がしたいので、来年はもっと語る場を作りたいと思います。

モデルを分離すればいい、Entity,ValueObjetを使えば全てうまくいくということはなく、それらを使ってどう表現すればいいかという問題。
ここをどう設計するかが、発展しやすいプロダクトになるかどうかの別れ道だと思っています。
もちろん一発では決まらない。どう改善するか、改善する時間をとるか、それは振り返りの時間をいかに取るかというところにもなってきます。

あとはどこを改善するかも大事。むやみやたらに改善しても、そこが収益につながらなければ意味ないし、ほとんど修正や追加が入らないところを改善してもそれはリソースの無駄使い。
どこがコアドメインなのか。そこの見極めも大事だと思います。


# 終わりに
つらつらと書き綴ってきましたが、来年も探究心を忘れずにより良いモデルが設計できるように精進していきたいと想います。
今年もありがとうございました！よい年の瀬をお過ごしください。

明日は [@TAKAyuki_atkwsk](https://qiita.com/TAKAyuki_atkwsk)さんの「ALBのgRPC対応を利用してみる話を書く予定」です。
業務でgRPC使っているので投稿楽しみです。

ではまた。