コードコンプリートのチェックリスト抜粋

要求仕様

要求仕様の内容
  • システムへの入力が、その発生源、正確度、値の範囲、頻度を含めて、すべて明記されているか
  • システムからの出力が、出力先、正確度、値の範囲、頻度、形式を含めて、すべて明記されているか
  • すべてのリポート形式が明記されているか
  • すべての外部ハードウェアインターフェイス、ソフトウェアインターフェイスについて明記されているか
  • すべての通信インターフェイスが、ハンドシェーク、エラー検出、通信プロトコルを含めて、明記されているか
  • ユーザが期待する反応時間が、必要な操作のすべてにわたって明記されているか
  • 処理時間、データ伝送速度、システムスループットなどのタイミングに関する考察が明記されているか
  • ユーザの希望する処理タスクのすべてが明記されているか
  • 各タスクによって使用されるすべてのデータおよび各タスクから得られるすべてのデータについて明記されているか
  • セキュリティレベルについて明記されているか
  • ソフトウェア欠陥の影響範囲、欠陥から守るべき重要なデータ、エラー検出の筋道、エラーからの復帰などを含む信頼性について明記されているか
  • 必要なメモリ容量は明記されているか
  • 必要な補助記憶装置の要領は明記されているか
  • 実行環境への変化への対応性、他のソフトウェアインターフェイスが変更された場合に対する適応性、実行環境の正確度の変化への適応性、実行環境のパフォーマンスの変化に対する適応性を含めて、システムの保守性は明記されているか
  • 相反する属性、たとえば作業量を減少することと正確さを要求することがあった場合の妥協点が明記されているか
  • 受容可能の定義はなされているか。また、受容不可能の定義はなされているか
要求仕様定義の完全性
  • 開発を始める前に用意できていない部分について、完全でないことが明記されているか
  • ソフトェアプロダクトがすべての要求仕様を満たしていればプロダクトは受け入れられる、という意味において要求仕様は完全か
  • 要求仕様のいずれかに不安を感じる部分はないか。どこかに客やボスを喜ばせるだけに書き込まれた、実現不可能な部分はないか
要求仕様の品質
  • 要求仕様はユーザの言葉で記述されているか。ユーザがそう考えるか
  • それぞれの要求仕様項目は他の要求仕様項目と矛盾せず整合しているか
  • 要求仕様が設計内容を指示していないか
  • 要求仕様の記述が一定の水準の範囲に保たれているか。より詳細に記述するべき項目はないか。詳細すぎる項目はないか
  • 要求仕様はプログラム作成のための別のグループに引き渡されても、理解できるように記述されているか
  • 各項目は問題点とその解決内容とが関連して記述されているか。各項目は問題領域のどの部分に源があるかを追跡できるように記述されているか。
  • それぞれの要求仕様項目について検査可能か。仕様を満たしているかどうかを他の項目から独立して検査可能か。
  • 確定した要求仕様について、変更される可能性を含めて、変更可能な使用がすべて明記されているか

アーキテクチャ

  • プログラムの全体的構成が、アーキテクチャ概要、理由付けを含めて明らかか
  • モジュール定義は、機能分担や他モジュールへのインターフェイスを含めて、適切か
  • 要求仕様で述べられた機能が、適切な数のモジュールによって、きちんとカバーされているか
  • アーキテクチャは予想される変更に対応可能か
  • 必要に即した”買うか作るか”の議論が含まれているか
  • アーキテクチャにおいて、他のプロジェクトにも適用することの可能な、再利用可能コードの作り方が記載されているか
  • すべての主要なデータ構造が記述されているか、正当性も述べられているか
  • 主要なデータ構造はアクセスルーチンの陰に隠蔽されているか
  • データベースの構成と内容が明示されているか
  • すべての鍵となるアルゴリズムが記述されているか、正当性も述べられているか
  • 主要なオブジェクトが記述され、正当性も示されているか
  • ユーザの入力の取り扱い規約が明記されているか
  • 入出力の取り扱い規約が記述されているか、また正当性も述べられているか
  • ユーザーインターフェイスの外観は定義されているか
  • ユーザーインターフェイスは、その変更が、プログラムの残りの部分に影響しないようにモジュール化されているか
  • 予想メモリ必要量とメモリ管理手法が記述されているか。正当性も述べられているか
  • アーキテクチャにおいて、それぞれのモジュールのスペースと速度予測がなされているか
  • メッセージ文字列の取り扱い規約が記述されているか。文字列記憶容量の予測はされているか
  • 首尾一貫したエラー処理となっているか
  • エラーメッセージは、ユーザインタフェイスに整然と表示されるようにまとめて管理されているか
  • 頑丈さのレベルが指定されているか
  • 手厚すぎたり、手抜きになっている部分はないか。この領域に関して期待されている内容が提示されているか
  • システムの主たる目的が明確に述べられているか
  • アークテクチャ全体は概念的に首尾一貫しているか
  • トップレベルデザインは使用されるマシンや言語から独立しているか
  • 主要な決定事項についての理由付けが記述されているか
  • システムを作り上げる一人のプログラマとして見て、そのアーキテクチャに満足できるか

