| @技術/プログラミング

最近、会社でリーダブルコードを輪読したり、Fukuoka.rb で Eloquent Ruby を読んだりしていて、メソッドや変数名の長さやコメントについての議論を読む機会があった。

昨日、たまたま 37signals のブログを読んでいたら、Rails の作者である David Heinemeier Hansson もこのトピックについて書いていた。

自分は WEB+DB PRESS で ukstudio さんの書いた RSpec についての記事を読んで感化されて以来、ソースコード中のコメントはすべて悪で、はっきりしたメソッド名、変数名を使えばコメントはいらないという考え方を持っている。DHH もそのような考え方のようだ。

要点をかいつまむ。

多くのプログラマーは短い変数名やメソッド名を好む。短い命名は明確性や簡潔性を犠牲にしているとみんな気づいてるんじゃないかと疑ってるんだけど、実際のところ短い命名を採用したコードが多い。特に「一行は80文字まで」教の連中に。

しかし最近のプログラミング言語は表現豊かなのだから、短い命名にこだわる必要は無い。

extension を ext と略してあるのを見かけると嫌気がさす。アプリケーション固有の略語を作るのはもっとひどい。そんなの二ヶ月後には絶対忘れてる。

過剰に明瞭な名前は一見するとバカっぽい。処理内容よりもメソッド名の方が長いとかね。でも一発でやってる内容が分かることの前ではそのバカっぽさは霧消する。

最近の Basecamp のコードにはこんなのがある。

def make_person_an_outside_subscriber_if_all_accesses_revoked
  person.update_attribute(:outside_subscriber, true) if person.reload.accesses.blank?
end

def shift_records_upward_starting_at(position)
  positioned_records.update_all "position = position - 1",
    ["position >= ?", position]
end

def someone_else_just_finished_writing?(document)
  if event = document.current_version_event
    !event.by_current_creator? and event.updated_at > 1.minute.ago
  end
end

もし十分に明確な命名をしているのであれば、コードにコメントを書く必要がない。コメントというものは往々にして不明瞭な命名をしているコードの中で必要になる。コメント付きのコードはやばい臭いを放っていると思っといた方がいい。

コメントはいらない

リーダブルコードの中にも「名前は短いコメントだと思えばいい」というくだりがあるけど、基本的にあの本には「いいコメントを書け」と書いてあるような気がする。コメントそのものを悪いとみなしていない。

先々週読んだ Eloquent Ruby の Chapter 8. Embrace Dynamic Typing の中では Ruby という言語の特性も踏まえ、コメントはいらないと書いてあった。

例えば Ruby ではメソッド名の最後にはてなをつけてあると Boolean を返すという慣習がある。だからコードの中に「○×を判定し true/false を返します」というようなコメントはいらない。

def is_longer_than?(number_of_characters)
  @content.length > number_of_characters
end

Eloquent Ruby は Chapter 1 でもコメントについて述べている。そこには「コメントを書くべき理由があるコードもある」と書いてある。そのコードの使い方を指南したコメントだ。「なぜそのようなコードを書いたのか」、「コード内で用いているアルゴリズムの説明」、「どのようにして高速化したか」というようなことは書くべきではないと言っている。この辺はリーダブルコードと正反対だ。リーダブルコードでは「なぜそのような実装にしたのか」を積極的に書くように奨励されていた。

ちょっと前にはてブでホッテントリに入ってた、ソースコード内のコメントでコードレビューをやるというやり方は最悪だと思う。売り物のコードの中でああでもないこうでもないと議論するなんて狂ってる。コードが修正されたときに議論の内容まで適切に修正されるとは思えない。下手をするとコメントとコードの内容が正反対になってしまうかも知れない。コードの背景についてはコード内に書かず、GitHub 使ってインラインコメントでやった方が良いと思う。

皆さんはどう思いますか?

| @技術/プログラミング

だいぶ前の記事では Jekyll は Git の hook を使って公開してると書いてた。

