2007-09-30

"C++ Coding Standards" Herb Sutter & Andrei Alexandrescu 著

じっくり読もうと思っていても肌が合わなくてパラパラっとめくって終わるものもあれば、その逆もある。本書はその逆のパターンである。それもいい感じで酔えるからである。
アル中ハイマーは、規則を固めるよりもメンバーの意識を共有できる方が効果が高いと思っている。特に、大組織に支配されるような宗教じみたコーディングルールに縛られることは嫌いである。それは、規則を守りたくても守る能力がないからである。アル中ハイマー病とはそうした病である。ただ、メンバーに共通意識を持たせるための手段としてガイドラインを提示するのは良いだろう。手段を目的と勘違いしていることはよくある。前書きにこう記されている。
「良質のコーディング標準は、単なるルール以上の良い習慣や原則を育てる。」
本書は、C++言語固有の作法に留まらず、組織運営、設計スタイルなど、チームの共通意識として持っておきたい事なども記されている。アル中ハイマーには昔からのC言語の癖がしみついているようだ。こうした古臭い作法にも気づかされる。かなり高度なものもあるが、酔っ払いでも参考にできる部分が多い。
また、当り前かもしれないが、前記事のスコット・メイヤーズ著「Effective C++ 第3版」と重複している項目も多い。では、せっかくのアドバイスを忘れないうちに、ざっとメモっておこう。

1. 時期尚早な最適化は行わない
どのコードが速くあるいは小さくなるか?どこがボトルネックになっているか?といった判断をプログラマはひどく苦手にしていると語る。CPUは複雑化しており、その上にコンパイラがいる。コンパイラもハードウェア性能を引き出すよう最善を尽くす。このような複雑な仕組みの頂上にプログラマがいる。よって最適化は測定と分析が必要である。また、CPUのみならず、メモリ、ネットワーク、周辺装置、データベースなど周辺環境も含めて総合的に判断しなければならない。部分的に最適化されても、全体としての効果がなければ意味がない。まずは、すっきりしたコードを書くことに専念すべきである。

2. 実行エラーよりも、コンパイルエラーとリンクエラーを歓迎する
コンパイラがチェックしてくれるようなコードを書くように薦めている。動的チェックも大切だが、静的チェックも利用しようということである。

3. 変数は全て初期化しよう
配列も、char path[MAX_PATH] = {'\0'}; 全ての文字を0で埋める。

4. 基本クラスとして設計していないクラスからは継承しない
子供ができることを好まないクラスもあるだろう。といっても、誰かに勝手に継承されることはある。完全に避妊する方法ってあるのだろうか?クラスの設計とは、型(子供)を設計しているようなものである。

5. 安全なオーバーライドを見に付けよう
オーバーライドは明示的にvirtualを指定して再宣言する。基本クラスにあるオーバーロードが隠蔽される場合もある。派生クラスにusing宣言すれば隠蔽されたものが使える。

6. 静的ポリモフィズムと動的ポリモフィズムを賢く組み合わせよう
動的ポリモフィズム?コンパイラが判断するのだから静的ではないのかい?
動的ポリモフィズムは、仮想関数を持つオブジェクトをポインタや参照により間接的に操作する形で生じる。アル中ハイマーは、どんな型がこようとも、発酵型だろうが蒸留型だろうが受け付ける。特に熟成型に弱い。

7. STLコンテナは決まった目的がなければ、まずvectorを使おう
更に、シーケンスに要素を追加する時は、どこでもいいならpush_backを使おう。いきなり唐突な表現である。このぐらいの言い分の方が、ド素人のアル中ハイマーにはありがたい。おいらが使うのも、vectorかstringぐらいなものである。

これで、今月の目標だった、積みあがった専門書20冊ほどの処理が終わった。すっきりした気分で温泉旅行に行けるというものである。真面目に読んだのは数冊だったような気がするのは、酔っ払いの錯覚である。呪文を唱えてスピリタスを一気に飲み干せば96%の仮想空間は現実となる。

2007-09-23

"Effective C++ 第3版" Scott Meyers 著

