プリンシプルオブプログラミングまとめ

自分用読書メモ
何となく良いなと思った言葉をメモしておきます

## コードは設計書である
コードとは製造するものではなく、それ自体が設計書なのである。
そう仮定すると良いコードを書くためには優秀な設計者（プログラマ）が必要で、新人が行う仕事ではない。まずは保守で全体を学んでから設計をやるというのはごく自然な流れなのではないかと思えるようになった。


## コードは必ず変更される
ソフトフェアがリリースされた後も変更はされるが、それ以前に開発段階から「昨日書いたコードの変更」と考えると常に変更されているということになる。
そのため、変更に強いコードを書くコードを目指す。そのためには「読みやすいコード」を書くことを意識する。何故ならばコードは書いている時間よりも読まれている時間の方が長いからだ。これはリーダブルコードでも散々言われていた事だが、コードはみんな（未来の自分も含めて）のために書くという意識を持った方が良さそう。

## KISS Keep It Simple Stupid.(シンプルにしておけ、愚か者よ。)

コードに余計なことをしてはいけない。
コードは自分の頭の良さを披露する場ではない。
一番意外だと思ったのは「勝手に要件を加えない」ということ。
他の職種だったら、要件の意図を汲み取って、こうした方が便利だ。ああした方が便利だ。と考えることが良いこととされるが、プログラマにとってはその限りではないらしい。

## OFOP One fact in One Place(一つの事実は1つの場所のみに存在させる)
DBにおいてOFOPを実現させるためには「正規化」させるしかない
<br>


## 名前重要
アホみたいな名言だなと思ったが、めっちゃ重要だった。
名前をつける点で大事なことは
・名前から振る舞いが容易に想像できる
・発音可能な名前にする
・短いコメントだと思う

リーダブルコードでも散々言われていたことなのでよほど重要なのだろう。


## プログラミングセオリー
・プログラミングにおいて「よくわからないけど動いてるからよし」、「よくわからないが直ったからこれでよし」としていると必ず後から品質的な問題が生じる。粘り強く説明できるまで理解することが重要
→今はそのつもりだが、格言になっているくらいだからきっとあるあるなのだろう。忙しくなってきてなあなあにならないように気をつけたい。
<br>

・読む人の気持ちになる
→報告書を書くような気持ちで書いてみよう。

・結果の局所化
影響の与える範囲を狭めて、修正を容易にすること。関係するコードをまとめると良い。
→クラスやファイルを跨ぐ場合はどうしたら良いのだろうか。
呼び出し前に値を参照させていることもコメントで明記したら良いのだろうか。

## アーキテクチャの根底技法
・抽象
複雑さへの対抗で、本質を剥き出しにすることらしいが、この話が抽象的すぎて具体的なコードへどう落とし込んだら良いのかわからない。

・カプセル化
関連性のあるモジュールを一つに閉じ込めること


・情報隠蔽
内部情報を遮断すること
カプセル化と違い外からアクセスできないようにすること

・パッケージ化
カプセル化したモジュールたちをさらにまとめること

・関心の分離
コードを関心のある単位で区切る。
一番わかりやすい例はMVCモデル

・ポリシーと実装の分離
ポリシーはフレームワークに依存していたりする部分。
実装は純粋なロジック部分。
ここを一緒にしてモジュール化してしまうと、フレームワークのバージョンアップとかについていけなくなる。

・分割統治
大きな問題を小さく分割すること。
モジュールに区切るということ。



おそらく、以上のことをまとめると理想系としては
```java
function(){
    funcA();
    funcB();
    funcC();
}
```
こんな感じなのかもしれない。
本の目次をイメージすれば良いのだろうか...


## 設計原理 

レビューする時にも使える原理 


・単純原理 
とにかくシンプル。KISSと同じ？ 

・同型原理 
一貫性にこだわる　

・対称原理 
ぱっと見の形、分岐しかた、命名にも対称性を持たせる。 

