Edited at
GunosyDay 5

UXを踏まえてDDDをまとめてみる

More than 3 years have passed since last update.

ddd.png


DDDって何?

エリック・エヴァンス氏の提唱するドメインモデルからソフトウェアを設計しましょうという設計手法のこと。

自分(半分Front-End Engineer・半分UI Designer)も半年前に存在を知りました。

ちょうどDDDを長らくやってこられたEngineerさんがジョインしてきて、運良く一緒にプロジェクトを回すことになり、Domain Driven Design(ドメイン駆動設計) Quickly 日本語版エリック・エヴァンスのドメイン駆動設計の輪読会や社内ワークショップ、実務のコードで体験していった流れです。もちろんまだまだ知識量は不十分ですが…。

ドメイン? モデル? 設計手法? コードを書かないUI Designerには関係ないなーと思うかもしれないですが、DDDの概念を深堀していくとあることに気づきます。それはUCD/HCD(User/Human Centered Design: ユーザ/人間中心設計)の概念と実は近いということ。

というわけで、ここではDDDがなぜ良いと思えたか・DDDってどんなものかをUI Designer目線で緩くまとめてみました。


ドメインモデルとは

ドメインは直訳すると、

領域・分野

ドメインモデルとは、

ソフトウェアとそれを使う利用者の知識や活動の領域から

抽象的な概念を抽出してモデルにしたもの

モデルとは、

モノやコトの仕組みを単純化した型

これらは別にEngineerが考える複雑なプログラムの話ではなく、あらゆる思考を整理する際に論理的にものを考える = 論理的思考。 論理的思考 は 具体と抽象 の関係を明確にしていくこと。煩雑に物事を捉えて作るより、正しく理解するために整理してから作ろうぜっていうのがDDDの本筋ではないかと思います。




「具体と抽象」 著: 細谷 功 より引用



アプリにはユーザが必ず存在します。そういうユーザを一言に ユーザ といってもユーザが存在している場所によって、ユーザが持っている具体的な情報や識別するための情報は異なります。


ユーザを例に考えてみる

例えば、病院の診察予約アプリがあったとして、そこに存在するユーザについて考えて見ると…

一言にユーザといっても次の3つくらいは存在すると思います。


  • 診察予約をするユーザ = 患者

  • 予約を管理するユーザ = 看護師

  • 診察をするユーザ = 医師

同じユーザでも役割やユースケースによって関係する領域は異なります。当然それぞれのユーザが持っている情報も異なります。

ドメインモデルとは、コトやモノの関係する領域というコンテクストから概念をモデル化したものということになります。

ちなみによくあるレガシーな設計では、実装上の都合で ユーザ という概念が捻じ曲げられる事があります。

例えば アプリを使うユーザー(患者) アプリを使うユーザー(病院関係者) とか。

しかし実際は、診察するまで というストーリーの中にアプリが介在しているだけであって、上のレガシーな概念では主従が逆になってしまいます。 アプリを使わされているユーザ 的な。

この最もたる例が UIドリブンデザインだと個人的に思います(UXドリブンデザインなら的を得ていると思いますが、UI/UXドリブンデザインは本質が見えてないなーと思います :cry: )。

UXデザインはコンテクストという線のデザインで、UIはその中にある点のデザイン。点を作って線を繋ぐのではなく、点は線の中にあるべきです。

DDDではこれを SmartUI(画面駆動開発) アンチパターン としています。画面駆動開発のメリットももちろんケースや規模によってはありますが、今や体験を売る時代においてSmartUIは本質的な考え方としてはスマートではないかもしれないです。

余談ですが、DDD知ってから、次の記事にあるデザインポエムとかピンとくるかなと思います。

- The Dribbblisation of Design: Only one of these weather apps is attempting to solve the real problem.


ユビキタス言語

ここまででドメインモデルが何かは一応説明できたはず。で、この流れで一つ気づくことがあります。それは、ユーザ という 言葉 です。

前述した通り、関係する領域でユーザといっても概念は異なります。これが開発や仕様を決める時にそのまま使われるとどうでしょうか?最悪の場合、コミュニケーションロスが起こります。

