yoskhdia’s diary

DDDとかプログラミングとかアーキテクチャとか雑多に

ドメイン駆動設計 第2章 ユビキタス言語を読みなおした

社内交流会でLTをする機会があったので「ユビキタス言語」についてDDD本を再度読みなおしてみました。

speakerdeck.com

最近、「DDDは負け犬」みたいな話が少しバズりましたが、ユビキタス言語=ユーザの言葉と解釈するのはあまりに勿体無いのではないかなと思います。 ユビキタス言語はより良い・深いモデルを探求するために必要なものです。

スライドの補足

第2章はスライドに書いたことよりも、もっと多くのことについて言及されています。 ここでは、それらの省略してしまった部分を補足しつつ、スライド構成の今ひとつだった部分を正したいと思います。

まず、第2章最初の一文

しなやかで知識豊富な設計を行うには、用途の幅広い、共有されたチームの言語と、その言葉を使った活発な実験が必要である。 – 書籍「ドメイン駆動設計」(p.24)

省略しようがないくらいに、この一文に詰まっているのですが、スライドでは活発な実験にフォーカスをあてたかったので説明では所々省略していました。順番に見ていきましょう。

その前に

まず設計とは何かを考えると、「ある解決したい問題に対して心のなかで持っているモデルを現実に動くもの(システムや機能)として作るために思考し、その結果を仕様や設計書などに落としこむ作業を指す」とここでは定義しておこうかなと思います。 この心のなかに持っているモデルは、視野・視点・視座が異なれば同じ問題であっても人によって描く姿が変わるものです。 DDD本から一部抜粋します。

ドメインエキスパートは、ソフトウェア開発における技術的な専門用語のことは部分的にしか理解せず、代わりに自分の得意分野の専門用語を使用する。それも、さまざまなニュアンスで使うだろう。(中略)ある問題に対して、それぞれ別の部分に取り組んでいる開発者たちは、自分たち独自の設計概念とドメインを記述する方法を、それぞれで考えだしてしまう。(p.24)

(中略)

同一人物でさえ話し言葉と書き言葉で違いがあるので、ドメインについての最も鋭い表現は、たいてい一時的なかたちでしか現れず、コードや文章ではとらえられることがない。通訳はコミュニケーションを鈍らせ、知識のかみ砕きを沈滞させる。(p.25)

二つの問題があるように思います。
一つは、何のモデルなのか、どの側面を見たモデルなのか、を共有できていない点。
もう一つは、共有できていても、言葉が厳密ではなく曖昧さを含んでいる点。

これらの問題があることを念頭に置いて、冒頭の一文に戻りましょう......

"しなやかで知識豊富な設計を行うには、"

DDDは、モデルとコードの距離を近づけて、変わり発展し続けるモデルに追随し、時にはコードからモデルへフィードバックすることを狙っています。 モデルとコードの距離を近づけるためには、コードも柔軟(しなやか)でなければいけません。 そうでなければ、モデルや言語の進化に追いつけず、システムが重荷となりビジネスにおけるシステムの占める位置が後退してしまうでしょう。ハードウェアやミドルウェアの進歩によるリプレースはあっても、モデルの進歩によるリプレースはコストが高くつくものです。

ドメイン駆動とは、問題を解決する(ドメイン)モデルをとらえることから始め、これをもって業務を噛み砕いて理解し、開発を行ってゆくものです。 モデルについては、これ以上は本筋から外れるためここまでとしますが、簡単にまとめると人によって描く解決策(モデル)が異なるため、そのモデルを共有し、かつ共有し続けることが大事ということです。 そして、そのために強固な共通言語(=ユビキタス言語)が必要とされています。 最終的にはこのモデルがコードとなって実現されますが、そのためには、モデルを理解する必要があります。ここでユビキタス言語が登場します。

"用途の幅広い、"

前段の強固なとはどういうことでしょうか。 私はこの「用途の幅広い」が相当するのだと解釈しています。 用途が幅広いとは、言い直すと「あらゆる場面で使うことができる」ということと思います。 それは開発者のなかだけでなく、業務に詳しい人とのコミュニケーションのなかにも現れます。

例えば、開発者の間でもコードだけでなく、タスクや機能を記述するときにも使用します。また、業務に詳しい人と開発者の間でも会話だけに留まらず文書でやり取りする際にも使用します。 そして、開発者でない人たちの間でも同じ言葉が使われ、チームの内から外へと波及していくことが理想とする世界のように思います。 ただし、DDDはあくまでより良い開発のためのものなので、少なくともチームのなか(開発者、ドメインエキスパート、デザイナ、etc)で翻訳のコストを下げることが主軸です。

同じ言葉を使うことそのものが大事なのではなく、翻訳のコストを下げる、ひいてはコードの適応性を高めることの方が肝要でしょう。

"共有されたチームの言語と、"

そうして、チームで共有された言語は維持し続けなければいけません。 今の瞬間に集まって言葉をすり合わせることはできますが、将来にわたってユビキタス言語を共有し続けることは、ユビキタス言語の意図を理解して尊重する意思が必要です。 とはいえ、ユビキタス言語だ!さぁやるぞ!と一人意気込んでも空回りすることも多々あるので、仲間を広げることが第一歩です。(この記事もその一環)

DDDにおけるユビキタス言語で難しいと感じるのは、それはユーザの言葉だけで完結しない点にあると思います。 本来、情報システムが何のためにあるかと考えれば、情報を処理するためであり、そこにはユーザの言葉だけでは不十分です。 我々開発者が設計を行うためという意識のもと、ドメインエキスパートと言葉を交換することが必要です。 これについては、以下の記事がとても勉強になります。