・階層原理　
階層ごとに処理のレイヤーを揃える

・線形原理
繰り返しや分岐を避けて処理を一直線にするようにこだわる 

・安全性原理　
あり得ないと思ってもNULLが渡された時のことを想定して分岐処理を書いたり、何があっても大丈夫なようにしておく　

## UNIX思想 

Linuxの前身のOSであるUNIX開発者の教訓らしい。
UNIXは1969年に誕生して今でも使われている＝生命力が高いソフトウェア。
それだけ当初の設計思想は学ぶ価値が高いということ。

・モジュールはシンプルに作る。そして機能は全て内包する
→カプセル化、隠蔽と同じ？

・コードは明確にする
３回以上「解読」をするようならそれは改善の余地あり

・分離の原則
ポリシーとメカニズムに分ける
ポリシーと実装の分離と同じ。
→普段何気なく使っているフレームワークなどがすでにその思想に基づいて設計されているのかもしれない

・単純性の原則
コードはなるべくシンプルにする。
エンジアは自分の実力をどうしても誇示したくなる。そうならないようにシンプルであることを褒め合う文化にする。 

・表現性の原則
どうしても複雑な表現が出てきてしまったら、迷わずロジックではなくデータを複雑にする方を選ぶ　

・修復の原理
修復失敗時のエラー通知は「けたたましく」する

<br>

## UNIX哲学
・1つ１仕事
１つのソフトウェア（モジュール？）にはシンプルな一機能だけを持たせる。機能を追加したくなったら新しいソフトウェア（モジュール）を追加する。コードに継ぎ足さない。


・即行プロトタイプ　
できるだけ早くプロトタイプを作成してそれを改良する。

・データはテキスト 
データはバイナリよりも万能なテキストにする
>バイナリ:0と1で表現されるデータ

・シェルスクリプトの活用
>シェルスクリプト:入力命令をマシンに伝えるプログラムのこと。バッチファイルのUNIX版みたいなもん



>バッチファイル：コマンドプロンプトで使える命令文の集まり。プログラムみたいなもん

>グルー言語：ソフトウェア同士の接着剤のこと。ここではシェルスクリプトがそれ。 

・90パーセントの解　
どんなことも100%やろうとすると困難なので90%を目指す。　

## モジュールの結合度　
モジュール間での結合度について気をつけた方が良いこと

・共有結合　
モジュール間で共通領域のデータを共同使用すること。
モジュール間のインターフェース（クラス上）には現れないので気を付ける
モジュールAからpublicな値Xを変更した際に、モジュールBでもXを参照しているときにバグが発生する

・データ結合（最も良い）
インターフェース間でデータをスカラ型（intとかStringとか基本型）で渡す。

## プログラマの観る角度

・コードのレイヤー化
上位のモジュールは下位のモジュールを呼び出すだけにする。
そうすればブラックボックス化できる。
７階層参照モデルもそういった設計思想なのかもしれない。　
デメリットは効率が悪くなることがあること。　

・コードの凶兆を見逃さない
長すぎる、モジュールが多すぎる、名前が噛み合っていない、コードが散らかっているなどの兆候があったらリファクタリングする。 

・汚いコードは借金である　
借金と同じで、すぐにリファクタリングしないと利子が乗っかってくる。　
<b>


## 習慣
・ボーイスカウトの規則
コードは少しでも改良してからコミットするという気持ちが大切。自分が出したわけではない山のゴミを１つでも持ち帰れば綺麗になるのと同じ。


・エゴレスプログラミング
エゴをなくしてプログラムしましょうねという事

`プログラマはしばしば自分が書いたコードを私物化します`
ちょっとわかる気がする...
自分の作品のような気分になっちゃうからこれは気をつけよう。
あくまで仕事の一環なので、全体が大切。
コードが大事なのではなくプロジェクト全体の方が大事という意識を忘れない。