自分が思っている ユーザ が病院関係者ユーザだったとしても、相手もそうだとは限らない(もちろん文脈で想像することはできますが、齟齬の発生確率は高い)。

言葉一つの概念が開発チームやビジネスパーソンの間で異なれば、下手をすれば双方が思っているものと違う機能をもったアプリケーションが開発されてしまいます。

もちろん極端な例なのでそうならないように要件定義書などを作るわけですが、そのドキュメント更新しやすいですか?しますか?する時に錯覚していきませんか? ドキュメントを更新するのが主な仕事 だと。

その闇の時間をなくすために、DDDでは ユビキタス言語 なるものを定義していきます。

ユビキタス = いつでも、どこでも、だれでも

つまり、ドメインモデルをさらにわかりやすい形にするために、齟齬を無くすために使う言葉とその意味をきちんとひも付けて、開発チームやビジネスパーソンの間で共有します。

診察予約アプリのユビキタス言語を決めるとすればこんな感じですかね?

ユビキタス言語
意味

患者
診察を受ける・予約をするユーザ

看護師
診察予約を受け付けて処理するユーザ

医師
診察を行うユーザ

この定義がどうあれば正しいかは、ドメインエキスパート というその関係する領域の知識を多く持つ人(業務知識を豊富に持つ人なので、この場合だと病院関係者の中でも診察予約にもっとも精通している人なので、看護師の代表者かと)とソフトウェアエキスパート(設計や実装の知識をもっとも持つ人)の会話から抽出と定義を繰り返します。

さらに設計や実装をすすめたり、実際にアプリを使ってもらう中で誤りがあれば正しく変更していきます(リファクタリング)。


ドメインドリブンデザイン(ドメイン駆動設計)

DDD = Domain Driven Design

ここまで説明してきた、ドメインモデルとユビキタス言語。これを明らかにしていくだけではDDDではありません。俺たちの本当のはじまりはここから。ソフトウェアは実装して使ってもらってなんぼです。つまりこのドメインモデルをオブジェクト志向プログラミングの オブジェクト にしていきます。


突然ですが、僕の好きな漫画に一本包丁満太郎という作品があります。料理対決漫画の祖ともいうべきビッグ錠先生の代表作の一つです。

主人公の風味満太郎は、実家の二代続く老舗カツ丼屋で頑なにカツ丼とカレーしか出さないスタイルに反発して家を飛び出し、流れで制限時間内におにぎり100個作るという、おにぎり勝負 という試合? に出ることになります。

対戦相手は、大阪にある示条流というこれまた歴史のある日本料理の名門の33代目にあたる娘の示条味味。満太郎は奇策で一度に10個のおにぎりを作る方法で挑み、味味は地道に一つづつ握って挑みます。

と、全然DDDと関係ないですね…。

でも、なぜこの話を書いたかというと… この関係性を示した文章をコードにしてみたかったからです(診察予約の方でやっても面白くなかったので)。

const numberOfOnigiri = 100;

const time = 0;
const limitTime = 60 * 60 * 1000;

const Person = {
'mantaro': {
'gender': 'man',
'name': '風味満太郎',
'profile': '二代続く老舗のカツ丼屋の息子',
'onigiri': 0,
'duration': 5 * 60 * 1000,
'incremental': 10
},
'mimi': {
'gender': 'woman',
'name': '示条味味',
'profile': '大阪にある日本料理の名門示条流の33代目',
'onigiri': 0,
'duration': 60 * 1000,
'incremental': 1
}
};

const makeOnigiri = (personObject)=> {
setTimeout(()=> {
if(numberOfOnigiri >= personObject.count) return;
personObject.count += 1;
makeOnigiri(personObject);
}, personObject.duration);
};
const countTime = ()=> {
time += 1;
if( limitTime >= time ) countTime();
return true;
};

const isWinner = ()=> {

makeOnigiri(Person.mantaro);
makeOnigiri(Person.mimi);

if(countTime()) {
if( Person.mantaro.count > Person.mimi.count ) {
alert('満太郎の勝ち');
}else if( Person.mantaro.count === Person.mimi.count ){
alert('引き分け');
}else{
alert('味味の勝ち');
}
}
};

