「達人プログラマー　熟達に向けたあなたの旅」を読んだ備忘録

## はじめに
[達人プログラマー(第2版): 熟達に向けたあなたの旅](https://www.amazon.co.jp/%E9%81%94%E4%BA%BA%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9E%E3%83%BC-%E7%AC%AC2%E7%89%88-%E7%86%9F%E9%81%94%E3%81%AB%E5%90%91%E3%81%91%E3%81%9F%E3%81%82%E3%81%AA%E3%81%9F%E3%81%AE%E6%97%85-David-Thomas/dp/4274226298)を読みました。
勉強になったのでメモを残して自分が再参照しやすいようにしておきます。

※自分なりの解釈と言葉でのメモなので、実際に手に取って読むことを推奨します。

# 達人プログラマーになるためには

■必要な要素

**・アーリーアダプター/新しい物好き
・研究好き
・批判的
・現実的
・何でも屋**

■自分なりの解釈

・アーリーアダプター/新しい物好き
　**→ 好奇心ドリブンで学習を自走できる力。**
・研究好き
　**→ WHYを追求できる。粘り強く諦めない力。**
・批判的
　**→ 問題解決能力、根本の問題を見つめる力。**
・現実的
　**→ 問題解決能力、根本の問題を見つめる力。**
・何でも屋
　**→ 必要な情報を都度収集する力、技術の幅を広げる力。**


## 責任を持つ
失敗に対して「猫がソースコードを食べちゃった」では通用しない。
いい加減な言い訳よりも対策を用意することが重要。

>自分自身の能力に誇りを持つのは良いことですが、自らの無知や過ちという欠点を素直に認めなければなりません。


## ソフトウェアのエントロピー

チーム、ソースコードにおいて負債や腐敗は無秩序に広がっていく。
→[割れ窓理論](https://ja.wikipedia.org/wiki/%E5%89%B2%E3%82%8C%E7%AA%93%E7%90%86%E8%AB%96#:~:text=%E5%89%B2%E3%82%8C%E7%AA%93%E7%90%86%E8%AB%96%EF%BC%88%E3%82%8F%E3%82%8C%E3%81%BE,%E3%82%B8%E3%83%A7%E3%83%BC%E3%82%B8%E3%83%BB%E3%82%B1%E3%83%AA%E3%83%B3%E3%82%B0%E3%81%8C%E8%80%83%E6%A1%88%E3%81%97%E3%81%9F%E3%80%82&text=%E7%A0%B4%E3%82%8C%E7%AA%93%E7%90%86%E8%AB%96%E3%80%81%E5%A3%8A%E3%82%8C%E7%AA%93,%E3%82%A6%E3%82%A3%E3%83%B3%E3%83%89%E3%82%A6%E7%90%86%E8%AB%96%E3%81%AA%E3%81%A9%E3%81%A8%E3%82%82%E3%81%84%E3%81%86%E3%80%82)

発見したら早急に直すことが重要。
もし、「割れた窓」(悪い設計、誤った意思決定、質の低いコード)を修復する時間が無い場合は適切な処置を行う。

## やめどきを知る
完璧なものなんて存在しない。
洗練されすぎて台無しになる可能性がある。

##よい設計の本質
**ETC原則(Easier To Change)** - よい設計は悪い設計よりも変更しやすい

下記は全てETC原則に繋がる。

**・結合を最小化
・責務を単一化
・正しい名前を付ける**

## DRY原則
**DRY原則(Don't Repeat Yourself)** - 繰り返しを避ける

・コードの二重化
　→ 同じ処理はきれいにまとめる。

・ドキュメントの二重化
　→ 冗長な説明は不要。

## 直行性の原則
**直行性の原則** - 関係の無いもの同士の影響を排除すること。

直行性に則った設計の手法は下記。

**・自己完結したコンポーネント(独立した単機能の目的にうまく適合したコンポーネント)で凝集度を高める。
・システム間の結合度を下げる。疎結合化。**

■メリット
**・問題発生部分を隔離できる。モジュールの交換で対応が可能。
・堅牢になり、変更や修正が最小限でおさまる。
・コンポーネント単位の設計、テストが容易になり、検証が捗る。
・外部ライブラリや特定の製品、プラットフォームとの強い結びつきがなくなる。**

## プロトタイピング
**プロトタイピング** - システムの最終形態が持つ側面を探求するもの。
 
プロトタイピングはコンセプトの確認を終えた後、作成したものを全て捨て去り、
得られた教訓をもとにもう一度正しいかたちで再構築する。

つまり**コードは使い捨て**となる。

## 曳光弾(えいこうだん)

**曳光弾** - 飛んだ軌跡がわかるようになっている弾丸のこと。アプリケーション全体がどのように連携するのかを知る手法の比喩。

プロトタイピングの後に着手する。
最小限の機能だけそろえた機能追加が容易な状態。つまり**使い捨てではない**。


## 見積もり

著書の中で書かれたものも方法論に過ぎないとのこと。
**要求を細かく分解して洗い出し、リスクを分析して答えを出す鍛錬を積む**ことが有効。

## 契約による設計(Dbc)

**契約による設計** - 満たすべき仕様をソースコードとして記述して安全性を高めようという考え方。要求された以上のことも、以下のことも行わない。

下記の契約条件を用いて安全性を高める。

**事前条件 - メソッドの実行前に満たすべき条件
事後条件 - メソッドの実行後に満たすべき条件
クラス不変表明 - 実行前でも実行後でも常に満たすべき条件**


↓こちらの記事非常にわかりやすかったです。圧倒的感謝。
[【Unity】アサーション（Assertクラス）の使い方と契約プログラミング](https://light11.hatenadiary.com/entry/2020/07/19/194744)


## 大域データの弊害
**大域データ** - どこからでもアクセスできるデータ、あらゆるメソッドの内部から利用できる。外部リソース、Singletonも含まれる。　

**大域データはコードの結合を招く。ETC原則に反してしまう。**
インターフェースでメソッドやモジュールを抽出したくても大域データを切り離すのが難しくなる。
　→ テスト環境を作り上げる上で問題が発生。大域変数を別途テスト用に用意することになる。


## 偶発的プログラミング

**偶発的プログラミング** - 幸運と行き当たりばったりの成功に頼る行為。なぜ動いているのか理解せずに進める。

**動かなかくなった時に原因がわからなくなる**要因となり得る。

■慎重なプログラミングの方法
**常に何をやっているのか意識**する。

何らかの機能を呼び出す際には、ドキュメント化された振る舞いのみを前提とする。
もし、その前提を外れる場合は自身のおいた仮定をドキュメント化しておく。

■対策
**・新人プログラマーに対してコードの詳細を説明できるか手を止めて確認する。
・明確なプランが頭の中にある状態で着手する。
・信頼のおけるものごとだけを前提とする。(公式ドキュメント、公式フォーラム、信頼ある人の技術記事)
・わからないときは仮定をドキュメント化する。
・仮定に対してもテストを行う。結果に応じてドキュメントもアップデートする。
・作業に優先順位をつける。
・既存のコードにしがみつかない。悪い部分は直す。**


## リファクタリング

■リファクタリングのきっかけ
**・二重化 - DRY原則(Don't Repeat Yourself)に反している箇所を発見した。
・直行していない設計 - 直行性を高められる箇所を発見した。
・時代遅れの知識 - 新たな問題を発見した、要求が変化した。
・パフォーマンス - パフォーマンスを向上させることが求められた。**


■リファクタリングのやり方
**・機能追加と同時に行わない。
・修正箇所にテストが用意されているか確認する。修正による異常を検知できるようにしておく。
・最小単位から着手し、慎重に進める。一気に変更しない。**

## テスト駆動コーディング
**テストについて考えることで、コードの結合度を低下させ、柔軟性を向上**させる。
　→ コードがちゃんと動くか、バグがないかを確認するためだけではない。

## ものの名前
**何かに名前をつける場合は常に、自らの意図を明確**にする方法を探し求める。
　→ 適切な名前が理解を深める

**名前を変更したいときに困ったら、ETC原則(Easier To Change)に違反**していることになる。
　→ まずETC原則に則った修正を行い、名前を変更する。

## おわりに
達人への道のりは果てしなく遠いな　と感じました。頑張ります。

## 参考リンク

[契約による設計事始め](https://speakerdeck.com/dnskimo/qi-yue-niyorushe-ji-shi-shi-me?slide=21 )
[Code Contracts の紹介](https://www.slideshare.net/yupotown/code-contracts-48772863)