はじめに
私は普段、サービスのフロント・デザイン面の実装をしています。
プリンシプルオブプログラミングを社内の輪読会で読み、私は第三章の「7つの設計原理」の章を担当しました。
「7つの設計原理」普段の実装やレビューに活かせるパートであり、重要だと思ったのでまとめました。
7つの設計原理
3.29 7つの設計原理とは
- どういうこと?
- コード妥当性レビュー観点
- 7つの設計原理とは障害を作り込まないために考慮すべき、コード構造上の7つの核心観点のこと。
- 実際の開発現場の分析から導き出された「経験則」
- 単純原理
- 同型原理
- 対象原理
- 階層原理
- 線型原理
- 明証原理
- 安全原理
- コード妥当性レビュー観点
- そもそもなんのために存在しているのか?
- コード価値観が「漏れない」「ブレない」ようにするため
- コードレビューは品質を保つもの。
- ただ、そのレビューには一定の価値観や観点がないと、指摘が散漫になる。
- 観点が漏れたり、ブレて一貫性がなくなることを防ぐため、「7つの設計原理」が核心的なチェック観点として生まれた。
- コード価値観が「漏れない」「ブレない」ようにするため
- 生かすためにどうすれば?
- 「7つの設計原理」をコードレビュー観点に使用しましょう!
- また、コードを書く時にも考慮するべき観点として、気をつけていきましょう。
3.30 7つの設計原理① 単純原理
- どういうこと?
- シンプルにこだわる
- 一貫して単純なコードを書くようにする。
- 複雑で全体的な関連性を重視するのではなく、局所的な完全性を重視するようにする。
- シンプルにこだわる
- どうして?
- 複雑なところにバグは出る。
- 障害は、特定の箇所に集中して発現する。
- そこは漏れなく複雑なところである。
- シンプルで見通しの良いコードを心がけると、そこに障害は発生しない。
- ただ、シンプルなコードは「素人っぽく」見えることもある。
- 経験の積んだプログラマは経験を積んだなりの”高級なコード”を書きたくなるが、その誘惑に負けないメンタリティを持つ必要がある。
- 複雑なところにバグは出る。
- どうすれば?
- 自然なコードを心がける。
- 高級なテクニックを使わず、単純なやり方で通すようにする。
- コードを無闇に複雑化、肥大化せずに、単純で小さいままに保つ。
- 自然なコードを心がける。
3.31 7つの設計原理② 同型原理
- どういうこと?
- 形にこだわる
- 同じことは同じように扱う。例外を設けないように、特別扱いしないようにする。
- 「同じように扱う」とは、あるモジュールにおいて扱う数値の単位の統一や、公開関数の引数の数が統一されていたり、使用順序が統一されていたりすること。
- 「一様性」を重視するため、一様原理と呼ばれることもある。
- 形にこだわる
- どうして?
- 「異物が目立つ」
- 同じようなことが同じように表現されていると、逆に「違うもの」が目立つ。
- 違うものはバグの原因になりやすい。
- 同型原則を守ることで、コード上の違和感に気づくようになり、障害を見つけやすくなる。
- また、統一感のあるコードの方が美しい。
- 美しいものは理解しやすい傾向があるので、コードの可読性も高まる。
- 「異物が目立つ」
- どうすれば?
- 一貫性のあるコードを書くように意識する。
- 他の部分との一貫性を無視して、自分の実力をアピールするような、独創的なコードは書かないようにする。
- 自己満足よりも、高品質なコードの方が大切。一貫性を守るようにする。
- 一貫性のあるコードを書くように意識する。
3.32 7つの設計原理③ 対称原理
- どういうこと?
- 形の対称性にこだわる。
- 上があれば下、右があれば左、getがあればsetという感じ
- 「対」になるものを考える 。
- 例: 接続されている ⇄ 接続が切れている
- 形の対称性にこだわる。
- どうして?
- 読む時に予測がつくから
- コードの形に対称性があると、予測がつきやすく、理解のスピードが速まる。
- さらに対称性が思考のフレームワークとなって、考慮漏れを防ぐことができる。
- 読む時に予測がつくから
- どうすれば?
- 対称性のあるコードを書く
- 「条件」があれば、「反条件」にもこだわる。
- 「例外的条件」は極力排除する。例外的条件は、特殊なケースであるがゆえに障害の温床となるため。
- そもそも要求が整理されていない可能性を考える。
- また、命名の対称性にもこだわること。「set/get」「start/stop」「begin/end」「push/pop」など。
- 対称性のあるコードを書く
3.33 7つの設計原理④ 階層原理
- どういうこと?
- 階層にこだわる
- 物事の主従関係、前後関係、本末関係など、階層関係を常に意識し、整理された関係性を構築する。
- 例えば、リソースの獲得を行ったら、同じ階層でリソースの解放を行う。
- 階層にこだわる
- どうして?
- 階層構造は読みやすい。
- 明確に表現された階層構造があると、読む人が全体を抽象化して理解することができる。
- 必要に応じて階層を下り、より詳細なレベルを把握できる。
- こうすることで、コードが読みやすく、プログラマの意図や使用が伝わりやすくなる。
- 階層構造は読みやすい。
- どうすれば?
- 抽象階層構造のあるコードを書く
- 抽象レベルを意識して、階層構造を構築する
- 1つの階層は、同じ抽象レベルのものだけで構成する
- 上位から見た時に、下位レベルは「それを外部から見ている」ような視点で記述する。
- 上位レベルの、下位レベルを呼び出すコードがわかりやすくなる。
- 抽象階層構造のあるコードを書く
3.34 7つの設計原理⑤ 線形原理
- どういうこと?
- 処理の流れは直線にこだわる
- 線形原理とは、「処理の流れは直線であることにこだわる」という原理です。
- いくつかの機能の重ね合わせによって実現されている(線形結合的である)のが、シンプルで良い構成
- 逆に、スイッチでコードを制御したり、状態の数を無闇に増やしたりすると、コードがわかりにくくなる。
- このようなことを避け、コードの見通しをよくする。
- 見通しが良いことを「透明」「透過」と表現するので、「透明原理」「透過原理」と呼ばれることもある。
- 処理の流れは直線にこだわる
- どうして?
- 一直線の処理は読みやすい
- 障害は実際、複雑な条件文や繰り返し文のところで多発する。
- GOTO文のように、ある種飛び道具に処理の流れがジャンプするところでも多発する。
- 階層の上位から下位に向かって流れていく処理の流れを意識して、反復を避け、一筆書きできるようなシーケンスにすることで、可読性が格段に向上する。保守性もつられてよくなり、機能追加などの改善が容易となる。
- 一般に、上から下に一方向に降下していく流れは、単純明快で分かりやすい。
- 上に行ったり来たりと、複雑に反復するようなものは避けるべき。
- 一直線の処理は読みやすい
- どうすれば?
- 分岐の少ないコードを書く
- 分岐を少なくすることで、処理の流れを直線的に読めるようなコードにする。
- 特殊な振る舞いを、主処理に混ぜない。
- 処理の一貫性やルートにこだわり、時おりコードを俯瞰して、複雑となっていないかを確認する。
- 保守していくうちに複雑になりすぎたものは、再構築することも検討。
- 自分だけでなく、後に続く人のためにも明確で堅牢な設計にすることを心がける。
- 分岐の少ないコードを書く
3.35 7つの設計原理⑥ 明証原理
- どういうこと?
- ロジックの明証性にこだわる
- 明証原理とは、はっきり証明すること。一見して明らかに正しい、と言えるようにコードを書くこと。少しでも不明瞭なところは明証しておく。
- コードだけで明証できない場合は、コメントを書いたり、別途ドキュメントを作成し、図を書くなどで、正しさを証明する。
- ただ、そうしているうちに、自然と明証的で骨太なロジックのコードを書くようになる。
- ロジックの明証性にこだわる
- どうして?
- 不確実性を取り除く
- コードは何度も読まれるため、読みやすい状態にしておかなければならない。
- 一見して明らかであると断言できるようなコードを心がける。
- 変に利口なトリッキーなコードを書かない。
- コードは人が読み、人が修正するものである。コンピューターだけが読んでるのではない。
- 人に対してコードを書く必要がある。
- 自分の作ったものには責任を持てるように、また後に続く保守を担当する人のためにもコードの不確実性は取り除く。
- 不確実性を取り除く
- どうすれば?
- ロジックが明瞭なコードを書く
- ロジックは直感的で分かりやすいものにする。
- コードを読む人が疑問に思うようなところは排除するか、コメントを残す。
- また、誰でも同じことを想像できる用語を使うようにする。
- ロジックが明瞭なコードを書く
3.36 7つの設計原理⑦ 安全原理
- どういうこと?
- 安全性にこだわる
- 必要性のないところや曖昧なところは安全サイドで設計・プログラミングする
- ありえないという条件をあえて考慮して、コードを書く。
- 例えばあるif文に対して、ありえないと思いつつもelse文を考慮したり、ある変数に対してありえないと思いつつもNULLチェックを行ったりすること。
- 安全性にこだわる
- どうして?
- 大事故への発展を防ぐ
- ソフトウェアもハードウェア同様、安全であるべきだから。
- ハードウェアの場合、ストーブは転倒に備えて自動消化装置を備えている。
- ソフトウェアもある状況において、さまざまな想定をしてそれぞれ安全な方向に動作するように設計するべき。
- これにより、サービスが継続できたり、データ破壊を未然に防いだりすることができる。
- 大事故への発展を防ぐ
- どうすれば?
- 安全サイドにコードを書く
- 必然性のないところや、曖昧なところは、安全サイドに設計する。
- 全ての動作を洗い出し、それぞれが安全になるように考慮する。
- 人によってブレが出てはいけないので、コードを書く前に、ある程度規約として定めておくようにする。
感想
7つの設計原理自体はシンプルで分かりやすいけど、全てを考慮したコードを実装するのは考えるべきことが多く、実際に実現するのは難しいです。しかし、この原理を軸として、優先順位をつけられるように生かすことが大事だと思いました。
普段自分の実装や、もらっているレビューは7つの設計原理に関連することも多く、それを通過してリリースしているものはある程度、質が保てているなと感じました。
コードは自分が理解できていて動いたら良い、というものではなく、相手にも伝わるように設計思想を理解して書くことが大事です。どこかから参考で持ってきたコードでも、使用する場合は自分が責任を持って扱うコードであるから、ちゃんと説明できないといけないなと思いました。
最後に出ていた十分条件満たせるかが「人による」ものではなく、そこに関わるメンバーで気づいていけるような体制づくりも大事だと思いました。