0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

私達はすでにDDDを実践している、かもしれないという話(Spring編)

Posted at

表題の一解釈について発表させていただきます。

先日、Wikiでドメイン駆動設計(DDD)の記事を目にしました。
https://ja.wikipedia.org/wiki/%E3%83%89%E3%83%A1%E3%82%A4%E3%83%B3%E9%A7%86%E5%8B%95%E8%A8%AD%E8%A8%88

その冒頭に、次の要約が載っていました。

ドメイン駆動設計(英: domain-driven design, DDD)とはソフトウェアの設計手法であり、「複雑なドメインの設計は、モデルベースで行うべき」であり、また「大半のソフトウェアプロジェクトでは、システムを実装するための特定の技術ではなく、ドメインそのものとドメインのロジックに焦点を置くべき」であるとする。

とりあえず、"モデルベースで行うべき"という点には賛成です。実際、ビジネスサイドの人と話をする時は、四角と線でできた簡単な図を、ホワイトボードに書いたりして打ち合わせします。

・・・この時点でもう、私達はすでにDDDを実践しているような気がします。

さて、焦点を置くべきところは"システムを実装するための特定の技術"ではないとのことなので、表題に含まれる"Spring"などの特定の技術に拘泥していてはいけないようです。耳が痛いです。

そうではなく、焦点を置くべきところは"ドメインそのものとドメインのロジック"とのことです。それをモデル化したものに"ドメインモデル"があり、それは以下の"ドメインモデルを表現する要素"によって表現できるようです。

エンティティ (参照オブジェクト): ドメインモデル内のオブジェクトであり、その属性によってではなく、連続性と識別性によって定義される。

値オブジェクト: 事物の特性を記述するオブジェクトである。特に識別する情報はなく、通例、読み出し専用のオブジェクトであり、Flyweight パターンを用いて共有できる。

サービス: 操作がオブジェクトに属さない場合に、問題の自然な解決策として、操作をサービスとして実現することができる。サービスの概念は、GRASPにおいて"純粋人工物"と呼ばれるものである。

リポジトリ:ドメインオブジェクトを取得するメソッドは、記憶域の実装を簡単に切り替えられるようにするため、専門のリポジトリオブジェクトに処理を委譲するべきである。

ファクトリー : ドメインオブジェクトを生成するメソッドは、実装を簡単に切り替えられるようにするため、専門のファクトリーオブジェクトに処理を委譲するべきである。

これらを見て、「これ全部、Springの用語で書き換えられるのでは?」と思ったことが、本稿起草の契機です。実際にやってみたものが下記になります。

  • エンティティ
    テーブルに格納されたレコードの入れ物。テーブルのカラムと同じフィールドを持つ。Repositoryの引数であり、戻り値でもある。テーブルのIDがAuto Incrementしている場合、IDフィールドにユニークな値が入る。

  • 値オブジェクト
    Enum。大抵、コード値とかはEnumにされる。

  • サービス
    Controller-Service-Repositoryの3層構造におけるServiceのこと。色々複雑なことをすることもあるようだけど、[ControllerのModel※] ⇔ [RepositoryのEntity] の詰め替え作業をしているだけのこともある。(※MVCにおけるModelのことっぽいけど、実際はただのデータの入れ物)

  • リポジトリ
    Controller-Service-Repositoryの3層構造におけるRepositoryのこと。要するに、DBに関わる処理をするところ。どんなORマッパーでも、内部ではSQLを実行している。あと、外部APIを読み出す箇所としても使われていたりする。

  • ファクトリー:
    DI。Controller-Service-Repositoryの3層構造は、DIで構築されている。@Autowiredを使うスタイルも、いまや古くなってしまったかも。

こんな感じで、概ね書き換えることが出来てしまいました。

ドメイン駆動開発は、そのアンチテーゼがトランザクションスクリプト(if-elseによる長大なメソッド群)らしいです。

トランザクションスクリプトにならないよう、上述の「ドメインモデルを表現する要素」を意識してリファクタリングに勤しめば、ボトムアップ式とはいえ、ドメイン駆動開発をしていることになりそうです。

それなら、"特定の技術"ということにはなりますが、Springを使って開発していたら、「ドメインモデルを表現する要素」を意識することになるので、自然とドメイン駆動開発をしていることになると言えそうです。

とはいえ、ドメインモデル欠乏症という言葉があって、setterとgetter以外に、なんの振る舞いもしないDTOを良しとしているとダメなようです。

実際の開発では、"ドメインそのものとドメインのロジック" を "ドメインモデル" に書き出す、なんて面倒なことはせず、よくある設計パターンを再利用する感じで進めている気がします。Springなら、Controller-Service-Repositoryの3層構造を守っていれば、そんなに困ることはないように思います。

しかし、Wiki冒頭の要約にあった"複雑なドメインの設計"においては、既存の設計パターンを簡単には適用できないのだと思います。

そうしたケースでは、適切なドメインモデルを構築すべく、ビジネスと開発の人の双方が分かるユビキタス言語を発見・発明したり、何度もER図とクラス図を書き直したり、ホワイトボードを前に喧々諤々したりする必要があるのだと思います。

いつか、"複雑なドメインの設計"をすることになっても大丈夫なように、普段から、"ドメインそのものとドメインのロジック"を意識しておくことが大切なのだと思います。

決して、「普段はそんなに意識する必要ないのでは?」なんて不遜なことを思ったりしていないです。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?