serial experiments lain で理解するドメイン駆動設計(DDD)

ITと開発

あるいは、「ドメイン駆動設計(Domain Driven Design 以下、DDD)で理解する serial experiments lain」

この記事は、serial experiments lain アドベントカレンダー 2024 の19日目の記事です。

お疲れ様です、くろぐろです。

lainTTLの期限もあと4年切ってますので焦りを感じています。
作りかけのゲーム開発を進めたいのですが、仕事優先になってしまいすっかり止まってしまいました。ワークライフバランス大事。

さて、毎年企画しているserial experiments lain アドベントカレンダーですが、今年は本当になにか作る余裕もなく、2年連続ブログ記事になりました。
とはいえ、ブログのネタになるようなインプットもアウトプットもできておらず……。

仕方がないので、今更ちゃんと理解しようと(本業のエンジニア業で)学習しているDDDについて、無理やりlainとこじつけて記事にしてみようという試みになります。

正直、単にlain好きな方にはポカンですし、単にDDDに興味ある方にもポカンな誰得な記事となってしまいますが、作品の内容的にlain✕ITエンジニアの方は意外と少なくないはずなので、なんとか成立することを期待して筆を取りました。

苦し紛れのネタですが、考えてみたらlainのリアルワールド(現実世界)とワイヤード(コンピューター・ネットワークの世界)は、領域や境界などの考えで設計に落とし込んでいくDDDとは相性が良さそうな気もしており、悪くないのではないかと思っています。

DDDの簡単な説明

DDDについて軽く説明しておかないと、lainから入ってきた読者の方は完全に置いてきぼりになってしまうので、できるだけわかりやすくなるように説明してみます。(※わかりやすくしようとした結果、誤解を招いてしまっても責任は負いかねます)

ちなみに、lainを知らないITエンジニアの方へのlainの説明については、アニメ全13話観てもらう方が早いのでさっさと観やがってください。

まずはDDDについて簡単に説明してもらおうと、ChatGPTに聞いてみました。

なるほど、よくわかりません。
これだけだと全く伝わらなさそうなので補足すると、
例えば、音楽制作で作曲をする際に、歌詞先、曲先という言葉があります。
歌詞を先に書いてからそれに合わせて曲を作るのか、曲を先に作ってからそれに合わせて歌詞を書くのか。

プログラミングの世界にも似たような考え方があり、先に作成するものや取り掛かるための考え方を指して◯◯駆動開発や◯◯駆動設計という用語がいくつか存在します。
DDD(ドメイン駆動設計)もその一つで、後述しますが「ドメイン」の面から設計を考えていこうという手法となります。

以下、lainに絡めて掻い摘んで説明してみます。

DDDの用語

DDDにはドメイン、バウンデッドコンテキスト、ユビキタス言語など、馴染みのない人には分かりづらい専門用語が多数存在します。
細かく説明していくと、本が一冊書けてしまうボリュームになってしまうので、この記事では簡単にその3つだけlainに絡めて説明してみます。

ドメインとは?

「ドメイン」とは「領域」という意味で、DDDにおいては「そのシステムが解決すべき問題の領域」と言い表せます。一般的な言葉だと「専門分野」が近く、ドメイン知識というと「その分野の専門知識」となります。
lainの世界でのドメイン/ドメイン知識がどの様になるか考えてみましょう。

  • 玲音がワイヤードへ入れるようにしたい
     ⇒解決するには「玲音」「ワイヤード」の専門知識が必要
  • レインがサイベリアに出現できるようにしたい
     ⇒解決するには「レイン」「サイベリア」の専門知識が必要
  • 記録/記憶をオールリセットできるようにしたい
     ⇒解決するには「記録/記憶」「オールリセット」の専門知識が必要

このように、問題を解決するにはその分野の専門知識が必要になり、そういった問題の領域を「ドメイン」といいます。

……う~ん、伝わる気がしないですが続けます。

バウンデッドコンテキストとは?

「バウンデッドコンテキスト」は、一つのモデル(概念やルール)が有効な範囲を明確に区切るものです。

例えば、lainのリアルワールドとワイヤードは、「物質的な現実世界」と「ネットワーク上の非物理的な空間」として、隔てられた世界となっています。それぞれの世界で、適用される概念やルールが異なります。その中で同じ「玲音」という言葉が使われていても、(性格や肉体を持つか否かなど)意味が異なることがあります。
バウンデッドコンテキストは、このような意味の違いを整理して、1つのエリア内では統一されたルールやモデルを適用するための枠組みとなります。