ルーチン作成

  • 準備内容が十分であることを確認したか
  • ルーチンが解決すべき問題を定義したか
  • ルーチンにふさわしい名前をつけることが可能なぐらい、アーキテクチャは明快か
  • ルーチンの検査方法を考えたか
  • モジュール化という観点から効率に配慮したか。あるいはスペースと速度の許容範囲という観点から考慮したか
  • 有用なアルゴリズムについて参考文献を調べたか
  • 詳細なPDL記述で設計を行ったか
  • データの考察を、必要に応じて論理設計に先だって行ったか
  • PDLの机上検査を行ったか。PDLはわかりやすいか
  • 警告に対して、アーキテクチャ設計まで戻らなければならない(グローバルデータの使用、他のルーチンで処理したほうがいい操作、等々)ものがあるか。
  • PDLからコードを起こしたか。PDL記述を元にしてコーディングし、オリジナルのPDL記述をコメントにしたか
  • PDLからコードの変換は正確か
  • 設定した動作条件をドキュメントに書いたか
  • 考えられる設計の中から最善のものを選択したか。はじめに思いついたものだけで満足していないか
  • 自分で書いたコードを完全に理解しているか。わかりやすいか

高品質ルーチン

全体に関する項目
  • ルーチンを作成する十分な理由付けがあるか
  • ルーチンのすべての部分からそれぞれ個別のルーチンにした方がよいルーチンは個別のルーチンにしたか
  • ルーチンの名前は、プロシージャの動作を表す強く明瞭な動詞+オブジェクトの形式をしているか。ファンクションの戻り値を記述する名前になっているか。
  • ルーチンの名前はルーチンの行うことをすべて表しているか
  • ルーチンには強い機能凝集があるか。ひとつのことだけを適切に処理しているか
  • ルーチン間の結合は粗か。ひとつのルーチンとほかのルーチンとの関係は小さく神話的でビジブル(見てすぐわかる)で柔軟か
  • ルーチンの長さは人為的なコーディング標準規則によって決められたのではなく、その機能、論理に従って決定されたものであるか
防衛的プログラミングに関して
  • アサーションを使用して仮定する条件をドキュメントしたか
  • ルーチンは不正な入力に対して自分自身を守っているか
  • ルーチンは例外を優雅に処理しているか
  • ルーチンは変更に対して優雅に対応できるか
  • デバック用の埋め込みは、大騒ぎをしなくても活性化したり不活性化したりできるようになっているか
  • 情報隠蔽、粗結合、データ検査を利用してエラーがルーチンの外に漏れ出さないように防火壁を作っているか
  • ルーチンはファンクションの戻り値を検査しているか
  • 製品コードに残された防衛的コードはプログラマのためではなくユーザーのためになるように設計されているか
引数渡しに関して
  • 仮引数と実引数は合致しているか
  • ルーチンの引数の順序は、似たルーチンの引数の順序と合致していることも含めて、意味のある順になっているか
  • インターフェイスの仮定する条件はドキュメントされているか
  • ルーチンの引数は7個あるいはそれ以下の個数か*1
  • 構造化変数全体を渡すのではなく必要な部分だけを渡しているか
  • すべての入力パラメータが使用されているか
  • すべての出力パラメータが使用されているか
  • ルーチンがファンクションであるならば、すべての状況で値を返しているか

モジュールの品質

  • モジュールにちゃんとした目的があるか
  • モジュールは共通データに基づいているか
  • モジュールは凝集したサービスを提供しているか
  • モジュールのサービスは、ほかのモジュールが中身を気にしなくていいほど完全か
  • モジュールはほかのモジュールから独立しているか。結合は粗か。
  • モジュールは機能実現の詳細をほかのモジュールから隠蔽しているか
  • モジュールのインターフェイスは、どのように機能を実現しているかを悟られないほど十分に抽象化されているか。モジュールをブラックボックスとみなせるか
  • モジュールをサブモジュールに分割できないかと考えたか。必要なだけサブモジュールに分割したか
  • 使用する言語が十分にモジュールをサポートしていない場合、サポートするためのプログラミング規約を設けたか