目の前に積みあがった専門書の中で一冊の本に目が留まった。パラパラっとめくってみると、落ち着いた色合いでなんとなくピート香がする。これはシングルモルト気分で飲めそうだ。
本書は、C++でプログラミングするためのガイドラインを提示してくれる。そこには、一般的なデザインやC++の使い方などが記されている。例えば、テンプレートと継承、public継承とprivate継承、メンバ関数と非メンバ関数、値渡しと参照渡しなど、それぞれどちらを選択するかについてのヒントを与えてくれる。また、奇抜なテクニックなどなく、むしろ基本から抑えられている点は感銘を受ける。哲学風な要素も含まれ、最近のプログラム思想も味あわせてくれる。但し、あくまでも効率的に使うためのアドバイスであり、よく吟味して使わないと味が薄れるであろう。アル中ハイマーには、いい感じに酔える本である。

C++を概観すると、複数言語の連合であると語られる。大まかな領域は4つである。1つはC言語の領域。2つはオブジェクト指向としての領域。3つはテンプレート。4つはSTL。
アル中ハイマーが関わっているのは、2つ目までの領域である。テンプレートは悪酔いのもとであり、STLはコンテナを使うぐらいなものである。
では、せっかくのアドバイスを忘れないうちに、ざっとメモっておこう。

1. プリプロセッサよりもコンパイラを使おう
#defineよりも、const、enum、inlineを薦めている。
#defineで定義したリテラルは、コンパイラが持つシンボル表には登録されないので、コンパイルエラーで混乱することもある。シンボリックデバッガでも同じことになる。
これは、高林哲氏著の「BINARY HACKS」でも、最近のプログラム手法として、#defineはなるべく使わないようにすると記されている。そこでは理由は記されてなかったが、本書では明確に記されている。

2. なるべくconstを使おう
constは、特定のオブジェクトについて「こうしてはいけない」という制約を明確にできる。メンバ関数へのconstには、物理的な不変性と論理的な不変性の意味がある。物理的な不変性は、オブジェクト内部が1ビットも変更しない場合にconstを付けるべきであると主張している。この長所はコンパイラが知らせてくれるのでルール違反もわかる。

3. オブジェクトを使う前の初期化
コンストラクタで初期値を代入しても、オブジェクト生成時に初期化されるわけではないのでオーバーラップした動作を定義していることになる。したがって、メンバ関数の初期化リストを使うと無駄な動作が省ける。

4. コンストラクタ、デストラクタ、コピー代入演算子
コンストラクタ、デストラクタ、コピー代入演算子は、宣言しなくてもコンパイラが自動生成する。もし、コンパイラが自動生成することを禁止するには、対応するメンバ関数をprivate宣言すれば良い。例えば、コピー代入演算子をprivateで宣言しておけば、このオブジェクトはコピーできない。

5. リソース管理
メモリ確保には必ず解放が必要である。よって、new/deleteは一式で使うことになるが、途中で例外処理が発生したりして解放を忘れることもある。この場合、スマートポインタなどのオブジェクトを使うと良い。そして、リソース管理クラスには、リソースへのアクセスする方法を提供しておく。つまり、メモリ解放時は、デストラクタで自動的に破棄させるように仕向ける。

6. 関数と変数の受け渡し
値渡しより、const参照渡しの方が効率的である。
関数にオブジェクトを渡したり、関数からオブジェクトを受け取る場合、関数の仮引数は、実引数のコピーとして初期化され、戻り値はコピーを受け取る。これはC言語から受け継いだもので、おいらの嫌いな性質である。これらのコピーはコピーコンストラクタによって生成されるので、参照渡しの方が効率が良い。但し、組込み型とSTLの反復子、関数オブジェクトには適用されない。これらは通常値渡しが適当である。

7. カプセル化の思想
データをなるべく遠ざけることにより、変更の柔軟性と機能拡張性を増すことがカプセル化の思想である。よって、データの近くにメンバ関数を置くよりも、メンバでもfriendでもない関数を使うと良いという。こうすれば、変更は限られたクライアント以外に影響を与えない。
個人的には、データを扱うメンバ関数は、データの近くに置くのが整理しやすいと考えていたが、カプセル化の主旨からは外れていると指摘されてしまった。この助言も分からなくはないが、その按配も状況に応じて考えたい。

