プリンシプルオブプログラミング5回目

# 前置き
今回は、3章の
【結果の局所化】【繰り返しの最小化】【ロジックとデータの一体化】
の３つを行いました。

https://academist-reading.connpass.com/event/341795/

# 3.5 結果の局所化
これはSOLIDのO、Open-Closedの原則に相当している。
変更時の影響が、なるべく小さい範囲になるようにするということです。

この設計思想は、様々な粒度感において重要な思想であり、
マイクロサービス間の疎結合性などにおいても、重要な思想となっています。

たとえば、あるマイクロサービス内への変更があった場合に、
影響範囲がそのマイクロサービス内だけに閉じるようにせよ　ということです。

## 他の思想との関係性
カプセル化との親和性が非常に高いです。
また、コンポーネントの凝集原則の１つである、閉鎖性共通の原則(CCP)
との関係性が高いです。

https://qiita.com/Kudo_panda/items/e143e6186bd840060d1c

## 修正が楽になるから
仕様変更の際には、まずどこを中心として変更が入るのか？
そしてそこを修正したことによって、どこまで変更の影響を受けるのか？
の範囲を特定するところから始まります。

影響範囲の特定には、ドメインモデル図を用いてステークホルダーに説明するのがおすすめです。
なぜなら数字だけ渡されても「？？？」となるからです。
図を見ながら「ここに変更を加えることで、ここに影響が出るので大体変更コストはこれくらいです。」と説明できるからです。

では、ためしに局所化されているケースと、そうでないケースとの定性的な比較をしてみましょう。

### 結果が局所化されていない時
あるモジュールへの変更が連鎖的に他のモジュールに伝搬します。
これでは仕様変更によって新たに生み出したい価値よりも、変更コストの方が高くついてしまいます。

### 結果が局所化されている時
局所化されていれば、まず読む範囲も、影響範囲の面積も小さく済みます。
結果的にコード全体をわざわざ読む必要性がなくなり、素早いデリバリーがしやすくなります。

## 実現方法①
これはそもそもカプセル化がされている上で、他のモジュールと疎結合状態だと
実現が可能なものです。

:::note info
関係性が密なものを近くに集める！
:::

１つにまとめたその内部では、頻繁にメッセージを送り合ったり、
頻繁にデータに対して何かしらの処理をするっていう状態です。

この考え方は、モジュールの最小単位であるクラス～
よりマクロなコンポーネント、マイクロサービス粒度の話まで、どのスケール感であっても重要な思想です。

## 実現方法②
他には仮説ベースでトップダウン的にまずは局所化されるような設計モデルを考え、
その後の組織のコミュニケーションパスの監視ツールなどを導入することで、
アーキテクチャの妥当性を検証する　というのも考えられます。

https://zenn.dev/offersmgr/articles/11446a55243d6a

👆は、実際に私は使ったことはないですが、コミュニケーションパスの可視化ツールのリンクです。
こういったものを使って逆コンウェイ戦略を実行しやすくなるでしょう。

## アンチパターン
:::note alert
逆に関係性の低いものをまとめてはいけません。
:::

たとえば、同じマイクロサービスコンテキスト内にいるA.aとA.bという
２つのコンポーネントがあるとしましょう。
これらのコンポーネントは図のように、サービスAの中に配置されています。
そしてサービスAは、別のマイクロサービスBと通信で連携しているとします。

この時に、以下のような状態はダメということです。

:::note alert
A.aとサービスBとの連携の頻度 ＞ A.aとA.bとの連携の頻度
:::

この状態では、本来同じサービス内にグルーピングされているべきものが、
分散配置されている可能性が非常に高いです。

そのため、A.aと頻繁にやり取りしているサービスB内のコンポーネントの方と
統合させたりする。
そのうえでモジュールの移動を行ったりする必要性があります。

この時に重要なのは、以下の２項目です。

:::note info
ECRS原則の手順を意識しながらのリファクタリング

参考ブログは以下↓
:::

https://qiita.com/Kudo_panda/items/339b94aa17cc28ab1b04

:::note info
別マイクロサービスを管理するチームとの
コラボレーションしながらのモデリングやペアプログラミング
:::

## 業務においても影響範囲を小さく
これはシステム内部のお話でだけではなく、業務においても言える話です。

頻繁に変更が入る業務領域と、本来は変えなくてもいいのに、
変更の影響受けてしまうような業務設計がなされた状態では、業務自体の安定稼働が難しくなってきます。

そのため、ビジネスアーキテクチャのレイヤーから、
この【結果の局所化】を意識した業務設計をなされていることで、
外部環境の変化にも迅速に対応できるビジネスを維持しやすくなります。


# 3.6 繰り返しの最小化
これはまさにDRY原則のことを指している。
完全に重複をなくすことは不可能であるものの、
極力重複を避ける、重複の排除は再利用パターンなどにおいても重要な考え方です。

## 再利用パターン
重複したコード群を１つにまとめて共有コードとして使用するというのは、
まさしく今回の繰り返しの最小化の目的のための手法です。
この【再利用パターン】は、以下の記事でも触れているので参考にしてください。

https://qiita.com/Kudo_panda/items/e8bad3a20b9e9c2c350b

:::note warn
ただし再利用の際のリスクなどは考慮する必要があります。
:::

## 修正コストを抑えるため
このセオリーを無視することによる問題は、再利用パターンの記事で触れている
コードレプリケーションのデメリットが対応しています。

重複コード量がシンプルに少ないのであれば、さほどそのデメリットは目立たないです。
しかしながら量が増えてくると、1か所のコードを変更した際に、
他の部分の似たコードを変更すべきなのかどうか？の判断が難しくなります。

