motion-modeについて #rubymotion


motion-modeについて

RubyMotion用emacsメジャーモードのmotion-mode、3月から地道に機能を実装しましたが、けっこういい感じに機能が揃ってきたのではないかと思いまして。改めて、解説記事書きます。

ainame/motion-mode

今回、motion-upgrade-major-mode-if-motion-projectとかいう長ったらしい名前だったhook用関数をmotion-recognize-projectという名前に変更したので、今まで利用していた方は設定の修正をお願いします。

(add-hook 'ruby-mode-hook 'motion-recognize-project)

インストール方法

ついに、package.el経由でインストールできるようになりました。

https://github.com/milkypostman/melpa/pull/758

MELPAのリポジトリにpull reqしてパッケージを追加してもらいました。MELPAを設定に追加して、M-x pakage-list-packageを使うだけで、motion-modeを導入出来ます。

Emacs24なら以下のコードをinit.elとかに書いておきます。Emacs23以下ならpackage.elをググって適当に入れて下さい。

(require 'package)
(add-to-list 'package-archives '("melpa" . "http://melpa.milkbox.net/packages/") t)
(package-initialize)

そのあと、M-x package-list-packageを起動して、表示されるメニューの中から、motion-modeを探して、iでマークを付けてxでインストールしちゃって下さい。

辞書ファイルの設定方法

motion-modeがインストールされたディレクトリまで移動して、make_dict.rbに対して、iOS SDKのヘッダーファイルがあるディレクトのfind結果を渡してやると、同じディレクトリにmotion-modeという辞書ファイルが作成されるので、auto-complete-modeで指定されている辞書の置き場に、そのファイルを設置してやると、motion-modeでファイルを開いた際に、辞書に含まれる単語を補完できます。

$ cd ~/.emacs.d/elpa/motion-mode/
$ find /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS6.1.sdk/System/Library/Frameworks -name "*.h" | xargs ruby bin/make_dict.rb
$ cp ./motion-mode ~/.emacs.d/ac-dict
$ emacs ~/.emacs.d/init.el # add following setting
(add-to-list 'load-path "~/.emacs.d/elisp/motion-mode")
(require 'motion-mode)
;; following adding of hook is very important.
(add-hook 'ruby-mode-hook 'motion-recognize-project)
(add-to-list 'ac-modes 'motion-mode)
(add-to-list 'ac-sources 'ac-source-dictionary)
;; set keybindings as you like
(define-key motion-mode-map (kbd "C-c C-c") 'motion-execute-rake)
(define-key motion-mode-map (kbd "C-c C-d") 'motion-dash-at-point)

機能紹介

motion-modeは、基本的にruby-modeの設定を受け継いで作成しているメジャーモードです。なので、SyntaxHighlight等はruby-modeのままです。 その他にもいろいろ機能があります。

1. RubyMotionプロジェクトかどうかを認識する

これがまずいちばん最初に実装した機能で、これによって、*.rbという拡張子のファイルを開いた時にただのRubyだったら、ruby-modeでファイルを開き、RubyMotionのプロジェクト内のファイルだったら、motion-modeでファイルを開くことができます。

Emacsでは、拡張に関する設定はメジャーモード毎に持てるため、motion-modeでファイルを開けるようになると、それに付随する様々な設定がmotion-mode専用に使えるようになります。

たとえば、キーバインドの設定は、motion-mode専用の物を設定したあとに、他のモードでファイルを開いても他のモードで開いたバッファにはキーバインドの設定は影響を及ぼしません。

なので、Emacsで特定の環境専用の拡張を書こうとしたら、どのタイミングで専用のmajor-modeとしてファイルを開くのかが最初のポイントなのかも。

最初、git rev-parseコマンドに依存した実装を使っていたのですが、syohexさんにリファクタした差分をpull requestしてもらい、gitに依存せずに利用することが出来ました。ありがとうございます!!!

2. auto-complete-modeによる辞書補完

これはひとえに、auto-complete-modeすげーっていうことではあるのですが、auto-complete-modeではメジャーモードに応じた辞書ファイルの読み込み+辞書補完が出来るため、github上のyasObjcというスクリプトを流用して、iOS SDKのヘッダーファイルから辞書を作り出す、make_dict.rbというスクリプトを作って対応しました。

ただ、今のところiOS SDKのヘッダーファイルに存在するクラス名、メソッド名だけっぽいので、Objective-Cに標準で存在するクラスなどの単語も辞書化出来るように改良の余地があるかなと思います。

3. rakeタスクの実行サポート

motion-execute-rakeというコマンドを実装しました。これを好きなキーバインドに割り当てると(デフォルトではキーバインドは用意していないので)、Emacs内からrakeタスクが実行できるようになります。C-c C-cがおすすめです。

単に、C-c C-cで実行すると、そのままrakeが実行され、C-uのprefixをつけて実行すると(つまりC-u C-c C-c)、ミニバッファにrakeのサブコマンドの入力を促すプロンプトが現れ、rake specなどが実行できるようになります。

4. Interactive Debuggerの操作 in Emacs

3のrakeタスクでデフォルトで実行される”rake”コマンドで、ビルドされ、その後のInteractive Debugger用のコンソールをEmacs上で操作出来ます。

3も4も、comint-modeってのを使ってます。

5. flymakeによる構文チェック

flymake自体はEmacs標準の構文チェック用の機能で、motion-mode上でも利用できるように対応しました。macruby -cを利用してエラーをチェックしています。

この対応の実装のためにflymake-easy(簡単にflymake対応するためのライブラリ)とflymake-cursor(エラー箇所にカーソルを合わせるとエラー内容がミニバッファに表示される)という拡張を使っています。

flymakeが嫌いな人はmotion-flymakeという変数にnilを設定すると、flymakeを利用しなくなります。

(setq motion-flymake nil)

6. Dash.appによるドキュメント検索

Dash.appって使ってますか?基本無料(時たま課金を促す表示が出る)で、いろいろな言語とかフレームワークのドキュメントがさくさく(ネットでググるよりレスポンスが良い)調べられてすごく好きです。

このアプリで、RubyMotionのドキュメントも検索出来るのですが、IDEみたいに簡単にドキュメント引けたらいいなと思い、カーソル上の単語にたいして、motion-dash-at-pointを実行するとそのままDash.appで単語の内容を検索できるようにしました。適当にキーバインドを割り当てるとだいぶ良い感じです。

これにはOS Xのopenコマンドを使って以下の様なスキーマで検索してます。

open dash://rubuymotion:hoge_keywords

7. Objective-Cの呼び出し形式からRuby形式にコードを変換

Watsonさんとnaoyaさんに煽られて、kyamaguchi/SublimeObjC2RubyMotionをEmacsに移植した機能になります。

以下の様なObjective-Cのコードを

_window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.window.rootViewController = self.myNavController;
[self.window makeKeyAndVisible];

以下の様なRuby形式の呼び出しに変換する機能です。

_window = UIWindow.alloc.initWithFrame(UIScreen.mainScreen.bounds)
self.window.rootViewController = self.myNavController
self.window.makeKeyAndVisible

元の拡張はSublime Text用だったのでpythonで書かれておりましたが、pythonに依存したくないため、Rubyで書きなおして(RubyならばRubyMotion利用者は利用できる前提)、Emacsから呼び出すようにしました。使用する時は、バッファー内で範囲を選択して、M-x motion-convert-code-regionを 呼び出すと選択部分が変換されます。

shell-command-on-regionという選択範囲を外部コマンドの標準入力に投げて出力をバッファに挿入するコマンドを利用しています。

おわりに

当初、RubyでiOS開発してみたいがためにRubyMotionを購入しました。いざemacsでコード書こうと思ったら、Emacsってそんなに書きやすい環境ではないな、と思ってちょっとした拡張書いてみようと思ったところからmotion-modeの開発が始まりました。

その後naoyaさんとかwatsonさんに煽られ、機能追加したりして、なりゆきで煽られ駆動開発していたら自分自身全然iOSアプリ書けないけど拡張書くみたいな人になっちゃって良くないなぁと思いました。

ということで最近は、まずiOS開発そのものを学ぶため詳解Objetive-CとかUIKit詳解リファレンスを読んだり、 最近ちょっと話題になっているミクシィ社のiOS開発研修資料を元にRubyMotionでコードを書いたりして勉強しております。

あと、github上の英語のREADME.md、TOEIC400点台の英語力で書いたのでおかしい所あれば直していただけるとすごく嬉しいです…

Perlの文法について


# 雑記です。

最近、Perlについて調べることが多い。 今年の頭にTokyoRuby会議で、自分は会社ではPerlを書き、家ではRubyを書く(すなわち家では一切Perlを書かない)みたいなことを対外的に発表したのが嘘みたいなぐらい最近Ruby書いていない。

昨年、Perlの会社に入ってPerlを覚えてPerlを書いて、Rubyの経験があったおかげかそんなに苦労せず社内で社内フレームワークに乗った開発を普通にするには問題ない程度に習得できたのではないかと思う。

ただ、CPANに置かれるようなモジュールだったり、社外でも使えるようなものを、とか、社内のコアなモジュールを弄ろうとか考えだすと、やっぱり今の知識だけでは全然足りないなと思って、最近は少しでも疑問を持ったらPerlの仕様からちゃんと 理解するようにしとようと考えている。

なぜそういう風にしようかと言うと、Rubyにおいて自分は同じ様な事をして自分の中での理解が大分進んだところがあったからである。 (Rubyの時はメタプログラミングRubyを読んでいろいろと捗るようになりました。)

そんな中で最近カルチャーショックを受けたこととして、Perlの正規表現周りの扱いである。 発端としては、正規表現のパターンを返すメソッドget_xxxx_regexみたいなものがあって、そのget_xxx_regexメソッドを別のモジュールに移動する際に新たにテストケースを書こうとして返り値の一致を確かめようと 以下の様なテストを書いたが通らなくてなんだろうと調べはじめたことだった。

sub get_xxx_regex {
    return "[pattern]*"; # 例なので適当です
}

my $pattern = get_xxx_regex;
is $pattern, qr/[pattern]*/; # not ok
ok "pattern" =~ $pattern;    # ok

そもそもこのメソッドget_xxx_regexは、最初はxxxに関する正規表現のパターンが返るもんかと思って上のようなテストを書いたのだけど、よく見るとただの文字列だったから比較のテストが通らないのは分かるんだけど、下の正規表現によるマッチが、エラーにならず通るのはなんでだろうと。($patternはただの文字列なのになんでマッチするのか)

(初めてがっつり勉強した言語がRubyなのでなんでもRubyで考えてしまうけど)例えばRubyだと、// って表記は、正規表現リテラルでRegexpクラスのインスタンスを生成しても実態は変わらないんだよ =~ ってのはRegexpのインスタンスメソッドの糖衣構文だから /pattern/.=~(string)と同じだよって、って説明のされ方はすごくわかりやすくて自分の頭のなかですっと理解できた。

そんな全てがオブジェクトな世界のメンタルモデルで生きていると、Perlの正規表現が以上に難しく思えてきて、例えば =~ ってのは何かに属しているメソッドではなくて、拘束演算子と呼ばれるもので、拘束演算子ってのはperldoc.jpから引用すると以下の様な挙動になっている。

二項演算子の “=~” は、スカラ式をパターンマッチに拘束します。 デフォルトで $_ の文字列を検索したり、変更したりする演算があります。 この演算子は、そのような演算を他の文字列に対して行なわせるようにするものです。 右引数は、検索パターン、置換、文字変換のいずれかです。 左引数は、デフォルトの $_ の代わりに検索、置換、文字変換の対象となるものです。 スカラコンテキストで使うと、返り値は一般的に演算の結果が成功したか否かです。 例外は、/r (非破壊) オプション付きの置換 (s///) と文字変換 (y///) です; この場合は変換した結果を返します。 リストコンテキストでの振る舞いは演算子に依存します。 詳しくは “Regexp Quote-Like Operators” を、これらの演算子を使った 例については perlretut を参照して下さい。

右引数が検索パターン、置換、文字変換ではなく、式であれば、 それは実行時に決まる検索パターンと解釈されます。 これは、内容が 2 回展開されることを意味することに注意してください; つまり:

‘\’ =~ q’\’; は正しくありません; 正規表現エンジンは最終的にパターン \ を コンパイルしようとして、これは文法エラーと考えるからです。

二項演算子の “!~” は、返される値が論理否定されることを除いて “=~” と同じです。

二項演算子の “!~” を非破壊置換 (s///r) や変換 (y///r) で使うと 文法エラーとなります。

perlop – Perl の演算子と優先順位 – perldoc.jp http://perldoc.jp/docs/perl/5.16.1/perlop.pod#Binding32Operators より

で、とりあえずこういう挙動になっているらしいけど、これをパッと見た時、上で示したような挙動が「> 右引数が検索パターン、置換、文字変換ではなく、式であれば、 それは実行時に決まる検索パターンと解釈されます。 これは、内容が 2 回展開されることを意味することに注意してください; つまり:」部分で示されていることに気づかず、なんだここに書いてないんじゃないかと思ってprogramming perlまで読みに行ってしまった。(プログラミングPerlの邦訳を早く電子書籍として配信して欲しい。)

programming perlを読んでみると、上の説明に加えてちゃんと「That is to say $_ =~ $pat is equivalent to $_ =~ /$pat/ 」って書いてあって=~の右項に式が来たら式が、正規表現の検索パターンの中に展開されたものとして評価されるということが分かった。

最初にperldocの説明がなんで理解できなかったかと考えると、「検索パターン、置換、文字列変換」って訳されていたものはm//、s///, tr///のパターンマッチ演算子でクオートされた文字列のことで、自分の中のメンタルモデルではそれが認識できてなかったみたいだった。

そんなこんなで、最初はPerlとRuby大分似てるしRubyやってたらPerlも出来るようになるかな〜みたいな甘い考えで生きてきたのですが、暗黙的な挙動がかなり多いため、Perlを真に使いこなすためにはやっぱりPerlの仕様をガッツリ覚え無いと難しいんだな〜と思ったGWでした。

正規表現周りで言うと、Perlの正規表現リテラルの中でどうやって文法の曖昧さを解決するのかって話がすごく興味深かったです。仮に自分がプログラミング言語作るんだったらこういうことはしたくないな〜って感じの実装でした。ぜひ併せてお読み下さい。

意識が高まりゆき、Test::More::Hooksというモジュールかいた #perl


先日から社内で、今年度の新卒向けにテストの講師やってくださいと仰せつかり、 別に誰かに強制されたわけではないのですが、去年までの講義資料だとチュートリアル的な感じで終始してしまったいたので、 資料をスクラッチで書き始めてしまい、しばらく苦しみが続きましたが、そこそこ体系的に知識突っ込めたような気がします。 Perl Advent Calendar 2011 Test Trackとか,tokuhiromさんのPerl テスティングハンドブック読んだりしましたし、 Perlだけじゃなくてユニットテスト全般の話をしたかったので、Junit実践入門読んだり、レガシーコード改善ガイドとか、 The RSpec Book読んだりしました。

そんな中、Perlでユニットテスト書くのってどうするのが最強なんだ?って言う疑問がすごいあって、 Test::Classが最強なんじゃないかと思ったりしたのですが、それでもみんなTest::Moreのsubtestを 使うという現実があり、また、subtestに嫌気を指したRSpec loverな人たちが、Test::Moreのラッパーのような モジュールを作り出しているものの、別に使いたいとあまり思えず(なぜなら本当にただのラッパーなので)という現実があり、 個人的にすごくモヤモヤし続けています。

そこで先日、Test::Moreのsubtestのテストはどう書くのが一番きれいなのか という記事を書いてみたら、lestrratさんやtokuhiromさんから返信があり、 世間のPerl Mongerな方々はsetup/teardownの代わりにGuardオブジェクト使ってるよ!とか、 t/Uitl.tに便利な奴入れてるよという話があった。

しかし、自分の中の気持ちとしては、テストを書くためにScope::Guardというモジュールを使うことで、 既存の資産でsetup/teardownが実現できるものの、若干テストが分かりづらくなる懸念があり、 (そんなに気にする必要はないかもしれないけど、誰もがScope::Guard使いこなせるわけではないと思う。)、 また、t/Util.tのようななんでも入りそうなファイルというのは100人規模で1つのPerlのコードベースを触るような、 狂気の環境においては、ファイルの設置場所として辛さがあるし、またファイルが適切になったとしても、 結局Guardオブジェクト問題があったり、$MOCKのような暗黙知的な変数は何か苦手だった。

やっぱり、subtest内にmy $setup = sub {..};とか書いて、毎回呼び出すのが一番気軽で分かりやすいだろう! と思っていたのですが、実際にコード内で多用してみると、明示的にsetupのコード呼び出し続けるのが やっぱりめんどくさくなってきてしまいました。

use strict;
use warnings;
 
use Test::Pretty;
use Test::More;
use Test::Warn;
 
my $class;
BEGIN {
    $class = "Bowling::Scorer";
    use_ok $class;
}
 
subtest "#new" => sub {
    my $subject = $class->new;
    isa_ok $subject, $class;
};
 
subtest "#calc" => sub {
    my $subject;
    my $setup = sub { $subject = $class->new };
    my $teardown = sub { $subject = undef };
 
    subtest "when calculate 1 frame score" => sub {
        subtest "given no result" => sub {
            $setup->();
            is $subject->calc(), 0,
                "it should return 0.";
            $teardown->();
        };
 
        subtest "given 1 roll" => sub {
            $setup->();
 
            is $subject->calc("1"), 1;
 
            $teardown->();
        };
 
        subtest "given 2 roll" => sub {
            $setup->();
 
            is $subject->calc("17"), 8;
 
            $teardown->();
        };
 
        subtest "given strike" => sub {
            $setup->();
 
            my $actual;
            warning_is { $actual = $subject->calc("X"); } "Score can't be determined.";
            is $actual, undef;
 
            $teardown->();
        };
 
        subtest "given spare" => sub {
            $setup->();
 
            my $actual;
            warning_is { $actual = $subject->calc("28"); } "Score can't be determined.";
            is $actual, undef;
 
            $teardown->();
        };
 
        subtest "given miss" => sub {
            $setup->();
 
            is $subject->calc("--"), 0;
 
            $teardown->();
        };
    };
 
};
 
done_testing;

これはもう何か自作するしか無いだろうと昨晩ふと意識が高まりコード書いてみました。 ainame/p5-Test-More-Hooks · GitHub

CPANにコードを置くための知識がないため,ご覧のとおりコード以外まだ何も整ってませんが、以下の様なことができます。

use strict;
use warnings;
 
use Test::More;
use Test::More::Hooks;
 
subtest "xxxxxxxxxxx" => sub {
    my $subject;
    before { $subject = Foo->new; };
    after  { undef $subject; };
 
    subtest "ooooooo" => sub {
        isa_ok $subject, 'Foo';
    };
 
    subtest "ooooooo" => sub {
        can_ok $subject, 'bar';
    };
};
 
done_testing;

RSpecパクリですが、subtestの中のCODEREFの先頭でbefore/afterをBLOCKで定義するだけで、 同じスコープの中で呼び出される全てのsubtestの中で、before/afterが実行されるようになります。 実装はとてもシンプルで、subtestを再定義して、本来のsubtestを呼び出す前と後に、beforeとafterで 定義したものを呼び出すだけです。subtestのネスト構造に対応するために、$Test::More::Hooks::Levelという グローバル変数を持ってネストの深さ毎にCODEREFを保存しています。(Levelはourで公開すべきではないかも?) 上書きをするために、use Test::More;を読んでから、use Test::More::Hooks;を呼ぶのが必須です。

pros

  • Test::Moreをそのまま使える
  • before/afterとわかり易い名前なので動作が直感的
  • フックポイントを設けてるだけなので余計なことは何もしない(他のRSpec likeなモジュールはいろいろ機能ついてる)
  • きちんとした名前がついたモジュールになっていてCPAN化(予定)なので、他の人にも使ってもらいやすい

cons

  • いちいちuseするのダルい
  • before/afterは名前が気に食わない人には向かない

どうでしょうか!!

Test::Moreのsubtestのテストはどう書くのが一番きれいなのか #perl


Perlでユニットテストを書いているといつもどうやって書くか迷う。

自分のよくやるやり方は、とりあえず弊社内の風潮に合わせてTest::Moreが多いので、 Test::Moreを使うとして、そっからsubtestでテストケースを クラス中のメソッドごとにわけて、さらにsubtestで前提条件毎に分けて、 その上で書く入力毎にok, is, is_deeply, dies_ok, lives_ok等々で 比較していくっていう方式で書いている。RSpec風?

subtest "foo_method" => sub {
    my $subject = Bar->new;

    subtest "A context" => sub {
        subtest "given xxx arguments" => sub {
            my $actual = $subject->foo_method;
            is $actual, $expect, "actual is expect";
        };
    };

    subtest "B context" => sub {
        subtest "given xxx arguments" => sub {
            $subject->baz_method;
            my $actual = $subject->foo_method;
            is $actual, $expect, "actual is expect";
        };
    };

    ....
};

こうやって書くと、$subjectのfoo_methodが副作用を持ってると、 A contextでfoo_methodを実行すると、B contextでは$subjectの状態が変わってしまうので困ることになるので、 いつも一番内側のsubtestでテスト対象クラスののインスタンスを生成していたりするのだけど、さすがにめんどくなってきた。

Test::Moreは、単純にコードを上から下に実行していくだけっぽいし、 他の言語のテスティングフレームワークのようにsetup/teardownの仕組みがない。 そのせいか、テストファイルごとにトップレベルにテスト共通で使う変数(Test::MockObject等)をバーっと定義して、 それをずっと使いまわすって書き方をよく見る。

my $mock = Test::MockObject->new;
...

subtest "foo_method" => sub {
    my $actual = SubjectClass->new->foo_method($mock);
};

subtest "bar_method" => sub {
    my $actual = SubjectClass->new->bar_method($mock);
};

みたいな。だけど、個人的には共通で使いまわす変数の状態が把握しづらくなるのでちょっと気持ち悪い。 $mockが変更なければ良いけど、途中でmockの内容変えたりするとなんだか辛い。

なので、グローバル変数祭にせずに、共通処理を効率良く使えるようにcoderefを使って 擬似的に他のテスティングフレームワークのsetup/teardownっぽいものを導入してみる。

subtest "foo_method" => sub {
    subtest "A context" => sub {
        my $subject;
        my $setup = sub { $subject = Bar->new };
        my $teardown = sub { $subject = undef };

        subtest "given xxxx arguments" => sub {
            $setup->();

            my $actual = $subject->foo_method;
            is $actual, $expect, "actual is expect";

            $teardown->();
        };
    };

    subtest "B context" => sub {
        my $subject;
        my $setup = sub { $subject = Bar->new };
        my $teardown = sub { $subject = undef };

        subtest "given xxxx arguments" => sub {
            $setup->();

            $subject->baz_method;
            my $actual = $subject->foo_method;
            is $actual, $expect, "actual is expect";

           $teardown->();
        };
    };

    ....
};

setup/teardownは、それぞれテストの前処理/後処理で、テスト毎に 実行されます。このテストでは以下の4つのフェーズを意識して書いてます。

  1. 事前準備(set up)
  2. 実行(execrcise)
  3. 検証(verify)
  4. 後処理(tear down)

このように4つのフェーズで記述していくテスト形式を、 4フェーズテストと呼ぶそうです。(JUnit実践入門より)

しかし、これだと一つのクラスのテストをするときに、 メソッド毎に同じような条件でテストする場合があるので、 setup/teardownの定義が重複しまくってしまうことが想定される。

したがって現状自分の中で、こう書くといいんじゃないか?と考えているのは以下の形式です。

subtest "A context" => sub {
    my $subject;
    my $setup = sub { $subject = Bar->new };
    my $teardown = sub { $subject = undef };

    subtest "foo_method" => sub {
        subtest "given xxxx arguments" => sub {
            $setup->();

            my $actual = $subject->foo_method;
            is $actual, $expect, "actual is expect";

            $teardown->();
        };
    };

    subtest "baz_method" => sub {
        subtest "given xxxx arguments" => sub {
            $setup->();

            my $actual = $subject->baz_method;
            is $actual, $expect, "actual is expect";

            $teardown->();
        };
    };

    ....
};

subtest "B context" => sub {
    ....
};

この書き方は、テストをオブジェクトのコンテキスト毎に区切って、 その中にsetup/teardown処理を書き、その中でメソッドごとの テストケースを並べていくという方式。こうすると、setup/teardownは コンテキスト毎に1つの定義で済む?まだ試してないですが何となくよさそうな気がします。 ちなみに、Rubyの話ですが、takaiさんのRSpecの書き方がこんな感じでした。 RSpecによるユニットテストの書き方 – tech.recompile.net

どうでしょうか?Perl Mongerの方々はみなさんどうやってテスト書いてるんですかね。 普段Perlの勉強しなさすぎてまだ良くわかってないです…

自分は、subtestの記述力は良いと思いますですが、JUnit実践入門を読み始めてみたら、 Test::Classも悪くないんじゃないかな〜と思い始めてきました。そのうちTest::Classのテストの 書き方もちょっと調べてみます。

RubyMotion用のmotion-mode.elを作った


Emacsのメジャーモードとしてmotion-modeを作りました。

ainame/motion-mode · GitHub

emacsでRubyMotionのコードを書くときに、各種メソッド名とかクラス名をシンボル補完したいという 思いがあっていろいろ調べてみて, (e|ctags)でやるとかyasnippet用のsnippetを作ってみるってのを試してみましたが 重いしイマイチ使い心地良くなかったです。

そこで、auto-completeの辞書補完使って補完をやってみたのですが、ヘッダーファイルから抜き出した4942個の単語を辞書に追加しても 補完自体はだいぶスムーズに行われて(候補が多いので結局絞り込むのが大変かもだけど)良い感じだったので、 最終的にRubyMotionのプロジェクトのディレクトリのファイルかどうかをチェックして、 RubyMotionのコードの時だけ、motion-modeでファイルを開くことが出来るようにしてみました。

motion-mode自体は全然機能を持ってなくて、基本的にはruby-modeの派生として作ってあるため、 ruby-modeのシンタックスハイライトとかインデントとかそのまま使います。

以下のコードで、リポジトリの中のRakefileを取り出して、中にMotion::Project::Appという、 文字列があるかどうかで、RubyMotionかどうかを判定しております。

(defun motion-get-rakefile-content ()
  (shell-command-to-string
   (format "cat git ls-files $(git rev-parse --show-toplevel) | grep Rakefile | head -1")))
(defun motion-detect-motion-project ()
  (with-temp-buffer
    (insert (motion-get-rakefile-content))
    (goto-char (point-min))
    (search-forward "Motion::Project::App" nil t)))

↓こんな感じでそれっぽい感じには補完される。でもオムニ補完じゃないのであくまでもtypoを防ぐための補完、って感じがする。 しかし昔はtypoがかなり多くて作業がはかどらなかったのでこれだけ出来れば十分嬉しいかも。

正直、Sublime Text2の拡張のほうがもっとリッチに補完できるみたいなのですが、 それでもemacs自体が手に馴染みすぎてまだ移行する気分にはなれませんでした(老害)。

あとは、キーバインド作って一発でrake出来るようになったら嬉しいかもと思ってます。

jQuery読み会を開いた #jquery_yomikai


jQuery読み会をやった

経緯はどこまで話していいのかわからないのでぼかしておきますが、 要約すると以下のようなものになります。

会社ではサーバーサイドをやっていて毎日Perlを書いているのだけど、 さすがに毎日Perlを書くのは飽きてくるので、気分を変えたいと思って、 普段全然書く機会がないJavaScriptを書きたいなーと思っていたら、 JavaScript委員会(see also javascript advent calendar)に入ることになり、 JS力を上げるためにとりあえずjQuery読み会を開いてみた。

いつもどおりzusaarを使って募集しました。便利ですね。 jQuery読み会 on Zusaar

読み進める方針

  • githubから最新のコードをcloneしてくる(2.0.0 preだった)
  • とりあえず、src/core.jsがメインっぽいので最初に読む
  • クエリセレクターのsizzile.jsはとりあえず後回し
  • ブラウザ依存のバグ回避系のコードを理解するの大変そうなので無視(あとから追加)
  • 意味不明なコードが出たらblameして歴史を紐解いてみる
  • github上に読むファイルをコミットしてコミットページにコメントを残して貰う

ということでsrc/core.jsを読んでみました。

src/core.jsとは

JavaScriptのライブラリを読むのは初めてだったので、 JavaScriptのライブラリの流儀は知らないけど、core.jsがメインなソースっぽい。 主に$()の実装が行われていました。

メモ

印象に残ったことを挙げていきます。

  • 上のほうに変数がグローバルにバーっと定義されているが、gruntでbuildする際に即時関数で囲まれる
    • 上から読んでいくスタイルだと非常に読みづらい
    • core_xxx(pushとか)系の初期化は、Array.prototype.xxxとかと同じなのだろうけど、既存の配列の変数から参照を取得していて気持ち悪い
  • jQuery.fn.initについて
    • いわゆる$()が定義されている
    • jQuery.fnはjQuery.prototyeのショートカット
    • $()が呼ばれるたびにjQuery.fn.initオブジェクトをnewすることでjQueryオブジェクトが作られていく
    • 最後にreturn jQuery.makeArray( selector, this ); を呼んで配列っぽいインスタンスを返している
    • 第一引数がHTMLタグかどうかは正規表現を駆使してサッとチェックしている
  • ブラウザ個別対応について
    • 2.0からIE8.0以下の対応を切るっぽいjQuery 2.0 Beta 2 Released | Official jQuery Blog
    • parseJSONやparseXMLなどの処理がブラウザのサポート切ったことによって若干スッキリしている
      • JSONオブジェクトとかDOMParserが使える
    • parseXMLの// Support IE9というのはIE9をサポートするのではなくIE8以下を切り捨てる(unsupport)という意味だった
  • jQuery.isPlainObjectについて
    • リテラルで記述される or new Objectのような普通のオブジェクトかどうかを判定している
  • jQuery.proxyについて
    • Object.prototype.callと基本的な使い方は変わらないが、jQueryオブジェクトを返す
    • 独自に持つguidで、proxy前と後を比較できる
      • proxyされたものをさらにproxyする時とか
  • jQuery.accessについて
    • $().attrとかcssを実装するために// Multifunctional method to get and set values of a collection として実装されている
    • 引数多くてゆるふわな感じ
    • コードの行数減らすための工夫?かもしれないがだんだん引数の種類増えてやばくなってきている
    • // Getsに笑ったjquery/src/core.js GitHub
  • jQuery.isWindowsについて
    • windowはwindowというプロパティで自身の参照を持つ
  • jQuery.makeArrayについて
    • jQuery.mergeに第一引数を渡す際に、JSでは文字列も配列なためmergeで一文字ずつ配列の要素に分解されてしまうので[]で囲んでいる
  • isArraylike()について
    • 配列か、関数ではないけどobj.lengthが0か、数字かつ0以上勝つ、配列の最後の要素を持っているかどうかをチェック
  • jQuery.globalEvalについて
    • evalの呼び出しは直接的な呼び出しか、間接的な呼び出し(一度変数に代入して呼び出す)によって挙動が違う
      • ECMAScript5の仕様
  • jQuery.readyとかその辺り
    • Deferredによって初期化処理をいろいろやってくれる
    • Deferred読んだらまた読みましょう

変数宣言を怠けて前に使った変数を使いまわしたりみたいなコードが結構あった。 こういうのって、最初から人間がやると分かりづらくなるからオプティマイザが自動的にやってくれれば良いのに。って思ったりしました。 また、例外投げてもよさそうなところでも、とりあえずundefinedを返すとかいう場所が結構あったり 広く使われるライブラリなのであえて緩く作ってるのだろうか?

13時から18時半までガッツリ読んで、そのあとととしぐれで飲みました。

第2回、またやります。

東京Ruby会議で発表して来ました #tkrk10


 
今更感強いですか、先日の東京Ruby会議10にて「趣味とRubyと私」というゆるい内容にて発表して来ました。

去年の4月に社会人になってから定期的にRubyコミュニティに参加することで、 ここ1年で随分といろんな人に知り合うことができました。

これまでは、社会人にもなりたてだし、Webエンジニアとしてもへっぽこだったので、 自分から情報を発信していくことがなかなか出来ておりませんでしたが、 これからは周りの人達から受けた刺激を元により健やかに開発力を身につけ、 どんどん情報発信しつつ、楽しい開発生活が送れたら良いなと思います。

RubyMotionメモ


小一時間いろいろ調べたのでリンク集作ってみた。

2012年振り返り


2012年を振り返ります。

1月:

切羽つまりながら修論書いていた。卒業できるかどうか怪しく、辛かった。

2月:

修論の提出はしたものの、発表が待っていた。

3月

グダグダしてたら4月になってしまっていた気がする。 内定者向けインターンでPerlを書いていた気がする。

4月

入社した。社会人になった。 この頃から、shibuya.rbとshinjuku.rbに行くようになった気がする。

5月

研修していた。RubyのWAFリーディング勉強会とかやってた気がする。 Rubyのコードリーディング勉強会またやりたい。

6月

配属された。部署内でも研修をやった。 毎週、開発T内でKPTの振り返りを行うようになり、業務で細々としたことをいろいろやっていたせいで毎回なんらか のPやTを上げてみたが、あんまりうまく行ってなかったような気がする。

インターネット的なつながりのおかげで、udzuraさんのWEB+DB PRESSのRuby記事の査読をやらせてもらえたりした。 WEB+DB PRESS で連載します « blog.udzura.jp あとは、土日にぱちぱち会と称して、渋谷のどこかでプログラミングする会をやってた気がする。

6月頭に、初任給入ったということで、同期の勧めにより999.9でメガネ買った。 眼鏡のブランドの違いはよくわかってないけど、眼鏡市場で買ったメガネより遥かに掛けやすくてよかった。

7月

細かい案件を実装してリリースしたりHiveに初めて触れて解析したり。

8月

夏 初めてメインの開発担当で機能を作成してリリースした。 機能がどれだけシンプルでも、3デバイス同時開発・施策を実行するための裏側の処理、 ユーザの行動の解析まで考えると結構大変なんだなぁということが分かった。

このあたりで、MacbookAirを買った気がする。

9月

9月は、かなりHiveで解析ばっかりやってた気がする。 YAPCに参加したりTGSに行ったりShibuya.el on Zusaarを開いたり、イベント多かった気がする。

10月

下期になり、チームが上期と若干変わった。 やはり今月も主にHiveで解析していたりして隣席の方にいろいろ教えてもらい、ノウハウが結構溜まった。 Hive自体がそんなに外部に情報多くない中、自社独自の環境で解析を行なっているためノウハウが無いとうまくいかない分野なので非常に助かった。

開発としては、7月にリリースしたキャンペーン用の機能をCMS化した。次から次へとキャンペーンが決まるので、 手動でのテンプレート作成・追加では追い付かず、効率化した。このあたりでスケジュールの管理も社内のカレンダーツール等では辛くなったので、自作スケジュール管理ツールを作っていた。IRCに連携して毎朝つぶやいてくれるので地味に便利。

他にも、裏側の管理ツールを作っていた。毎回手動でテンプレートをいじってはリリースを繰り返してという作業は非常に辛いので作ってよかったとは思うけど、特に管理ツールの様なユーザーには直接使われない系の物は、さくっと1週間程度で作りたい。他にもいろいろ作業してたり、もともと色々な相談が社内で必要になって時間がかかるとはいえ、3人で2〜3週間ぐらいかかってたような気がするのでもうちょっと何とかしたい。(そしてレビューに出す前の開発は完了したのだが、優先度が代わり、まだリリースできていないが辛い。)

今月もudzuraさんの記事の査読をさせていただいた。ひらがなで書いた時に、うずらさんなのか、うづらさんなのか未だにどっちが正解なのかよくわかってない。

11月

10月末から、キャンペーン用のページを作り始めていた。 前回やってたものよりも規模はでかい(とはいっても全ユーザーが使うような機能ではないので大規模ではない)。 キャンペーンの都合上、リリーススケジュールがすでに決まっていたので、今までやっていたアジャイルを破り捨て、上長の方が作ってくれたExcelのスケジュールに沿って開発を進めていった。こういう状況で、Scrumのような開発手法で開発していくのがうまくいくのかどうか今だにわからない。MTGする分だけ時間が取られて絶対的な作業量は減るし、最終的な開発完了の姿がわからなくて不安感もある。

もうちょっと余裕があれば、Scrumによって開発していたならリリース前にもうちょっと改善出来る所がいろいろあったのではないかなと思ったりもした。

12月

成果はともかく、初めて合コンに行った。

作ってたキャンペーンページがリリースされた。キャンペーン期間中、1日毎に違った内容が体験できる仕組みになっているけど果たしてこの仕組が上手く行ったのかどうか、年明けには検証しなければならないなと思った。社内の評価制度の関係で、エンジニアはただ物を作っただけではそんなに評価されず、そのため施策の効果がよくわからないまま作り続けるのは辛い。

あと、入社後半年後研修(半年はすでに過ぎてるけど)というものがあって、改めて3年後自分がどうなりたいのかってを考えさせられた。ひたすらプログラミングし続けないといけないなーと思った。頑張ります。

業務外であんまりプログラム書いてなかった。コードの自動生成について考えてたりしたけど、まだイマイチ形になってない。

前回まで査読していた縁があり、udzuraさんと一緒にコードレビューの記事を書いて発売された。Amazonで名前を検索すると引っかかるのは感動する。とはいえ、記事の内容は弊社のエンジニアブログ記事と社内Wikiをまとめたような内容であり、自分自身の経験・知識を書いたものではないので次回もし執筆するような機会があるようならば、自分自身の経験・知識で記事を書きたい。Web+DB Press vol.72 にコードレビューについて書きました&簡易ふりかえり « blog.udzura.jp

まとめ

会社入っていろいろ学んだりしたけど、まだまだ成長は出来る気がする。 というか、しないといけないので来年もひたすら勉強します。

ブログに書いたのは割りと反省点が多いけど、学いんだこともいっぱいある。 ただ書いてたらキリがないので割愛。

おまけ

今年はあんまり二郎食ってなかった。 だいたい定時に帰ってイベントに参加するか、遅くまで残って作業していたので、どちらにせよ二郎へ行く余裕があまりなかった。 来年は、たまにひばりヶ丘二郎とか桜台二郎行きたい。

そして、彼女欲しい。

Aiming Study #6に行ってきた #aimingstudy


AimingStudy#6に行ってきた。

@mizchiが発表していたけど、(ほぼ)新卒として入社して半年でよくここまでやってるなぁと非常に感心させられた。発表内容自体は、俺は仕事でJS全然書いてないし、 ましてやゲームを作ってるわけでもないので、すぐさま使える話ではないけど「普通」の技術でリッチなゲームを作るっていう発想は割と参考になる考え方だと思った。

「普通」= ウェブサイトを組み立てる技術

つまりHTML+JavaScript(+サーバーサイド)だけで作るということで、 そうすることで、情報見つけやすいしキャッチアップもしやすいし人員増加にも耐えられるとか。 http://www.slideshare.net/mizchi/aiming-study6pdf/22

今流行のソーシャルゲームはページ遷移をバリバリ使ったWebベースの物が多いので、 その流れで今回発表のあったリッチなゲームがもうちょっと楽に作れる土壌が整えば、 Web屋さんでもバリバリとリッチなゲーム作っていけそうだな〜と思った。

さすがにいきなりBackborn.jsとかHaXeをすぐさま使ってみよう!って気にはならなかったけど、 やっぱりJavaScript周辺技術はキャッチアップしていかないとこれからの 世の中の流れについていけなくなるな〜と思いました。

あとは発表でいいなーと思ったのはこのあたりですかね。

あと、2つ目の発表の方、BackbornのViewのヘルパーをテスト付きでpull requestしてくるJSの書けるデザイナーの方らしいめちゃくちゃ素晴らしい。やばい。 SCSSとかSASSとかLessよくわからんし近寄らんとこって思ってたけど、Compass便利そうだったので今度触ってみます。

@ 岩野さんはJSをテストコード付きでPullReqできるデザイナ #aimingstudy
@mizchi
高意識エネルギー体
@ ビューのヘルパーとかは書いてくれてました。
@ffu_
fujimura

はーJavaScript書かなければ。