しかし記事の本数が増えてくると、 jekyll コマンドで生成した静的なファイルも Git でトラックするのがだるいと感じるようになった。ので Rakefile に以下のような task を追加して、公開先のサーバーに rsync でファイルを転送するように変更した。

desc "Publish"
task :publish do
  path = File.expand_path("_site")
  if system("rsync -avz --delete #{path}/ portalshit:sites/tech.portalshit.net/_site/")
    puts "Your blog was successfully published!"
  else
    puts "Something went wrong..."
  end
end

だいぶデプロイが手軽になった。

| @技術/プログラミング

社畜なのでVドメインからMドメインにドメインの管理業者を変更した。そしたらDNSの設定やらなんやらを忘れていて、tech.portalshit.net が死んでた。最近は技術っぽい内容も www.portalshit.net に書いてるしここの存在意義が微妙になってきた。Jekyll、便利ではあるんだけど、rbenv で Ruby のバージョン上げるごとに gem install jekyll gsl とかやるのが若干めんどくさく感じられるようになってきてしまった。ただ記事を書くためだけにそこまでやりたくないかも。

| @技術/プログラミング

自戒エントリー。

自分は Mongoid を使って開発してるんですけど、時間の境界値のテストが不十分で問題に遭遇したのでメモっておきます。

Mongoid には Date 型や DateTime 型があるけど、データベースにデータを保存するときには Time 型に変換されます(MongoDB に Date とか DateTime がないから?)。Mongo Shell で DB の中の値を見ると Time 型の値が入ってる。

だからクエリを生成するときに Date.today はなるべく使わない方がいい。Date.today では時間を 00:00:00 として扱い、月末のデータの取得に失敗する可能性が高いから。Rails console で確認すると、以下のようになります。

pry(1.9.3-p194)> 1.month.ago.end_of_month
# => Fri, 31 Aug 2012 23:59:59 JST +09:00
pry(1.9.3-p194)> Date.today.prev_month.end_of_month.to_time
# => 2012-08-31 00:00:00 +0900

上記は二つとも「先月末の月の終わり」を検索していますが、後者では時間が 00:00:00 になっています。例えば以下のような Mongoid でのクエリでは、8月31日の午前0時0分1秒以降に作成された Document を取得することが出来ません。ナンテコッタイ!!!

Model.where(:created_at.lte => Date.today.prev_month.end_of_month)

Date.today を時刻の生成の起点にしたとしても、to_time してあげればいいのでは?」と思う方もいるでしょう。確認してみましょう。

pry(1.9.3-p194)> Date.today.prev_month.end_of_month.to_datetime
# => Fri, 31 Aug 2012 00:00:00 +0000

#prev_month メソッドが呼び出された時点のオブジェクトの型は Date 型なので、Date 型に対して時間の操作を行って最後に DateTime 型に

結論

時刻まで考慮した時間の範囲でクエリを作るときは以下に留意すると良いでしょう。

  • Date.today は使わない
  • DateTime.now1.month.ago などを使う

| @技術/プログラミング

ここにはっつけるコードのシンタックスハイライトには Google Code Prettify をこれまで使ってたんですけど、どうもいまいちでした。有名な SyntaxHighlighter も好きになれなかった。はてなブログのように綺麗なシンタックスハイライトさせたい! ということで作った。

かなりシャレオツな感じにシンタックスハイライトできるようになったと思います。拾ってきた Monokai スタイルの CSS を当てています。

動作環境

裏側で使っているのは Python の Pygments。JavaScript オンリーで色付けするやつよりもこいつの方が圧倒的に綺麗でした。なのでこのプラグインを使うには Python と Pygments が必要です。Heroku では動くんでしょうか。動作未確認です。

使い方

HTML の pre タグのクラス名を lexer として Pygments に渡します。Ruby のコードを書くのであれば以下のようにします。

<pre class="ruby">
  <code>
  class Book
    def off
      "all your book is 10 yen"
    end
  end
  </code>
