DDDを踏み外してからもう一度踏み出してみた

前回エントリ単体テストMVCとDDDについて個人的見解を書いた。

結果、@ktz_aliasさんや@j5ik2oさん、@hidenorigotoさんにアドバイス頂き、ちょっと俺踏み外してる感あるなーと。 そもそも「もしかしてこれをDDDと呼んでいるんじゃ...?」みたいな、知見の狭さや浅さがあった。 そこで単体テストとかMVCとかレガシーシステムとか置いといて、DDDについて勉強してみることにした。

今現在は、以下のような認識を持っている。

DDDがまず解決する領域

前回エントリの振り返りを少し。

僕がソフトウェアエンジニアリングにおいて解決したい領域はコードのメンテナンス性だった。 既存のコードをリファクタリングしてテストを追加するのは、費用対効果の面においてとても現実的ではなかった。というかやり遂げる自信がない。そこで、少なくとも機能追加に関してはメンテナンス性の高いコードを書こうという方針の元、試行錯誤を重ねていった。 そこで、「あれ?これってDDDって余分じゃ...?」みたいな感じになってきた。

DDDについて理解を進めていくうちに、これらの前回エントリで話していることは全て実装世界の話であるということがわかってきた。 DDDがまず解決する領域は、実装世界ではなく概念世界であることがとても重要だった。

アプリケーションフレームワーク

多分陥りやすい罠なんだろうと思う。アプリケーションフレームワークに概念世界が引っ張られる。

文字にすると嘘みたいな話だが、実際にそうなっていた。 MVCやDDDの`モデル'をいわゆるActiveRecordと混同し、アプリケーション全体の設計がフレームワークに依存する形になっていた。 個人的にはアプリケーションフレームワークとの付き合い方というか、新しい見方が出来るようになったのは大きな変化だった。 DDDとアプリケーションフレームワークは互いに依存するものではない。

ユビキタス言語とドメインモデル

概念世界という言葉を前置きなく使っているけど、この2つのことなんだと思う。 今の解釈としては、ユビキタス言語とはドメインモデルを導き出すための言葉で、アプリケーションが実現することを言葉に表したもの。ドメインモデルは、その言葉から抜き出した名詞や動詞、つまり、

「勇者は薬草を使うとHPが回復する」→ ユビキタス言語

「勇者」「薬草」「使う」「HP」「回復する」→ ドメインモデル

だと思っている。

そしてこのドメインモデルと実装は密接な関係を持っている。

レイヤーという概念

DDDを学んでいると、たくさんの聞き慣れない専門用語が出てきてつらい。

そんな時、レイヤーという概念がとてもわかりやすく、なんとなく全体像をつかむのに役立ったと思う。 以下のような感じ。

  • プレゼンテーション層
  • アプリケーション層
  • ドメイン
  • インフラストラクチャ層

プレゼンテーション層

表示。UI。ユーザー入力を受け付ける層。

最近は、このプレゼンテーション層内でのMVVMとかあるようだけど(e.g, AngularJS, Backbone.js)、触ったこともないのであまり言わない。

アプリケーション層

ドメイン層を使ってアプリケーションを実現する層。

実装に置き換えるとアプリケーションフレームワークのコントローラがここのイメージ。

ドメイン

ドメインモデルを実装に落とし込んだ層。 ドメインモデル(Entity, ValueObject, Service, Aggregate)の他に、ドメインモデルのライフサイクルを管理するファクトリやリポジトリという概念がある。

  • Entity → IDを持つオブジェクト(複数人の勇者は全て区別する必要がある。何から何まで全て同じ属性を持つとしても違う人間である。)
  • ValueObject → IDによって区別できないオブジェクト(薬草は何個あっても薬草。回復量が違う薬草はどうなる?それは属性が違うだけで薬草であることに変わりがない。)
  • Service → フッ....むずい。
  • Aggregate → Entity, ValueObjectの集合。裏技的にトランザクションの単位と考えられる??

実装に置き換えると、ドメインモデルはドメインの属性や役割を実現するオブジェクトであり、ファクトリはドメインモデルの生成、リポジトリはデータ(例えばRDBデータ)をドメインモデルに変換する(Data eXchange Object)オブジェクトである。

今はこれ以上の説明がうまく出来そうに無い。

インフラストラクチャ層

全ての層を支える基本的な機能。

多分、ルーティングとかDB接続とかアプリケーションフレームワークのコア部分という印象。

とまぁこれくらいの知識で、一度社内ツールを設計、実装してみた。 さらに社内エンジニアに集まってもらって少し喋ってみた。(時期尚早。。)

しかしなかなかうまくいかないんだこれが。 特に難しいと感じる部分が、ユビキタス言語からドメインの切り出し。すごくセンスがいると思う。無駄に実装クラスの継承関係が深くなってしまったり。。

それから、ファクトリ、リポジトリの実装も実際に手を動かしてみるとわからなくなることも多い。例えばクエリの実行回数とか、同じオブジェクトでも場合によって生成パターンが違ったり(ビルダーを使うのかな)。

あとAggregateとServiceはうまく使いこなせていない。というかよくわかっていない。

ただ手を動かしたり喋ったりすることで、なんだかボヤっとしていたところがクリアになる。

エリック・エヴァンスのドメイン駆動設計 (IT Architects’Archive ソフトウェア開発の実践)

エリック・エヴァンスのドメイン駆動設計 (IT Architects’Archive ソフトウェア開発の実践)

これも買ったしちょっとDDDがんばろうと思う。