本ブログでの記事「基本設計から逃げるための手法:要件定義とアジャイル」へのPhil(id:nekosoi)氏のコメントが興味深い。
こんにちは。
本ポストと似たような問題関心からDDDとアジャイルの経典を読み漁ったり、WEB系のコミュニティに顔を出しています。
そこで分かったことは、OOPの隆盛、DDDの隆盛(エヴァンス本)、TDD手法(ケント・ベックに代表される)はJavaやRuby、PHPの色彩が極めて強いです。つまりざっくり言ってしまうと、所謂WEB系の生態系です。彼らの思想傾向は、業務要件を「クラス設計」に落とし込むことが前提かつ至上命題となっており、RDBは単にその後のデータの格納場所(永続化層)として存在していれば良い、というものです。そしてその思想的な傾向・潮流は2000年以降ずっと続いているということです。
ここからは私見ですが、業務をモデリングした結果は本来的には物理モデルであるRDBに落とし込まれるべきです。しかし、WEB系の開発者はIDのみの主キーで定義されたRDBを、「クラスに対応づけられた置き場所」としてしか見ていない。この潮流がこの20年近くマジョリティを締めているのは、シャレになっていないと思います。
2000年代当時、業務モデルをクラスに落とし込むための手法が、様々な形で喧伝されましたが、その「クラス」がRDBのテーブル構造とインピーダンス・ミスマッチを起こしていることに対しては、誰も解を見出すことができず、皆一様に口をつぐんだと聞きます。これが間違いの始まりなのではないかなと思っています。
そのとおりだと思う。「WEB系」とひとくくりにするのはいささか乱暴ではあるのだが、いきさつを考えるとどうにも仕方ない。
WEB制御と業務ロジック
業務システム(企業の基幹システム。エンタープライズシステム)を、ブラウザとWEBサーバとアプリサーバでエミュレートしたい。そのためには、HTMLとCSSとOOPとORMとRDBとあれやこれやを組み合わせた複雑かつ辛気臭い制御が必要になるが、技術的にはじゅうぶん可能ではある。ところがその枠組みの中では、案件固有の業務ロジックはあちこちに分散される形で記述されてしまう。
そんな涙ぐましい努力の中で、「業務ロジックをスマートに扱うための手法A」が編み出される。OOP技術者は関連書の読書会やセミナーをハシゴするが、適用してもどうもうまくいかない。その後に「業務ロジックをスマートに扱うための手法B」が台頭し、これにも飛びつくがうまくいかない。いずれの手法も局所的にはうまくいくのだが、業務システムのようにデータ構造や更新ロックやトランザクション制御が複雑なソフトウエアを対象にした場合、どうしてもどこかに無理が生じる。不全感が残る中、「業務ロジックをスマートに扱うための手法C」が提唱されて...(以下同文)。
じつは、2010年代に普及したローコード基盤のような技術を使えば、複雑なシステム制御を基盤に委譲できる。つまり、案件固有の業務ロジックを、システム制御の諸問題から切り離して集中管理できるようになる。ところが、オブジェクト指向技術者は「それではきめ細かく制御できない」などとして、その種の合理化を毛嫌いする。これは不合理だし、もったいない。
ドメインクラスにドメインエキスパートの知識を注入する?
もう少し具体的に説明しよう。業務ロジックが各所に断片的に記述されることへの反省から、DDD(ドメイン駆動設計)は、それらを「ドメインクラス」上のドメインロジックとして一元管理せよと主張した。ここで言うドメインとは、「案件固有の業務要件」くらいの意味だ。
これも「言うは易し」である。手練手管を使えば可能だとしても、その方針で可読性と保守性を維持できるのは、ごく優秀な技術者だけ。彼らが代替わりしてしまえば、膨大なコードで構築された緻密なシステム仕様は、少しずつカオスに落ち込んでゆく。実装方針に関する制約が存在しないゆえに、担当者の美意識や癖に沿ってクラス構造が改変され続けるからだ。
彼らがドメインクラスの仕様化について、いわゆるドメインエキスパートを頼るようになったのも自然な流れである。ソフトウエアの制御ばかりに時間と情熱が奪われて、業務知識の学びが手薄になったためだ。DDD関連本を読み漁るわりに、彼らは減価償却の仕訳さえ説明できない。
じっさいのところ、技術者自身が顧客の現状にダメ出しできるくらいの経験や業務知識がないと、業務システムの抜本的かつ合理的な仕様は創造できない。ドメインエキスパートなどに頼れば、彼らのタコツボ的な経験に即した「ピカピカの竪穴式住居」が生み出されるだけだ。
データモデリングとドメイン特化基盤で立ち向かう
DDDで言うドメインロジックは、RDB上の適切なテーブル構造と、それらのテーブルやフィールドに従属するロジックとして宣言的に、またはコードで記述できるし、そのように構成されるべきだ。適切なデータモデルと、書いた仕様書どおりにアプリを動作させる開発基盤(ローコード基盤)があれば、スマートかつ手早く対処できる。
もちろん、適切なデータモデルを確立することは簡単ではない。しかし、それさえ確立すれば、ローコード基盤上での開発・保守は「ふつうの技術者」が担える。ただし、データモデルが確立できたとしても、OOPで実装してはいけない。たとえ優秀な技術者が張り付いたとしても、{id}のような単独主キーを要求するORマッパー側の制約によって、クラス構造はやはりカオスに落ち込んでいくからだ。
OOPがダメだと言うのではない。これまで何度も言ってきたが、OOPは個別案件の開発ではなく、ローコード基盤のような「実装を劇的に合理化するためのソフトウエア」そのものを開発するための手段とすればよい。個別案件の実装方針に関して、ある種の制約を基盤レベルに意図的に盛り込もうという話でもある。
譬えるならば、「表計算をともなうデータ管理案件」にきめ細かく対応するために、毎回丁寧にOOPすべきだ、と考えるのをやめようという話だ。その代わりに、「表計算をともなうデータ管理」というドメイン(ソフトウエア分野。DDDのドメインより意味が広い)を効率的に扱うための「ドメイン特化基盤(DSP,domain specific platform)」、すなわり「表計算ソフト」をOOPして、個別案件の開発を合理化すればいい。そのような製品(Excel)がすでにあるのならそれを利用すればいい。Excelがイマイチというのなら、自分の手に馴染む表計算ソフトをOOPしたうえで、個別案件で利用すればいい。
私は20年前に自分の手に馴染む「業務システム開発用DSP(ローコード基盤)」を自作した結果、日々の案件でオブジェクト指向を意識することがなくなった。自作したローコード基盤を改修するときだけ、クラス構造の大伽藍を保守する喜びにひたる。私にとっては前者は「業務システム開発の専門家として経験を深めるためのケの時間」で、後者は「OOPのためのハレの時間」である。どっちも欠かせないし、どっちも楽しい。