Clean Architecture 第Ⅱ部 構成要素から始めよ

https://qiita.com/tak001/items/0e0c7d7c641e7fd6e60d

https://qiita.com/tak001/items/425c5f8ec5a2c7d0143d

https://qiita.com/tak001/items/20a5dc9d7785495a6e60

# パラダイムの概要
プログラミングの歴史上、重要な革命がありそれはプログラミングパラダイムの革命とされています。パラダイムとはプログラミングの方法のことであり、言語とは比較的関係のないものでプログラミングの考え方と記述方法の枠組みを規定するもです。パラダイムには大きく3つ存在しています。

これらは新しい能力を提供しているのではなく、必ず何かの規律を課しています。

つまり、「何をすべきか」ではなく「何をすべきではないか」を伝えています。

goto文や関数ポインタ、代入を奪っている。

ではこれらパラダイムがアーキテクチャとどのように関係しているかですが、「全て」において関係してるといえます。

例えばアーキテクチャの境界を超えるための仕組みとして、ポリフォーフィズムが使われたりしています。

## 構造化プログラミング
1968年に制限のないジャンプ(goto)が有害であると示した
gotoをif/then/elseなどに置き換えた
要約すると、直接的な制御の移行に規律を課すもの

## オブジェクト指向プログラミング(OO言語)
1966年に2人のプログラマーによって発見された
要約すると、間接的な制御の移行に規律を課すもの

## 関数型プログラミング
3つのパラダイムの中で最も早く発見されている
要約すると、代入に規律を課すもの


# 構造化プログラミング
1986年、Edsger W Dijkstra（エドガー・ダイクストラ）によってGOTO文が有害であると論文を発表した。
そもそもgoto文ですが、指定されたラベル名の行に強制的に移動するという「どこでもドアのような存在」です。
これは、多用するとプログラムに一貫性がなくなりプログラムの流れが不定になり、構造が崩れるのが容易にイメージできると思います。

一方構造化プログラミングは、コンピュータプログラムの開発や理解、修正を円滑に行えるよう、プログラムを整理された構造の組み合わせによって構成する、つまりは順次、分岐、反復の三つの制御構造によって処理の流れを記述することであると理解されています。


# オブジェクト指向プログラミング
続いてオブジェクト指向プログラミングについてです。先程の構造化プログラミングの2年前の1966年に、Ole-Johan Dahl（オーレ＝ヨハン・ダール/ノルウェーの計算機科学者）と、Kristen Nygaar（クリステン・ニゴール/ノルウェー人の数学者）によって発見されます。

オブジェクト指向が普及している背景として、コンピューター技術が急速に発展する中で、プログラミングが複雑化する環境がありました。
目的に合ったプログラムを書くために、莫大な行数のコードが必要となり分業も困難となっている状況を解決するために、プログラミングを「モノの集まり」として捉えたのがオブジェクト指向になります。

オブジェクト指向の3大要素といられる、
1. カプセル化
2. 継承
3. 多様性
について解説いたします。

## 1. カプセル化(隠蔽)
まず、カプセル化についてです。

カプセル化の特徴は、
フィールドに対して勝手に操作されるのを防ぎ、データ隠ぺいを実現させます。

カプセル化を実現させるためには、
・privateアクセス修飾子を付与
・フィールドの値を利用する場合、アクセサメソッド（get/set）を使用
します。

これにより影響範囲を小さくし大規模でも安全なシステム構築に繋がります。

## 2. 継承
あるクラスの機能を引き継ぐことができるので、共通部分をまとめてクラスの再利用性を高めてくれます。

- あるクラスの機能（フィールド、メソッド）を引き継いだクラス
- 引き継ぎ元：基底クラス/スーパークラス
- 引き継ぎ先：派生クラス/サブクラス
- extends

## 3. 多態性/ポリモーフィズム
続いて、多態性（タタイセイ）ポリモーフィズムについてです。

オーバライドやオーバロードによって、メソッドを状況によって使い分けることができることです。
※ オーバロード(多重定義): 同一クラス内で引数の違いによってメソッドを呼び分けること、同じ名称のメソッドを複数定義することができる
※ オーバライド(再定義): 親クラスのメソッドを子クラスで上書きすること、同じ名称、同じ引数のメソッドを再定義できる

これにより、引数の違いやクラスの違いごとにケース分けして別のメソッドを定義する必要がなくなり、呼び出しもとは場面に応じてメソッドを使い分けたり、各メソッドを知る必要がなくなります。

要するに、同じ命令で異なる挙動が実現できます。

このポリモーフィズムは、具像と抽象、そして依存関係逆転の法則と深い関わりがあります。
通常では、上位レベルの関数を1つ呼び出すには、ソースコードの依存関係(つまりimport)と制御の流れが一緒になりますが、インターフェースでポリモーフィズムを用いると、結合度を緩やかにすることができます。

この時、ソースコードの依存関係が制御の流れと逆転します。
これは「依存関係逆転の法則」と呼ばれますが、詳しい内容は後述いたします。
変更に強くする構成や単体テストをしやすくするには、この法則がとても重要になります。

クリーンアーキテクチャでも「これこそがオブジェクト指向の提供するパワーである」と記述されています。

# 関数型プログラミング
続いて、「関数型プログラミング」です。
オブジェクト指向では、インスタンスという塊の中に状態(つまり変数)や振る舞い(つまりメソッド)を持っており、それを参照したり変更するのに対し、関数型は「データに何らかの処理を加えていく」の連続で組み立ていきます。

ものすごく乱暴にいうと、オブジェクト指向のようにクラスの中にメソッドを記述せずに、外に書いていき、データと振る舞いを分離させ、プログラムの状態を変化させない関数を作成し、組み合わせる。

可変変数（プログラムの実行中に状態を変化させる変数）を使用しないので、引数が同じであれば必ず同じ戻り値となる。

並行処理においてアプリケーションの直面するあらゆる問題は、可変変数がなければ発生しない。

次は、不変性を得てそういった問題から堅牢に動作させるために「可変性の分離」について見てみます。

## 可変性の分離
- 「可変コンポーネント」と「不変コンポーネント」に分離する
- 不変コンポーネント
  - 可変変数を使わずに純粋に関数的にタスクを行う
  - 可変コンポーネントと1つ以上と通信する
- 可変コンポーネント
  - 変数の状態の変更を許可している
  - 並行処理や競合状態から保護するためトランザクショナルメモリを使用する

一般的な妥協となるのは、「可変コンポーネント」と「不変コンポーネント」に分離することです。

アーキテクトでの視点でいえば、不変コンポーネントにできるだけ多くの処理を記述して、可変コンポーネントからできるだけ多くのコードを省いていくべきです。

# まとめ
- パラダイムの概要
  - 大きく3つのパラダイムがあり、それらは与えるのではなく制限をかけている
- 構造化プログラミング
  - 直接的な制御の移行に規律を課すものである（goto分）
- オブジェクト指向プログラミング
  - 間接的な制御の移行に規律を課すものである
- 関数型プログラミング
  - 代入に規律を課すものである（変数の不変性）