・一度に一つのことを
コードを追加するとき、リファクタリングする時も一度に一つのことを確実にこなしていく。
関数の移動、変数名の変更などその都度動くかどうかチェックして慎重に行なっていく。

## 手法
・ドッグフーディング
味見するようにユーザー目線でプログラムを使ってみる
開発時には気づかなかったバグや使い勝手の悪さなどに気づいたりする

・ラバーダッキング
何か無機物、たとえばラバーダック（風呂に浮かべるアヒル）に相談するだけでも思考が整理されて問題解決の糸口になるということ。何か困ったら一旦、何かに相談すると良い。

・チームはハイコンテキストであれ
>ハイコンテキスト:暗黙の了解。"空気を読む" の "空気"

チームではハイコンテキストさが求められる。エンジニアに限らずなんの職種や職場でもそうなのかもしれない。最初にチームに入ったら、目的や文化みたいなのをしっかり学ぶところから始めよう。 

・精神的にも"割り込み"は良くない
PCもタスクの割り込みを発生させると作業効率が落ちるが、プログラマも話しかけられたり電話対応で"割り込み"が生じると作業効率が悪くなる。話しけるときは最新の注意を払おう。
<br>


## 法則
・人と月は交換不可
プロジェクトの作業量を定量的に表す方法として人月が使われたりするが、人と月は交換不可能。
>例：2人6ヶ月 ≠ 6人2ヶ月 

・割れた窓の法則
一枚でも割れた窓が放置されているとみんなも周囲が汚くなったり、汚れていることを気にしなくなるという有名なアレ。
コードの中においてもそれが適応されるらしい。

・エントロピーの法則
物理現象と同じで、コードも自然状態に任せておくとコードのエントロピーが増大していく。つまり無秩序になっていく。


・80-10-10の法則
ユーザーが求める機能のうち80%は簡単に実現できるが、残りの10%は相当努力が必要で、さらに残りの10%は実現不可能ということ。だから90%の解という言葉がある。
あとの10%は他のツールを使ったりして泥臭くいくしかない。

・車輪の再発明
意図せずしてしまう場合は努力不足。
学習のためならそれは大いなる力になる。
つまり独学で学ぶときは最低限の知識で車輪を作りまくって後から「こんなに便利な車輪があった」と学ぶのも悪くない。

・ヤクの毛刈り
ヤクという動物は毛がすごすぎて刈ってもなかなか本体に辿りつかない。トラブルも解決しようとしたら新たなトラブルが出てきて、なかなか本質に辿りつかない。その間に問題を忘れてしまう。ということが発生する。 

ヤクの毛刈りを行っていると感じたときは一旦立ち止まって、本質をもう一度思い出して、早々に切り上げるか、他の解決策がないかを考える。


それでもヤクの毛刈りに立ち向かわないといけないときは、思考がオーバーフローしないようにメモをとりながら問題を整理していくと良い。


## 感想
あとがきでもあったように、この本は一貫して、人のため（チームのため）にコードを書けと言われているような気がした。当たり前のことだが、我々エンジニアはサラリーマンであり、プログラミングは仕事である。しかし、仕事の性質上どうしても職人気質になってしまうのは仕方のないことだし、意識しなければ誰でもそうなってしまうことは自然の事なのかもしれないということが良くわかった。一見すると当たり前のことを延々と言われている気にもなるが、ことわざと同じで「時代の波を超えて多くの人が言っているのだから正しい」という類のものだと思う。自分は特別と思わず、これらの言葉は真摯に受け止めたい。今回、経験不足で理解できなかったプリンシプルがいくつもあったので、もう少し経験を積んでから読み返したい。そのときに今回学んだことが実践できているかどうかをチェックできると良いかもしれない。

自分の承認欲求を満たすためではなく、常にプロジェクトや会社のことを第一に考えたプログラミングができるように心がけたいと思った。