例がクソコードすぎてアレですが、変数名やメソッド名でそれらが何を意味しているのかプログラム書いたことなくてもわかると思います。

要は何がいいたいかというと、皆が使っている日本語という自然言語をプログラム言語でも表現(翻訳)できるわけです。なぜならどちらも同じ 言語 だから。

そして、自然言語と同じように物事を説明できるコードだと何が良いか。それはコード自体がドキュメントと同じ役割を持てるということです。

a = 0;

b = a + 10;

例えば、上のようなコードがあったとして、これを自然言語にするとすれば

aは0です。bはaに10を追加したものです。

となります。aとbって何かわからないです。変数というプログラム的な意味がありますが…。これって人にはあまり優しくないですね。

私たちが普段生活の中で抽象と具体を行き来しながら自然に定義しているモノやコト・ユースケースと同じ意味を持つコードや構造なら、元になるモノやコト・ユースケースが変化した際、コードも同じように変化できるしし易いだろうというのが、ドメインドリブンデザインです。


レイヤードアーキテクチャ

上のような、ドメインも振る舞いも一緒くたになっているクソコード(スパゲッティコード)が増える害悪があります。

モノやコト・ユースケースの変化などによる新しい気づきによって概念の変更の必要性が高まった時、いざコードの改修を行おうにも、どこになにがあるの?そのクラスやメソッドの責務て何?… という設計とは何だったのか?そもそも設計がないという状態では、グロースしたりピボットしたりしたいのようなビジネス的な転換期に何もできず… 仕方がないので小さい施策で益を得るような体質になってしまうかもしれない…。

そんな変化に寄り添える設計には役割に応じてきちんと整理されていることが大切です。

ドメインモデル・ドメインの持つ情報(値オブジェクトやエンティティ)の振る舞い・データベースなど技術的都合との接続・画面に表示するUIなどに整理・設計しておけば、あれどこにあったっけ?これなにを意味するの?は減っていきます。


リファクタリング

大切なのは変化を恐れることではなく、変化に寄り添えるようにしなやかな設計をすること、そして概念からのリファクタリングを行えるようなコードやそれを行うことの重要性を理解できる組織にしておくことがとても大切だとDDDでは言われています。

そして概念は人の暮らしや文化、技術革新によって変わっていきます。実装都合やビジネス側の一方的な思い込みによる都合での仕様が普遍な概念でできていれば良いですけど…。

そういう普遍的なものも含めて日々懐疑的に評価をしこうぜって思います(とはいえなかなか組織が村化すると難しいですが)。




というわけで最後。

最初に述べた HCD(人間中心設計)と概念が似ている話です。

DDD = モノやコト・ユースケースの変化に寄り添った設計手法

DDDを一言でいうとコレかなと自分は思います。つまりソフトウェア開発は実装的な都合に合わせるのではなく、使う人のメンタルモデルに合わせて作られるべきであり、それって人間中心設計だと思います。

昨今の利用者へ提供する価値は 所有 から 体験 に変化しています。

所有の価値はモノ自体を所有 = 購入するまで。でも体験は、


  • 利用する際

  • 利用する時

  • 利用した後

  • また利用したいと振りかふりかえったりする時

いわゆる UX(ユーザ体験) ってやつです。それぞれのフェーズでモノやコトの概念はどうなのか探って、それに対してどうあるべきなのかがサービスの核になる。デザイナーや企画者などが人間中心やユーザファーストで考え、デザイナーとエンジニアが協業してDDDで実装を行う。この共通した流れをチームで行えれば、ユーザにとって真にハッピーなプロダクトが提供できるし、そうなれば利益にもつながるのではと思います。

保守的に職域を守ったり、変化に耐えられない文化を頑なに守ったり…そんな意味も意義もないドメイン(領域)から抜け出して最高の体験を提案できるプロダクトを作ろう!


というわけで、2016年2月くらいに[ DDD, HCD, デザインスプリント, LeanUX, スクラム ] とUIデザイン的なのをごった煮にした勉強会をやろうと思っています。興味ある方は @tyshgc まで。