8. 継承とオブジェクト指向
オブジェクト指向で最も重要なルールは、「public継承はis-a 関係を意味する」であると語る。基底クラスに適応できるものは、全て派生クラスにも適用できるようにしなければならない。コンポジションは、has-a関係と実装関係になる。非仮想のメンバ関数を派生クラスで再定義しない。継承された関数のデフォルト引数値を再定義しない。
おいらは、コンポジションを多く使う。というより自然とそうなってしまう。それと、public継承ぐらいしか使わない。酔っ払いには、この2つで充分である。

9. テンプレートのジェネリックプログラム
操作しているオブジェクトに依存しないジェネリックプログラムが脚光を浴びているようだ。例えば、STLのfindやmergeなどがそれである。テンプレートは進化している。もともとは、コンテナのためだったのだろうが、多様な使われ方をしている。ジェネリックプログラムやコンパイル時にコンパイラ内で実行できるメタプログラミングの手法など。もはやコンテナはテンプレートの一部に過ぎない。ますます悪酔いしそうな世界へと広がる。アル中ハイマーはどう転んでもテンプレートプログラマになることはなさそうだ。

2007-09-16

"C++標準ライブラリの使い方 完全ガイド" 柏原正三 著

買ったはいいが、まだ処理してない専門書がいくつかのグループに分かれて積みあがっている。中でも一番隅っこにあるグループは、なんとなく異様な香りを漂わせている。その中で一番近寄り堅い分厚くて真っ黒なところから処理するとしよう。アル中ハイマーには、美味いところを後に残す癖があるのだ。

いきなりサンプルコードのless()は、std::lessとぶつかるなあ。名前空間で逃げとこう。名前空間は嫌いな機能ではない。ただ、無名の空間で、データをグローバル化するのは肌に合わない。スコープは明確に、しかも狭められた方が好きである。のぞき穴から局所的に覗くからハッスルできるのだ。

もともとはコンテナの情報が欲しくて購入した本である。大量データを扱うにはコンテナは便利である。一見良さそうな本だと思ったんだけどなあ。リファレンスとしてもいまいちかなあ?妙に詳しく書かれた部分もある。読んでみると、なんとなく波長が合わない。だんだん読むペースが速くなる。というよりめくるスピードが上がってくる。アルゴリズムにおもしろそうなものがある。収穫はこのあたりかあ。それにしてもSTLは随分と多様化したものだ。
どうせ読むならBjarne Stroustrup著「プログラミング言語C++(第3版)」を読み返すべきだった。まあ、そう悲観しなくても辞書として使えばいいのだ。ネット検索でもええような気がするのはきっと悪酔いしたせいである。
著者の経歴に経済学部卒とある。へー!おもしろそうな人生を送ってそうだ。アマゾンでは、高い評価をしている人が多い。優秀な方々が読む本のようだ。無能なアル中ハイマーが読む本ではないのかもしれない。皆さんのお邪魔虫にならないように心がけなければならない。
これでSTL嫌いが更に進行しないことを祈りたい。
ああテンプレート!悪酔いさせるテープレート!これ以上おいらに呪文をかけないでおくれ!

この積みあがっていた専門書のグループは直感的に避けていた領域かもしれない。人間の直感は案外正しい!というのをどっかの本で読んだ覚えがある。
ということで、このグループは読んだことにしよう。いや、読んだのだ。
呪文を唱えてスピリタスを一気に飲むと、96%の仮想空間は現実となる。

2007-09-09

"The Art of UNIX Programming" Eric S.Raymond 著

立ち読みしていると、おもしろい酒肴(趣向)を見つけた。
「Unixは口承文学だ!」アル中ハイマーはこの宣伝文句にいちころである。本書は専門書風哲学書である。おいらはUnixオンチであるが、勉強意欲がわく。哲学書はこうでなくてはいけない。ただ、美しい思想ばかりではない。醜い部分もさらけ出してくれる。哲学書はこうでなくてはいけない。