作中ではこの隔てる境界が崩されることで何が現実か曖昧になり、視聴者が理解に苦しみ混乱することになります。
同じように、プログラミングの世界でも本来別々のものとして扱うコンテキストを、境界を曖昧にして構築してしまうと、変化に対する影響範囲が特定できなくなり問題が発生する要因となります。

もう少し具体的に考えてみると、リアルワールドでの玲音とワイヤードでのレインは、同じ玲音(レイン)という存在ですが、文脈によって役割が異なります。
境界としてわかりやすいようにリアルワールドとワイヤードの境を例に挙げていますが、日常生活でも家庭での役割と、学校での役割など、シーンによって同じ言葉でも意味が異なります。
そういった違う文脈で玲音という存在を同一のものと扱うと矛盾が生じるため、違う文脈に対しては分けて考える必要があり、線を引いてコンテキストを分けることをDDDではバウンデッドコンテキストと言います。

ユビキタス言語の重要性

最後にユビキタス言語についての説明となります。

実はユビキタスという単語は、lainファンの皆さんには馴染のある言葉です。
そう、「遍在」です。
ユビキタス言語とは「遍在する言語」、つまり、どこででも通用する共通言語と考えてください。

※ここでの「どこででも」という範囲は、前述のバウンデッドコンテキストは”超えない”範囲で、ビジネスサイドと開発サイドで共通して同じ言葉を使う、という意味になります。

普段の日常会話でも、lainのドメイン知識(lainに関する専門知識)があれば、「お父さん=岩倉康男」「神様=英利政美」とすぐにイメージできるとは思います。
しかし、全員が必ずしも詳しいドメイン知識を持っているわけではありません。単に「玲音」と言ってもリアルワールドの岩倉玲音か、ワイヤードのレインか(訓練されたファンであれば簡単だとしても)誰もがすぐに分かるわけではありません。(ここでPS版lainの存在も持ち出すと更にややこしくなりますね)
そこで、ユビキタス言語を一覧表にまとめておくことが重要になります。

  • 「玲音」(Lain)=岩倉玲音。リアルワールドで学校に通うおとなしい性格の少女。
  • 「レイン」(laIn)=通称カタカナレイン。主にワイヤードで観測される強気な性格の少女。玲音がワイヤードに接続するとレインの人格が現れることが多い。
  • 「リアルワールド」(RealWorld)=現実世界。玲音を始め肉体を持ち生きている人間が暮らす領域。
  • 「ワイヤード」(Wired)=コンピューター・ネットワークの世界。NAVIと呼ばれるコンピューター端末を介してアクセスする事ができる領域。リアルワールドでの姿をワイヤードで保つにはマシンパワーが必要。死して肉体を捨てても意識のみをワイヤードにおいて存在し続けることができる。

ちょっと適当ですが、上記のように言葉に意味を定義していくことが重要となります。
簡単に言えば共通認識を持てるようにする用語集ですね。
設計するうえで表記揺れをしないようにするのも目的の一つです。
特にプログラミング言語の多くは英語を使うものが多いので、日本語と英語での記述を明確に関連付けておかないと、「お知らせ=info?/news?」など、人によって表記のズレが発生し、管理が難しくなったり不具合の元となったりします。

以上、DDDのほんの一部の考え方ですが、このような考え方でlainの世界を分解していきましょう。

この記事では、DDDの設計手順の中で、「バウンデッドコンテキストの定義→ドメインモデルの設計→コンテキスト間の連携設計」の範囲にしぼり解説していきます。

lainの世界を分解する

(バウンデッドコンテキストの定義)

まずは、lainの世界を構成する要素を文脈毎に分けるとどのように分けられるかを考えてみます。
今回は登場人物を増やすとキリが無くなってしまうので、玲音と玲音を取り巻く空間のみに絞りました。

これまでの説明でも度々出てきているリアルワールドとワイヤード、大きくこの2つに分けられそうです。

図にすると以下のようになりました。

細かく分けようと思えば、リアルワールドの中も岩倉家自宅や学校、サイベリアなど、解像度を上げれば上げるほどいくらでも分けられますが、なぜ分けるのかを意識して必要な解像度で落とし込む必要があります。
解像度の違いについては、例えば”通信手段”という点から考えるとNAVI(PCやスマホ)は一つの最小単位ですが、そのNAVIの”製造”という点から見れば、NAVIはCPUやメモリ、ストレージなどから構成される大きな単位となります。目的に応じてバウンデッドコンテキストの分け方も考える必要があり、設計の経験が問われる部分となります。
今回はわかりやすさを重視してシンプルに2つにしています。