高水準設計

  • 周遊設計を行ったか。最初に試した方法に固執せずにいくつかの方法を試したか
  • それぞれのサブプログラムの設計は関連するサブプログラムと一貫性があるか
  • 設計はアーキテクチャレベルで宣言され、据え置かれた目的を十分に果たしているか
  • プログラムをモジュールあるいはオブジェクトに分解する方法に満足しているか
  • モジュールをルーチンに分解する方法に満足しているか
  • サブプログラムの境界は適正に定義されているか
  • サブプログラムは互いの関連が最少になっているか
  • 設計はトップダウンの観点からもボトムアップの観点からも適正か
  • 設計は問題領域の要素、ユーザーインターフェイス要素、そしてデータ管理要素の区別ができているか
  • 設計は知的に管理可能か
  • 設計は簡素か
  • プログラムの保守は容易か
  • 設計はサブプログラムの連結を最少にしているか
  • 設計は将来におけるプログラムの拡張を考慮しているか
  • サブプログラムは、ほかのシステムでも使用可能なように設計されているか
  • ローレベルのルーチンは高いファンイン(fan-in)*2であるか
  • ルーチンのほとんどが低い水準のファンアウト(fan-out)*3であるか
  • 設計を容易にほかの環境に移行できるか
  • 設計は痩身であるか。すべての部分が本当に必要か
  • 設計は階層化されているか
  • 設計は標準テクニックを使用しているか。見慣れない理解しにくい要素はないか

データ作成

型作成
  • 変更される可能性のあるデータの種類ごとに異なった型を使用しているか
  • 型名はプログラミング言語の型に基づくものではなく、実世界の対象に基づいているか
  • 型名は変数を宣言する際に、ドキュメントとして役に立つものであるか
  • 組み込み型を再定義していないか(intやcharなどを再定義するなということ)
データ宣言
  • データ宣言にテンプレートを利用しているか。表記上の一貫性を保っているか(shortはSHORT,charはCHARみたいに環境が変わってもいいように定義しとけということ。Victorは大丈夫ですな)
  • 使用する言語に暗黙の宣言機能が備わっているならば、それによる問題を補うように手段を講じているか
初期化
  • それぞれのルーチンは入力パラメータの正当性を検査しているか
  • 変数が使用される位置の近くで初期化を行っているか
  • カウンタやアキュムレータは適切に初期化されているか。そして、必要ならば使用するつど、再初期化しているか
  • 繰り返し実行されるコードにおいて、変数の再初期化が適切に行われているか
  • コンパイラが警告なしにコンパイルを終えるか

データ命名

一般的命名に関する考察
  • 名前が、変数を表すものを完全に正確に記述しているか
  • 名前は、プログラミングによる解法ではなく実世界の問題を表しているか
  • 名前は、パズルを解くのに必要なだけ十分に長いか
  • 計算値を示す限定子が、もしあれば、名前の末尾にあるか
  • Numではなく、CountやIndexを使用しているか
特殊なデータの命名
  • ループのインデックスは名前の意味のある名前か(ループが数行以上の長さであるか、ネスティングしている場合には、i,j,kなど以外のものであること)
  • すべてのテンポラリ(一時)変数を意味のある名前に変更してあるか
  • ブーリアン変数の名前はTrueであることが明らかになる名前か
  • 列挙型の名前は、たとえばColorを使用してColorRed,ColorGreen,ColorBlueのように、カテゴリを示す要素がプリフィックス(先頭)あるいはサフィックス(末尾)として付加されているか
  • 名前付き定数は、表す数値ではなく、抽象的実体を示す名前になっているか
命名規約
  • 命名規約はローカル、モジュール、グローバルのデータを区別しているか
  • 命名規約は型名、名前付き定数、列挙型、変数を区別しているか
  • 命名規約は、その言語にその機能がない場合、ルーチンの入力(参照)のみの引数を識別するか
  • 命名規約は、できる限り、言語の標準規約と互換性があるか
  • 名前は読みやすく構成されているか
短い名前
  • コードは(短い名前を使用しなければならない場合を除いて)長い名前を使用しているか
  • 1文字だけの省略をしていないか
  • すべての語の省略形は一貫しているか
  • 名前は読めるか
  • 読み間違いをされやすい名前を避けてあるか
  • 短い名前を変換表によって説明しているか
共通する問題;避けるべきこと
  • 意味を取り違えやすい名前
  • 同じ意味の名前
  • 1文字あるいは2文字だけが異なる名前
  • 同じ発音になる名前
  • 数詞を使用した名前
  • 短くするためにわざと誤った綴りにした名前
  • 英語でよく綴り間違いされる名前
  • 標準ライブラリにある名前、組み込み変数名と衝突する名前
  • 無関係の名前
  • 読みにくい文字のある名前

変数の使用に関する一般論

