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


はじめに

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

第6章 手法〜プログラマの道具箱〜

一言まとめ

  • 曳光弾
    • 実際にリリースするものとして初期の段階で最低限の機能を備えた骨格となるシステムを作成する。
  • 契約による設計
    • 関数と関数を呼び出す側で、役割を分ける。
  • 防御的プログラミング
    • 受け取ったデータについて、まず検証しエラーないし停止の措置を取る。
  • ドッグフーディング
    • 自らの作ったシステムを自ら使ってみる。
  • ラバーダッキング
    • 悩んだら、その内容を整理して話してみる。
  • コンテキスト
    • 一番最初にコンテキストを読み取り、設計に活かす。

補足

曳光弾

 プロジェクトを進める際、まずは「曳光弾」として優先的に検証したい部分、土台となる部分のみのソフトウェアを作り実際の環境下で動作させることで、開発の精度が向上する。今まで構築したことのないようなソフトウェアを開発する場合は、特に重要となってくる。その利点としては以下が挙げられる。

  • ユーザーからのフィードバックが早いうちから得られる
  • コードに具体化することでプログラマ作業を行いやすい状態となり、全員が生産的になることが出来る
  • デバックやテストが早く正確に出来る
  • ステークホルダーに対するデモが可能なソフトウェアを確保できる。
  • 進捗が明確になる

 ソフトウェアの最終形態まで残るコードとして作成をする。そこに少しずつ肉付けをしていく形で作り上げていく。これはプロトタイプと似ているが明確に異なるものである。

 プロトタイプとは問題に対しての解決策を得られるような使い捨てのソフトウェア、例えばUIの確認のために本物の機能を搭載しない見た目にだけ動作をする画面を作り、作成の方針について「学ぶ」ためのものである。曳光弾とはソフトウェア全体がどのように連携するのかを明らかにするものであり、今後も使用し続けること前提で作成をする。そしてシンプルながらも実際の機能を搭載し動作するものを作成し、システム最終型の骨格とする。

契約による設計

 関数と関数を呼び出す側で、互いに「契約」を結んでいると見なしてプログラミングをすることを「契約による設計」という。関数を呼び出す側は正しい引数を渡すことを「契約」とし、関数は呼び出し後に保証されるべき条件を整えることを「契約」とする。これらを守ることで以下のようなメリットがある。

  • 要求通りのことを行うコードを書くことが出来る
  • 正しい引数が渡されていることを前提として関数の処理コードを書くのでコードをシンプルにすることが出来る。
  • 問題を早めに見つけることが出来る

 これを実現するために必要なことは、呼び出し側の仕事と呼び出される側(関数)の仕事を分けることである。呼び出し側では呼び出される側に、正しい値を渡せるよう、入力値(ユーザー入力値などにミスがないか)を検証し、呼び出され側ではそのチェックのみを行い、条件に沿うように変換する処理は行わない。また、書くコードを減らすために、受け付ける想定は厳格にし、結果を戻す際には可能な限り確約を少なくするよう努める。

 プログラミング言語には、たいてい「assert」という真偽式をチェックする機能が提供されている、これは「アサーション」と呼ばれる。アサーションが真であることは、全てが順調に実行されていることを意味する。アサーションが偽であることは、コードから「予想外」のエラーが検出されたことを意味する。偽になった際には、早期に実行を停止する必要がある。
 このアサーションを使用する際には、注意点が有り、アサーションに渡す条件式には変数の値を変えないものにする。また、アサーションはエンドユーザー用では無いため、リリース版には組み込まないよう気をつける。

防御的プログラミング

 関数に不正なデータが渡された時に、被害を受けないよう「防御的な」コードを書く必要がある。外部インターフェースからデータを取得した場合は、そのデータが許容範囲内のものか検証し、エラー処理を行う必要があり、また、別の関数から渡された場合は、不正な値であれば直ちにプログラムを停止するようにする。
これらを行うことで、開発中、運用中の安全性を担保できる。例えば、開発中には、早めに不正なデータを見つけエラー等で把握することによって、別の場所への波及を防ぐことが出来る。また、運用中には、二次災害の防止だけでなくセキュリティの観点でも、エラー処理の不備を無くすことが重要となる。具体的には、インターフェースを使用し、通過するデータを検証して適切でないデータからモジュールを守ることが肝要である。

ドッグフーディング

 自らが作ったソフトウェアをリリース前に自分で実際に使用してみることは非常に効果的である。いち開発者としてではなく、いちユーザーとして使用することで、必要のない機能や、付け加えるべき点が見えやすくなる。そしてリリース後も、自ら使い続け、それが「便利」であることを自ら証明するべきである。

ラバーダッキング

 作業する中で何か問題が発生した際には、まずその問題について説明してみることで、問題の原因に気付けることが多くある。順を追って説明することで、コードの中に存在する暗黙の仮定など自分では見えづらくなっていたことが浮き彫りになり、問題解決が早まる。話す相手としては同僚が最適だが、時間を取ることとなるので、最初は無機物相手でも構わないので話してみても効果がある。

コンテキスト

 コンテキストとは、周りの状況は背景のことである。コードを読み書きする際に、モジュール名や変数名によってその機能の説明を端的に行ったり、そのコードの周囲の状況を考える手がかりになったりする。このコンテキストから適した作業方法を読み取れるか否かが達人プログラマと初心者プログラマの差である。
 コードを書く際は先にコンテキストを示すようにし、何についてのコードか読み手に把握してもらえるようにする。また、問題解決の際には、コンテキストを前提に考えるようにする。作業全般において、最終的には絶対的なルールにただ従うのではなく、主体的に問題を解決できるようになるべきである。また、作業にあたる戦略としては「着眼対局、着手小局」を心がけていく必要がある。
 チーム間ではハイコンテキスト、つまり共通認識が多く、少ない情報で様々なことをやる取りする状況が望ましい。ただ、新しいメンバーに対してはローコンテキスト、つまりは自明であると思われることに関しても順を追って説明するようにする必要はある。

参考文献

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