</pre>

やってること

JavaScript で pre タグを探してサーバーにコードの中身と pre タグのクラス名を投げると、Pygmentize された HTML が返ってくるようになっております。そいつを JavaScript で拾って pre タグの中身を入れ替え。

当初は

```ruby
class Book
  def off
    "all your book is 10 yen"
  end
end
```

みたいな感じで GitHub 風にしたいと思っていて、以下のような JavaScript を書いていたんですが JavaScript 力が低すぎて断念。

$('.body').each(function() {

  var Pygmentize = function(lexar, snippet) {
    var result;

    $.ajax({
      type: 'POST',
      url: '/pygmentize',
      async: false,
      data: {
        lexar: lexar,
        snippet: snippet
      },
    }).done(function(data) {
      result = data;
    });

    return result;
  }

  var entryBody = $(this).text();

  entryBody = entryBody.replace(/```(.+?) ([sS]*?)```/g,
    function(whole, lexar, snippet) {
      return Pygmentize(lexar, snippet);
    }
  );

  $(this).html(entryBody);
})

※Ajax なのに async: false とかしててイマイチ感ありますね。

とはいえ、汎用性の高い pre タグのクラス名を拾ってくる、という形での実装にしたので、 Markdown でなくても HTML でも Textile でもハイライトできるので結果オーライとします。

ちなみに Kramdown でクラス名を指定したいときは以下のようにするみたいです。

> hogehoge
{: .hoge }

| @技術/プログラミング

RSense という Ruby のプログラムを書いているときに、レシーバの型に応じた補完候補を表示してくれるソフトがあります。Emacs とか Vim と組み合わせて使うと便利らしいです。Java で IDE 使って開発すると補完候補がわさわさ出てきて殆ど鼻くそほじってるだけでプログラミングできるという話を聞いたので、Ruby でも鼻くそほじりながらプログラミングしたいなと思ってこいつを導入してみることにしました。春頃やったときはなかなかうまく Vim から使うことが出来なくて諦めてたんだけど 、つい最近できるようになったのでやり方をメモっておきます。

Mac でのお話です

前提条件ですが、Mac で使ってます。環境は Homebrew で構築してます。また RSense を使うには Java Runtime Environment が必要です。あなたと Java

RSense のインストール

JRE のインストールは済んでいるものとします。Homebre で RSense をインストールしましょう。簡単です。

brew install rsense

インストールが済んだら以下のようなメッセージが表示されると思うので、指示に従いましょう。

If this is your first install, create default config file:
    ruby /usr/local/Cellar/rsense/0.3/libexec/etc/config.rb > ~/.rsense

すると ~/.rsense というファイルが作られ、中身は以下のようになっています。

home = /usr/local/Cellar/rsense/0.3/libexec
load-path = /Users/morygonzalez/.rbenv/versions/1.9.3-p194/lib/ruby/site_ruby/1.9.1:/Users/morygonzalez/.rbenv/versions/1.9.3-p194/lib/ruby/site_ruby/1.9.1/x86_64-darwin11.4.0:/Users/morygonzalez/.rbenv/versions/1.9.3-p194/lib/ruby/site_ruby:/Users/morygonzalez/.rbenv/versions/1.9.3-p194/lib/ruby/vendor_ruby/1.9.1:/Users/morygonzalez/.rbenv/versions/1.9.3-p194/lib/ruby/vendor_ruby/1.9.1/x86_64-darwin11.4.0:/Users/morygonzalez/.rbenv/versions/1.9.3-p194/lib/ruby/vendor_ruby:/Users/morygonzalez/.rbenv/versions/1.9.3-p194/lib/ruby/1.9.1:/Users/morygonzalez/.rbenv/versions/1.9.3-p194/lib/ruby/1.9.1/x86_64-darwin11.4.0
gem-path = /Users/morygonzalez/.rbenv/versions/1.9.3-p194/lib/ruby/gems/1.9.1:/Users/morygonzalez/.gem/ruby/1.9.1

