おもしろwebサービス開発日記

Ruby や Rails を中心に、web技術について書いています

プログラミング作法 第一章「スタイル」

最近、効率のよい○○にはまっています。

  • 効率のよいコードの書き方
  • 効率のよいテストの仕方
  • 効率のよいDBの設計

などなど。
この中から、まず手始めに効率の良いコードの書き方を学ぶことにしました。個人的に、小手先のテクニックを学ぶよりも基礎から勉強した方が長い目で見た時に効率がいい!と思うので、思いっきり基礎から勉強していきます。そこで、基礎からの勉強のためにプログラミング作法と言う本を買ってみました。

プログラミング作法

プログラミング作法

ざっと読んだ感じ、ただ読んだだけだと頭に残らなそうなので、個人的に気になったところについてブログでまとめていこうと思います。


最近いろんなことに手を出しているので、全部読みきるまでには結構かかりそうですが…気長にお付き合いください。まずは第一章。

名前

グローバルにはわかりやすい名前を、ローカルには短い名前を

ローカルグローバルにかかわらず、長くてもわかりやすい名前をつけた方がよいと思っていた。

関数には能動的な名前をつける。名前は動詞+名詞の順番がよい。(getTime()とか)

time_displayみたいな名前つけてたかも><。統一しよう。

式と文

自然な形の式を使おう。式は自分で音読するつもりで書こう。条件式に否定が含まれていると、間違いなく分かりづらくなる。

unlessはいいのかな?railsで結構多用するんだけど。こんな感じで。

name = params[:name] unless params[:name].blank?
複雑な式は分割しよう

式を分割してコードが複数行になった時に、途中結果を変数に格納しなくてはいけなくなって、変数名が増えて書きにくい→短くしちゃえ
みたいなことをしがちなので、これから自重しようと思います。

一貫性と慣用句

getsは絶対に使ってはならない。getsで読み込まれる入力の量を制限する手段がないからだ。この点はセキュリティの問題を引き起こす。*1

そうだっけ?やばい。Cだいぶ忘れてるなー。

多分岐の判定にはelse-ifを使おう

else-ifを使うっていうだけなら、「当たり前じゃん」って思うんだけど。

間違い例

if (argc == 3)
  if ((fin = fopen(argv[1], "r")) != NULL)
    if ((fout = fopen(argv[2], "w")) != NULL) {
      while ((c = getc(fin)) != EOF)
        putc(c, fout);
      fclose(fin); fclose(fout);
    } else
      printf("Can't open output file %s\n", argv[2]);
  else
    printf("Can't optn input file %s\n", argv[1]);
else
  printf("Usage: cp inputfile outputfile\n");

正解例

if (argc != 3)
  printf("Usage: cp inputfile outputfile\n");
else if ((fin = fopen(argv[1], "r")) == NULL)
  printf("Can't optn input file %s\n", argv[1]);