データ一般
  • 変数が最小のスコープを持っているか
  • 変数への参照はまとまっているか
  • 制御構造はデータ構造に対応しているか
  • それぞれの変数の意味は明示的で、隠れた意味を持っていないか
  • 宣言された変数はみな使用されているか
グローバルデータ
  • 真にグローバルデータであることが必要なものを除き、すべての変数はローカルか
  • 変数命名規約はローカル、モジュール、グローバルを区別しているか
  • すべてのグローバル変数は説明されているか
  • 擬似グローバルデータが使用されていないか。巨大データ構造に何もかも詰め込んでルーチンに引き渡されていないか
  • グローバルデータの代わりにアクセスルーチンを使用しているか
  • アクセスルーチンとデータとは、まとめてあるだけではなく、モジュールとして構成されているか
  • アクセスルーチンは、コンピュータサイエンスのことばではなく、抽象レベルのことばで語っているか
  • 関連するアクセスルーチンはみな、同一の抽象レベルを持つか。

基本データ型

数値一般
  • コードはマジックナンバー*4を避けているか
  • コードはゼロによる除算に備えているか
  • 型変換(キャスト)は自明か
  • 異なる二つの型がひとつの式で使用されている場合、式の評価は希望どおりになされているか
  • コードは異なる型の比較を避けているか
  • プログラムを警告なしにコンパイルできるか
整数
  • 整数除算を含む式は、目的を果たしているか(整数除算では7/10=0だよ、0.7じゃないよってこと)
  • 整数式は整数オーバーフロー問題を回避しているか
浮動小数点数
  • 絶対値が大きく異なる数の加算や減算を避けているか
  • コードは丸め誤差を回避する策を講じているか
  • 浮動小数点数の等号比較(==)を避けているか
文字と文字列
  • コードはマジックキャラクタ、マジックストリングを避けているか(ソースに直接文字列書くな。define定義とかしろ、ということ)
  • 文字列の参照はひとつ違いエラーを避けているか(参照が文字列の終端を通り越してBOM!に注意しろということ)
  • Cでは、文字列へのポインタと文字配列を区別しているか
  • Cでは、文字列はconstant+1の長さに宣言する規約に従っているか(必要な長さに+1して宣言しろということ)
  • Cでは、文字列を扱う際に、なるべくポインタではなく文字配列を使用しているか
  • Cでは、無限文字列を避けるために文字列をNULLに初期化しているか(文末の\0が抜けてBOM!を防げということ)
  • Cでは、strcpy()よりstrncpy()を使用し、strcat()よりstrncatを使用しているか
ブーリアン変数
  • 条件テストを説明するためのブーリアン変数を追加しているか
  • 条件テストを単純化するためにのブーリアン変数を追加しているか
列挙型
  • 読みやすさ、信頼性、変更への対応性のために、名前つき定数ではなく列挙型を使用しているか
  • 読みやすさ、柔軟性のためにブーリアン変数ではなく列挙型を使用しているか
  • 列挙型を使用した検査では無効値の検査を行っているか
  • 列挙型の最初の要素を"無効"として予約しているか
名前付き定数
  • データ宣言に名前つき定数を使用しているか
  • 名前つき定数の使用は一貫しているか。名前つき定数、リテラル(定数)が混在していないか
配列
  • すべての配列インデックスは配列の範囲内にあるか
  • 配列参照はひとつ違いエラーを避けているか
  • 多次元配列の添え字はみな正しい順か
  • ネストしたループでは、配列の添え字が正しいか。ループ変数のクロストーク*5は起きてないか。
ポインタ
  • ポインタ操作をファンクション(関数)に分離しているか
  • ポインタ参照は有効か。ポインタは浮遊していないか
  • ポインタを使用する変数を使用する前に有効性確認をしているか
  • ポインタを開放した後はNULL、あるいはNILにしているか
  • 読みやすさを考慮したポインタの使用をしているか
  • リンクリストのポインタは正しい順序で開放されているか
  • メモリ不足エラーになった場合に穏やかにシャットダウンできるように、避難用メモリを確保しているか
  • ポインタの使用は、ほかに方法がない場合だけに抑えられているか

コードをストレートに構成する

  • ステートメント間の依存関係が明らかなコードか
  • ルーチン名は依存性を明らかにしているか
  • ルーチンの引数は依存性を明らかにしているか
  • コメントは、コメントでなければ明らかにできない依存性を説明しているか
  • コードを上から下に読み進めるか
  • 変数の参照は、次の参照の観点でも全依存期間の観点でも、可能なかぎり近くにあるか
  • 関連するステートメントはまとまっているか
  • ステートメントの比較的独立したまとまりを独立したルーチンにしたか

条件判定