(余談)
作中ではリアルワールドとワイヤードの境界を壊す展開もあり、それぞれの領域が不明瞭になっていきます。それをプログラミングの世界では密結合といってお互いに複雑に依存し合い、一つの領域の変更に対して他の領域に影響が起こりやすくなります。そうなると、どこに影響するか特定するのが非常に難しくなり、変更に耐えられないもはや想定した機能動作を維持し続けるのが難しいカオスな状態となっていきます。(畏怖)

lainの世界を構成するものをモデル化する

(ドメインモデルの設計、モデリング)

世界の分け方が決まったところで、作中に登場する要素をわかりやすくするため抽象化していきます。
抽象化とはどういうことかというと、先程の例でNAVIを出しましたが、目的によって必要な情報量は変わってきます。NAVIの色や傷があるかどうかなどは、仮に”修理”という観点からは必要な情報ですが、それ以外の文脈では必要のない情報になりえます。
問題を解決するための必要十分な情報となるように、不要な情報は削り必要な情報のみに整理していきます。

なお、この手順をドメインモデルの設計=モデリングと呼びますが、DDDの中でも難易度の高いステップとなります。

DDDの良いところは、必ずしも最初から完璧な設計を目指す必要がないことです。
まずはざっくりドメインモデルの設計を書き出してみて、それを元にユースケースの洗い出しをします。そして、モデルがユースケースを満たすか検証して、必要であれば調整を繰り返していきます。
この辺りのユースケースの洗い出しから始めるか、ドメインモデルの設計から始めるかは、特に決まりはなさそうで、重要なのはそれぞれ行き来しながら精度を高めていくことという理解にしています。

まずは、間違っていてもいいので書き出してみます。
この段階でユビキタス言語の一覧を書き出し始めるとよいでしょう。

リアルワールドのモデル

  • 玲音(アグリゲートルート)
  • NAVI(エンティティ)
  • 服装(エンティティ)
    • 制服(値オブジェクト)
    • くまパジャマ(値オブジェクト)

ワイヤードのモデル

  • レイン(アグリゲートルート)
  • 性格(エンティティ)
    • 強気(値オブジェクト)

上記のようなモデルを図にすると以下のようになります。

粒度も適当で、同じ単語の玲音とレインに共通要素もないのでこれでよいのか怪しいですが、気にせずユースケースを考えてみましょう。
(アグリゲートルート、エンティティ、値オブジェクトについては、DDDを学習していけばわかる用語となっていますが、今回の記事では割愛しますので、気になさらなくても大丈夫です)

リアルワールドでの玲音のユースケース

今回は玲音個人で完結するものとワイヤードに関わることのみに絞って書き出してみます

  • 玲音は制服に着替える
  • 玲音はくまパジャマに着替える
  • 玲音はNAVIを起動する
  • 玲音はNAVIを使ってワイヤードにアクセスする

ワイヤードでのレインのユースケース

同じくレイン個人で完結するものと、リアルワールドに関わることのみに絞って書き出します

  • レインはワイヤードにフルレンジ・フルモーションでメタファライズできる
  • レインはサイベリアに現れる(※)
  • レインは玲音を介してリアルワールドに具現する(※)

※この辺りはドメイン知識が試されるところ……ややこしくなるので文字通りの解釈として進めます

一旦出したモデルとユースケースを見比べて、不足や矛盾しているところがないか確認し、調整していきます。

モデルとユースケースの修正

ユースケースに合ってモデルに無い要素を考えると、モデルに不足している要素が見えてきます。

リアルワールド側は問題なさそうですが、ワイヤード側のモデルがいくつか足りてなさそうです。

  • フルレンジ・フルモーションでメタファライズできる
    ⇒lainのドメイン知識がないと何を言っているかわからないと思いますが、ワイヤードにどのような状態で存在しているかを表している用語です。現実世界になぞらえて解説すると、VRChatなどでフルレンジ=全身をリアルワールドそのままの姿で、フルモーション=動きを高フレームで描画できる状態のメタファライズ=アバター化ができる、となります。(私は公式設定をあまり読まない質なので、正直文脈でなんとなく理解した気になっているだけですが……)
  • サイベリア
    ⇒サイベリアはリアルワールドに存在する場所の名前ですが、今回のドメイン分類としてはリアルワールドに属するため、「レインはリアルワールドに(特定条件によって)現れる」として、今回は特定条件については組み込まないことにします。
  • 具現する
    ⇒リアルワールドからワイヤードに入ることを作中用語でメタファライズと言いますが、逆にワイヤードの存在がリアルワールドに肉体を持って現れることは特に用語化されていないので、今回は「具現する」という用語を適用することにします。

