pooh3's memo

Android周りを中心に。軽めに、いい加減さ50%程度で

AndroidでもDDDは有効かどうかという話について

お題どおりです。できるだけ内容を絞って書いたつもりですが、
ところどころ簡潔ではないのでお見苦しいこともあろうと思います。
ですがどなたかの参考になればと思います。



DDDの問題解決領域はどこなのか?

 ビジネスロジックが複雑になりやすい
 変更が多いため、ドキュメントと実装の乖離が大きくドキュメントの管理が面倒
 コードに一貫性がなく、他者もしくは時間をおいた自分が理解するのが面倒

実際複雑なビジネスロジックに立ち向かえるのか?

  Q. エリックエバンス氏のDDD本の触れ込みにもあるが、実際複雑なビジネスロジックに立ち向かえるのか?
  A. 結局ビジネスロジックが複雑になる問題は、コードとそれに対するドキュメント二つの観点で整理していくしかない。
  
   ソフトウェアを管理していくときの技術的負債に関する一番の問題は、ソフトウェアというものの存在自体が多くの変更が必要になり、複雑になりやすい性質のものであるにもかかわらず、ソフトウェアを管理していく問題に対しては多くの開発に関わる人間で軽視されがちであること。
   その点でDDDでは、ドキュメントとコードの乖離が起きにくいスタイルの開発手段を採用していると言える。つまり、DDDでの開発はドメイン駆動であること。
   DDDはドメイン駆動、またモデル駆動による、ドメインモデルというコードの設計を主体にしたやり方である事。
   DDDにおけるモデル駆動による設計とは、あるドメインビジネスロジックについてのアレコレを文章や、図などでモデリングし、それがそのままドメインモデルのコードで表現されているように作る事だ。そして適切な粒度のドメインモデルを形成しようとした時に、適切なドメインの分析が必要になる。(そこらへんの細かな部分は自分じゃなくても言葉にされている方のブログや書籍はあるのでそちらを見てもらった方が良い)
   また、ドメインに関するモデリングで表すものは図、言葉、コード自体とあるので、どれを選ぶのかはそれぞれの利点、欠点を知りつつ利用するのが適切な選び方だと思うので、自分たちが取り扱う日本語という母国語と、コードを書く時に必要になるAlphabetによる記述(or英語)のギャップを意識した上で適切な手段を選択できれば良い。
   そして、ドメインモデルを構成する要素であるドメインオブジェクト(Entity/ValueObject/Service)はコードの一貫性を部分的に持たらすので、メンテしやすいものとなる。

ここでのまとめ

  ソフトウェアを実現するコードは複雑になりやすく、容易に実装者とステークスホルダーとの実装での知識差が生まれやすい。DDDではコードが解決する特定領域のビジネスロジックモデリングを基軸にドメインモデルのコードを作成することで、この問題に対処しやすくしている。


Androidではどうか?

 ビジネスロジックが複雑になりやすい → △サービス・アプリの性質に依存
 変更が多く、キュメントとの乖離が大きくなりやすい → ◎通常のサービスでは、変更が当たり前
 コードに一貫性がない → ◎現存のほとんどのソフトウェア、プログラミング言語に言えること

 上記にあるように、適合率は高い。逆に適合率が低いコードとは、その後拡張、メンテされることが殆どないとわかっているようなデモレベルのアプリ。
 

AndroidでDDDをやっていく上での問題点はあるか?

 既存のコードがある場合に、大きな衝突が発生する。例えばAndroidでは適切にドメインロジックとUIや永続データの処理を分けないものが散見される。DDDを扱う上では、できるだけ構造をシンプルにし、domain層とそれ以外は分離しておきたい。そのためAndroidAPIに依存した部分と、ドメインロジックが書かれる部分は明確に分けることができるレイヤードアーキテクチャを採用すべき。また、各レイヤ依存関係をできるだけ単一方向にしたほうがいい。DIPという観点からで、DIをすべきという話ではない。(DIPだからDIが捗るという話はある)

Serviceについて

 DDDではEntityとValueObjectに分離できたもの以外についてはServiceという名前をつけているが、AndroidのServiceと名前がかぶる。
 この場合明確に分ける方法として、DDDで言うところのApplicationというレイヤで外部と接触を持つServiceは"Android Clean Architecture"(以下ACA)にならって、UseCaseクラスを利用するのが良いかもしれない。しかし概念が似ているとはいえ、それだとACAのコードと純粋なDDDのコードが混ざるのは混乱を生むかもしれないので、あえて代替例を用意するならServiceも結局はドメインに属するサービス。ドメインサービスというところから、DDDのServiceにはクラスのSuffix(接尾語)にDomaiServiceという言葉を使うと良いかもしれない。すでにACAやClean Architectureの導入をしていて、後付けでDDDを利用する場合はUseCaseクラスはそのままでも良いかもしれない。

AndroidのServiceとDDDのレイヤードアーキテクチャ

 基本的にDDDでは、外部→Application層→Domain層→Data層(Repository+memory/local/remote)という依存関係になることが多い。
 これはソフトウェアが断続的に利用され、主に外部からそのビジネスロジックの処理が必要になることが原因。
 AndroidのService(以下AS)を利用する時も同様にApplication層のモデル(Service)を利用することになる。AS側からビジネスロジックの利用がシンプルになるように実装するために、ASとApplication層の間に、MVPのPresenterのようにASに入りそうなロジックを入れるクラスを用意しても良いかもしれない。

導入時の戸惑い

 いざ導入となると、そもそもドメインが何なのか?についてから始まって、いきなり多くの問題にぶつかりそうに思うかもしれない。
 Androidで適応していくにはAndroidで見える問題解決領域が狭すぎて、モデリングに差し支えが出るかもしれない。
 そういう時はとりあえず、コードを真似してみるでも良いではないかと思っている。

github.com

 にあるコードを読んで、そのアプリなりにまずはEntity/ValueObject/Serviceを利用してみてはいかがだろうか。
 

最後に

DDDのEntity/ValueObject/Serviceの取り扱いについても、
どのように扱うのがベストなのかという点がいろんな文章で曖昧だったりするので、別記事にしようと思う。