Cプログラミング診断室という思想書

#技術者としての土台
[Cプログラミング診断室](https://amzn.to/3dJghXf)という書籍をご存じだろうか。
初版は平成5年（1993年）で、当時のパソコンは[こんな感じ](https://www.eonet.ne.jp/~building-pc/pc/PC1993/pc1993.htm)である。
通信環境は[この有様](https://bb.watch.impress.co.jp/cda/special/16691.html#:~:text=BB%E3%81%AE%E5%A7%8B%E3%81%BE%E3%81%A3%E3%81%9F2001,%E3%83%95%E3%83%AC%E3%83%83%E3%83%84%E3%81%8C%E9%96%8B%E5%A7%8B%E3%81%95%E3%82%8C%E3%81%9F%E3%80%82)で、**携帯電話はdocomo誕生直後だ**。

その後、この書籍は途中絶版を挟んで改訂を重ね、[現在に至る。](http://www.pro.or.jp/~fuji/mybooks/cdiag/)
この書籍は技術書というより、誤解を恐れずに言うなら**思想書**である。
例題のプログラミング言語はC言語だが、**言語は問題ではない。**

この書籍の趣旨は、悪いコード例を取り上げて

- どこが悪いのか？
- なぜ悪いのか？
- 悪い実装に至った理由は何か？
- 思想をどう切り替えるべきか？
- そしてどう作るべきか？

について、丁寧に解説した書籍である。
一時絶版したため、著者のご厚意で一冊丸ごとWebで公開されている。
なんと無料である。
ではWeb上の内容をベースに、大切なところを紹介していく。
概要の紹介に留めるので、実際の記事も参照してほしい。
なお**リンク先はSSL非対応**であることに注意されたい。

#[開院準備](http://www.pro.or.jp/~fuji/mybooks/cdiag/cdiag.0.1.html)
ここは技術的内容の前の導入部である。深く読む必要はない。
古株の技術者にとってはクスっとする内容もあるかもしれない。
平成生まれのエンジニアにとってはピンとこないかもしれない。

#[第１章　普通の初心者](http://www.pro.or.jp/~fuji/mybooks/cdiag/cdiag.1.1.html)
ここはコードを設計・実装するための基本の基本を解説している。

- 関数などの処理単位を長くしすぎない(100行以下)
- 処理単位は機能に着目して適切な長さに分割する
- 意味のわかるコメントを残す
- 車輪の再発明をしない（ライブラリを活用する）
- 命名規則は開発環境における標準的なものを採用する

#[第２章　これでもプロ](http://www.pro.or.jp/~fuji/mybooks/cdiag/cdiag.2.1.html)
ここは第１章よりもひどいコードが登場する。
コードはリンク先を見てじっくり堪能してほしい。実に味わい深い。
ここでの趣旨はこうだ。

- コメントを書く
- 処理単位を長くしすぎない
- 悪いとされている goto を使わない（例外はある）
- ほかはC/C++に依存した部分が多いので割愛する

#[第３章　上司が問題](http://www.pro.or.jp/~fuji/mybooks/cdiag/cdiag.3.1.html)
これまでとは別の意味で味わい深いコードである。

- 命名規則はその環境で標準的な形式を使用する
- グローバル変数を極力使わない
- フラグの乱用を避ける
- ユーザ定義型やコード片をコピペしない

ここで重要だと思うのは最後の２つである。
ある処理単位において、実装にフラグが増えるほど難易度も上がる。
条件分けの数が

- フラグ１つ＞２通り
- フラグ２つ＞４通り
- フラグ３つ＞８通り

条件分けが２のべき乗で増えていく。こういう実装はバグを呼ぶ。
さらに、次のコード片のコピペはより深刻である。

- コピペしたコード片にバグがあったらすべて修正が必要
- そもそもコピペでコードの総量を増やすのは悪である
- コピペを考える前にリファクタリングを考えるべきである
- いかなる理由でもコピペで解決してはならない

#[第４章　キャストが好き](http://www.pro.or.jp/~fuji/mybooks/cdiag/cdiag.4.1.html)
C/C++依存のため割愛。リンク先を参照されたい。

#[第５章　管理は複雑に](http://www.pro.or.jp/~fuji/mybooks/cdiag/cdiag.5.1.html)
C/C++依存のため割愛。リンク先を参照されたい。

#[第６章　不慣れ](http://www.pro.or.jp/~fuji/mybooks/cdiag/cdiag.6.1.html)
X-Window、というかウィンドウシステムでのプログラミング問題。
ここでの趣旨はこうだ。

- 長い処理単位を避ける
- 適切なインデント
- 読みやすい１行の文字数（これは当時の環境での話）
- メモリの動的確保は必要な場合に限る

#[第７章　文字列処理は得意](http://www.pro.or.jp/~fuji/mybooks/cdiag/cdiag.7.1.html)
C/C++依存のため割愛。リンク先を参照されたい。
コードは味わい深いので興味のある人は堪能してほしい。

#[第８章　Pascalが好き](http://www.pro.or.jp/~fuji/mybooks/cdiag/cdiag.8.1.html)
C/C++依存のため割愛。リンク先を参照されたい。
開発者の姿勢としては論外である。

#第２部　集中治療室
#[第９章　珠玉の力作](http://www.pro.or.jp/~fuji/mybooks/cdiag/cdiag.9.1.html)
ここでの趣旨はこうだ。

- 言語仕様は正しく理解して楽をしよう
- ライブラリの使い方を学習しよう
- コメントアウトで古いコードを残すのはやめよう(*1)
- ウィンドウシステムのサービスコールを確認しよう
- ライブラリやOSの提供機能を把握して極限までサボろう

*1については理由があってあえて残しているケースも存在する。
だが基本としては一時的な利用に限定するべきである。

#[第10章　最長不到関数](http://www.pro.or.jp/~fuji/mybooks/cdiag/cdiag.10.1.html)
ここでの趣旨はこうだ。

- 処理単位が一定の行数（目安100行）を超えたら立ち止まろう
- 動的なメモリの確保・解放は必要最小限にしよう
- 複雑な条件判断は正常判定より異常判定を優先しよう

なお、C/C++限定だが、delete演算子とfree()関数にnullptrを
渡すのは問題ないことが保証されている。

#[第11章　奇っ怪な条件](http://www.pro.or.jp/~fuji/mybooks/cdiag/cdiag.11.1.html)
ここでの趣旨もこれまでの繰り返しになる。

- OSのサービスコールの機能はよく調べておこう
- すでにあるものを使って無駄なコード書くのはやめよう

#[第12章　芸術的字下げ](http://www.pro.or.jp/~fuji/mybooks/cdiag/cdiag.12.1.html)
ここでの趣旨はこうだ。

- エラー処理を優先しよう
- エラー処理限定の関数内ジャンプであればgotoにも価値がある

個人的な経験則だが、インデントが3段以上のコードには問題がある。

#[第13章　計算は自分で](http://www.pro.or.jp/~fuji/mybooks/cdiag/cdiag.13.1.html)
ここでの趣旨はこうだ。

- コンパイラ（処理系）の自動計算を活用しよう
- 環境ごとにデータを差し替えるならリソース化しよう

#[第14章　メモリが足りない](http://www.pro.or.jp/~fuji/mybooks/cdiag/cdiag.14.1.html)
ここでの趣旨はこうだ。

- 巨大なデータを扱う必要がある時は「扱える単位」に分割しよう
- 性能ネックになりやすい（遅い）実装に注意しよう
- 実行しても無駄な処理を実装しないようにしよう
- 本当に遅くて問題ならプロファイラを活用（ネック部分に対処）

#まとめ
たくさんコードを書くと、たくさんデバッグすることになる。
[プログラマの三大美徳](https://www.google.com/search?q=%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9E%E3%81%AE%E4%B8%89%E5%A4%A7%E7%BE%8E%E5%BE%B3&oq=%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9E%E3%81%AE%E4%B8%89%E5%A4%A7%E7%BE%8E%E5%BE%B3&aqs=chrome..69i57j0i30.5256j1j7&sourceid=chrome&ie=UTF-8)でも言われる通り前向きな怠惰になろう。

- より少ないコード量で済ませる方法はないか？
- ライブラリやサービスコールでやらせることはできないか？
- 力ずくでコードを書いていないか？（コピペは論外）
- 正常系判定を優先してコードが長くなっていないか？

目安としては**処理単位の行数とインデントの段数**である。
関数などの処理単位が100行を超える場合は立ち止まろう。
処理単位の中でインデントが３段以上なら注意しよう。
１行の長さは気にしなくてもいいが、目安は200文字以下だろう。
この傾向は**処理単位の中に複数の機能が存在する**ことを示唆する。
処理単位を精査して、機能ごとに単位を分割しよう。
これは現在に至るまで通用する法則だと自分は信じている。
言うまでもないがコピペは厳禁である。
なおC/C++プログラマには[こちら](https://amzn.to/32CTwxO)もお勧めしたいのだが絶版のようだ。

Good Luck !