こうして、ユースケースを考える際に出てきた用語を、ユビキタス言語として策定していき、曖昧な部分を詰めていきます。

また、モデル図を眺めていると、ユースケースに現れていない要素にも気づきます。

ワイヤードのレインには、「性格→強気」という要素がありますが、何に対してかが表現できておらず違和感があります。
そこでユースケースを改めて考えて、以下のようにユースケースを追加してみましょう。

  • 玲音はワイヤードにアクセスするとレインの性格として振る舞う
    ⇒やや表現がはっきりしないのですが、レインはワイヤードに偏在する存在としても扱われているため、玲音とレインが完全に同一存在とは言い切れない難しさがあります。 性格の表現についても、最初は単に「強気」と表現しましたが、玲音とレインを相対的にした場合、弱気⇔強気という表現も違う気がするので、少し表現を変えてみます。
  • 玲音
    ⇒内向的で繊細/純粋で素直
  • レイン
    ⇒大胆で挑発的/冷酷で計算的

ワイヤードにメタファライズしているときの玲音は、レインの性格として振る舞うため、レインの性格は一つとなりますが、リアルワールドの玲音は、ベースとなる内向的な性格のときと、レインが具現している状態の挑発的な性格と2つの性格が切り替わることになります。

このような要素を図に表すと以下のようになりました。

このようにモデルを図として表現していくことで、複雑な問題を見えるようにして理解しやすい形に落とし込んでいくことができます。(本当かな…)

リアルワールドとワイヤードを玲音/レインを軸に連携する

(コンテキスト間の連携設計)

このままだと、図の中ではリアルワールドの玲音とワイヤードのレインが完全に独立している状態なので、ドメイン知識がない人には、どのように玲音とレインが繋がっているのか伝わりません。

そこで、コンテキスト間の連携を表現する必要があります。

今回は、各コンテキスト間の要素を「玲音/レイン」のみとして考えてみます。
リアルワールドとワイヤードでは物質的な依存は存在しないので、NAVIや服装、状態的なものは依存させる必要はありません。性格も両方で共通した状態をもつわけではなく、リアルワールドの玲音の状態によって変化するものなので連携の要素はなさそうです。

では、何をもって玲音とレインが関係するのかというと、作中の表現で「記憶」と考えられそうです。
玲音がワイヤードにメタファライズするときは、玲音の記憶を持ってレインとなり、レインとなってワイヤードで活動している間の記憶を玲音は維持しています。

こちらを先程のモデルの図に足しても良いのですが、コンテキスト間の関係はコンテキストマップという別の図にすることで、多数のコンテキストが存在する際にシンプル化して、コンテキスト間の連携数を見やすく整理することができます。

このような形で、DDDの設計で「バウンデッドコンテキストの定義→ドメインモデルの設計→コンテキスト間の連携設計」をすることができました。

DDDが教えてくれる新たな視点

ここまで、DDDを通じて「serial experiments lain」をプログラミング開発的に理解しやすいよう設計に落とし込むという方法をやってみました。

lainのように複雑な作品の場合、ある側面からのみ説明しようとすると、矛盾が発生して理解が難しい部分も多く発生してしまいます。
リアルワールドとワイヤードをバウンデッドコンテキストに分けることで、特定の文脈でのルールを明確にして、それ以外の文脈とどう交わるのかを明確にしていけば、混乱する要素を減らしていけると考えています。
プログラミングの世界では、依存の向きというのは重要な要素となるので、ワイヤードがリアルワールドに依存しているのか、リアルワールドがワイヤードに依存しているのか、またはその両方か、ということも見えるようにすることも役立ちます。

作中では、前述の通り、次第にリアルワールドとワイヤードの境界は崩れていくため、その場合は再度設計をし直して、新しい世界での最適な理解を深めて行く必要がありますが、それはまた別の機会に。(そんな機会は来ないと思いますが)

まとめ

DDDは複雑なシステムや物語を解きほぐす強力なツールとなります。
今回はアドベントカレンダーをきっかけとして、かなりのこじつけでしたが「serial experiments lain」をDDDの手法で設計に落とし込んでみるという暴挙に出てみました。

私自身DDDを学習中なので、理解をもっと深めていく必要があると思いますが、実際にlainという曖昧な部分が多い世界をモデリングしてみることで、やりやすい面ややりにくい面を感じることができました。

流石にこの記事を読んで、lainに興味を持っていただけたり、DDDに興味を持っていただけたりする方は相当奇特な方だとは思いますが、誰か一人にでもこの記事が刺さることがあれば嬉しく思います。

それでは、また来年。

コメント

タイトルとURLをコピーしました