抽象について学んでみる

### はじめに
転職活動時期に「抽象度を意識した実装を教えてください」と言われてから「抽象度・・・？」と戸惑ってしまい、うまく答えられなかった苦い思い出を突如として思い出して悔しくなってきたので改めて学んでみました
学ぶうちに抽象という概念だけで1記事できてしまったので抽象度は次の記事に記載します

### 参考文献
[エンジニアの知的生産術](https://amzn.asia/d/htUPtJG)

## 抽象とは

- **具体的な対象から重要な部分を抜き出すこと**
- abstract（抽象）は、要約や概要という意味もある
    - 要約とは、文章の重要な部分だけを抜き出したものである

## モデルとは

- **複雑なシステムから、重要な一部だけを抜き出したもの**
- 例えば子供が遊ぶ車の模型は、現実の車ではないが、「車を走らせて遊ぶ」という目的を達成するうえで重要な部分だけ抜き出して作られている
- モデルは、現実世界の仕組みを説明するための簡素化された表現である
    - 現実世界に起きている現象は複雑なので、人間に限られた認知能力でも扱えるように、重要でない部分をそぎ落としてシンプルにする
- モデルの価値は、現実との一致度合いではなく。モデルの操作が、現実を直接操作することに比べてどれくらい低コストになるかによって決まる
- MVCにおいては、プログラムから、表示に関わる部分と、操作にかかわる部分を取り除いた**プログラムの本質的な部分**となる

## モジュール

- プログラミング言語においては**中身の一部を外に見せて残りは見せないもの**
    - タイヤは車を走らせるのに重要だが、タイヤの仕組みは重要でない
    - 重要でない部分を隠す＝重要な部分を抜き出す

## パターンの発見

- **具体的な事例を集めて、規則性や共通の特徴、繰り返し現れるものを見つける**という意味で使われる

## なぜ抽象が必要なのか？

例えば、高校数学の問題Q1を解けなるようになったら、似た問題のQ2を解けるのか？という点において

具体的なA1を暗記しても、類似問題のQ2が解けるようにはならない

なぜなら丸暗記した場合のA1は「抽象化されていない具体的な知識」だからである

いくつか似た問題を解いているうちに解き方に共通のパターンが見つかり、その後で類似問題Q2を解けるようになる

解き方のパターンは具体的な答えよりも、より抽象化・一般化・汎用化された知識であり、

この知識を、パターンを発見すること、つまりは抽象化によって獲得できる知識である

この知識が不明瞭な問題を解決してくれる鍵となる

受験や資格の過去問を解いていると出題パターンが自分の中で理解でき、本番試験で解きやすくなるのと同じである

## パターンの発見による一般化

抽象化はパターンの発見によて行われる

例えばQ1とQ2の解き方から「この手の問題はこうすれば解ける」と考えたり、鳩やスズメや燕が飛ぶのをみて「鳥は飛ぶものだ」と考えたりするのはパターンの発見となる

だが、「鳥は飛ぶものだ」というパターンには例外があり、ペンギンは空を飛べない

だからと言ってこのパターンは間違っているので　抽象化されないというようにはならず、

抽象化していないと、鶯を見たといに「鶯が飛ぶかどうかは観察していないからわからない」と考えるようになってしまう

「見たことがないからわからない」「教えてもらっていないからわからない」という態度では、新しい問題に対処できない

逆を言うならこれまでの抽象化を基に問題を対処するとスムーズに解決することだってできる

## どうやって抽象化するか

### 比較して学ぶ

抽象化・パターンの発見のためには、まずは具体的な情報を集める

具体的な情報を集めた後にすることは、`比較` である

ここを掘り下げてみる


### 「同じ」と「違う」の間に注目

それでは何を比較すれば良いのか？それは`同じ`と`違う`の間にあるものである。

現実には、完全に同じもの、とてもよく似ていて大部分は同じだけど少しだけ違うもの、

ほとんど似ていないけど少しだけ共通部分のあるもの、完全にちがうもの、とグラデーションになっている

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282722/236b570c-ad1a-053e-4833-b62e22815d66.png)

新しいパターンを発見には、「同じ」でも「違う」でもない、一部同じで一部違う「似ている」もの同士を比較する必要がある

具体例として、電動ドリルは、先端の工具部分が交換できるようになっている。


それぞれの工具は「同じ」ではない。しかし、ドリルの回転する部分に差し込んで使うことができるように、根本部分は同じ構造になっている。
下記はAIで画像を生成したもので、ドリルの部分は異なる種類のドリルに代替できる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282722/77dc5699-a0b7-09dc-6580-a3d92ea9a8cf.png)

