前提
IT企業に転職する前に、デザインパターンを勉強している最中に、
このパターンの背景はいったいなんだ?と混乱していて、
SOLID原則に行きつく際に、たまたまこのGRASPパターンを通った。
その上で、デザインパターンを学んだらめちゃくちゃ理解が早かったので、
原理原則からトップダウンで学習されたい方は、是非設計原則とこのパターンを同時に学習されることを薦める。
この考え方は、マイクロサービスなどのアーキテクチャを考える際にもヒントになる指針が多いので、
是非とも常識にしていただけると今後楽である。
ちなみに以下のパターンは、単体で使うものではなく、ときには組み合わせで使うこともある。
今回は特に切っても切り離せない、情報エキスパートと高凝集の2つについて触れる。
この設計パターンは、高い生産性を出すためのタスクの割当設計の際にも必須の考え方である。
対象者と背景
主にこれを読んでほしいのは、設計する人々もそうだが、タスクの割当を決める【PMの方々】である。
コンウェイの法則について書かれたチームトポロジーを読まれた方はお気づきと思うが、タスクの割当(持たせるべき情報も含む)の際に、以下の設計思想を意識せずにチーム設計してしまうと、マジで生産性が低いトラブルが続出してしまう。
それは開発者体験という品質を低下させる要因となり、最悪優秀な人材が離れてしまう事態まで引き起こしかねない。
情報エキスパート
概要説明
「その責務を全うするのに必要な情報を持つクラスに割り当てるべきである」という考え。
どういうことかというと、
【処理は、その処理が必要とするデータがある所に割り当てよ】ってこと。
つまりこれは
「関係性の高いデータとそのデータを必要とする処理を一か所にまとめよ」というカプセル化の手立てのことです。
開発者体験という観点では
チームへのタスクの割当でも重要なパターンです。
ここでしくじると、無関係な責務が混在してしまい、チームは度重なるコンテキストスイッチによって集中力が低下しやすく、成果物の品質低下にも繋がります。
ドメイン貧血アンチパターン
ドメイン貧血という名前を目にしたことがある人、
またはドメイン貧血を引き起こしたことがある人はお分かりかもですが、
本来割り当てられるべき場所に処理が割り当てられていないと、症状を引き起こします。
その結果、ただ値を返すだけの謎のGetterロジックが出てきたりします。
ドメインに対する理解が浅いうちは、ドメイン貧血になってしまうのは避けられないですが、継続的なリファクタリング活動によって、最終的に正しい概念に対して割り当てるためにも情報エキスパートの考え方はマストです。
この考えがないと、何度DDDモデリングとリファクタリングをしても永遠に次の項目の高い凝集は実現ができないと思ってください。
改善のためのモデリングではなく、ただ単にコストがかかるだけのモデリングとならぬようにするためにも、この情報エキスパートは常識になるように身体にしみこませてください。
カプセル化のための手段
処理が必要とするデータのない所に、その処理を割り当てないですよね?
ちなみにこの情報エキスパート、静的な概念モデルの動的な側面からの検証として、
シーケンス図を描きながら概念モデルの妥当性の検証と、
各概念に責務の割当をする際に、必ずマストで抑えておかないと正しくカプセル化ができません。
これができていない状況では、実体験としてほぼほぼ
その処理が必要とするデータをどっかからGetterのように引っ張ってくるような処理が高確率で発生してしまいます。
その状態では、データとデータを必要とする処理を纏めよというカプセル化の原則に反します。
補足 - マイクロサービスのデータ所有権の考察時 -
またこの情報エキスパートの考え方を常識にしておくと、
マイクロサービスのデータの所有権を考える際に、非常にヒントになると感じます。
そのテーブルに対して書き込み系をしている、密にアクセスしているサービスに対して所有権を割り当てるっていうのが、基本的な発想なので。
情報エキスパートの考え方のみではマイクロサービスのデータ所有権は考えられないけど、ヒントにはなるという意味です。
高凝集
概要説明
「一つの責務を全うするのに必要最低限かつ、その責務に特化しているプロパティとメソッドのみで構成されるべきである」ということ。
つまりはこれ、単一責任原則にどれだけ近いか?てことを言っています。
もしも情報エキスパートを使って適切に処理の割当がされていないと、この高凝集を満たすことは難しいです。
低凝集アンチパターン
ラフスケッチですが、図のように1つのクラス内で
関連の非常に強いデータ群として緑の方のデータ群、
それとは別で
関連の非常に強いデータ群としてブルーの方のデータ群があったとする。

この時に情報エキスパートに従って、適切に割り当てられた処理が図のように
なっている時、これは関連性の高いものが密になっている高凝集といえるだろうか?
もちろん、図を見てお分かりの通りNOだ。
だって、緑の方とブルーの方が疎な関係性になっている。
高凝集とは、1つのクラス内で密にデータや処理が関係しあっている状況である。
この場合には、
顧客という1つの概念を【顧客】と【顧客ボディサイズ】て2つに分解してあげるのが望ましいです。
一旦ここでは、顧客という曖昧な名前であることは保留とします。
本来は下図のようになっているのが、もっとも高凝集な状態です。