IF-THEN文
  • コード本来のパスが明確か(正常処理とエラー処理を整理して書けということ)
  • if-thenにおいて等号成立の場合正しく分岐するか
  • else節が存在し、ドキュメントされているか
  • else節は正しいか
  • if節とelse節を正しく使用しているか。逆になっていないか
  • 通常の場合が、else節ではなく、if節にあるか
IF-THEN-ELSE-IFの連鎖
  • 複雑な判定はブーリアンファンクション呼び出しに置き換えたか
  • もっとも一般的な場合が最初に判定されているか
  • すべての場合が尽くされているか
  • if-then-else-ifの連鎖が最適な方法か。case文の方が適してないか
case文
  • すべてのcase文の並び順は意味のあるものか
  • それぞれのcaseの処理は簡潔か。必要ならルーチン呼び出しをしているか
  • case文は本物の変数を判定しているか、判定だけの仮変数を使用してないか。case文を誤用していないか
  • デフォルト節の使用は正しいか。
  • デフォルト節は予期せぬ場合を検出すし、報告するために使用されているか
  • Cでは、それぞれのcaseはbreakで終わっているか

ループ

  • ループには先頭から入っているか
  • 初期化コードはループの直前にあるか
  • ループが無限ループあるいはイベントループであるなら、そのことが明示されているか。for i=1 to 9999 のような嘘が書いてないか
  • ループがCのforループであるなら、ループヘッダはループ制御のために使用されているか
  • ループの本体は、変更のときに誤らないように、beginとendあるいは同等のものによって囲んであるか
  • ループの中身はちゃんとあるか。空ループではないか
  • ハウスキーピング*6はループの頭部あるいは末尾にまとめてあるか
  • ループはファンクションと同様に、ひとつの目的かつひとつだけの目的のための処理を、きれいに設計されたルーチンと同様に行っているか
  • ループは可能な条件すべてで終了するか
  • ループの終了条件は明瞭か
  • ループがforループであるなら、中身のコードがループインデックスにいたずらをしてないか
  • ループ外のループ変数を使用するのではなく、大切なループインデックスを保存するために変数を使用しているか
  • ループで安全カウンタを使用しているか。安全カウンタの仕様基準を設定しているか
  • ループ変数は順序数あるいは列挙型であるか
  • ループ変数には意味のある名前が付けてあるか
  • ループ変数のクロストーク*7が避けてあるか
  • ループはひとめで見渡せる程度に短いか
  • ループのネストは3レベル以下か
  • ループが長いなら、とくに明瞭に書かれているか

特殊な制御構造

goto
  • gotoの使用は最終手段であるか。それはコードを読みやすくし、保守をしやすくするためであるか。
  • gotoが効率のために使用されているとすれば、効率を測定したか。それをドキュメントしてあるか。
  • gotoはひとつのルーチンに付き、ひとつのラベルだけに制限してあるか。
  • すべてのgotoは前方参照であるか。後方参照してないか
  • すべてのgotoラベルが使用されているか
return
  • それぞれのルーチンのreturnは、必要最小限であるか
  • returnは読みやすさを高めているか
再帰
  • 再帰ルーチンには再帰を停止するコードが含まれているか
  • ルーチンが停止することを保障するために安全カウンタを使用しているか
  • 再帰はひとつのルーチンに収まっているか
  • ルーチンの再帰の深さはプログラムスタックのサイズの限界に収まっているか
  • 再帰は最善の方法か。単なる繰り返しより優れているか。

制御構造関連

  • 式では1と0ではなくTrueとFalseを使っているか
  • 式を簡潔にする目的で、新たなブーリアン変数を追加したり、ブーリアンファンクションを使用したり、ディシジョンテーブル(DecisionTable)を使用したりしているか。
  • ブーリアン式は肯定的に使用されているか(例えばif文で否定文はelse側に書けということ)
  • Cでは、数値、文字、ポインタ、それらと0との比較が明示的であるか
  • 空文を確認しやすいか
  • ネスとしたステートメントを条件の再判定、if-then-elseやcase文への変更、あるいはネストしたコードをルーチンに分離独立させる、などによって簡潔にしたか
  • ルーチンのディシジョンポイント(DecisionPoint)が10を超える場合、再設計を行わない合理的な理由があるか

レイアウト

一般論
  • フォーマッティングはコードの論理構造を明らかにすることを第一目的にしているか
  • フォーマッティング方式を一貫して使用できるか
  • フォーマッティングの結果、コードの保守が容易になるか
  • フォーマッティングによりコードの読みやすさが改善されるか