PHP Mentors -> 杉本 啓「2つのドメインモデル―DDDの含意」

業務を学び、システム・ビジネスに適した情報処理のモデルを探求する、ただの御用聞きではない開発のあり方が求められているのではないでしょうか。 ・・・というのは、一部建前で、私としては金を生み出さないものを作りたくないという点に集約されます。役に立ってるのか分からないものをつくるほど優しい人間ではないではないですし、そんなストレスはご免です。そのために、開発者もビジネスに寄与する主体となれるDDDに魅力を感じているのかもしれません。

"その言葉を使った活発な実験が必要である。"

始めから知識豊かなモデルをつくることは多くの場合難しいです。 そのため、継続的にモデルを実験し続けることが必要です。 この実験のためにユビキタス言語が使用されます。 DDD本から一部抜粋します。

知識をかみ砕くプロセスが、より役立つモデルを作り出せるかどうかは、モデルに基づく言語に対してチームが献身するかどうかにかかっている。粘り強くユビキタス言語を使用すれば、モデルの弱点は明らかにならざるを得ない。チームは実験を行って、用語や、用語の組み合わせがぎこちない場合に、その代わりとなる表現を探す。(p.26)

(中略)

モデルに基づく言語を広く使用し、妥協せずにそれがよどみなく流れるようにすることによって、我々は完全で包括的なモデルに近づいていくのである。こうしたモデルはシンプルな要素から成り立っており、この要素が結合して複雑な概念を表現するのだ。(p.26)

(中略)

システムについて語る際には、モデルをいろいろと試してみること。モデルの要素と相互作用を使い、モデルに許された方法で概念を結びつけながら、シナリオを声に出して描写すること。表現すべきことをより簡単に言う方法を見つけ、その新しい考え方を図とコードに再び反映させること。(p.32)

綺麗な設計書を書いたりするよりも、言葉を交わす方がコストは安いという面もありますが、言葉の有用性としてDDD本ではピジン語(通商用混合語)との比較をあげています。 ピジン語は異なる言語で育った人々が貿易のために集まった時、さしあたりの作業のために生み出す言語です。 会話をしていると、単語の解釈や意味が違っていることが自然に見つかり、その違いが自然に解消されていきます。 ユビキタス言語も同様に、議論で使用することによって、全員がその言語で話せるようになり、ニュアンスを互いに教え合うようになる、としています。

これをチームで約束すれば、図やドキュメント、会話のなかで問題をみつけ、代わりの表現を用いて実験することで、問題を取り除くことができるようになります。 更にDDD本から抜粋します。

ドメインエキスパートは、ドメインについての理解を伝えるには使いにくかったり不適切だったりする用語や構造に異議を唱えるべきであり、開発者は、設計を妨害することになるあいまいさや不整合に目を光らせるべきである。(p.27)

スライド中では、ユビキタス言語を通じてお互いを支え合うことに注目しました。 人間は誰しも思考の矛盾や曖昧さを抱えています。 チーム全員でユビキタス言語を使ってモデルに目を向けることで、これらの問題に向き合うことができるようになるのだと思います。 最後にもう一節DDD本から抜粋して終わりたいと思います。

ユビキタス言語を用いることによって、モデルは単なる設計成果物ではなくなり、開発者とドメインエキスパートが協同で行うすべてにおいて、欠かせないものとなる。また、ユビキタス言語は知識を生き生きとした形式で伝える。そうしたユビキタス言語を使って議論することによって、図とコードの背後にある意味に命が吹き込まれるのだ。(p.27)

(ここまでの内容は主に2章の前半であり、後半にも深い洞察がありますが、それらはまたの機会に。)

Scalaマクロへの誘いTweetまとめと補足

Scala 2.11時点でマクロはexperimentalな機能です。 将来のバージョンでは変わる可能性がある点にご注意ください。 将来的には scala.meta というプロジェクトに移るようです。 公開されているスライドを見ると、今のマクロ記述から新しい記述へはこう変わるという点が示されています。

と呟いたように、リフレクションをまず学ぶのが遠そうで実は近道だと思います。 Scalaのリフレクションもまだ改善の余地がある気がするのですが、scala.metaが出るともっと良くなるのでしょうか? Javaのリフレクションとは異なり、Scalaはコンパニオンオブジェクトやトレイトなどコンパイル時に解決されるものがあるため、Javaの感覚で理解しないままClassオブジェクトを使うのは危険らしいです。

他にはimplicitマクロや抽出子マクロがあるようですが、defマクロが一番基本だと思います。 implicitマクロはまだ使う機会がありそうかなと思えますが、ライブラリならともかくプロダクションコードでimplicitを多用するのも...という論もあり、implicit + macroの組み合わせはデバッグがしづらくなるデメリットの方が大きいんじゃないかなというところです。

展開するコードを書く場面では準クォートがあるので良いのですが、受け取ったTreeを分解する過程ではどんなオブジェクトがあるかを知らないと分解のしようがないので、準クォートの前にオブジェクトを学んでおいた方が良いです。 分解の仕方を知っておくと、例えば引数で渡される式を分解しながら、途中に特定のメソッドが呼ばれているかを判定するなどができるようになります。 (こういった使い方をするには、ユースケースを限定しないと複雑度が上がってしまうので難しいところですが...)

scala.metaになったら手を入れなきゃいけなくなりそうな雰囲気がありますので、マクロを使いたいならしっかりテストを書いておくことをオススメします。

補足

※補足4は間違って抜かしてしまっただけです。
Twitterのツイートをembedすると連ツイだと見難いですね...。