記事を書く目的
情報をインプットしてアウトプットする練習のため、毎週本を読み理解したことや気になったことをまとめてみようと思い、投稿します。
以下記載する内容は個人の見解であり、内容が正しいかどうかは保証できないことをご理解ください。
はじめに
読み進める中で面白かったところや気になった箇所を抜き出して、説明したいと思います。
目次
- 前提
- コードそのものが設計書
- 読みやすいコードを書く
- 原則
- PIEの原則
- SLAPの原則
- Naming is Important
- 思想
- プログラミングセオリーを実現する6つの原則
- アーキテクチャ根底技法
- 手法
- 曳光弾
- 契約による設計
- 防御的プログラミング
内容
前提
コードそのものが設計書
ハードウェアとソフトウェアはそのエンジニアリングのプロセスにおいて対比される。
ハードウェアでは、「設計」を行い設計図をアウトプットする。そして、設計図をインプットとして物理的に製造する。
一方ソフトウェアでは、基本設計〜詳細設計〜プログラミング〜テストまでが設計で、コードをアウトプットする。そして、そのコードをインプットとしてコンパイラやビルドシステムが行うリリースビルドが製造を行う。
従って、ソフトウェアエンジニアリングにおいてはコードそのものが設計書
なのである。
読みやすいコードを書く
コードは一度書いて終わりということはない。
機能改善、障害対応..etcなどによって、必ず修正されるものである。
故に、プログラミングにおける一つ一つの判断は、「そのコードが変更される」という前提で行う必要がある。
言い換えると、「変更に強いコードを書く」ということである。
そして、そのためには「コードが読みやすい」ということが何よりも重要である。
原則
PIEの原則
PIE(Programming Intently and Expressively)とは、
「コードの意図を表現してプログラミングせよ」、
ということである。
コードを書くうえ、意図を明確に表現することが重要である。
なぜなら、コードは「コンパイラ」ではなく「人」が読むためのものであるからである。
コードは書く時間よりも、読んでいる時間の方が圧倒的に多い。
故に、「書きやすさ」よりも「読みやすさ」を重視するべきである。
SLAPの原則
SLAP(Single Level Of Abstraction)とは、
抽象レベルを統一せよ、
ということである。
少し噛み砕くと、
関数を実装する際、処理の中身を抽象度に合わせて分割せよ
ということである。
なぜ、抽象度を統一することが重要なのか。
それは、抽象度のレベルが揃った関数は
関数の一覧が目次のような役割を果たす「要約性」と
関数の処理内容の見通しが良くなる「閲覧性」
をもたらすからである。
この二つの要素があると、コードの可読性は高くなるのだ。
Naming is Important
命名は、最重要課題である。
命名において、以下2つの要素がどちらも重要である。
「名前をつける行為」
適切な名前をつけれるということは、その要素が正しく理解されて、正しく設計されていることと同義である。
「名前そのもの」
名前は、コードを通じて、プログラマ同士がコミュニケーションをするための最大の場となる。
それでは、どのように命名すれば良いのか。
以下の質問を自分のした命名にぶつけてみると良い。
- 誤解されるような命名になっていないか。
- 「効果」と「目的」について説明されているか。
思想
プログラミングセオリーを実現する6つの原則
以下、6つの原則の名前を言及するにとどめる。
- 結果の局所化
- 繰り返しの最小化
- ロジックとデータの一体化
- 対称性
- 宣言型の表現
- 変更頻度
アーキテクチャ根底技法
以下、10個の技法の名前を言及するにとどめる。
- 抽象
- カプセル化
- 情報隠蔽
- パッケージ化
- 関心の分離
- 充足性、完全性、プリミティブ性
- ポリシーと実装の分離
- インターフェースと実装の分離
- 参照の一点性
- 分割統治
手法
曳光弾
曳光弾とは、発光することで、飛んだ軌跡がわかるようになっている弾丸のことで、
ソフトウェアの世界では、
優先的に検証したい部分を先行的にプログラミングをすることである。
どうして、曳光弾の考えが重要か。
即座にユーザーからのフィードバックをもらうことができるからである。
その際、余計な部分を削ぎ落として、最低限動作する土台をいち早く作ることが重要である。
契約による設計
契約による設計(Design By Contract)とは、
「呼び出し側」と「呼び出される側」の取り決めである。
関数は何かしらの作業を行うもので、その何かしらの作業を行う際に、その世界の状態について「想定」をおき、
その想定の中で、関数の終了後に何かしらの作業結果として、確約をするものである。
契約による設計(Design By Contract)では、
呼び出し側は、契約に従い呼び出す関数の前提を守る必要があり、
正しい引数を渡すのは、呼び出す側の責務としている。
なぜ、契約による設計が重要か。
それは、「思い違いを早期発見」できるから。
では、どのようにプログラミングすればよいか。
それは、コメントとアサーション
を利用することで実現可能である。
とりわけ、アサーションでは、引数と処理結果をassertすることで契約が守られているかを確認するのだ。
その際、以下に注意してください。
- 関数側で引数の調整を行わない。(渡された引数を加工したりしない。)
- 関数側のアサーションを入力チェックなどの外部入力値のチェックに使用しないこと。(後述)
防御的プログラミング
「こうなるはずだ」と決めつけないで、プログラミングをする。
具体的には以下のような観点のことである。
- 外部ソースのデータの入力の値を確認する。(想定内のエラー)
具体的には、ファイル、ユーザーインターフェース、ネットワークなどからデータを取得する場合に、データが有効な範囲に収まっているかなどをチェックする。
このような場合は想定したエラーに対する処理をプログラミングする必要がある。
- 関数の入力引数の値を確認する。(想定外のエラー)
別の関数から渡された、関数の入力引数を確認する。
外部ソースから渡された場合と異なり、無効な入力を検出するということは、コードのバグである。ということである。
外部値のチェックなど、想定内のエラーについてはエラー処理を行う。
関数の引数チェックについては想定外のエラーとして、(というのもバグなので)、アサーションを適用する。
来週読む予定の本
おしまい。
(2週間サボってしまった。。)