[プリンシプルオブプログラミング] プログラミングに特効薬は無い。コードの原則など

# プログラミングに銀の弾丸はない
プログラムをする上で、エラーが発生するもの、処理が上手くいかないものなど、たくさんの事例があります。それらに対抗する銀の弾丸はありません。なぜならば、プログラムで最終的に出来上がるソフトウェアは困難であるからです。

## ソフトウェアは基本的に困難である
ソフトウェアが困難な理由は以下の４つがあるからです。

- 複雑性
- 同調性
- 可変性
- 不可視性

### 複雑性
ソフトウェアは複雑です。
作っていくうちにファイル数が増え、依存関係が増え、また自分以外の人が書いた部分もあるでしょう。
規模が大きくなるうち、それらは非線形に増大します。

### 同調性
ソフトウェアは実世界に同調していなければなりません。
ハードウェアやネットワーク、他のソフトウェアの連携、それを使う人間…
ソフトウェアはそれらと接続され、使用します。

### 可変性
ソフトウェアは変化し続けるものです。
作り終えたソフトウェアは使われるうちに、さまざまな課題や問題点や改良点が見つかるでしょう。
ソフトウェアの開発に安寧はありません。

### 不可視性
ソフトウェアは概念の集合体です。
製品の決定プロセスなどの経緯を見ることは出来ません。
抽象化して図などで再現は出来ますが、その全てをソフトウェアで再現することは出来ません。

このように、ソフトウェアの性質は困難です。
それゆえに、ソフトウェアを作り上げる作業であるプログラミングも同様に困難なものとなります。
なので、それらの困難性を解決する銀の弾丸は存在しないのです。

## 歴史を学び「複雑さ」と戦う
ソフトウェアの性質は困難ですが、その最たるものは複雑性です。
ソフトウェア開発の歴史は、その複雑性との戦いです。
昨今さまざまな開発手法やライブラリ、コマンドなどが生まれていますが、それらはソフトウェアの歴史から生まれた戦いの副産物です。
ソフトウェア開発の歴史を学び、それらを学び、ソフトウェアの複雑性を軽減するようにしましょう

## ソフトウェア偶有部分の改善
ソフトウェアには本質部分と偶有部分があります。
本質部分とは、それがなければ成り立たない部分です。
偶有部分とは、それが無くても成り立つ部分です。
ソフトウェアにおいての偶有部分とは、プログラム言語、スキル、フレームワーク、ライブラリです。
それらが無くても、ソフトウェアの本質を作るのは可能ですが、非常に困難になるでしょう。
したがって、偶有部分で改善出来る部分は改善し、生産性を向上させましょう。

# コードこそが設計図
ソフトウェアとハードウェアの製造工程はよく比較されます。
ソフトウェアでは、基本的に上流工程と呼ばれる設計書の作成を行い、次に製造と呼ばれるプログラムの作業に入ると思いますが、これは間違いです。
製造はコンパイラやビルドツールが行うことであり、コードを書く行為は設計です。
基本設計やデバック、テストなどは設計であり、コードはそのアウトプットです。
そのように考えると、コードはソフトウェア開発においてのドキュメントと呼べるものはコードだけと言えます。
また、設計行為の成果物はコードだとも言えます。

## 改善対象はコードである
製品の改良は設計で行います。製造の工程で良くなることはありません。
上で書いたとおり、コードは設計です。よって、プログラミングの工程は設計工程と呼べます。
また、設計のアウトプットはコードです。いかに設計書が素晴らしくとも、その他仕様書の出来が良くとも、コードが悪ければ意味がありません。
これらを改善するには、優秀な設計者(プログラマー)が必要です。

## ロゼッタストーン
コードは設計書ではありますが、唯一のドキュメントがコードだけとは限りません。他にも必要なドキュメントはたくさんあります。
その中で、重要なものはロゼッタストーンと呼ばれる手引書です。これは、将来保守を担当する方にわたすものです。
プログラミングではHowやwhatは表現出来ますが、whyが表現出来ません。なぜこれが必要なのか？　の部分をドキュメントに記載すると保守や改善に役立ちます。