これとよく似たことがプログラミングの中で交換可能な部品を作る際にも使われている。

JavaやPHPでは「インターフェース」という継ぎ目のような仕組みによって、「クラスがどのようなメソッドを持っているか」を決めることができる。
下記はPHPのソースコード（chatgptより生成した円の計算に関するクラス）

```php
<?php
interface Shape {
    public function calculateArea();
    public function calculatePerimeter();
}

class Circle implements Shape {
    // Circle クラスが Shape インターフェースを実装
    public function calculateArea() {
        // 円の面積を計算するコード
    }

    public function calculatePerimeter() {
        // 円の周囲の長さを計算するコード
    }
}
?>

```

これにより、異なるクラスが同じメソッドを実装することが保証され、コードの一貫性を保つことができる

物理的な工具でも、プログラミング言語でも「交換可能な部品は継ぎ目が共通化されている」と言うパターンがあると言うことになる

### 歴史から学ぶ

歴史から学ぶのは、今と昔の比較である。

例えば、過去の出来事の中に、現在進行中の出来事と似た構造があるのかもしれない。

共通のパターンを見つけることで、次に何が起こりそうかを予想できる。

また、変更前と変更後を比較して、どう変わったのか、なぜ変わったのかを考えることで理解が深まる。

プログラムなどの人工物は、誰かが「必要だ」と思って作ったものであり、「作る前はどうだったのか、今とどう違うのか」を考えることで、「なぜそれを作ったのか」が見えてくる。

しかし、ソースコードには基本的に「今」の「how」の情報しかない「変更前にどう言う問題があったのか」と言う「過去」の情報や、「なぜ変更する必要があったのか」「なぜこの選択肢を選んだのか」と言う「why」の情報はソースコードからはわからない。

そのような情報は、コメントやコミットログ、開発マニュアル、コミュニケーションツールでのやり取りに記述されている。

開発プロジェクトの歴史を知るにはマニュアル、コミットログを流し見すると目的の全体像が読めるようになり、現状の課題に対してどの手段をとったかがわかるようになる

開発手法も含めてその辺りの情報はどの要なプロジェクトに参画しても必須となると考えている

## 抽象化をLaravelで活用
Chatgptから生成して若干修正
### 抽象化とは？モジュールとMVCアーキテクチャを用いて理解する

### MVCアーキテクチャと抽象化

MVCアーキテクチャはモデル、ビュー、コントローラの3つの主要なコンポーネントにアプリケーションを分割します。これにより、抽象化がより効果的に行える。

### モデル (Model)

モデルはデータとビジネスロジックを提供。以下はMVCアーキテクチャでのLaravelの例になる

```php
// model.php
// User.php (Eloquent モデル)
class User extends Model {
    // モデルの実装
}
```

### ビュー (View)

ビューは結果の表示を担当。表示に関する詳細は隠蔽され、抽象的なインターフェースを提供

```php
// view_file.blade.php
<h1>User Details</h1>
<p>Name: {{ $user->name }}</p>
<p>Email: {{ $user->email }}</p>
```

### コントローラ (Controller)

コントローラはユーザー入力を処理し、モデルとビューを制御して連携させる

LaravelはMVC（Model-View-Controller）アーキテクチャを採用しているため、これを考慮して抽象化やインターフェースの例を示すことができます。以下は、Laravelのコントローラ（Controller）とモデル（Model）にインターフェースを導入する例。

まず、簡単な例として、UserController コントローラとそれに関連する User モデルを考える。

```php
// UserControllerInterface.php
interface UserControllerInterface {
    public function show($id);
}

// UserController.php
class UserController implements UserControllerInterface {
    protected $userModel;

    public function __construct(User $userModel) {
        $this->userModel = $userModel;
    }

    public function show($id) {
        $user = $this->userModel->find($id);
        // ユーザーを表示するコード
        return view('view_file')->with($user);
    }
}
```

これにより、モデル、ビュー、コントローラはそれぞれの役割を果たし、変更が生じても他の部分に影響を与えないようになっている

### まとめ

抽象化はソフトウェア開発において欠かせない要素であり、モジュールやMVCアーキテクチャはその実現をサポートするためにある。コードを整理し、各コンポーネントを独立させることで、保守性が向上し、柔軟性が増します。開発者は抽象化を理解し、適切に利用することで、効果的かつ効率的なプログラミングが可能となる。