読者です 読者をやめる 読者になる 読者になる

冥冥乃志

ソフトウェア開発会社でチームマネージャをしているエンジニアの雑記。アウトプットは少なめです。

follow us in feedly

DDD本読了記念:独りDDDにトライしてみてる

コップ本といい、DDD本といい、最近鈍器系の本づいてます。仕事のピークが重なっていたので、会社の行き帰りの電車の中か昼休みにしか読む時間が取れず、読み切るまでに非常に時間がかかってしまいました(3ヶ月以上かな?)。
副題にある通り、開発者がユーザとともに複雑さに対峙するための方法を(問題を切り分けよう、とかそういうお題目レベルではなく)実際の設計プロセスやパターンにまで落とし込んでいて、実践的であり具体的です。パターンそのもの以外にも、著者の経験に基づく設計現場のサンプル(開発者とユーザの対話とそれに伴うモデルの変化)が豊富で、パターンだけだとわかりづらくなる箇所を捕捉してくれています*1。しかも、理論ばかりの設計方式ではなく、ちゃんと実装とビジネスをモデルでつなぐための方法であるというのもすばらしいです。ってか、技術を知らずに設計ができると思っているご用聞きSEさんは遠慮なく死んで下さい。
ユーザへの価値提供はビジネスから開発者までをなるべくワンストップでやるのが一番理想的だと思うので、受託が面白いと思っている開発者にとって、ステップアップするには非常に良い本だと思います。ですが、やはりパターン言語なので多少の抽象性は否めません。具体性を持った理解をどこまでできるか、というところがポイントだと思いますので、今回は「DDDを体感する」をテーマに展開してみようと思います。

DDD(Domain Driven Design:ドメイン駆動設計)とは

まずはDDD(ドメイン駆動設計)の概要から押さえていきましょう。以下はDDD本を読んで思った私の理解です。正確な定義はドメイン駆動設計 - Wikipediaドメイン駆動設計入門 - Digital Romanticismをご参照ください。

DDDで重要な要素を乱暴に三つにまとめると以下だと理解しています。

これらを開発者とドメインエキスパートの間で対話を繰り返すことによって実践していきます。モデルの設計だけでなく、実際にソフトウェアを開発する際にもユビキタス言語が行き渡っていなければなりません。ソフトウェアを開発することで、ユビキタス言語やモデルの正しさを証明して、ドメインモデルをさらに洗練させるための気づきを得ることも重要です。
つまり、ユーザと開発をもっと密にして、ドメインの知識をより反映してユーザにとって高価値なソフトウェアを作るための活動です。要件を正しく理解し、それをコードに適切に反映する。もちろんそれらに取り組んだ上でコードの品質に対する高い情熱と取り組みも必要です。言葉で表すのは簡単ですが、実践には研鑽と経験が必要です。開発に携わる全ての人がユビキタス言語で語れることが重要なので、今のSIerのような仕事の仕方には無駄を感じることが多くなるかもしれない、と密かに思っております。そうなると開発プロセスや契約の話にも踏み込んでいかなければならないと思いますが、それはそれで別の話ということで。

読むだけじゃもったいない、よね?

前置きであげたようなペースでこの手の本を読んでいると、読んだときの記憶が断片的になってなかなか理解が深まりません。それに、理解を深める一番の近道は何より実践してみることです。まあ、仕事を通じて試せるのが一番近道なんですが、できれば事前に準備した上でことに望みたいものです*2。という訳で、まずは自分のプロダクトで試してみようと思います。開発者もドメインエキスパートも自分がやります。言うなれば「独りDDD」です。ちゃんと自分一人で対話やモデルを深められるかどうかに疑問はありますが、実践してみれば、より大きなフィードバックを得られるに決まっています。

で、何かを作らなければ始まらない訳ですが、とりあえずこういうものを作ることにしました。

Shinsuke-Abe/ttsukutter · GitHub

まだ開発途上ですが(だいたい2ヶ月くらい前から着手しています)、今回のブログを書くまでに洗練させてきたモデルとコードを公開しています。アイデア自体は元からあったものなので、今回のために考えたものではありません。多少漠然としてはいますが今の段階で私の頭の中に作りたいもののビジョンがある訳なので、これなら私でも何とかドメインエキスパートのまねごとができそうです。では、実践の中で気づいたことをまとめていきます。

気づいたこと1:オブジェクトのライフサイクルについて

まず、ユビキタス言語とかモデル駆動開発のオブジェクトのライフサイクルあたりはそこそこすんなり入ってきます。クラスや変数の名前を真剣に考えたり、OOの原則に基づいて責務を考えたりすると言った開発者の活動に非常に近いからです。可読性や保守性の高いコードを常に意識できている人であれば、さほど概念に迷うことはないでしょう。このオブジェクトのライフサイクルを意識しておくことで、ドメインモデルのコードが少しずつ特化した内容に変化し、自然言語ドメインのことを考える流れに近くなっていくように思いました。
また、各オブジェクトの責務についてはシンプルに物事を切り分ける指針にもなりますし、言葉を整理するきっかけにもなります。ドメインにおいて、どの言葉が主語となり述語となり形容詞となるのか、という対話をする上で非常に重要な概念をオブジェクトのあり方である程度制約することができるからです。特に、目から鱗が落ちたのは仕様パターンです。これを使うことで、コード上でのオブジェクトの制約の可読性が格段にあがりました。未だに永続化の責務がリポジトリとファクトリのどちらになるかちゃんと腑に落ちていないところはありますが*3、ポイントはつかめているのではないかと思います。

