速度／品質／汎化を最適化する共通の設計思想

# はじめに
タイトル通りの情報です！

### 記事を書いた経緯
- 去年末から進めていたデータ基盤構築が一段落
- データ基盤設計をアウトプットする際，設計する際に工夫した点について深く考える
- 結果，今まで経験してきた様々なプロダクトに応用できる共通点が洗い出された
- 記事にまとめてみよう，，，

ここでいう**プロダクト**は，幅広い分野のプログラムやシステム，サービスのことを指しています．

### 向いているケース
- それなりの規模で更新や機能追加が多いプロダクトの新規開発や改修
- 複雑に絡み合ってぐちゃぐちゃになってしまったプロダクトのリプレイス
- 市販ツールなどのプロダクトを複数組み合わせたプロダクトの新規開発や改修

### 向いていないケース
- 今後機能追加や更新する可能性が低いプロダクト
- プロトタイピングやスクラップ＆ビルドを行う新規開発の最初のほう

向いていないケースに安易に適用すると，開発工数が増えるだけでメリットを得ることができないかもしれません，，，

### 似た思想やプロダクト
- [ヘッドレスコマース](http://www.ebisumart.com/blog/headless-c/)
- [ヘッドレスCMS](https://depart-inc.com/blog/blog-20355/)
- [MVCフレームワーク](https://snome.jp/framework/mvc-model/)
- [Pub/Sub](https://cloud.google.com/pubsub/docs/overview?hl=ja)
- データ分析基盤

これらを参考に共通点を洗い出してみた感じです．

### 設計思想の名前
この設計はまさに○○だ！みたいな情報を見つけることができませんでした..ただのオブジェクト指向のインターフェースに工夫をいくつか加えたようなイメージなので，既に名前が付いていると思うのですが，，上手く探索できなかっただけかもしれないので，ご存知の方はコメント頂けると嬉しいです．構成はMVCフレームワークに近いような気がしています．そこまで真新しいものでもないと思います..

### ポエムであること
速度／品質／汎化を両立するための1つの方法として個人的に洗い出したものです．これ以外の設計思想を否定するものでは決してありません．

# 説明
ここからは設計思想の詳細を記載します．

### 全体図

![全体図.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44273/6598267f-420d-d589-7fd9-cb1330c1fe11.png)

大きく3つの集合からなっており，その中に複数の要素が入っています．各要素の繋がり（結合度）や管理方針にはそれぞれ方針があり，それがこの設計思想のキモになっています．

### 集合の構成

| 名前 | 説明 |
|:--|:--|
| バック | プロダクトの実装側に近い機能の集合 |
| フロント | プロダクトを使う側から見える機能の集合 |
| インターフェース | フロント側から見える機能の集合．フロント側からバックの機能は見えないし，アクセスできない． |

ここで挙げている**バック**，**フロント**は，Webサービスなどにおけるバックエンドやフロントエンドの事ではなく，もっと抽象的な概念として，バックは物理的な実装の集合，フロントは担当者など使う側から見える機能の集合を指しています．

### 各要素の結合度

| 要素 | 要素 | 結合度 |
|:--|:--|:-:|
| バック | インターフェース | 密 |
| フロント | インターフェース | 密 |
|  バック | フロント | 疎 |
| バックの機能 | バックの機能　| 疎 |
| フロントの機能 | フロントの機能　| 疎 |
| インターフェース | インターフェース | 疎？ |

バックとインターフェース，フロントとインターフェースが**密**であるのに対し，各集合内の要素同士は**疎**です．

インターフェースの要素同士については，なるべく疎結合である状態が望ましいものの，次項に記載したように厳密に管理するのであれば入れ子構造などで結合しても，そこまでリスクは上がらないのではないか，と考えています．あくまでバック・フロントの機能の結合度と比較しての話ですが..ここについてはあまり深く考えることができていません．

### 集合の管理

前提として，もちろんすべてを厳密に管理できるのであれば，それに越したことはありません，，，管理工数が足りないなど様々な理由からそれができない場合は，以下のようにインターフェースだけをより厳密に管理することで，速度と品質と汎化のバランスが最適化できるのではないか，と考えます．

| 名前 | 管理 |
|:--|:-:|
| バック | 柔軟 |
| インターフェース | 厳密 |
| フロント | 柔軟 |

厳密な管理の具体的な例としては，実装のバージョン管理やレビュー体制，テストなどです．インターフェース以外は一切管理しない，といった極端な話ではなく，必要な柔軟性と確保できる工数を把握した上で，それらの管理方針に差を付けるということです．

# 得られるメリット

### 影響範囲の限定と吸収
要素の追加や変更があったとき，インターフェースがクッションになって影響を吸収してくれます．

例えば，バックそのものの差し替えや要素の追加・変更が起こったとしても，インターフェースに合わせて変更を実装すれば，影響を最小限に抑えることができます．インターフェースに流れる情報に変更が無い場合は，フロント側のことを考える必要もありません．インターフェースに流れる情報に変更がある場合も，フロントへの影響が判りやすくなるはずです．フロント側の変更による影響についても同様のことが言えます．

その反面，変化を吸収しやすいインターフェースの設計と変更管理が重要になってきます．

### 段階的な適用が可能
既にプロダクトが出来上がっていて，そこにこの設計思想を導入するときの話です．例えば，バックやフロントぐちゃぐちゃで密結合な状況に対してリプレイスを行うとき，以下のように段階的にアプローチできます．
1. インターフェースを整理してバックに繋げる
1. 次にフロントをインタフェースに繋ぎ替えて整理していく
1. バックを綺麗にしたり，ツールを導入して差し替える

この方法を取ったとき，1が完了した時点でフロント側の運用が楽になりはじめます．つまり，リプレイスの早い段階でプロダクトに対して効果を発揮することができます．

もちろんこのアプローチだとバックの負債が放置されてしまう懸念があります..何処から手を付けるかはケースバイケースですが，少なくとも設計思想の段階的な適用が可能，という点はメリットだと感じています．

# 例
他のプロダクトの構成要素の名前を当てはめてみました．個人的にはなんとなくしっくり来ていますが，如何でしょうか..

### データ分析基盤

![dwh.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44273/e41ed267-7139-5bda-4ae5-283eb97f3bb2.png)
![データ基盤.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44273/4a0dd3a4-8ea9-27fd-af1c-006c50ecb629.png)

### MVCフレームワーク

![MVC.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44273/789284ec-41c4-1069-4070-1dc2a7a6d3e5.png)

### API

![API.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44273/b8516b28-deba-f5e4-c799-3f01aba3d11a.png)


# おわりに
今回は，速度／品質／汎化を最適化するための設計思想について，様々なプロダクトの共通部分を洗い出して記事にまとめてみました．既に様々なサービスが提供されている現在では，既存のサービスをそのまま使えば，このようなことを認識せずに最適化ができることも多いと思います．

しかし，既存サービスを組み合わせてプロダクトを作ったり，部分的に機能を手作りする必要がある場合，この設計思想が何かの役に立つかもしれません..皆様の参考になれば幸いです．

### 追記 2022−06−28
いくつか似ているアーキテクチャについて指摘を頂きました．ありがとうございます．

- [世界一わかりやすいClean Architecture](https://www.nuits.jp/entry/easiest-clean-architecture-2019-09)
- [ヘキサゴナルアーキテクチャ(ポートアンドアダプター)とは何か](https://qiita.com/cocoa-maemae/items/b08c4cf95d47e314e2dc)
- [オニオンアーキテクチャとは何か](https://qiita.com/cocoa-maemae/items/e3f2eabbe0877c2af8d0)

そこまで深く考えることなく抽象度高めに洗い出しただけなので，構造はどれとも若干異なっていますが，ヘキサゴナルアーキテクチャが似ているような印象，，，