制御構造
  • begin-endペアの部分で二重インデントを避けているか(※ちゃんと見やすいようにインデントしろよということ)
  • シーケンシャルブロックはお互いに空行によって分離されているか(※役割、意味合いの違う部分は空行で分けろということ)
  • 複雑な式は読みやすくフォーマットされているか
  • 単一ステートメントのブロックのフォーマットは一貫しているか(※if文の括弧の付け方は一貫した書き方をしろよということ)
  • case文は、ほかの制御構文のフォーマッティングと一貫しているか
  • gotoは、gotoを使用していることが明らかになるようなフォーマッティングを使用しているか
個々のステートメント
  • 未完成の行末は、未完であることが明らかになる形式か(※一行に書ききれなくて次の行にもありますよとわかるように書けということ)
  • 継続行は賢明にインデントされているか(※二行以上にわたる式はわかりやすくインデントしてねということ)
  • 関連するステートメントからなるグループは整列しているか
  • 関連しないステートメントからなるグループは非整列か
  • それぞれの行にはひとつのステートメントのみ書いてあるか
  • それぞれのステートメントは副作用なく書かれているか(※if文等の判断式の中に計算式を書くと、思わぬ副作用が出たりするので注意!ということ)
  • データ宣言は整列しているか
  • データ宣言は一行にひとつずつであるか
コメント
  • コメントのインデントは、コメントしようとするコードと同じインデント量になっているか
  • コメントのスタイルは保守が容易なものか
ルーチン
  • ルーチンの引数は、それぞれの引数が読みやすく、変更が容易で、コメントしやすいようにフォーマットされているか
ファイル、モジュール、プログラム
  • 複数のソースファイルを使用可能な言語では、それぞれのファイルはひとつの、そしてひとつのみのモジュールのコードであるか。
  • ファイル内のルーチンはお互いに空行によって分離されているか
  • ファイルに複数のモジュールが含まれる場合、それぞれのモジュールにルーチンはグループ化されているか。それぞれのモジュールは明瞭に区別できているか
  • 上記の区分けが難しい場合、代替手段としてすべてのルーチンはアルファベット順の列になっているか

正しいコメント付けテクニック

一般
  • ソースリストにはプログラムに関する情報のほとんどが含まれているか
  • コードを取り出した人が誰であれ、コードを直ちに理解できるか
  • コメントはコードの意図を説明しているか。あるいはコードを繰り返すのでなくコードのすることをまとめているか
  • PDLからコードを起こすプロセスを使用してコメント付けの時間を減らしているか
  • トリッキーなコードはコメントするのではなく書き直したか
  • コメントは最新情報になっているか
  • コメントは明瞭で正確か
  • 使用するコメントスタイルはコメントの変更が容易か
ステートメントとパラグラフ
  • コードは行末コメントを避けているか
  • コメントはHOWではなくWHYに焦点をおいているか
  • コメントによって読み手は、コメントに続くコードに対する準備をできるか
  • コメント全ての個数を数えたか。冗長、余分、自己陶酔などのコメントは取り除くか改善したか
  • 驚きはドキュメントされているか
  • 省略形は避けたか
  • 主コメントと副コメントの違いは明らかか
  • エラーあるいは非公開機能に依存するコードをコメントしたか
データ宣言
  • 宣言するデータの単位をコメントしたか
  • 数値データの値の範囲をコメントしたか
  • コードにした意味をコメントしたか
  • 入力データに関する制限をコメントしたか
  • フラグのドキュメントはビットレベルでしたか
  • それぞれのグローバル変数は宣言の時点でドキュメントしたか
  • それぞれのグローバル変数の使用目的などを命名規約あるいはコメントによって明示したか
  • マジックナンバーをドキュメントしたか、あるいはできるなら名前付き定数または変数に置き換えたか
制御構造
  • それぞれの制御構造をコメントしたか
  • 長い、あるいは複雑な制御構造の終了点にコメントしたか
ルーチン
  • それぞれのルーチンの目的をコメントしたか
  • それぞれのルーチンに関するそのほかの事実をコメントで与えたか。必要であれば入力データおよび出力データ、インターフェイス条件、能力限界、エラー検出、グローバルへの影響、あるいはアルゴリズムの出典などを含める
ファイル、モジュールおよびプログラム
  • プログラムには、本のパラダイムで示したようなプログラムがどのように構成されているかを概観できるような短いドキュメントが付けてあるか
  • それぞれのファイルの目的が記述されているか
  • 作者の名前と電話番号がリスティングされているか

コンフィグレーション管理

一般
  • ソフトウェアコンフィグレーション管理計画は、プログラマの作業を助けるものであり、オーバーヘッドを最少にするものであるか
  • SCM(ソフトウェアコンフィグレーション管理)アプローチはプロジェクトの過管理になっていないか
  • 私的な変更保留リスト、あるいは公的な変更管理委員会などによって変更要求をまとめているか
  • それぞれの変更提案による影響の公式予測を行っているか
  • 大きな変更要求は、要求仕様解析がすんでいないので、危険なものだと認識しているか