# コードは必ず変更される
## コードは修正されるもの
コードは一回作って終わりというものではありません。必ず変更や修正が入ります。コードが変更されることを念頭に置き、組む必要があります。

## コードとは無情である
初めから完璧なコードは存在しません。ソフトウェアをリリースしたあと、必ずユーザーの意見やライブラリの改善により、コードの変更が余儀なくされます。初めに書いたコードを全部書き直すということも起こり得るでしょう。今のコードの書き方に拘らず、常に修正し続けていくということが重要です。

## 変更に強いコードを書く
プログラミングは上記に書いたとおり、コードが変更されるということを念頭にコードを書くようにしましょう。それはつまり、変更に強いコードを書くということです。
コードは、書く時間よりも読む時間のほうが長くなります。変更されることを念頭に書くコードは、書く時間が長くなってしまうかもしれませんが、読む時間がそれで短縮できるならば、元を取ることができます。

# 原則
## KISS
コードをシンプルに単純に保つ原則です。
プログラミングをする中で、コードが複雑になるケースはよくあることだと思いますが、それを複雑なままにしておくと無秩序な状態へとなってしまいます。ギチギチにロジックが積み込まれた関数やメソッドが絡み合ったコードはリファクタリングやテストがしにくく、なおかつコードを理解する時間が増えてしまいます。なるべくコードはシンプルに保ちましょう。

## DRY
コードの重複化を防ぐ原則です。
同じようなコードがたくさんあった場合、それはコードの肥大化のみならず、コードを理解する時間が増えてしまいます。このような時には抽象化を行って、同じような処理をする部分を共通して使い回せるようにしましょう。

## YAGNI
必要最低限なコードを推奨する原則です。
コードに必要なのは汎用性より単純性です。
今後必要になると思うコードは大抵の場合不必要になります。今後を予測してプログラミングするのはやめて、今を見定めてコードを書きましょう。

## PIE
コードの意図を伝える、読みやすさを最優先にした原則です。
コードだけがソフトウェアの動作を正確に完全に知るための設計書です。しかし、それが読みにくいと理解しにくく、間違った理解をしてしまう可能性があります。
書きやすさより読みやすさを重視して書きましょう。

## SLAP
抽象度合いを同じにする原則です。
同じファイルの関数が複数あった場合

- 低階層に接続するゴチャついたコード
- APIからデータを取ってくる単純なコード
- 表示に関する長いコード

読むのが大変です。
このファイルで機能が完結していたらまだ良いものの、やはり改善する時になればそれぞれの機能を理解しなければならないため、非常に時間がかかりそうです。
そういった時には、抽象度を階層順で分けましょう。

- 抽象度が高いコード
- 抽象度が中くらいのコード
- 抽象度が低いコード

こうすることにより、本の章のようになります。
技術本などでは、前半部分に抽象度が高いものがあり、章の後半に向けて低くなり、読みやすいように、コードでもそれを実践していきましょう。

## OCP
オープンクローズドの原則です。
コードの改善、修正に強くなります。
具体的な例で言えば、インターフェースを使ってコード間や、サーバーとクライアントのやりとりを行いましょう。
もしクライアントでコードの変更があったとしても、それをインターフェースが吸収し、サーバー側では何もしなくても良いようになります。

## 名前重要
コードの命名を重要視する原則です。
関数の名前がテキトウに付けられていたらどうでしょう。
たとえばLoginしたユーザーにアラートを出すJSのコードを書いてみましょう。

```javascript:アラートを出す
userLogin(){
  alert()
}
```

これではLoginする時に呼び出すのか、ログインに失敗していたら呼び出すのかわかりません。適切な名前を付けましょう。

```javascript:適切な名前
userSuccessfulLoginAlert(){
  alert();
}
```
この命名によって、ユーザーがログインに成功した時に呼び出す処理だというのが関数名を見るだけでわかります。
例に出したものはさすがに長過ぎるので、少し短いほうが良いですが、適切な名前を付けることによって関数の使い方がパッと見で分かるようになります。

##