文化を語るには、その歴史を振り返るのが一番である。
Unixは幾度となく危機に直面する。BSDとSystemVの内部紛争に始まり、かつてMac文化にユーザ思想を持ち込まれ、今や豊富な物量を武器にMS文化に圧倒される。パソコン市場を支配するMS信望者からは、カルト集団という差別扱いを受けている。しかし、現在ではLinuxを始めとするオープンソースの逆襲は見逃せない。Linux自体はUnixの系譜とは違って最初から書き直されたOSだが、本書では、Unix標準と同じ動作をするという意味で同列に扱っている。
本書は、Unixの生命力の長さは初期段階で開発者達が下した設計上の判断が正しかったことを意味すると語る。また一方で、古いUnixコミュニティが失敗してきた罪も見逃さない。IBMやAT&Tと同じくらい将来見通しを欠いていたこと。旧来の企業組織、金融資本、市場論理の命令機構を全て受け入れたために、プロフェッショナルの自覚を失ったこと。などが語られる。

Unix思想を表す有名な言葉は、
「K.I.S.S.」Keep It Simple, Stupid!
Unixというよりはソフトウェアエンジニアの心得が語られている。
どんなOSにも文化的偏向が見られるだろうが、ここで簡単に特徴を挙げてみよう。
・APIの基本思想で最も重要なのは「すべてはファイル」という考え方。
・マルチタスク機能をサポート。
・プロセス間通信が簡単でパイプやフィルタを可能にする。
また、Unixは、第三者ユーザの入りこむ余地を防いでいる。
・MMUによるアドレス空間の侵入を防ぐ。
・マルチユーザをサポートするための特権グループが存在する。
・重大な影響を及ぼす特権的プログラムを限定している。
ここで、Word, Excel, PowerPointなどのプログラムは互いの内部構造にベタベタの知識を持っていると皮肉っている。Unixでは具体的な通信相手を想定することなく通信できることを前提としている。Unixだからというわけではないが、アル中ハイマーがプログラムI/Fを考える時、基本はテキストストリームである。酔っ払いは単純なものしか受け入れられない。頭が悪いからモジュール構成も簡単である必要がある。よって、単純なコマンドストリームは好きである。
本書では、GUI環境が整っていないOSは問題であるということに異論を唱える人はほとんどいなくなった一方で、CLI環境が整っていないのは、GUI環境が整っていないのと同じくらい問題な欠陥であると語られる。
この見解は同感である。よって、おいは、WindowsにまずCygwinをインストールしている。

データ駆動プログラムとオブジェクト指向の違いについて語られる。
正しいデータ構造を選びうまく構成できればアルゴリズムはほとんど自明なものになる。プログラムの中心はアルゴリズムではなくデータ構造である。こうしたデータ構成が中心である考え方は共通であるが、オブジェクト指向と混同してはいけないと述べている。データ駆動プログラムは、データは単にオブジェクトの状態であるのではなく、実質的にプログラム制御を定義している。オブジェクト指向がカプセル化に関心を持つのに対し、できる限り固定されたコードを少なくすることだ。Unixの伝統はオブジェクト指向よりも深いものをもっていると語る。

