読書要点「プリンシプルオブプログラミング」第1章, 第2章


第1章 前提

プログラミングの性質とも言える前提知識である。
これを受け入れてプログラミングに取り組む必要がある。

プログラミングに銀の弾丸はない

プログラミングには、「とりあえずこれをすればいい」という特効薬はない。
プログラミングの成果物はソフトウェアだが、ソフトウェアの性質はそもそも困難性を持っている。
ソフトウェアの困難性を示す性質は以下のとおりである。

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

困難性を示すソフトウェアを構築するためのプログラミングという工程も当然困難なものになる。
プログラミングの歴史の中で、複雑さに対抗する手段がいくつも提案されてきている。
歴史に学ぶことはプログラミングの困難性に対抗するヒントとなりうる。

コードは設計書である

プログラマーが行うソフトウェアの設計からデバッグに至るまで、全ては設計行為である。
プログラミングの成果物であるコードは設計書である。

製品の改良は基本的に設計時に行うが、プログラミング全体が設計行為である以上、「基本設計」「詳細設計」「プログラミング」「テスト」「デバッグ」はどれも不可分な作業であることを認識しなければならない。
これらの不可分な一連の作業は、一種の創造行為であり、人と分担して行うことはそれなりに難しいことである。

コードは設計であるため、コードはできるだけ早く書き始めたほうがいい。
不明確な部分だらけで、いつまでも設計が終わらないからである。

コードは必ず変更される

ソフトウェアの持つ可変性を考えれば、コードは使い捨てではなく何度も使いまわされるという性質を持っていることになる。
アップデートを繰り返し常に変更されうるという前提のもとコードを書く必要がある。
そのため前提として、コードは変更に強いものを書く必要がある。
書く時間が増えたとしても、それ以降の変更に強いコードになれば十分に元を取れる。

第2章 原則

多くの場合に共通して適用されるべき、プログラミングにおける決まりごとである。
ただし絶対ということはなく、状況に応じて調整していくことができれば良いコードを書くことに繋がっていく。

KISS

コードはシンプルに保ち、単純かつ簡潔であるべきだということである。
コードは意識しなければ複雑になっていく。
複雑になるほど修正されにくく、腐ったコードになっていく。
コードは変更されるものであるため、修正容易性を度外視した複雑なプログラムを組んではいけない。

単純性、簡潔性の維持のためにはコードに余計なことをしないことが重要である。
単純であるほど結果的に応用が効きやすく、様々な状況に対応しやすいことも念頭に置いておきたい。

DRY

同じコードを重複して書いてはいけないということである。
重複を許してしまうと、コードを読む側は同じ記述を複数回読むことになり無駄が生まれる。
コードの修正時も、似たような記述を何度も正確に修正しなければならず、大きな労力が必要になる。

コードから重複を排除するためには、コードを抽象化するのがよい。
つまり、処理のまとまりを関数化、モジュール化する。
抽象化自体が労力や時間を要する作業だが、重複による将来的なリスクの発生よりはよほど良い。
多くのプログラミングに関わる技術は重複を避けるための機能を備えているため、上手に活用してDRYを実現したい。

YAGNI

コードは必要最低限のものだけを書くべきだということである。
これから使うかもしれないといって追加したコードは結局利用されないことがほとんどである。
また、そのことによって余計な複雑性を盛り込み、KISSの原則に逆らうことにもつながる。

汎用性よりも単純性を求め、コードに余計なことをしないという意識が重要である。
一見単純に見えるコードのほうが汎用的に使えるケースも多い。

PIE

コードを人が読む表現として書くべきだということである。
ソフトウェアの動作を真に記述しているのはコードだけであり、人に意図を伝えるためには最終的にコードを読んでもらうことになる。

コードは書かれることよりも読まれることのほうが多い。
書く時間が長くなってしまっても、読みやすいコードを書いたほうが価値として高くなる。
コードで表現できない場合は積極的にコメントも利用するべきである。

SLAP

コードを書くときは抽象レベルを統一するべきだということである。
つまり階層構造を作り、同じ抽象レベルの概念をまとめていくべきだということである。
SLAPの実施により、コードに要約性と閲覧性が生まれる。
読む側も目的に応じてどの階層に着目すればいいのかがわかりやすくなる。

上手に階層化されたコードは、スッキリとした1冊の書籍のようにとても読みやすいものとなる。

OCP

拡張に対して開いている、修正に対して閉じているコードを書くべきだということである。
性質として変更され続けるソフトウェアは、変更に対して柔軟であるべきだ。
柔軟であることに必要な要素が「閣僚に対して開いている」「修正に対して閉じている」ことだ。

クライアントとサーバの間にクライアントインターフェースを用意して設計するのが良い。
それによってクライアントは、サーバーの変更に際して最小限の変更で済むようになる。
ただし、過剰なOCPの適用は無駄で冗長なコードを生み出すことにつながる。
変更が起きそうな場所を予測する、あるいは運用の中で変更が必要な場所を掴んでいく必要がある。

名前重要

プログラミングにおいて、命名を最重要な問題として取り組むべきだということ。
わかりやすい名前は、そのメンバの責務を伝えつつ、内部処理の詳細を隠蔽してくれる。
結果としてそのメンバを読むのが楽になり、それを使用してコードを書く行為も楽になりそのコードを読むことも楽になる。
一方で悪い命名は逆の効果を生み、負債のようにマイナスの影響を与え続ける。

名前重要を達成するためには、使う側、読む側を意識しつつはじめに命名することを意識するのが良い。