〇が属性、□が処理です。
緑の四角は、緑側の属性しか使っていない処理。
ブルー資格は、ブルーの方の属性しか使っていない処理。
赤い四角は、緑の方の属性とブルーの方の属性を両方使う処理だとします。
ではなぜ下図では適切に情報エキスパートに従って適切に処理を割当たのにも関わらず、高凝集になっていないのであろうか?

実はこれわたしも過去にやってしまったアンチパターンである。
そして体験したからこそ、以下の理由に集約されると思っている。
関係性が疎なデータを混ぜ込んでしまう
実は高凝集には2段階があると考えている。
その1段階目は概念モデリング時のデータのまとまりという静的側面でのまとめ方。
このフェーズにおける密なデータをまとめる作業時に、関係ないデータを混ぜ込んでしまうケース。
その状態では、どんなに情報エキスパートを適切に使いこなしても、不要なものが混ざった1つのクラスが完成してしまう。
静的なモデリングのみで決めにかかってしまう
高凝集の2段階目が動的側面からの検証およびフィードバックだ。
基本的に概念モデリングのような静的側面からのみでモデル図を完成させてしまうのは危険だと私は思っている。
なぜならトランザクションの単位のチェック含めた、
動的側面からその概念モデルを検証してみないことにはわからないことが多々あるからだ。
たとえば下図のような1つのクラスを例にとって考えてみよう。

この属性の区画に注目してみてほしい。
静的側面でのモデリングの時には、緑のデータ群とブルーのデータ群には密な関係性が見られなかったことを意味している。
たったそれだけでこれらは概念として分けると決め打ちにかかってしまってはいけない!!
アンチパターンにはまらないための対処法
データのまとまりに対して名前を付けてみる
概念モデルの段階で無関係なデータが混ざらないようにするためには様々な手法があるが、ここではその1つの手法を紹介する。
これはデータの側面での境界付けられたコンテキストである【データドメイン】の考え方を学ばれると、さらに理解が向上すると感じる。
まずは初期フェーズのDDDモデリング時には、ユビキタス言語を定義するためにスコープを定義した上で、関係性の高いデータの集合を列挙していっていると思う。
この時1つ1つのデータは意図が明確なほどわかりやすいのが理想である。
ユビキタス言語を集団でモデリングする際に、皆さんが意識してやられていると思う。
くれぐれも【顧客】みたいないかんようにも捉えられる名前を付けてはいけない。
次に集めた関係が密であると思われるデータの集合に対して名前を付けてみるのだ。
データドメインに対して名前を付けるという作業である。
その際、その名前意図が唯一1つに名前が決まらないようであれば、無関係なデータが混ざっている可能性が非常に高い。
これが情報エキスパートに従っていたけど、高凝集を実現できないという最大の理由である。
データのまとめ方というフェーズにおいてそもそも無関係なものをまぜこんでいたということ。
概念モデルを動的側面のモデリングで検証
一旦初期の概念モデルのフェーズでは、分けるか分けないのか不明だからとりあえず分けておくとかならOK。
ここでは、一旦概念モデル時に
【オーダーメイドスーツ購入者】と【購入者ボディサイズ】分けたと仮定して記述を進める。
ビジネスフロー、動的側面からも考えてみてこの静的側面モデルを検証してみてからでないと、必要十分に安全なドメインモデルとは言い切れない。
そして処理を割り当てていった結果、下図のように赤い処理に関しては分けた概念の両方にまたがることが分かった。
この時点で概念モデル時に分けた2つの概念はシーケンス図などを用いた動的側面から検証した際、実は1つに纏まっているべきだと判明したのである。
よって概念モデルを更新した結果、1つの高凝集を実現したクラスが出来上がるのである。

責務に対して名前を考えてみる
情報エキスパートに従って割り当てた後に、その処理の集合に対して名前を考えてみる。
もしもこの際に名前が具体的に付けようがない、または複数の名前が付けられ得るって時には、その1つのクラスに複数の責務が集中しており、高凝集とはいえない状態である。
なんでもクラスの単位まできっちり単一責務になるように分けるのは過剰なリファクタリングをしていると言えなくもないので、同じパッケージ内に存在する別のクラスにあるべきものが1つに纏まってしまっている程度なら定性的にも許容範囲内であろう。
その場合でもパッケージ名は責務が明確になっていなければ、全く別のパッケージにあるべき責務が混在している可能性がある。
まとめ
概念モデリングの時に、このデータとこのデータ密な関係ともいえるし、
そうでないともいえるよなっていう時には、
迷う時間が無駄なので、一旦シーケンス図を描いて動的側面から検証してしまいましょう。
情報エキスパートと 高凝集は、2つ揃ってデータ隠蔽してカプセル化がやっと完成です。
モデリングとセットで是非とも常識といえるくらい練習してみてください。
というのも、クラスよりマクロなパッケージだのサービスとかの粒度のものとかでも、
この 高凝集という考え方が非常に重要になってくるからです。
詳しくは私が以前書いたコンポーネントの凝集原則を参照ください。