本書は言語の紹介もしている。
アル中ハイマーは、すっかり、CやC++でプログラミングする機会が無くなった。最近は面倒なのでスクリプト言語で済ませる。酔っ払いには、動的な記憶管理などランタイムに任せるのが身のためである。
シェルについてはUnix伝統でもあり触れられるのは当然である。ただ意外な一言があった。
「これらの中でもっともよく知られているのは、おそらくcshだが、これはスクリプトを書くのに適していないことで悪名高い。」
へー!おいらはbashを主に使っているが、周りにcshを使っている人も少なくない。
Perlは、行指向のテキストをパターン処理する組み込み機能は強力である。この点はPerlを凌駕するものは今のところないようだ。おいらも時々使う。ただ、表現が醜い。自分で書いたコードでさえ暗号文に見える時がある。そこで、Pythonに興味を持っている。本書でも紹介しれくれる。
Pythonはモジュール化のための優れた機能を持ちクリーンでエレガントな設計になっているそうだ。Perlと比べても癖は強くないらしい。これだけで勉強してみる価値がありそうだ。標準Pythonディストリビューションには、インターネットプロトコル(smtp,pop3,ftp,imap,http)のクライアントクラスとhtmlのジェネレータクラスが含まれているという。ネットワーク管理ツールの構築に適しているようだ。これで更に興味を持つ。その分重そうでもある。
Javaは一度勉強したことがある。ただアル中ハイマーは政治的な話が嫌いである。SCSL(Sun Community Source License)には多くのプログラマが失望しているようだ。OSに依存しない独自環境というのは魅力があるので再挑戦したいと思っている。しかし、Java1.2とJ2EEEで分裂の話を紹介してくれるだけでもやる気は失せてしまう。
Emacs-Lispは、Emacs上でmewを動かすために数十行書いた程度で全く勉強したことがない。Paul Graham著の「ハッカーと画家」では、Lispの魅力を述べている。Lispハッカーはデータ構造を柔軟に持つことの価値を知っているという。アル中ハイマーには、こうしたリスト型言語を避けてきたところがある。一度は踏み入れてみようという意欲がわく。
makeの話も出てくる。おいらの好きなツールの一つだ。ただ、許せないのがコマンド行の先頭にタブを置く思想である。これは、Unixの歴史で最悪の設計ミスの1つだと認めてくれている。そうだろう!そうだろう!
インターフェースの醜さでは、アル中ハイマーはもう一つ言いたい。正規表現がそれである。まるで暗号文である。慣れれば良いとしても、ものによって微妙に表現が違うのは許せない。

Unix文化の問題点も明記している。
そこにはコミュニティ問題としてエリート主義の克服が語られる。Unixはもともと専門家相手に発展してきた経緯がある。特に年長者は自分の方が賢いという強い意識があるらしい。一方、Mac文化はエンドユーザが限りなく素人であることを念頭においている。ただ、恐ろしくインフラストラクチャーが脆弱である。Unix文化はインフラストラクチャーが全てである。Mac文化はUnix文化を取り入れ始めている。Mac OS X はUnixを基盤としている。逆に、Unix陣営は、これからはMac文化の一意的な合理性を認められるかどうかであると述べている。オープンソースの世界では、GNOMEやKDEなどのプロジェクトに力を注いでいる。これらの文化は融合されていくように見える。
Unix文化は、あまりに長い時間、非技術系のユーザを無視してきたために、MS文化がソフトウェアの品質の標準を酷く押し下げる横行を許した。
「今までは、Unixのハッカーの負けに賭けると短期的には賢く、長期的には愚かだという結果になってきた。」と締めくくる。
本書のおまけに、Master Fooの話もある。これは禅の世界へ連れて行ってくれる。哲学書はこうでなくてはいけない。

本書はUnixの話だけに留まらない。中でもオープンソース運動には魅力がある。ベンダーが握っていた主導権から市民権を獲得した感がある。道徳とは、コミュニティの中で育つ規定であり、一部のエリートが定めた法からは生まれないのである。自然のコミュニティから生まれた暗黙の規定にこそ説得力がある。技術者は上司に押し付けられた規定よりもエレガントなものを取り入れたがる。そして、良いものはコミュニティを通して広がる。
おいらは、使うツールまでもが規定されるような宗教じみたコーディングルールに縛られることを嫌う。それは、ルールを守りたくても守る能力がないからである。アル中ハイマー病とはそうした病である。

2007-09-02

"BINARY HACKS" 高林哲 他4名 著

