よっぴブログ

【技術書メモ5】プリンシプルオブプログラミング 3年目までに身につけたい一生役立つ101の原則

 

f:id:yoppi-y:20190427171220p:plain

技術書メモ5冊目!
今回は、よいコードとはどのようなものか、よいコードを書くためにはどうしたらいいのかが書いてあるこちらの本を読みました!

今までは動くことが目的になっていて、よいコードについてあまり意識をしたことがなかったので、この本に書いてあったことを念頭に置いてコードを書いていきたいです。

まだ知識不足なので、半年後に読んだらまた新しい発見がたくさんありそうな本!

 

第1章 前提

・プログラミングに特効薬はない
ソフトウェアは本質的に困難であるので、歴史を学び地道に改善していく。
⇨物事には「本質的」な面と、「偶有的」な面があり、偶有的な部分は容易に改善することができる。偶有的な部分を見つけたら自動化して本質的な部分にできるだけ時間を割けるようにしていく。
 
・コードは必ず変更される
コードが変更されるという前提で行うようにする。
書いている時間よりも読んでいる時間の方がはるかに長くなる。
⇨変更されるという視点に立つと、書くのにどれだけ時間がかかっても読む時間を短縮できるなら十分に元を取ることができる。
 

第2章 原則

・コードをシンプルに保つ
コードは自然に任せて修正していくと、無秩序になり複雑になっていく。
⇨プログラミング中、「動作させるためにもっとシンプルなものは何か」と常に問いかけることが大切。
 
・DRY(繰り返すな)
コードのコピペは厳禁である
コードに重複があると障害修正や機能追加など、コードを改善していくことが困難になる。
⇨コードを抽象化することによって重複を排除する。そのために、処理のまとまりに名前をつけて「関数化」「モジュール化」する。
 
・コードの意図を伝える
コードだけがソフトウェアの動作を「正確に」「完全に」知るための手がかりである。
⇨コードを書くときには「書きやすさ」より「読みやすさ」を重視する。読みやすければ書くときの効率が多少落ちたとしてもそれに見合う価値がある。
 
・コードで命名は最重要課題
名前はコードを読む人へのユーザーインターフェース。適切に名前がつけられているコードは「何を」「どのように」やっているか明確に理解できる。
⇨コードはまず名前を決める。名前を短いコメントとして考えると伝えるべき情報が含まれやすくなる。
名前には「効果」と「目的」を説明し、「手段」には言及しない。
 

第3章 思想

・コードはコミュニケーションの場である
ソフトウェアの開発コストの大半は保守のコストになる。そのコストを節約するためにコードは読みやすくする必要がある。
⇨コードで良好なコミュニケーションをとるには、コードを書いているときに他の人のことを考えるようにすることである。コードには「コンパイラやインタスプリタへの入力である」という側面だけでなく、「人に見せる文章である」という側面もある。この後者を「コミュニケーション」として価値を置くようにする。
 
・コードの複雑性は排除する
シンプルとはコードから余分な複雑性が取り除かれた状態のこと。余分な複雑性とはコードが達成しようとしている目的の複雑さを反映したものではなく、コードを動かそうとして格闘した痕跡による複雑性のこと。余分な複雑性は正しく動作する確率を減らし、将来の変更を困難にする。
⇨本質的な部分を目立つようにして、それ以外の余分な要素がそこに紛れこまないようにする。
 
・変更頻度でグルーピング
「変更頻度」とはコードを修正するタイミングが同じという意味。つまり、「変更理由」が同じということ。同じタイミングで変更される要素は同じ場所に置き、異なるタイミングで変剋される要素は別の場所に分けておく。
⇨例えば、「一般的な計算ロジック」と「年ごとに固有なロジック」があったらそれらを分離する。こうすると、「年ごとに固有なロジック」を毎年変更しても「一般的な計算ロジック」の品質は担保される。
 
・効果的にテストする能力
テスト容易性とはソフトウェアに対して、「効果的」かつ「効率的」にテストを行う能力のこと。また、テストが効率的とはテストのコストや労力が少ないことを指し、安く早くその品質を検証することができる。
⇨テスト容易性のための設計では、モジュール間の依存関係の排除がポイントになる。依存関係があるとテストしにくい部分に全体が足を引っ張られる可能性が高くなる。
 
・安全性にこだわる
例えば、あるif文に対してありえないと思いつつもelse文を考慮したり、あるcase文に対してありえないと思いつつもdefault句を考慮したり、ある変数に対してありえないと思いつつもnullチェックを行ったりすること。
⇨必然性のないところや曖昧なところは安全サイドに設計する。全ての動作を洗い出し、それぞれが安全になるように考慮する。
 
