やる気がストロングZERO

やる気のストロングスタイル

DDDのメリットを勘違いしてた件

僕はDDDで「俺が考える最強の契約管理システムを作る」というのをやってみている。
もう100回を超えた。

www.youtube.com

目的としては、外部からあれこれ言われず自分が思う通りに実装を進めて、自分だけの責任で躓いて、自分で「良い・悪い」を体験する事である。 アーキテクチャとしてはDDDを意識している。

着手当初思っていたこと =>すぐに実装速度があがってくる

DDDで実装すると、最初は手数が多い分実装スピード遅いが、次第に実装スピードが上がっていき「Railsのドキュメントに愚直に沿った開発」よりも早く完成させることができると思っていた。

なぜなら、DDDで実装すると凝集性が高まりコードの再利用がしやすくなるので、次第に書くコード量が減っていき実装速度が上がってくるはず、と思っていたからだ。

着手中感じたこと => 全然実装速度があがってこない

「あれ?ぜんぜん実装速度があがってこない。」

新しい機能を載せようとするたびに、アプリケーションサービス、ドメインサービス、リポジトリ、エンティティ、データマッパー、DTOを定義してそれぞれに責務を守らせたメソッドを定義していかないと行けない。

どこに何をもたせるか?を考えたり「DB => データマッパー => エンティティ(or 集約) => DTO => view」のように似たような構成のデータ構造体にデータを受け渡していくのもかったるいと感じた。

たぶんRailsだったらActiveRecordモデルを定義して、処理メソッドを定義して、これをViewまで持ち回るようにすればもっと手数が少なくて実装できるだろうなと感じた。

これじゃあ「DDDで〜とか息巻いて言ってるけど実装速度遅いし、単なる意識高い系じゃん」とか現場で言われそうで不安になった。

新規開発のステージではDDDはコスト感を感じやすい

twitterでこんな感じでつぶやいてた。

開発に費やしている時間は、その後保守を含めたライフサイクルのなかでほんの少しの時間でしかない。
ここで少しばかり時間がかかったとしても、その後の保守が楽になるのであれば投資としては成功と言える。

DDDでの初期開発中はメリットよりもデメリットを感じやすい期間なのだと感じた。

何に実装時間(コスト)がかかっているか? => レイヤー分割

Railsのドキュメントに愚直に沿った開発と比べて、DDDでの開発で時間を食っている主な部分は「レイヤー分割のために発生する作業」である。

レイヤー分割するにはある程度の実装コストを払わなければならない。

レイヤー分割の大切さとそれにかかるコストについては Clean Architectureでも述べられている。

※この書籍、2年ほど前に読んだときは内容が抽象的に思えてイマイチ内容を掴みきれなかったが、以下のドメイン駆動設計入門を読んでコードでの実装イメージを掴んでから再度読んでみると色々理解できた。

なんのためにレイヤー分割するのか? => コアドメインを依存から守るため

コストのかかるレイヤー分割をわざわざやるのは、コアドメインを依存から守るためである。

コアドメインで実装される処理は、Railsでなければ実現できないわけでも、CSV出力でしか実現できないわけでもない。

たとえば販売管理の処理はRailsが登場する前から存在しているし、出力は紙帳票や、web viewでも、エクセルで吐かせても、なんでもいいはず。

なのに「フレームワークRails以外に切り替えられない」や「出力はCSVでしか対応できない」みたいな販売管理システムはたぶん多く存在する。

これらはレイヤー分割しておらず、ActiveRecordのメソッドや、出力CSVの生成の処理がコアドメインの内部に食い込んできていてこれらを引き剥がせなくなってしまっているのが原因である。

レイヤー分割するメリットは?

不必要な依存を持ち込まないようにする

工数を余計にかけてまでレイヤー分割するメリットは、上記に記載したActiveRecordCSVへの依存のような、不必要な依存をコアドメインに持ち込まないように出来ることである。

こうすることで、コアドメインが長生きする。
時代とともにフレームワークや、データストアや、スマホアプリや、今後生まれるかもしれないウェアラブルバイスが、どのように移り変わろうとも、これらに依存していなければコアドメインを使い続けられる。

フレームワークが変わったらまるごと実装しなおさなければならない、というような事が起きない。

仕様変更にも追従しやすい

開発プロジェクトを進めていると、仕様変更が頻繁に起こる。

レイヤー分割をきれいに行っておくと、副次的だが単体処理の組み合わせで処理を実現する感じになりやすいため、仕様変更の影響範囲が小さくて済む。

レイヤー分割していなければ、DBからのデータ取得、処理、view用のデータ整形までひっくるめた巨大な処理になっていて「処理自体がDBの機能に依存したものになっていて入れ替えられない」など発生する。

レイヤー分割されたコードだと、少なくとも各レイヤーで処理分割されていて、たとえばデータの読み込み先がDBからcsvになったりしてもデータ取得部分だけ変更すれば良い感じになってる。

実装速度に差が出てくるのはもう少し先の話。

現在「俺が考える最強の契約管理システムを作る」は新規開発の段階で、まだコストを払っているステージだという認識になった。
ただし、試行錯誤しながら機能追加していっている状況で既存コードを修正して追加実装する作業で、もしかしたら既にDDDのメリットを享受し始めているかもしれない、、とも感じている。

というのも、今までのシステム開発にて既存コードに新機能を追加する際「素直に追加実装できない色んな問題(主に不要な依存が原因)がそこにあり、それらを回避してギリギリの形で実装した(初期予想工数の数倍かかった)」という経験をたくさんしてきているが、今の所そういった問題に発展していないので、これは既にメリットなのかもしれない。