02 September 2009

M-x help-with-tutorial

思い立ってemacs付属のチュートリアルを流し読み。知らないことがいくつかありました。

  • M-a, M-e でsentenceの最初、最後へ飛ぶ。
  • "prefix-argument" C-u でcommandをdigit回繰り返す。しってたけどほぼ使ったことがなかった。
  • C-x 1 でメインのウィンドウ1枚にもどる。
  • C-x s で全てのバッファをセーブ
  • Terminalでemacsを使っている場合、C-z でemacsをサスペンドし、シェルのプロンプトに戻ることができる。fgでemacsに復帰。
  • C-h m (僕の環境ではC-hはバックスペースにバインドしているため、F1 m で代用)で、現在のモードのヘルプが出る。
  • auto-fillモードで C-u C-x f でマージン幅を設定。M-qでパラグラフの幅を先ほど設定したマージン幅に整形する。
  • C-M-v でアクティブでないもう一枚のウィンドウをスクロールする。ちなみに、Evernoteの"Paste to Evernote"とかぶってたので、evernoteの方のショートカットを切りました。
  • C-x 4 C-f で新しいウィンドウにファイルを開く。
  • でrecursive editing modeから抜ける。recursive editing modeが何なのかはわからない。はミニバッファから抜けるときにも使える(でもこれはC-gでいいと思う。)
  • C-h (F1) がヘルプの入り口
    • C-h ? でヘルプのヘルプ
    • C-h c でcommandの説明
    • C-h k でcommandの詳細説明
    • C-h f でfunctionの説明
    • C-h a でコマンドをキーワード検索
    • C-h i でオンラインドキュメント

普通に勉強になった。C-x 1が便利すぎ。

達人プログラマー The Pragmatic Programmer 読了

帰省の車中などで達人プログラマーを読み切りました。より良いソフトウエアを開発するための方法論が、多岐にわたり、さらにプラクティカルなレベルにまで具体的に説明されており、ためになりました。ただ、デバッグの仕方やDRY原則・直行性(のコーディングの場面への適用)といDRYった、ふだんからよくやったり悩んだりしている項目に関してはとても役に立ったのですが、チームの編成や要求の聞き出しなどのあまり経験のない部分に関しては、頭では理解しても腑に落ちるところまではいってないなという感想です。これは読み手側の問題ですし、また本書は前から順番に読まなくて項目ごとに拾い読みしても大丈夫なようにできているので、興味があったり悩んだりしている項目からよんでいくのが良いと思います。また内容的に、実践することに意味のある本ですので、また今後も読み返すことになりそうです。

以下、特に面白いと思った項目をメモしていきます。

知識のポートフォリオ

知識のポートフォリオ / 達人プログラマー - フリーフォーム フリークアウト

WISDOM

WISDOMとは、文章やプレゼンなど、相手に何かを伝える際に気をつけるべき6原則です。

  • W (what): 聞き手に何を知ってほしいか。
  • I (interest): 言いたいことの中にある彼らの興味とは何か
  • S (sophisticate): それはどれくらい洗練されているか
  • D (detail): 彼らはどの程度詳細を知りたがっているか
  • O (own): 誰にその情報を知ってもらいたいか
  • M (motivate): 話を聞いてもらえるには、どうするか

DRY原則と直行性

DRYはDon't Repeat Yourselfの略で、"すべての知識はシステム内において、単一、かつ明確な、そして信頼できる表現になっていなければならない"とする原則です。つまりは、繰り返しは悪だと言っています。この原則を適用できる範囲は、なにもコードだけではなく、ドキュメントや設計、チーム編成にまで及びます。ジェネレーターなどを導入し、とにかく変更点を一カ所にとどめ、その変更が必要な部分には自動的に波及するシステムをつくることが大切です。

直行性とは、幾何学由来の概念で、例えば直角に交わる2本のベクトルのように、一方のベクトルの大きさがどれだけ変化しても、もう一方のベクトルへ射影された位置がまったくかわらない。つまりある2つのものの独立性が高い(結合度が低い)状態のことを言います。この概念はDRYと密接に関係しています。なぜなら、DRYを押し進めることで、関連のある事柄は一カ所にまとまり、別々のもの同士の結合度は下がるからです。

DRY、直行性の両方とも、よく言われている有名な概念です。それだけあって、とても適用範囲が広く、効果も大きい、重要な概念だと思います。

デバッグ

デバッグを始めるにあたり、まずは「落ち着く」必要があります。本書では次の2つのヒントが提示されています。

  • 非難するのではなく、問題を修復すること
  • パニックに陥らないこと

たしかに、バグがおこるということは、自分がおいていた前提が崩れることなので、心情的にもいらっとしてしまいますし、さらにそれを修復するには、その仮説や思い込みの誤りを探す必要があります。これはやみくもにやっても時間がかかる、論理的な攻め方が必要とされる部分です。よってまず落ち着けというのは、大げさではないアドバイスです。

心が落ち着いたあとは、現象について調べます。まずそれがきちんとコンパイルされたものかを見ます。警告レベルは常にmaxにし、どんなワーニングが出ているかも見ます。エラーメッセージが出ている場合は、その内容もつぶさに追います。個人的には、エラーメッセージの内容をきちんと理解しないままデバッグをはじめてしまい、時間を食ってしまったことがたびたびあったので、気をつけたいところです。そしてバグを再現します。その際はバグ報告者への詳細なインタビューが必要になります。