・速いコードより正しいコード
十分に動作するものがない段階で細かいところを磨いていくことには意味がない。
パフォーマンスが低い上に必要以上に複雑なコードが残ることになる。
⇨まず動かし、正しくしてから速くする。コードの複雑度を上げないようにして、シンプルな状態を保つ。
 

第4章 視点

 
・モジュールは「純粋」に
凝集度の低いモジュールは関係性のない仕事をしたり、仕事が多すぎたりする特徴がある。これは以下のような問題を発生させる。
・コードが理解しにくい
・コードが保守しにくい
・コードが再利用しにくい
・コードが脆弱で変更による影響を絶えず受ける
⇨モジュールの独立性を高めるためにできるだけ機能的強度モジュールを目指す。
実際にモジュール化を行う場合は、色々な事情の兼ね合いで情報的強度や機能的強度以外のモジュールになってしまうときがある。
止むを得ずそこに行き着くにしても、明確な評価基準の下にどれだけ代替案を検討するのかのプロセスは重要。
 
・コードの吉凶を見逃すな
コードを改善するには「リファクタリングが必要」。ただ、リファクタリングをしてコードを改善するためにはどのコードを改善すれば良いかを判断しなくてはいけない。
⇨「コードの臭い」について把握しておくことが重要。
・よく見る
重複しているコードは修正しにくくなる。重複コードは1つにまとめるようにする。
・長すぎる
長すぎたら分割して短くする
・大きすぎる
モジュールが大きすぎて管理不能な状態。モジュールが大きすぎるということは、そのモジュールが担っている責務が大きすぎるということ。
大きすぎたら分解して小さくする。
・名前が合わない
修正を加えていくうちに、はじめは正しかった名前が不適切になる場合が非常に多くある。
表現したい概念と名前があっていないコードを発見したら直ちに適切な名前に変更する。
 

第5章 習慣

プログラマの三代美徳 プログラマは「怠惰」「短気」「傲慢」であれ
・怠惰
全体の労力を減らすために手間を惜しまない気質
・短気
コンピューターがサボっているときに怒りを感じる気質
・傲慢
高いプライドを持ち人様に恥ずかしくないコードをかく
 
自分がそこに来た時よりも綺麗にしてからその場を立ち去る。最初にそのコードを書いたのが誰であるかに関係なく、少しずつでもコードを改善する努力を続ける。
コードの改善を続けていくことがプログラマのミッションである。
⇨変数名をより良くしたり、大きすぎる関数を分割したり、重複を排除したり、条件分の連なりを無くしたり、循環参照を解消したり、インターフェースを追加することで使用方法と実現方法を切り離したり、なんでも、どれくらいでも構わない。
 
・エゴを捨てよ
「うぬぼれ」や「プライド」を捨て、仲間に協力を求めるようにする。
自分の書いたコードを積極的に仲間に見せ、改善点を指摘してもらう。
同僚にコードを見せ、アドバイスを謙虚に受け入れる開発スタイルはソフトウェアの品質を向上させることがわかっている。
⇨書いたコードは自分自身ではない。「人に優しく、コードに厳しく」して、人ではなくコードを批評することを念頭に置いてコードを書くようにする。
 

第6章 手法

・「かもしれない」プログラミング
関数に不正なデータを渡された時に、それが他の関数のせいであったとしても被害を受けないよう「防御的な」コードを書いておく。
不正なデータを早めに見つけようとすると、デバックの効率が上がる。また、不正なデータを早めに処理することで運用中の問題が大きくなることを防ぐ。
⇨「バリケード戦略」をとる。コードにバリケードを築くためには特定のインターフェースを「安全地帯への境界」として使用する。そして、「安全地帯への境界」を通過するデータを検証して、不正なデータには適切な処置をとるようにする。
 
第7章 法則
・悪いコードは「蟻の一穴」
ソフトウェアの「悪い設計」「間違った意思決定」「悪いコード」を放置すると、それがどんなに小さなものでも、ソフトウェア全体をごく短期間で腐敗させることになる。
ソフトウェアに「割れた窓」が少しでもあると、修正するプログラマに「きっと残りの全てのコードもガラクタなんだから、自分も適当に作業してしまえ」という考え方が身につく。
⇨コードの良くない部分はそのままにせず、発見と同時に修復する。コードが清潔で美しく保たれていれば、プログラマはそれを汚さないよう、細心の注意を払うことになる。
 
・2番目のリリースは昨日過多
2番目のバージョンには機能を盛り込みすぎてしまい、品質が悪く、機能の使い勝手も悪くなる傾向がある。機能を盛り込みすぎるとコードが複雑になり、コードの保守性が悪くなる。
⇨ユーザーを明確に定義し、イメージすることが重要。
プログラミング中は以下の問いを改めて考えてみる
・ユーザーは誰なのか
・ユーザーは何を必要としているのか
・ユーザーは何が必要だと考えているか
・ユーザーは何を望んでいるか