else if ((fout = fopen(argv[2], "w")) == NULL) {
  printf("Can't open output file %s\n", argv[2]);
  fclose(fin);
else {
  while ((c = getc(fin)) != EOF)
    putc(c, fout);
    fclose(fin);
    fclose(fout);	
}

僕は正常系を先に書いて異常系を後に書くってことを意識している(気がする)ので、その感覚で書くと間違い例のようになってしまいそうな気がした。(まあさすがにこの例では正解例を書くと思うけど)

個々の判定とそれに対応する動作はできるだけ近くに記述するのが原則だ。

って書いてあったけど、これは覚えておこうと思う。

関数マクロ

これはCオンリーな話なので飛ばす。

マジックナンバー

マジックナンバーとは、定数、配列サイズ、文字位置、変換ファクタその他、プログラム中に登場するリテラルな数値を指す。

数値はマクロではなく定数として定義しよう

Cで定数を定義するのって#defineするのが普通だと思ってた。enum文を使うのがいいらしい。

マジックナンバーまとめ
  • 2とか17とか、数値はそのまま使ってはだめ
  • 定数として定義するかライブラリを使うかなどすべき

ということらしい。

コメント

コードと矛盾させるな

これだけだと「そうだよねー」という話。でも

コメントはコードと一致しているだけではだめで、それに沿っていなければならない。

これは参考になった気がする。以下例。

time(&now);
strcpy(date, ctime(&now));
/* ctimeからコピーされた末尾の改行文字を除去 */
i = 0;
while(date[i] >= ' ') i++;
date[i] = 0;

コメントとコードは一致しているんだけど、コメントは改行文字について書いてあるのにコードは空白について書いてあるのが問題だよねーという話。これだと確かに一見コメントとコードが一致してない内容に見えてわかりづらい。

コメントまとめ

太字の部分を抜粋。

  • 当たり前のことはいちいち書くな
  • 関数とグローバルデータにコメントを
  • 悪いコードにコメントをつけるな。書き直せ。
  • あくまでも明解に、混乱を招くな

最後の部分を引用

コメントは、コード自体からは即座に意図を読み取れないプログラムの部分を解読しやすくするためのものだ。とにかくできるだけわかりやすいコードを各個と。そうすればそうするほど必要なコメントは少なくなる。優れたコードは下手なコードよりコメントが少なくて住むのだ。

コメントが少なくても分かるコードを書けるように頑張ろう。

感想

Cをだいぶ忘れている気がするので、ちょっとリハビリしたい。

*1:この本に書かれているサンプルプログラムは、ほとんどCです

マイエディタ探求日

今の僕のrails開発環境はemacs + emacs-railsです。でもemacs-railsがどうもいまいち。

  • viewからcontrolに戻ると、一番上の行に戻る
  • viewやcontrolからC-nでmodelには行けるけど、modelからcontrolやviewへは戻れない
  • C-RETが効かないときがある
  • html.erb編集時のsnippetがhtmlモード?

多分railsが2.0にバージョンアップしたのに、emacs-railsは去年の5月から更新が途絶えているのが原因。で、ちょっとtextmateに浮気をしてみた。


TextMate ― The Missing Editor for Mac OS X
インストールはあっさり。起動して、rhtmlの編集モードにしてみると・・・おー。タグの折りたたみができる。すごい。
でもC-hがバックスペースにならない。やり方調べても???バインドエディタやKeyBindings.dicsをいじってもうまくできなかったので、とりあえずTextMateを使うのは保留にします。


使いこなせたらものすごく生産性が上がりそうなんだけどね。

google 日本のページレイアウト変更

今日、google 日本のレイアウトが変更になったようです。
Google Japan Blog: Google 日本のホームページが変わりました。
日本では、yahooの方がユーザ数が多い*1のを受けての変更だと思うけど、なぜ日本ではyahooの方が強いんでしょうか。

なぜ日本ではyahooの方が強い?

僕は日本の国民性なのかなーと思っています。

  • 日本人は受動的(多分)なので、検索文字を自分で考えるよりも、画面にあるリンクを辿っていく方が楽と考えるのでは?
  • 日本人は保守的(多分)なので、もともとyahoo使っている人は変更するのがめんどくさいと思うのでは?

まとめ

上に書いたことはあくまで推測で、本当は別に理由があるのかもしれないけど、サービスを開発する側としては

  • 日本で流行るサービス
  • 世界で流行るサービス
  • 日本でも世界でも流行るサービス

はそれぞれ異なるってことを心に留めておきたいと思いました。

*1:でも、今googleもだいぶ追い上げているみたい(右のリンク参考)なので、もうじきgoogleがyahooを抜くかも。comScore Introduces qSearch 2.0 in Japan

Rails勉強会@東京第28回に参加しました。

参加しました。オフラインでの勉強会は初めてです*1

最近あまり時間がないので感想箇条書き。

  • mac使いが多かった(半分以上)
  • 無線がなぜかつながらなかった。
  • small talkは変態。でも面白そう。
    • gaucheとかsmalltalkとか言語はどれも面白そうだけど、色々手を出すのはまず一つ固めてからだな。
  • seasideすごい。
    • 通常版とブラウザ版の2つの開発環境。
    • エラーがおこったら一時停止。ブラウザ上でちょこっとバグを直して、何事もなかったように再開!
  • 事前にかるーく参加者の人たちのPPなどを見たけど、全然顔と名前が一致しなかった。顔さらした方が色々やりやすそう。検討する。
  • rspecは便利そうなので近日中に導入する。
  • parttyも面白そうだった。
  • 幹事な方たちに感謝!

土、日と勉強会に出席して、自分の死角になっているところにたくさん気づけました。
勉強会っていいね。これからもいろんな勉強会に参加するつもりです。

Rails' Wiki - Rails勉強会@東京第28回

*1:オンラインでの初参加はこっち。jQuery Code Readingに参加 - willnetの日記

jQuery Code Readingに参加

javascriptはまだいまいちわかっていないのですが、とりあえず参加してみました。
3/15(sat) - Roppongi.JS#1 jQuery Code Reading(1)のお知らせ - devlog.holy-grail.jp

最初の方はなんとかついていけたつもりなのですが、pushStackメソッドなどの各種メソッドのあたりからしんどくなってきて、
途中からサイ本を読んでました。基本的なことを全然覚えてないので、まあ当たり前の結果なのですが・・・

でも、Code Readingに参加したおかげで、自分一人でやったら理解するのに3日はかかりそうな部分がわかった!

わかったところまとめ

jquery-1.2.3 17〜27行め
var jQuery = window.jQuery = function( selector, context ) {
	// The jQuery object is actually just the init constructor 'enhanced'
	return new jQuery.prototype.init( selector, context );
};

// Map over the $ in case of overwrite
if ( window.$ )
	var _$ = window.$;
	
// Map the jQuery namespace to the '$' one
window.$ = jQuery;
  • $(hoge)とするとnew jQuery.prototype.init(hoge)が返ってくるように設定している。
  • $が既に設定されていたら、それを_$に退避させている。(prototype.jsなどとの共存のため)
jquery-1.2.3 36行目〜
jQuery.fn = jQuery.prototype = {
	init: function( selector, context ) { 
        // 省略
        }
        // 省略
        size: function() {
        // 省略
        }
        // 省略
        get: function( num ) {
        // 省略
        }
        // 省略・・・・
}

こんな感じで、jQuery.prototypeにいろんなメソッドがあるオブジェクトを定義している。
でも、ここまでだと、$はjQuery.prototype.initに定義されているメソッドしか使うことができない。(sizeやgetが使えない)

jquery-1.2.3 512〜513行目
// Give the init function the jQuery prototype for later instantiation
jQuery.prototype.init.prototype = jQuery.prototype;

ここで、jQuery.prototype.init.prototypeにjQuery.prototypeを代入している。これにより、initと同レベル(っていう書き方でいいのかな)のsizeやgetなどが
$.sizeや$.getで使えるようになる!

感想

javascriptって、親が子を継承するみたいなこともできるのね。面白い。これが今日一番勉強になったところでした。
次回のコードリーディングっていつなんだろう?次までには基礎を固めていろいろ発言したいと思います。
あとjQueryも一回きちんと使ってみないと。

JavaScript 第5版

JavaScript 第5版