憂鬱である。買ったはいいが、処理しきれていない専門書が20冊ほど積みあがっている。アル中ハイマーにはネット注文でついでに専門書をもぐらせるという悪い癖がある。更に悪いことに専門書を読むのがおもいっきり遅い。1ページを理解するのに下手すると半日かかることもある。右脳は酔っ払っているが左脳はもう死んでいる。論理的思考などはるか彼方へいってしまっているのだ。
本屋ではこんな行動パターンもある。高価な分厚い専門書を立ち読みしていると欲しい情報を数ページ見つける。これだけのために一冊買うのはもったいない。必死に目に焼きつける。帰って実践すると微妙に記憶が辿れない。そして、翌日買いに行く羽目になる。記憶プロセスもはるか彼方へいってしまっているのだ。
温泉旅行の前に数冊でも片付けないと落ち着かない。まずは目の前のオライリー君を本棚深く沈めてしまおう。
ただ、アル中ハイマーにとって専門書の良書をブログの記事にするのは最悪だろう。だって、自分自身の無能ぶりをさらけ出すようなものである。だからと言って隠し立てをすることもないだろう。もっと恥ずかしいことを普段からさらけ出しているではないか。あんなことや、こんなことまで。それを記事にすると思えば、恥ずかしさなどはるか彼方へいってしまうのだ。どっかの本ではないが、歳をとると鈍感力が養われるものである。

それにしても、なになにhacksという本が随分と増えたものである。hacksという言葉は、技術レベルを高めてくれるような異様な香りがする。しかし、こう多いとありがたみを感じないものである。
本書は低レイヤ(ハードウェアに近い領域)のプログラミング技術を紹介してくれる。gccの最適化手法からセキュアプログラミング、OSやプロセッサの機能を利用したものなど満載である。ただ、ド素人のアル中ハイマーがここまではやることはないだろう。
西田亙氏の「GNU Development Tools」を読んだ時はなかなか味わいがあった。本書はなかなかこくがある。
さっそく忘れないうちに、思い立ったところを摘んでおこう。

1. gccのビルトイン関数による最適化の項
文字列リテラルへポインタを宣言する時の注意点として、即値が埋め込まれずに高速化されない場合の例を示してくれる。
その中で気になる一文がある。
「最近のプログラム手法として、#defineはなるべく使わないようにする。というものがある。」
なぜだろう?その理由は書かれていない。確かに、マクロ展開そのものはエラー診断をわかりにくくしたり、引数があると意図した形に展開されないなど注意はいろいろとありそうだ。

2. TLS(スレッドローカルストレージ)という技を紹介
複数のスレッドで同じ名前の変数を共有しても、格納する場所はスレッド毎に独立できる。

3. ヒープ上に置いたコードを実行できる
最近のプロセッサやOSはメモリ保護がしっかりしているから、まずやることはないだろう。
ただ、mprotectシステムコールを使えばやれる。その延長上で自分自身の挙動を書き換えるプログラム例を紹介してくれる。ちょっと遊んでみると、これがなかなかおもしろい。アル中ハイマーは調子に乗って作ったものをウェブで公開しようと思ったが、こんなもんはメモリリークのテロリストのようなものだ。

4. プロセッサのメモリオーダーリングの話はおもしろい
複数のスレッドがクリティカルセクションに入る時、CPUの仕組みによって同時進入の可能性を紹介してくれる。最近のプロセッサではほとんどの場合問題になるようだ。パフォーマンス向上のために命令順とは異なるメモリアクセスを認めているからである。メモリアクセスのためのWAR,RAWなどの機構がそれである。これはマルチスレッドのプログラムを作る時は意識しなければならない。対処方法として、メモリバリア、アトミック命令を使った例を紹介してくれる。現在では、C/C++言語レベルではインラインアセンブラや組み込み関数でしか対応できないようだ。今後言語レベルやAPIでサポートされることを期待するとある。

5. ランタイムHack
elfバイナリが実際に実行されるまでの手順や、システムコールの呼び出し手順などを解説してくれる。このあたりは読み物としてもおもしろい。

本書は全般的に知っていて損はないだろう。アル中ハイマーが避けていたマルチスレッドの勉強でも、少しはやってみようかと思ってしまう。スレッド間のメモリ共有などは酔っ払いには辛い。まさしくチャンポンで悪い酔いしそうである。
また、細かいところで、アル中ハイマーは結構抜けたことをやっていることに気づかされる。もしかしたら、過去に作ったものの中に偶然動いてるものがあるかもしれない。なんとなく煙臭い。いや、そこに熟成されたスコッチがあるからだ。