プログラミング・テクニックについて書かれた名著です。
コード・コンプリート 完全なプログラミングを目指して
2、3年プログラムの世界に浸ってからふと『自分のやり方はこれでいいのかな?』と疑問に思ったときに是非手に取ってほしい一冊です。これからプログラミングを学ぶ段階や初心者の方にはお勧めできません。上巻だけで600ページ、このボリュームにひるんでプログラミングが嫌いになりそうです。
技術的な内容において素晴らしいことはもちろんですが、出てくるたとえ話がこの種の本にはめずらしく思わず笑ってしまう箇所がたくさん。あるあるネタも多くてとても面白いです。少し経験がある人には単純に読み物としても楽しめると思います。
使用方法としては最初から通して読もうとすると挫折しそうなので、知りたいことを目次で探してピンポイントで活用するのがいいのではないでしょうか。
それでは気になったトピックをピックアップ。
コンストラクションにおける設計・階層化
高品質な設計を行うために考慮するべきことはいろいろありますが、『階層化』はその中のひとつです。
たとえば、新しいシステムを作成しているが、欠陥の多い古いコードの多くを使用しなければならない場合は、古いコードのインターフェイスの役目を果たす層を新しいシステムに作成する。この層は古いコードの品質の悪さを多い隠し、新しい層に一貫したサービスを提供するように設計する。そして、システムの新しい部分には、古いコードではなくこの層のクラスを使用させる。このように階層化された設計には、次のような利点がある。
- コードの欠陥による混乱が囲い込まれる。
- 古いコードのリファクタリングをするときに、インターフェイス層以外の新しいコードを変更する必要がない。
コンストラクションにおける設計・状態変数
状態変数としてブール型の変数を使用しない。代わりに列挙型を使用する。状態変数に新しい状態を追加するのはよくあることで、列挙型に新しい値を追加するとしても、その状態変数を参照する全てのコードを大幅に変更する必要はなく、再コンパイルするだけで済む。
ふむふむ。後戻りが少なくてすむよう予防線を張れということですね。
高品質なルーチン・ルーチンの引数の使用
インターフェイスの問題を最小限に抑えるためのガイドラインが提案されています。以下はその一部。
- 引数は入力、変更、出力の順に配置する
- 全ての引数を使用する ← 忘れている引数はありませんか?
- ルーチンの引数を作業用変数として使用しない ← 混乱の元
- ルーチンの引数の数はだいたい7個に制限する ← 人間は7つ以上の情報のかたまりを一度に覚えられないから
ルーチンの引数が多いということはルーチンの結合度が強いということ。結合度が弱くなるようルーチンは設計しなさい、とあります。
疑似コードによるプログラミング・疑似コードプログラミングプロセス
疑似コードプログラミングプロセス(Pseudocode Programming Process)とは、コーディングにとりかかるまえに普通の文章でルーチンの構成を作成すること。
- 特定の処理を正確に説明する文章を使用する。
- プログラミング言語の構文要素を使用しない。疑似コードを使用すれば、コードそのものよりも少し上位レベルで設計を行うことが可能になる。
- 目的のレベルで疑似コードを書く。その方法をプログラミング言語でどのように実装するかではなく、その方法を取ることの意味を説明する。
- ほぼそのままコーディングできるくらいの詳細レベルで疑似コードを書く。
悪い疑似コード
1 2 3 4 5 6 |
リソース数を1つインクリメントする malloc()を使ってdlg構造体を割り当てる malloc()がNULLを返したら、1を返す OSrsrc_initを呼び出し、オペレーティングシステムのリソースを初期化する *hRsrcPtr = リソース数 0を返す |
これを書いた本人は満足かもしれませんが、他人には何をしようとしているのかが分かりにくい。それとC言語のコーディング要素が含まれているため、使用言語を選びます。疑似コードはコーディングでなく設計に焦点を合わせて作成するべきです。
良い疑似コード
1 2 3 4 5 6 7 8 9 10 |
使用しているリソースの数を記録する If 別のリソースが利用できる ダイアログボックス構造体を割り当てる If ダイアログボックス構造体の割り当てが可能である 使用するリソースが1つ増えることを記録する リソースを初期化する 呼び出し元から提供された場所にリソースの数を格納する End If End If 新しいリソースが作成された場合はtrueを返し、そうでない場合はfalseを返す |
読んだらすぐにコーディングのイメージが浮かんでくる書き方です。このレベルで疑似コードが書けたらあとは文章の部分を実際のコードに書き換えていきます。文章はこのままコメントで残しておくとよいですね。
なかなか時間に追われてこのレベルで実践することは難しい場合もありますが、設計ミスに関してはこの段階で発見できる可能性が高く、後戻り削減に効果的なことはよくわかります。コードの見通しが良くなり、あとから仕様変更に対応するときも影響がある部分を見つけやすそうです。
特殊な制御構造・goto文の使用に関するガイドラインのまとめ
goto文をめぐる議論はすっかり途絶えてしまったと思っているかもしれないが、SourceForge.netといったソースコードリポジトリをちょっとのぞくと、goto文が今も健在で、会社のサーバーの奥底に潜んでいることがわかる。
goto文の使用は宗教的な問題である。私の独断的な考えでは、現代の言語では、10個のgoto文のうちの9割は、それに相当するシーケンシャルな構造に簡単に置き換えることができる。
goto文についてはいろんな人がいろんなことを言ってますが、ここは結構笑ってしまう部分が多かったです。もう一度賛否の両論に目を通しておくといつか役に立つときがくるかもしれません。
最初の方で上流の設計工程についても言及があります。設計が変だったり曖昧だったら『完全なプログラミング』なんて無理ですもん。
それから『クラス』と『ポインタ』について、言語の解説本で説明を読んでも「なぜクラスを使用すると便利なのか」「なぜポインタという考え方をするのか」については「だってそうするものと決まっているから」みたいな書き方ばかりで「そもそも…」についてあんまり触れられていないことが多いです。
本著は「そもそもクラスって何のため?」「そもそもポインタって何の役に立つの?」という素朴な疑問への答えがわかりやすく説明されてました。過去にくじけた経験があるなら一度目を通してほしいです。
上巻はここまで。下巻を読んだらまた書きます。