FLINTERS Engineer's Blog

FLINTERSのエンジニアによる技術ブログ

エリック・エヴァンスのドメイン駆動設計 読書メモ3

元記事はこちら

読書メモ2 の続き。 引き続き第3部を読みました。

第3部 より深い洞察へ向かうリファクタリング

リファクタリングというとプログラムの機能を変えずに、例えば関数などの小さな単位でより良い実装へ変更することを指すことが多いと思う。 ここで話しているリファクタリングの対象は設計。設計を段階的、継続的に変えていくことを指している。

第8章 ブレイクスルー

リファクタリングによって得られる成果は連続的ではなく、一気に成果が増える出来事が起こる(らしい)。

銀行ローンのモデルにおいて、モデルが適切ではなかったというアハ体験を得てモデルの適切さが飛躍的に上がって大勝利という物語が語られている。 飛躍的に良くなったモデルを目の前にしてハッピーかといえば、実装に反映させるためのコストを思って「気が重くなった」。歯を食いしばって3週間かけて実装したらしい。

第9章 暗黙的な概念を明示的にする

モデルのリファクタリングは、概念を発見してモデル上に表現することから始まる。

ドメインエキスパートが複雑なことを簡単に話すとき、自分の話した言葉が訂正されるときに、概念発見のヒントが潜んでいる。 モデルにない言葉を見聞きしたら注意すること。

モデルがぎこちないと感じるときは、ドメインエキスパートを引っ張り込むことで助けになることがある。引っ張り込めない場合はドメインについて書かれた文献を当たると良いこともある。

明白にモノではないものをモデルに含めることでうまいくこともある。 その代表的な例として制約(ポリシー)とプロセスが挙げられる。

他のオブジェクトの状態に関しての複雑な言及はアプリケーションレイヤに置かれやすいが、ドメインレイヤーに置くべきだ。仕様オブジェクトを検討するべき。

第10章 しなやかな設計

既存コードに押しつぶされず、楽しく変更を呼び込むような設計のことを、しなやかな設計とよぶ。 銀の弾丸はないが、役立つパターンはある。

  • 意図の明白なインタフェース
    • クライアントが実装を見ることなく利用法を推測できる程度にインタフェースは明白でなければならない
    • TDDが助けになる
  • 副作用のない関数
    • システム状態を変更するコマンドと、変更しないクエリを区別する
    • できるだけ多くを副作用のない関数に置く
  • 表明
    • 事後条件、不変条件を宣言する
    • プログラムで表明するか、ユニットテストする
  • 概念の輪郭
    • メソッド、インタフェース、クラス、集約などの要素を、自分の直感を考慮に入れて凝集した単位に分解する
    • 継続的なリファクタリングによって分割パターンを探す
  • 独立したクラス
    • 依存関係が多くなるにつれ精神的負荷が高まる
    • メソッド引数の型、戻り値の型などが依存関係だ
    • 本質的ではない依存関係を取り除こう
  • 閉じた操作
    • 閉じた操作により、依存関係を増やさず高度なインタフェースを提供できる
    • 戻り値の型が引数の型と同じにできる場合はそうする

宣言的な設計

宣言的な設計により仕様をそのまま動作させることは魅力的な取り組みだ。 拡張の困難さ、生成コードを改変することによる再生成のしづらさは、宣言的な設計でハマりがちな点だ。 モデルやアプリケーションが単純化されてしまうという点にも注意しなければならない。

永続化、ORマッパーなどスコープの狭いフレームワークならうまくいきやすい。

ドメイン特化言語 (DSL)

ドメインモデル、ユビキタス言語とコードが深く結びつくのがメリット。 言語の修正をするにはスキルが必要だ。 開発チームに加え、将来の保守チームに予想されるスキルを考慮し、取り入れるか決めるべきだ。

攻める角度

しなやかな設計にたどり着くためにどこから攻めたらよいだろうか?

設計の一部を切り出してしなやかになるように努力する。広く浅いより、狭く深い努力が有効だ。

確立されている概念フレームワークを使うのも有効だ。 会計、数学など確立されているものであれば、モデルが十分に発達している。

第11章 アナリシスパターンを適用する

アナリシスパターンとは、ビジネスモデリングにおける共通の構造を表す、概念のグループである。ただ1つのドメインにしか適さないものもあれば、多くのドメインに及ぶものもある。(Fowler 1997, p.8)

アナリシスパターンモデリングに活用する方法について。 具体的な要求に答えることは滅多にないが、調査の有益な手がかりと、抽象化された語彙を与えてくれる。 設計のリファクタリングに活用できる。

第12章 デザインパターンをモデルに関連付ける

オブジェクト指向における再利用のためのデザインパターンモデリングに活用する方法について。 技術的なデザインパターンの視点を変えて、概念的なパターンとして捉えることで活用可能になる。

ストラテジー、コンポジットなどのパターンは概念的なパターンとしても捉えることができるため活用可能だが、フライウェイトは実装としてのみ意味を持つため活用できない。

第13章 より深い洞察へ向かうリファクタリング

重点的に取り組むべきこと

コードがもつ複雑さ、ぎこちなさがリファクタリングを開始するきっかけになるかもしれない。 コードが整然としてもモデルと切り離された実装になってしまったら失敗だ。

変更を先導する人が、問題を考え抜くことが得意な開発者、該当領域に精通している人、ドメインエキスパートなど4~5人のグループを集め、会議室やコーヒーショップで30分~1時間のブレーンストーミングする。 満足が行けばコーディングする。そうでなければ、しばらく寝かして考え、数日後に再度ブレーンストーミングする。

  • メンバはアドホックに招集すればよい
  • 数日間隔で短時間ミーティングを数度持てば、試してみたい設計が出てくるはず。出てこなければ対象を絞ったほうが良い。
  • ユビキタス言語を駆使するように努める

コードを変更するリスクと実装時間を考えると、設計のリファクタリングに対するハードルが高いことが多い。 リファクタリングの正当性を証明するように求めることで、ほとんど不可能にする傾向がある。 しかし、ソフトウェア開発プロセスは変更による利益や変更しないことによる費用を正確に割り出せないのだ。

ドメインに関するチームの理解が設計に反映されていない場合や、重要な概念が明示されていない場合には機をみてリファクタリングするべきである。

リファクタリングを継続していると、あるとき今のモデルが明らかに不適切であるとわかることがある。一見すると危機的だが、ブレイクスルーのチャンスである。

感想

この部は継続的に設計のリファクタリングをすることについて書いている。 設計を何度もくりかえることによってより良い設計(本の言葉で言えば「しなやかな設計」が手に入ることは直感に反しない。

しかし設計変更を実装に反映するのは大変な苦労を伴うのは間違いない。実装時間はかかるだろうし、デグレも起きるかもしれない。外部へ露出している場合は、利用側も書き換える必要がある。互換性にも気を配る必要があるだろう。行為の正当性を主張するのは大変だ(DDD本に書いてあったよ、というのは主張を後押しするだろうが権威主義的ではある)。

テクニック的な部分はともあれ、結局のところ、開発への参加者間でモデルを大事にしようという意思が共有できるか、がポイントになるよな、という印象を持っている。