それは図における似たコード部分を取り巻くコードとの関係性、
たとえば事前条件や事後条件、不変条件など含めて完全に同じなのか？
によっても微妙に変わってしまうためです。

重複箇所の粒度感が小さく、２，３箇所ならまだかわいいレベルですが、
マイクロサービス内のコンポーネント粒度レベルになってくると、
たったの２，３箇所だけでもかなりメンテコストは高くつきます。

## 実現方法 -分割せよ-
コード自体を分割統治して、変更の単位や再利用の単位ごとに小さく分けます。
大きな塊のままでは、関心の分離が適切にされておらず、共通コードの部分も見えにくくなってしまいます。

どの部分が「完全に同じ」という概念としての重複コードであり、
どの部分がまだ「完全に同じ」とは言えない「似ている」部分であるのか？
そしてそれ以外の異なる部分なのか？
これらが明確になっていると、修正しやすいコードを維持しやすくなります。

### 最初からDRY原則を無理に適用しない
なんでもDRY原則の国いつでも従うのはナンセンスです。
本来なら、とりあえず似ているだけで、概念としては異なるコードを
「DRY原則じゃ～」と無理やり一か所にまとめてしまい、
その後実は異なるコードであったと発覚した際の元に戻す労力は絶大です。

### わからない時はあえて重複させる
「ここは絶対に概念としても重複部分だ」と確証を持っていえる時に、
はじめてDRYに従って一か所にまとめるというのが現実的に感じます。

その際に必ず行いたいのは、他のチームとのコラボレーション連携。
チームトポロジーでいう所の、他のチームコンテキストと意図的に一部蜜結合状態にすることです。

![コラボ連駅.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2781175/6abcca8b-f50e-8e3d-6d22-14ac8b011c35.png)

これによってオレンジの方の似たコードと、ブルーの方の似たコードが、
いつでも同じタイミングで変更もされているのか？
バージョンも同じなのか？
といった具合に対話を重ねた上で「ここは本当に概念としての重複なのか？」
という論点に答えを出すことができます。

## 他の原則との関係性
上記のように実現していくためには、

:::note info
意図のわかりやすい名前設計(PIE)
:::

:::note info
シンプルさ(KISS原則)を満たしている
:::

:::note info
関係性が密なものがまとまっている状態(カプセル化)
:::

:::note info
抽象度を揃えつつ分割(SLAP)されている
:::

などが複合的に合わさって、概念の重複部分、
つまりDRY原則に準拠した方がいい箇所がより顕著に浮き彫りになっていく。

# 3.7 ロジックとデータの一体化
これはまさしく【カプセル化】のことをいっています。
データと、そのデータを使う処理は１つにまとめよと！いうあれです。
これを実行することによって、高凝集状態を実現できます。

また、一度適切にカプセル化したからといって終わりってわけではなく、
仕様変更などの外部要因によって、まとめ方は変化しえます。
そのためにDDD本などで語られているように、継続的にリファクタリングなどを行い、
特に変更頻度が高い領域については、コストを割いてこのカプセル化を意識した設計が
求められます。

## 変更コストを抑える & リードタイム短縮のため
ロジックと、そのロジックが必要とするデータは、同じタイミングで修正されることが多い。
それらがもしもばらばらな場所にあった場合と、そうでない場合とに分けて考察する。

### ばらばらな場所にあった場合
・離れて配置されてる分、どこを変更したらいいのか探すのに時間がかかる。
・そこを変更した際、どこにどの程度影響するのか？の分析にも時間がかかってしまう。

:::note alert
変更時のコストは跳ね上がり、おまけにリードタイムも伸びてしまう。
:::

### 同じ場所や近い場所にあった場合
・まとまっているので、探すのにかかるコストが低くなる。
・変更した際の影響範囲の特定などしやすい。

:::note info
変更時のコストは下がり、素早いデリバリーがしやすくなる。
:::


## 実現方法①
これはトップダウンによるモデリングと、
ボトムアップによるリファクタリング手法との掛け合わせが手っ取り早いと感じます。

書籍にはコードを変えて動かしてみてからとありますが、
ビジネスアーキテクトをしている私の目線では、コードへする前に、
ビジネスモデリングで仮説を立ててみて、実際にアナログに人が運用してみて、
その結果を用いて、どのようにまとめるのがいいのか　を考える方法もありと感じます。

## 実現方法②
ロジックをデータに寄せる際、重要な考え方として【情報エキスパート】があります。
この思想は非常に大事ですので、カプセル化の際には必ず意識しましょう。

https://qiita.com/Kudo_panda/items/6d4cff3dff0f7d060405

## データ所有権パターンとの関連性
マイクロサービス粒度での、データの所有権の考える際にも、
このデータとロジックをどうまとめるか？　という思想はベースになってくると感じる。

https://qiita.com/Kudo_panda/items/efac4de634a8c1852650#%E3%82%B5%E3%83%BC%E3%83%93%E3%82%B9%E3%82%B3%E3%83%B3%E3%82%BD%E3%83%AA%E3%83%87%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%83%91%E3%82%BF%E3%83%BC%E3%83%B3

それは、情報エキスパートの思想が、このデータの所有者の割り当てに反映されているからと感じる。

## 注意点
モジュール内の属性リストをモデリングするデータエンジニアと、
ロジックを主に担当するアプリケーションエンジニアとの間に分断が起きてしまっている状態では、このロジックとデータの一体化は非常に難しくなってしまいます。

必ずデータエンジニアもアプリケーションエンジニアもいる状態で、
一緒にモデリングを行い、どうまとめるのがいいのか？を探索しましょう。