ツール
  • コンフィグレーション管理を容易にするためにバージョン管理ソフトウェアを使用しているか
  • チーム作業における行き違いを減少するためにバージョン管理ソフトウェアを使用しているか
  • プログラムの自動生成を効率よくかつ信頼性高く行うためにmakeあるいはその他の依存関係管理ソフトウェアを使用しているか
バックアップ
  • 全てのプロジェクト資産を周期的にバックアップしているか
  • プロジェクトのバックアップは周期的に別の保管場所に移動されているか
  • 全てのものがバックアップされているか。ソースコード、ドキュメント、図表、重要なノートなど
  • バックアップ復帰作業を検証したか

品質保証計画

  • プロジェクトに必要な品質特性が何であるかを特定したか
  • プロジェクトの全員にプロジェクトの品質目標を知らしめたか
  • 外面的品質特性と内面的品質特性とを区別しているか
  • ある特性が別の特性とどのように競合するか、あるいは補い合うかを考察したか
  • プロジェクトでは、ソフトウェア開発の各段階においてソフトウェア品質を補修するための計画を含んでいるか
  • なんらかの方法に沿って測定した品質指数によって、改善されたか退行したかを判断できるか
  • 品質保証は、あとの費用を削減するために最初に追加費用が必要であるということを管理者が理解しているか

効果的査閲

  • リビューアの注意を、過去に問題になった領域にひきつけるようなチェックリストを使用しているか
  • 不具合の修正ではなく、検出に力点をおいているか
  • 査閲者は、査閲ミーティングの前に準備のための十分な時間を与えられているか。全員が準備できているか
  • ミーティングは生産的速度で進行しているか
  • ミーティングは2時間に限っているか
  • モダレータ*8は査閲を指揮するための専門の訓練を受けたか
  • 毎回の査閲で収集されたエラーの種別に関するデータは、将来の準備や査閲をよりよいものにするために利用できるようになっているか
  • 準備速度および査閲速度に関して集められたデータは、将来の準備や査閲をよりよいものにするために利用できるようになっているか
  • それぞれの査閲で支持された行動項目は、モダレータによる個人的手段あるいは再査閲によってフォローアップされているか
  • 管理者は、なぜ自分が査閲に参加しないほうがよいかを理解しているか

デバッキング

エラーを発見するテクニック
  • あらゆるデータを使用して仮説を立てる
  • エラーが発生する検査項目を洗練する
  • エラーを複数の異なる方法で再現させる
  • 多くの仮説をたてるための多くのデータを生成する
  • 反証*9検査の結果を使用する
  • 可能な仮説をブレーンストームする
  • コードの疑わしい領域を狭める
  • 最近変更されたコードを調査する
  • コードの疑わしい領域を拡大する
  • インクリメンタルに統合する
  • かつてエラーのあったルーチンを疑う
  • 力技を使う
  • やっつけ仕事のデバッキングには制限時間を設定する
  • よく発生するエラーを調べる
  • 告白デバッキングを使用する
  • 問題から一休みする
エラーを修正するテクニック
  • 問題を理解する
  • 単に問題だけでなく、プログラムを理解する
  • エラー診断を確認する
  • リラックス
  • オリジナルのソースコードを保存する
  • 問題を修正する。兆候を修正するのではない
  • 正しい理由に基づいてのみコードを変更する
  • 一度にひとつの変更をする
  • 作業したことを調べる。修正が正しいことを確認する
  • 同様のエラーを探す
デバッキングの一般的方法
  • デバッキングをプログラム、誤り、コード品質、および問題解決方法をよりよく知るための機会として使用しているか
  • 試行錯誤や先入観にとらわれたデバッキング方法を避けているか
  • エラーはあなたの過ちである、と考えているか
  • ときどき発生するエラーを安定して再現させるための科学的手法を使用しているか
  • エラーを発見するための科学的手法を使用しているか
  • エラーを発見するために、いつも同じ方法で使用するのではなく、複数の異なった方法を使用しているか
  • 修正が正しいものであったことを確認しているか
  • 警告メッセージ、実行プロファイル、足場*10、そして会話型デバッキングを使用しているか

インクリメンタルインテグレーション戦略

  • その戦略は、インテグレーション対象のルーチンやモジュールを統合する際の最適順序を認識しているか
  • インテグレーション(統合)順序は、適切な時点でルーチンがインテグレーションに間に合うように、コンストラクション(組立て)順序と協調しているか
  • その戦略は欠陥の損段が容易になることを意識しているか
  • その戦略は足場を最小にすることを心がけているか
  • その戦略はほかの方法より優れているか
  • コンポーネント間のインターフェイスはきちんと指示されているか(インターフェイス仕様を定義することはインテグレーション作業には属さないが、きちんと定義されていることを確認する)

