インピーダンスミスマッチとどう向き合うか

どうも、最近コーラゼロにはまっている人です

TLに流れてきたおもしろそうなものがあったので、まずはこれを聞いてみてください

[Software Development in 2003](https://anchor.fm/textafm/episodes/1--Software-Development-in-2003-eimq17)

DDD登場当時の話とかがされていて、全然知らない部分もあったのでかなりおもしろかったですｗ
で、「Sideshow 1. The School of OOP」という部分でDDDとRDBの距離についての話がありました

今回はその部分を掘り下げて考えていこうと思います

#そもそもインピーダンスミスマッチって何？
パラダイム間のズレのことです
ここではオブジェクト指向プログラミング言語とRDBMSの間にある溝のことをインピーダンスミスマッチと言っています
(本来は電気関係の用語なので別の意味を持っているのですが、習慣的？にインピーダンスミスマッチと呼ばれています)

リレーション(R)ではカラム、レコード、テーブルで表現していますが、オブジェクト指向(O)ではオブジェクトで表現しています
この「O」と「R」の間をどう取り持つか、というのが問題になっています

というか、このラジオを聞くまでインピーダンスミスマッチという言葉自体を知りませんでしたｗ
ただ、このパラダイム間のズレというのは[エリック・エヴァンスのドメイン駆動設計](https://www.amazon.co.jp/gp/product/4798121967/ref=ppx_yo_dt_b_asin_title_o06_s00?ie=UTF8&psc=1)でも指摘されており、僕もどうすれば良いかちょこちょこ考えていました
インピーダンスミスマッチという言葉を知る前、どんなことを考えていたのかちょっと書いてみようと思います

#OとRの間をどう埋めるか

 - **OODB使えば良いじゃん！**

真っ先に思いついたのはこれでしたｗ
OODB(オブジェクト指向データベース)であればパラダイム間のズレが発生しないので、かなり手間を節約できると思ってました
が、実際調べてみると全然ヒットしない…ｗ
OODBはほぼ絶滅してました

何故絶滅したのか、先ほどのラジオでも少し触れられていましたが、RDBMSのバックグラウンドにある理論が強固であることが原因だそうです
OODBだとデータにアクセスするときに掛かる時間がバラバラになっちゃったり、そもそもパフォーマンスが出なかったり…など難しい部分がかなり多いです

 - **オブジェクト指向のORMは？**

これについては既に知っていたのですが、相手がOODBではなくRDBなのでテーブル構造を意識した感じになってしまうのであんまりピンときませんでした
JavaでいうとSpring Data JPAがオブジェクト指向のORMにあたるのですが、MyBatisというSQLを自分で書くほうが人気があるというなんとも微妙な感じになってます

すごいもやもやな感じで毎日を過ごしていたのですが、インピーダンスミスマッチという言葉で調べてみたらボロボロ出てきましたｗ

#今の最善策

色々調べたところ、**「オブジェクトとテーブルを1:1で紐づける」**というのが最善策のようです

これを最初聞いた時にはあんまり納得できませんでした
何故かというとRDBのテーブル構造がごちゃごちゃになるものをイメージしていたからです
しかし、よくよく調べてみると「オブジェクトとテーブルを1:1で紐づける」というのはデータの不整合を受け入れる、という意味ではなかったのです

#ドメインへのアプローチ
まずは下記の記事を読んでみてください
少し長いのですが、とても良いことが書いてあります

[結果整合性を使うということはDBで正規化を捨てるということだと君は理解しているか](https://kbigwheel.hateblo.jp/entry/2019/04/06/011312)

ここで問題になっていたのはユーザーが組織に参加できるかどうかの判定をどこでどのように実装するか、という話でした
いくつかの解決方法があったのですが、僕が一番良いと思ったのは「所属(ユーザー一覧)を定義する」というものでした
組織、ユーザーと考えていると所属という概念を忘れてしまいがちですが、間違いなくそこにあります

このような暗黙的な概念をどうすれば簡単に明示できるのかー
僕はTMと呼ばれている手法がかなり役に立つと思っています
TMについて前書いた記事があるので読んでみてください

[T字形ER手法って何？？？](https://qiita.com/bouitengineer12/items/530d04075e68b3f1a6f6)

TMを使って考えてみましょう
「組織」というresource、「ユーザー」というresourceがあり、その対照表を生成することが出来ます
組織・ユーザー対照表にタイムスタンプを付けると「所属」というeventにできます

対照表を生成する、というのはTMで言えば基本中の基本なのですが、この手法を用いることによって「所属」という暗黙的だった概念を一瞬で明示的にすることができました
これってめっちゃ便利じゃないですか？ｗ

TMはDOA(Data Oriented Approach)と呼ばれるアプローチの方法です
DDDはドメインエキスパートとの話からモデリングをしていきますが、TMの場合データがあればある程度はモデリングが出来てしまいます
しかし、データ構造でドメインを表すのには限界があります

先ほどのラジオでも触れられていましたが、ドメインロジックを直接書き込むソースコードとRDBとで比べた場合、ソースコードのほうがドメインの記述が濃くなります(ドメインロジックを直接書いているので当然と言えば当然)

TMはモデリングを行うヒントにはなるが、全てを表現することはできない、というのが僕の見解です
ただし、このヒントというのがかなり重要だと思っています

まずTMを用いて骨組みを作り、DDDを使って肉付けしていく、というのが一番良いと思っています

![骨付き肉.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/529608/b41a026e-5d93-28b2-0bdf-f94427bcf916.png)

TMでは「不定の値」を認めていません
つまり、リポジトリーがアクセスするテーブルは複数の場合がある、ということです

所属を例に図にしてみました
![モデル例.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/529608/e7afbb81-676d-0723-6fb7-70aab3dd7a6c.png)

(ドメイン層～RDB間については省略しました)

~~TMで所属をモデリングする場合、現在所属している組織、過去所属していた組織、に分ける必要があります
分けないと不定の値が発生してしまうためです~~
今回の所属では、配属日だけではなく終了日(移動日)も保存しなければならないとします
この場合、所属をひとつのテーブルで表現しようとすると不定の値(移動日がnull)が生まれてしまいます(配属したばかりの人は次の組織への移動日は決定していません)

このような場合にはTMではもうひとつエンティティを生成します(今回は所属(過去)のこと)

しかし、テーブルが2つあるのに対してそれに関連するオブジェクトがひとつになってしまうと「オブジェクトとテーブルを1:1で紐づける」を守ることが出来なくなってしまいます
そこで、ドメイン層にも過去所属していた組織、というオブジェクトを追加しました
このオブジェクトが無い場合、集約ルートである所属に現在の情報と過去の情報が混ざってしまうため、分けたほうが良いと考えました

これが正解かどうかはわかりませんが、考え方としては間違っていないような気がしていますｗ

RDBのテーブル構造に引っ張られている感はありますが、TMでもDDDでもいきつくモデルはかなり似通ったものになるはずなので、それほどかけ離れてはいないかなと思ってますｗ

※データをどこまで保存しておくのか、どこまで捨てるのか、というのは長くなってしまうので別の記事で深堀しようと思います
<font color = "red">追記</font>
これについてはこちらをご覧ください
[どこまでデータを消すのか](https://qiita.com/bouitengineer12/items/5eba8b3ee3dcd407cff9)

#ドメインとデータの関係性
2020/9/9追記

完全に個人的な考え方なのでそこらへんはご了承の上読んでください

 - **ドメインとは**

企業が提供するサービスをお金に変えるまでのルールや手順のこと、というようなイメージで捉えてます
つまり、「ドメインが無い=商売できない」くらいの感じで考えてます

 - **データとは**

ユーザーにサービスを提供する上で必要になる情報や、継続的にサービスを提供したときに得られる情報のこと、というようなイメージで捉えてます
つまり、サービスを提供する上でデータが必須になる、と考えてます

###どっちを重視するのか
両方ともビジネスには欠かせないものです
どちらかがなくなると継続的にサービスを提供することが難しくなります

データはまた採取すれば良い、と考える方もいるかもしれませんが、お金や個人情報を扱っている会社の場合それだけで致命的になります
ドメインが急に無くなる、ということはあり得ないかもしれませんが、利益が出せなくなって無くなる可能性はあります
利益を出すために構造を変える可能性があるため、ドメインモデルは柔軟でないと対応できません
ドメインが変わると、勿論データも変わります
新しいデータが生まれるだけかもしれないし、現行のデータの意味が変わって構造を変える必要が出てくるかもしれません

このように、どちらも密に関連し合っています

そのため、ドメインモデルを作ろうとしたときにはデータを元にモデリングの骨組みを作り、それを元に肉付けしていく、というアプローチはかなり有効だと考えています

![アプローチの仕方.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/529608/fbc7de0b-ef49-b55b-07d4-ae31c9b392aa.png)


<font color = "red">※TMは既存のビジネスを逆解析する方法のため、新規に立ち上げるビジネスにはこのアプローチは使えません</font>


#まとめ
DDDとRDBの距離について自分なりに考えてみました
TMは今あるデータを元にしている分、地に足を付けて歩いている感じがして良いですね！

※なんとなく思いついた内容なので、意見あれば歓迎します！

[本当にあったやらかしDB設計シリーズ一覧](https://qiita.com/bouitengineer12/items/e63e5f7d6f628da11362)