ライティングソリッドコード: バグのないプログラミングを目指して (マイクロソフトプレス・シリーズ)
- アスキー (1995年3月1日発売)
- Amazon.co.jp ・本 (261ページ)
- / ISBN・EAN: 9784756103642
作品紹介・あらすじ
ソフトウェアの複雑化、大型化にともなって増加するバグを根絶するためにマイクロソフトが実践しているプログラミングノウハウを一挙公開。
感想・レビュー・書評
-
コードコンプリートやプログラミング作法で引用されている1990年ごろの書籍。
1989年12月にANSI C89、1990年12月にISO C90 が制定されたが、コンパイラメーカ独自の実装が乱立していたり、Windows 3.xなどの16bit OSが主流だった当時ならではの注意点で、今日では定石として定着しているようなものなどもあり、やや役割を終えた感もある。
しかし防御的プログラミングで仕様の本質から外れるようなフェールソフト化した結果、見つけづらいバグを埋め込むこともある。過剰な柔軟性もバグの元になる、といった指摘は今でもその光を失っていないと感じた。
技術的チャレンジやひとりよがりな親切心から、必要以上の機能を追加したりどんな場合にも使えるような柔軟性を持たせすぎることで、メンテナンスのしづらいシステムになり、膨大なコストがかさんだり、リリース中止になったりすることを繰り返した点は当時、どこの会社でも見られた闇歴史だったらしい。
今となっては他書籍でも注意されている部分が多いが、この当時ですら、メモリサイズや数クロックの微々たる性能差のために、可読性を犠牲にすることの問題点を指摘するなど参考になる部分も多い。
---
ライティングソリッドコード
STEVE MAGUIRE
1995/03/21 初版発行
1993年1月序文
1981年UNIXの走るPDP-11、アセンブラ、Pascalを用いるのが普通。
1983年8080/Z80, 6502, Z8000, TI99/a, 8086 むけインタプリタ。
1985年IBM PCビデオモードの規格統一。
---
著者1986年マイクロソフト入社。Macintosh向けアプリケーション開発
プログラム書法 The Elements of Programming Style Brian Kernighan, P.J.Plauger
ガイダンスには従うべきだが、ガイダンスを破ることで結果がよくなるときには
破るべきである。
どうしたらこのバグを自動的に検出することができただろうか?
どうしたらこのバグを防ぐことができただろうか?
ANSI標準以前のコードとの互換性のため、char int
ハンガリアン記法 マイクロソフト Charles Simonyi
イディオム : よく使われるひとまとまりの命令。
打ちまくって観察する pound and observe テストしかテスターにはできない。
コンパイラの警告を使う。lint 静的解析ツールを使う。
出荷およびデバッグバージョンの両方を管理する。
アルゴリズムも2つメンテナンスすることでバグを見つけやすくする。
ASSERTをデバッグバージョンのみで使う。両方を常に正常に動作させる。
ASSERTになった原因をコメント文で残す。アサート、デバッグ出力のみでしか使用しない変数や処理がないように注意する。
防御的プログラミングによるフェールソフトでバグを見つけづらくするな。
引数に柔軟性をもたせすぎるな。
ブールの引数は直感的でないことが多いので使わない。
危険性を警告する関数コメントを記載する。
P137 ANSI標準は既存のコードを重視し、ポータブルなコードが保証されなくても、
速度を向上させる 実装を行って良いとした。コンパイラメーカのため。
トリッキーな実装で、オーバーフロー、アンダーフローを見落とさない。
アドレス値の演算をミスしない。
コードの冗長性を取り除くのと、1行にまとめることは同じではない。
コードの共通部を複数箇所に配置するようなif文はNG。高速化?省メモリ?より
読みやすさ。
char 型が0-127
int x:8 は 0 - 127
signed int x:8 なら -128 - 127
int 2byte や 4byte になることでCPU命令、メモリアクセスが早くなる。
上位bit に正しい値が入らないことがある。
realoc関数は凝集度が低い。P119
ハイゼンベルクの不確定性原理
ある粒子の運動量と位置を 同時に正確に知ることは、原理的に不可能である
出荷バージョンとデバッグバージョンが同時に正確だということを知るのは不可能。
解放後のメモリにA3などのガベージ値を入れる。0では駄目。
サブシステムにラッパーを用意し、ASSERTなどのチェック、ロギングを行う。
コードをステップ実行して確認する。
コンパイラが想定通りに値を埋めていないかもしれない。
分岐数を整理し、テストしやすいコードを書くようになる。
オーバーフローなども検知できる。
最適化を無効化してステップ実行する。
getchar の EOF を扱うため int 型にする必要がある。
1978年プログラミング言語C初版。ANSI前。
戻り値にエラー値を混同させるのは良くない。libc にはよくある例だが。
自分の持ち物でないメモリ領域を読み書きしない。どんなタイミングで値が変わるか
わからない。静的変数、大域変数もNG。
出力用メモリも作業用バッファとして使用しない。
柔軟性がバグを生む。
P184
新しく書いたコードの量は、自分が開発している製品の内部動作の理解度に直接比例する。
初心者でもバグを引き起こすことがないように配慮した記載。過度なトリックを
埋め込まない。
メモリマップドIOのレジスタ値変化でタイミングにより読み込みが失敗する。
関数ジャンプアセンブリコードで2byte勝手に飛ばす。
バグは勝手に消えない。再現し、原因を断定しておく。
バグは早めになおす。1年前のコードを読み返すだけでもかなりの工数が必要。
間違いを繰り返さなくて済む。
スケジュールが読めなくなる。機能を削るといった調整もできなくなる。
根本的にミスを起こしやすいIFをリファクタリングする。対処デバッグをしない。
コードを読みやすくすることで、動作が変わることもある。下手に触らない。
思いつきの機能、技術的チャレンジは製品化が決まるまで実施しない。
簡単に載せられる機能もマニュアル作成やテスト、メンテナンスコストのものになる。
試すのではなく、マニュアルを読み正攻法で実装する。
テスターを頼り過ぎない、別の役割を持っている。悪者扱いしない。
軽度のバグでもバグがあることが問題。
---
P113 ハラペーニョ。ヤラペーニョ。
---
再現させるテストコードを書く。ログを見る。事実と予測を切り分けて共有する。詳細をみるコメント0件をすべて表示 -
ソースコードを書く人すべてに読んでもらいたい本。ステップ実行を行う・assert()を活用する等、役に立つ話ばかりです。