現象がはっきりした後は、原因を探ります。ここでデバッガの登場です。データとその内部関係を可視化、スタックトレースなどを行います。またバイナリサーチで原因の箇所を探すのも、よくとられる手法です。この他にも、「基本的にライブラリでなく、自分の書いたアプリケーションコードを疑え」「仮定せずに、証明すること」といった教えがあります。

面白いアプローチとして、「誰かにバグを説明してみる」というものが紹介されています。説明を試みることで、問題が整理され、原因にたどり着くこともたびたびあります。確かに、わからないことを質問しようと思って、質問を考えている過程で、問題がうまく整理できることがよくあります。

以下はこの説の最後にあった、デバッグ時のチェックリストです。

  • 報告を受けた問題は、もととなるバグの直接的な結果でしょうか、それともたんなる症状なのでしょうか。
  • 本当にコンパイラのバグでしょうか。OSのバグでしょうか。あなたのコードのバグなのでしょうか。
  • この問題を同僚に説明するとしたら、どのように説明すれば良いでしょうか。
  • 疑わしいコードが単体テストを終了していたのであれば、テストはちゃんと行われていたのでしょうか。このデータを使って単体テストを実行していたなら、どうなっていたのでしょうか。
  • このバグを発生させた条件が、システム内のどこか他の部分に残っていないでしょうか。

コード・ジェネレータ

毎回同じことをタイプせず、1キーストロークでも減らせるよう、自動生成せよという教えです。これもDRYのひとつの応用だと思います。

ここではコードジェネレータを2つに分類しています。

  • 「消極的なコードジェネレータ」は一度だけコードを生成し、その後は生成されたコードをもとにコーディングしていくというインスタントなものです。開発の最初にひな形を生成するジェネレータやウィザードなどがこれにあたります。
  • 「積極的なコードジェネレータ」は必要になるたびに何度も呼び出されます。何らかのスクリプトやファイルを読込んで、結果を生成します。

消極的なコードジェネレータの利用法として、

  • 新規ソースファイルの生成。プロジェクトの最初に起動し、毎回同じであるヘッダなどが書かれたひな形ファイルを生成します。
  • 一括変換。例えばあるテキストをtexフォーマットに一括変換するコードです。100%の変換精度にする必要はなく、90%を変換し、残りを手で直すことで、効率をあげることを目的とします。
  • 検索テーブルなどのリソース生成。例えば三角関数を計算する代わりに、サイン値コサイン値のテーブルを生成するという具合です。

積極的なコードジェネレータは、使い捨てではなく何度も使われるジェネレータで、一つの形態の情報を色々な形に変換するために使われるものです。DRY原則を実践する上で有用です。このような特徴から、makeのなかにルールとして組み込まれたりもします。

DRYと、下で出てくる自動化の話にもつながるので、コードジェネレータは積極的に書いていきたいです。

メタプログラミング

メタデータとコードを分離せよという指針です。チューニング用のパラメータやユーザのプレファレンスなど、ソフトウエアの動作に関する具体的な値は、全て別ファイルにまとめておき、コードからそれを読み込んで使います。

こうすることで、抽象概念をコード上に、詳細はメタデータにまとまるので、設計上も分離がよく柔軟性が高まります。ユーザとしても、設定ファイルを書き換えるだけで容易にチューニングできます。プログラムを変更ごとに再コンパイルしないですむのも魅力です。また情報が一カ所にまとまり、そこを変更するだけでコード中の必要な部分全てに作用するので、DRY原則にも沿っています。

実際のコーディング中では、「原則コード中に具体的な値はハードコードしない」というルールをもうけるのとうまくいきました。これができるとコードが奇麗になり、自分の満足度も上がります。非常に導入しやすいので、とっかかりには良いtipsではないでしょうか。

MVC

有名なMVCアーキテクチャです。モデルはデータとそれ自身の共通操作。ビューはモデルの表示・解釈。コントローラはそれぞれのビューに応じたビューの操作や、新たな入力をモデルに伝えるという役割です。

ビューはGUIや画面表示などのグラフィクスはもちろんですが、それだけにとどまらず、モデルをどう解釈するかという所まで発展できます。モデルというデータがあり、それを用途に応じて様々な形態(ビュー)に解釈します。このようにより高いレイヤーで、データと手続きを分離させている訳です。

どこでも自動化

人は間違えるものなので、繰り返し作業は繰り返しが得意なコンピュータにまかせようという指針です。こうすることで、整合性、再現性がよりしっかりとしたものになります。makeやcron、perlなどのLLが自動化ツールとして有用です。

具体例としては、まずビルドです。ワンステップでビルドできるようにしろというのは、よく言われていることですね。先のコードジェネレータはもちろん、makeのルールによってコード以外のドキュメントなども自動生成できますし、リグレッションテストもmakeに入れることができます。さらにビルドそのものを自動化し、夜間の自動ビルドを行うのも有用です(この辺は大きめのプロジェクトに関する話題ですね)。

この他にも、煩雑な「管理」を自動化するためのアイデアもあります。例えば、チェックインやバグ報告に応じて、webサイトの内容を最新のものにアップデートする仕組みや、レビューが必要なコードがあったとき自動で担当者にメールを飛ばすスケジューリングシステムなどが考えられます。

リソース