気づいたこと2:開発プロセスについて

DDD本には具体的なプロセスに触れていなかったり、独りでドメインエキスパートと開発者を兼任していることもあって、試行錯誤しながら取り組んでいきましたが最終的にはイテレーティブな開発プロセスに落ち着きました。
具体的には以下のような流れになります。

土日:

  1. モデルに対してコメントをばしばし貼って行く
  2. モデルを修正する

コメントを貼るときの観点は「実現したい内容を素直に表しているか」です。上記の流れは、独りでやっていることが影響しているのかもしれませんが、だいたい1〜2時間でまわります。ちなみにこれをやっている間はコードを書きません。
そうして続けるうちに、モデルが完璧になったと思いたくなってくるタイミングが来ます*4。私の場合、だいたい日曜の夜、お風呂に入る前くらいにそうなります。

平日:

  1. ドメインモデルから手を付ける
  2. 違和感を感じたときは、モデルから反しても違和感を感じない方のコードを選ぶ

いよいよコードを書き始めます。モデルの洗練に戻ったタイミングで大きくドメイン言語が変わることがあるので、テストコードのメンテナンスは重要です。また、ドメインモデルからだと案外テスト駆動開発で進めやすいことが判明しました。土日のプロセスの中で、ドメインモデルが果たす役割を言葉で解釈するプロセスが入っているからかもしれません。
また、2に関してDDD的にどうなのかという指針的なものはわかりませんが、モデルを無視する訳ではなく後で「こっちの方がより自然だった」ということをモデルに反映するための選択だと思っています。モデルをちゃんとコードに落とし込めないときは、どこかにまだ不自然な感じが残っているのでしょう。
ちなみにこの開発を始めてしばらくしてから、QCon Tokyo 2012でDDD本の訳者である和智右桂さん id:digitalsoul のセッションを聴いたのですが、偶然なのかその中で触れていた「Model Exploration Whirlpool」というサイクルに似た感じになりました。また、このプロセスを私が今まで学習してきたScrumと比べるとマッピングしない部分が多いような気がします。私の場合、Scrumを補完するプロセスと考えるとかなり腑に落ちました。かなり乱暴ですが、以下の図のような感じでScrumは今回の私のプロセスでいう平日の動き、土日のDDDの動きはプロダクトバックログを洗練させていく動きなのだと理解しています。


気づいたこと3:ドメイン以外のレイヤについて

一応、レイヤ化には気をつけて、ドメイン層にその他のレイヤが入り込まないようにしているのですが、基本的に今回はWebサービスで言語もフレームワークもデプロイ環境も自分の好みで決めているので、フレームワークに多く依存するUIやアプリケーションをコントロールする層についてはモデルを明記していません。この辺り、業務で実践している方々はどうされているのでしょうか?
また、今回想定されるシナリオを整理するためにユースケース図を書きました*5。ただ、ユースケース図とユースケースだけだと、シナリオの具体的なフローまでは表現されないので、その用途で使うつもりならユースケース記述をある程度書き込むのが良いのではないかと思いました。

気づいたこと4:その他

その他感じたことを箇条書きにしてみます。

  • 一人でもモデルを洗練するにつれてブレークスルーが起きる
  • チームで取り組むときは一人のモデラが中心となってモデリングするのか?
    • 役割分担とか具体的にどうしてる?
  • ScalaだとUMLとの表現でマッピングしないところがあるかも
    • case classとかobjectとか
    • 責務についても少し不自然になっている箇所がある
    • 今は脳内補完しているけどチームになったらこのぶれは許容できないかも
  • 大規模のエンタープライズ系に適用することを想定してるパターンは一人では難しい
    • twitter4jとかそれを利用する箇所を仮想的にそう見なすことはできるかも
  • ドメインビジョン声明文とかはそのままインセプションデッキとかにできそう
    • もしかしたらエレベータピッチかも
    • チームで共有は必須
  • 洗練を重ねた自然なモデルは楽に覚えられる

モデルはどんな感じ?

ドメインモデルのクラス図は以下です。

仕様関連のクラス図は以下です。

なお、図は5/14時点でのモデルです。githubの最新は変わっている可能性があります。

最後に

本来ならばリリースまで持っていった状態で、最終的な結論を出さなければならないとは思いますが、今のところ実践によって得たものはかなりあると思います。次は少しずつビジネスの場に拡張していくことで、今一人では取り組むことができないパターンについても、取り組んでいくことができれば良いなあと思っています。
ソフトウェアは大量生産品ではありません*6ドメインに課題を抱えているユーザに対して、その課題にフォーカスして解決するためのソフトウェアをオーダーメイドで作ることにこそ価値があります。オーダーメイド品を工場で作っていることがないのと同様、ソフトウェアファクトリのような幻想が成り立たないことも容易に想像できるかと思います。そして、オーダーメイド品を作るエンジニアは、ユーザの課題(ドメイン)を共有する方法もまた洗練させなければなりません。DDDを学んで実践することで確実にそこに近づいていけると体感することができました。

*1:多少本にする過程での省略はあるでしょうが

*2:まあ、開発プロセスへの取り組みの中で似たようなことをしているケースはありますが

*3:役割としてはリポジトリなのですが、ファクトリでも良いんじゃないかと思ってしまいます

*4:もちろん完璧ではありませんが、不自然な感じが消えるという意味合いです

*5:なんでシナリオを意識したのかについて

を参照

*6:エンドユーザが多いので勘違いしがちですが、配布が大量にできるだけです