発展的デリバリ

  • 完全な最終的な機能を持ったソフトウェアの前に複数のリリースをすることを計画したか
  • 最初のリリースにはプログラムの核、つまり、それ以後で開発されるプログラムの残りの部分の種となるもの、が含まれているか
  • ボールが回転し始める前のなるべく早い時点で最初のリリースがされるか
  • 最初のリリースは、少なくても何らかの最小レベルにおいて、使用に耐えられるか
  • それぞれのリリースごとに機能の確実な前進があるか
  • プロセスはユーザのフィードバックを受け入れるだけの柔軟性を持っているか。もしそうでないなら、意図的に柔軟でなくしているのか
  • アーキテクチャは複数のリリースを通して多くの変更に対応できるようにオープンであるか
  • それぞれのリリースは、独自のコーディングと検査と、ある意味で、独自の要求仕様解析と設計を持った小プロジェクトとみなされているか
  • 既存のプログラムの変更に対し、発展的デリバリを適用することを考えたか
  • それぞれのリリースの段階の結果を、次の段階の予測および計画の改善に利用しているか

チューニングテクニック

速度とサイズの両方を改善する
  • ループジャンプ
  • 複雑なロジックをテーブル参照で置き換える
  • 浮動小数点変数の代わりに整数変数を使用する
  • データをコンパイル時に初期化する
  • 正しい定数型を使用する
  • 結果を事前計算する
  • 共通部分式を除去する
  • 問題となるルーチンをアセンブラに変換する
速度のみを改善する
  • ループ内でifでスイッチしない
  • ループを展開する
  • ループ内での処理を最小化する
  • 検索ループではセンチネル(標識)を使用する
  • ネストしたループでは最も忙しいループを中におく
  • ループ内部での演算の強度リダクションを行う
  • 答えがわかっているなら判定を行わない
  • case文やif-then-else連鎖の順序は頻度に従う
  • レイジー*11評価を使用する(全体を一気に計算するより必要なときに必要なだけ計算したほうが賢明な場合があるということ)
  • 多次元配列を1次元配列に変更する
  • 配列参照を最少にする
  • インデックスを使用した補助配列を使用する
  • よく使用される値をキャッシュする
  • 数学的量を使用する
  • 論理式および数式の強度リダクションを行う
  • システムルーチンに注意を払う
  • ルーチンをインラインで書き直す

変更を行う

  • それぞれの変更は変更計画に基づいているか
  • 変更は、最初の開発と同じように十分にリビューされたか
  • ソフトウェアは変更によってグレードを落としていないことを確認するための退化(デグレード)検査を行ったか。
  • 変更は、プログラム内部のグレードを落とすことなく品質を向上しているか
  • 可能な限りルーチンをより小さいルーチンに分割してシステムのモジュラリティ*12を高めたか
  • 可能な限りグローバル変数の使用を減らしたか
  • プログラミングスタイルを改善したか。変数名、ルーチン名、フォーマッティング、コメント、などなど。
  • もし変更によって共通コードの可能性が考えられるなら、上位レベルでのコード共有を考慮したか、そして、低位レベルでのコード共有を考慮したか。
  • 今回の変更は、次回の変更をより容易にするものであるか

Code Complete第2版〈上〉―完全なプログラミングを目指して

Code Complete第2版〈上〉―完全なプログラミングを目指して


Code Complete第2版〈下〉―完全なプログラミングを目指して

Code Complete第2版〈下〉―完全なプログラミングを目指して

*1:ARMの場合4個[引数の合計が4ワード]以下だと効率よくコンパイルされます

*2:ロジックICの入力が,そのロジックを駆動するロジックに与える負荷を単位ロジックの入力本数で表したもの。ファンイン数が小さいほど,そのロジックを駆動する前段のロジックに与える影響が少ない。

*3:ファンインの逆。ファンアウトが大きいほど,駆動能力が大きく,したがって,より多くのロジック入力を接続できる。

*4:1,1024,0x80等の直値

*5:ネストしたループを使用してる際、Array[i]を誤ってArray[j]などに間違ってしまうこと

*6:ループの制御に関係する記述のこと

*7:ネストしたループを使用してる際、Array[i]を誤ってArray[j]などに間違ってしまうこと

*8:司会進行者

*9:相手の主張に証拠をあげて否定すること。反対の証拠

*10:問題のあるコード部分を切り出して、そのコードの検査コードを書いたりすること

*11:この本の作者の友達の名前。人が焦って行っている多くの物事は、単にしなくてもいいことをしてるだけである、と自分を正当化していたグズ人間らしい

*12:モジュール:機能単位