『プリンシプル オブ プログラミング』読書記録 第4章


はじめに

今回『プリンシプル オブ プログラミング』という本を読みましたので、自分なりにアウトプットしていく目的でまとめます。
リンク:『プリンシプル オブ プログラミング 3年目までに身につけたい一生役立つ101の原理原則』

第4章 視点〜プログラマの観る角度〜

凝集度

 凝縮度とはモジュールに含まれている機能の純粋さを表す尺度で、モジュールの「強さ」を測るものである。そのレベルは7つある。数字が大きくなる方が強度の高いレベルのものである。

  • レベル1:暗号的強度
    • モジュール内の要素内に特別の関係がなく、偶然重複が起きているだけの状態
  • レベル2:論理的強度
    • すべての入出力操作をまとめたモジュールなど、ある機能を抽象的に捉えてまとめている状態
  • レベル3:時間的強度
    • 特定の時点で連続して実行する複数の機能を1つのモジュールにまとめている状態
  • レベル4:手順的強度
    • 問題を処理するための複数個の機能を手順通りの順番で実行するようまとめている状態
  • レベル5:連絡的強度
    • 手順て強度の特性を持ち、且つ、モジュール内機能間でデータの受け渡しをしたり、同じデータを参照する状態。
  • レベル6:情報的強度
    • 特定のデータ構造を扱う複数の機能を1つのモジュールにまとめた状態
  • レベル7:機能的強度
    • モジュール内のすべての命令が1つの役割を実行するために関連しあっている状態

 コードを独立したモジュールとして小さく分割して管理することで、強度は増す。できるだけ、機能的強度モジュールまたは情報的強度モジュールを目指すべきであるが、やむを得ずそれ以下の強度モジュールになる際には、明確な評価基準を設け多く代替案を検討することが重要である。

結合度

 結合度とは、モジュール同士の関係の密接さを表す尺度である。結合度のレベルは6つあり、数字が大きいほど関係が薄く、良いモジュールであると言える。

  • レベル1:内容結合
    • あるモジュールと他のモジュールが一部を共有するような結合形態
  • レベル2:共通結合
    • 共通域に定義したデータをいくつかのモジュールが共同使用するような結合形態
  • レベル3:外部結合
    • 外部宣言したデータを共有したモジュール間の結合形態(例:public宣言された変数)
  • レベル4:制御結合
    • 呼び出し側のモジュールが、呼び出されるモジュールの制御を指示するデータを、パラメータとして渡す結合形態
  • レベル5:スタンプ結合
    • 共通域にないデータ構造を2つのモジュールで受け渡す結合形態
  • レベル6:データ結合
    • モジュール間のインターフェースとしてスカラ型のデータ要素だけを、パラメータとして受け渡す結合形態

 結合が密なモジュールは互いに影響を及ぼすため、脆いと言える。また、そのモジュールを使用するために依存するモジュールも必要になるため再利用性が低い。モジュールの独立性を保つことは重要である。
 独立性を保つためには、モジュール間のインターフェースはできるだけ低いレベルの結合度を目指す。気をつけることは3つある。

  • データの受け渡しは引数で行う
  • データの置き場所はローカル変数に置く
  • 渡す値によって動作が変わるコードを書かない(引数で渡すフラグの内容が「A」なら追加、「D」なら削除、など)

 モジュールや関数の持つ性質として、べき等性と安全性という考え方がある。

  • べき等性

    • べき等とは、ある操作を何回行っても結果が同じであることを指す。
  • 安全性

    • 操作対象の状態を変化させないことを指す。

 この2つを持っていることで、仮に同じ操作を何度も行っても、同じ値をそのサーバーに実質的な影響を及ぼさずに呼び出すことが出来るため、安全なモジュールと言える。

直交性

 2つ以上のコードの塊があり、片方を変更しても他方に影響を与えないコードを「直交性」のあるコードという。直交性のあるコードの利点として以下2つがある。

  • 生産性の向上
    • 変更が局所化するため、開発機関とテスト期間を短縮できる。また、コード画素結合であるため再利用性が高い。
  • リスクの軽減
    • 問題のある部分を容易に隔離できるためコードが堅牢になり、またテストや検証が容易である。

コード間の結合度を最小化するには、レイヤー化のアプローチが有効である。各レイヤーでその直下レイヤーが提供している抽象化された機能のみを使用することで、上位レイヤーに影響を及ぼすこと無く、下記レイヤーの実装を変更できるようになる。逆にコード間の結合度が最大化するのはグローバル・データ(グローバル変数)の使用である。グローバル・データを利用すると、データを共有しているその他のコンポーネントと強い結びつきを持つようになるので、使用しないようする。

可逆性

 プロジェクトにおいて変化はつきものであるので、可逆性、つまりは柔軟な設計を行うことが肝要である。ある1つの特定の技術に依存した設計を行うと、万が一その使用技術が変更になった場合、それまで行った設計が破棄されることとなり、大きなコストとなる。変更に耐えうるため、やり直しが効く設計することが重要であるが、過剰に行うと複雑化しかねないので、リスク発生時のインパクトやリスクの発生確立などを考慮して後戻りが出来る設計と、シンプルな設計のバランスを取るよう心がけることが必要になってくる。

コードの臭い

 「コードの臭い」とはコードの中で、理解しにくい、修正しにくい、拡張しにくい、と感じられる部分のことである。コード改善には「リファクタリング」が必要となる。そのためには、どのコードを改善すれば良いか判断しなければならない。判断材料となる「臭い」について、いくつかの傾向がある。

  • よく見る
    • 重複したコードが多く見られる
  • 長すぎる
    • 1つの関数が長い
  • 大きすぎる
    • モジュールが大きすぎる
  • 多すぎる
    • モジュールが多すぎる
  • 名前が合わない
    • 表現したい概念と名前が合っていない

 これらのことが感じられる場合は、コードを見直す必要がある。

技術的負債

 プロジェクトにおいて、不完全なコード、設計でリリースすることがやむ終えない状況も存在する。このようなコードを「技術的負債」という。深刻な障害が発生した場合など、素早く汚いコード修正を行う事は誤った選択ではない。しかし、技術的負債は修正を後回しにすると、大きな問題となってしまうため、早めに改修し、本来書くべき正しくきれいなコードに書き換える必要がある。
 コードに詳しくない人に対して、コードの改修を行う意味について説明する際、この技術的負債という例えは有用である。また、技術的負債はコードの問題部分を「借金」に例えているが「病気」に例えられることもある。他に似た概念として「暫定ソリューション」といういわゆる「ドラフト」のようなソフトウェアのことである。一度作成されると、暫定であったはずのものが長期的に使用されてしまうケースもあるため、気をつける必要がある。

参考文献

『プリンシプル オブ プログラミング 3年目までに身につけたい一生役立つ101の原理原則』上田勲 著 株式会社秀和システム 2016年3月29日 p.184-212