rbenv 使ってる人は load-path にちゃんと rbenv のパスが含まれているか確認して下さい。

Vim の設定

このままではまだ RSense がインストールされただけで、Vim から利用することができません。Homebrew で入れた RSense には rsense.vim がついてくるので、こいつを Vim の plugin ディレクトリにコピーします。

cp /usr/local/Cellar/rsense/0.3/libexec/etc/rsense.vim ~/.vim/plugin/

次に .vimrc で rsenseHome を指定しなければなりません。

let g:rsenseHome = "RSense home"

と書きます。僕はこの rsenseHome が分からなくてハマりました。先ほどの config.rb を実行したときに生成された ~/.rsense に書いてある home をここに指定します。なので rsenseHome は /usr/local/Cellar/rsense/0.3/libexec です。

ここまで済んだところで Vim から RSense が認識されているか確かめます。適当に Vim を起動して :se ft=ruby とし、:RSenseVersion とコマンドを打ってみます。ここで RSense 0.3 のように成功されたら設定完了です。filetype が ruby になっているファイルで 1. と打った後、補完候補を呼び出すコマンド(^X ^U)で候補を呼び出せます。以下のような感じ。

8da56d016a74ebc9d38afcf593bfeadd.png (200×116)

“ネオコン” と連携させましょう

さらに言うと、たいていの Vim ユーザーの皆さんは neocomplcache も使ってるでしょうから、neocomplcache と RSense を連携させましょう。ネオコン作者の Shougo さんのブログ記事を参考にして下さい。

以上で完了です。これで Vim で Ruby な皆さんも鼻くそほじりながらプログラミングできますね。

| @技術/プログラミング

今年の3月くらいから、寿限無の和田さんが発起人になって Fukuoka.rb という勉強会をやってる。毎週木曜の 19:30 からで、ペ社は会場を提供している。勉強会と言ってもやってることは技術書の輪読で、最初は『メタプログラミング Ruby』を読んだ。メタプログラミング Ruby は中級者以上向けの本でなかなかレベルが高く、当初は 30人ちかくいた参加者が回を重ねるごとに減っていき、最後は5, 6人くらいしか参加者がいなかったけれども、歯を食いしばって出席し続けた。簡潔に書ける、美しいコードが書ける、という以上のことができる Ruby の側面を学んだと思う。いまは二冊目の課題図書として洋書の『Eloquent Ruby』を読んでいる。

福岡でやってる Ruby の勉強会、何回か出たことあるけど、Rails ハンズオンみたいな初心者向けの内容だったり技術より精神面を重視した内容だったりで個人的には消化不良な感じがあった。また開催が不定期で、プログラマ同士の情報交換がしにくいと感じていた。

Fukuoka.rb は原則的に毎週開催で、扱う内容も初心者よりというよりは中上級者向けで、本を読みながら喧々諤々とした議論も繰り広げられるし、自分はあまり参加しないのだけど勉強会の後はみんなで飲みに行ったりもする。業務で感じていた疑問を詳しい人に尋ねたり情報交換しやすい。

個人的には、中学生の頃に通っていた隣町の塾を思い出す。自分は田舎に住んでいたので、都会の塾に行くだけでレベルの高さに驚くとともに刺激を受けて、都会っ子に追いつこうと勉強を頑張った。Fukuoka.rb は参加者のレベルが高く、なかなかついて行くのが大変なのだけど、確実に Ruby 力が高まっていると思うし、出てて良かったと感じる。

Asakusa.rb や Yokohama.rb のような Ruby コミュニティをずっとうらやましく思っていたけど、これらに近い Ruby コミュニティが福岡にできつつあると思う。時々は Ruby コミッターの @nagachika さんも参加している。福岡在住の Ruby プログラマで腕に覚えがある人は、是非毎週木曜日に天神プライムビル8階で開催されている Fukuoka.rb にお越しください。面白くしていきましょう。