@kyanny's blog

To be a cross-functional developer

Speaker としての #rubykaigi 2014 を終えて

f:id:a666666:20140922110431j:plain

RubyKaigi 2014 二日目 9/19 11:30 から Hall A にて <%= link_to "bundle", "update" %> - Make "bundle update" more fun to review という発表をさせていただきました。お聞きいただいた皆さん、ありがとうございました。

https://speakerdeck.com/kyanny/percent-equals-link-to-bundle-update-percent-make-bundle-update-more-fun-to-review

Compare Linker というツールの紹介と、なぜそれを作ったのか、そして開発を通じて得た学び、などについて発表しました。


Compare Linker については You can review "bundle update" efficiently with Compare Linker - @kyanny's blog で詳しく説明していますが、この記事も発表も英語のみで、日本語での説明が無いことに気づいたので、この場で改めて説明します。

  • bundle update して依存 gem が更新されると Gemfile.lock の差分が発生します。GitHub の pull request を使った開発フローでは Gemfile.lock の差分を含むコードレビューをする機会があります。しかし Gemfile.lock の diff はレビューに適しているとは言えません。
  • ある gem のバージョンが変化したことはわかりますが、具体的に何がどのように変化したかについての情報はありません。何が変わったのかを知りたければ、まず gem のソースコードリポジトリを検索し、バージョン間の diff を見る、などの作業を全て手作業で行うことになります。
  • 実際にそういうことを何度も繰り返した結果、面倒なので自動化しようと思い立ち、 Compare Linker を作りました。
  • Compare Linker を Rack アプリケーションとして Heroku などで起動し、 GitHub のリポジトリの設定で pull request webhook の送信先に URL を登録します。新しい pull request が作られると Compare Linker は webhook を受け取り、Gemfile.lock が変更されているか調べます。
  • Gemfile.lock が変更されていれば、 pull request の base ブランチ(通常は master です)と head ブランチ(pull request のもとになっているブランチです)それぞれの Gemfile.lock を比較し、変更のあった gem について GitHub の compare view URL を作成し、リンクの一覧を pull request ページにコメントします。

発表ではさらに、 Compare Linker の開発を通じて学んだことについても話しました。それは「アイデアを思いついただけではだめで、行動をおこさなければ価値はうまれない。しかし行動してみただけでもまだ不十分で、改善し続けることが最も大切だ」ということです。

このことに気づいたのは、Junior Designers vs. Senior Designers — The Year of the Looking Glass — Medium という記事を読んだときでした。 Compare Linker を開発し、仕事のワークフローに組み込んで数ヶ月使ってみたものの、思ったほど便利ではなかったかな、と感じていました。その理由はなぜだったのか、この記事を読んでわかった気がしました。なので、どうしてもそのことを伝えたくなり、記事の著者に引用の許可をいただき、話の結論にあたる部分のスライドに記事中の図を使った、という経緯があります。

自分としては、「単なる自作ツールの紹介ならブログで十分。わざわざ話を聞いてもらうからには、自分が得た知見まで含めて伝えたい」との想いからこのようなストーリーを組み立てたのですが、ちょっと説明不足だったかもしれません。


発表の準備をするにあたって、いくつか影響をうけたことがありました。

@deeeet さんの コマンドラインツールについて語るときに僕の語ること のスライドの美しさを目にしたことが、それまで既存の自作テーマを使い回して作っていたスライドを見つめ直すきっかけになりました。この内容を伝えるために最も適した表現方法が他にあるのではないか?と考え直し、結果的に満足のいくものが作れました。

また、 @deeeet さんのブログ記事 や、 GitHub の Zach Holman 氏による The Talk on Talkshttp://speaking.io/ からは、スピーカーとしての心構え、特に準備や練習を入念にすべし、ということを再認識させられました。振り返ると、準備、練習ともに不十分だったと感じており、反省すべき点が多々ありました。

Zach Holman 氏からは心構え以外にも、スライドの文字を大きくすることや、目にやさしく見やすい配色を選ぶこと、元気よく情熱的に喋ることなど、多くを学びました。それから、 Keynote の ⌘D というキーボードショートカットを知ったおかげで、スライド作りがだいぶ楽になりました。スライドの見栄えについては、事前のコネクタ接続チェック時にちらりと確認した限りでは、まずまずの出来だったのではないかと自負しています。喋りについては、声はちゃんと出ていたと思いますが、なにぶん経験の浅い英語スピーチだったのでしっかり前を向いて喋れなかったのが反省点です。

そして、最も強く影響を受けたのは、四月に開催された RESTful Meetup vol.3 における @koriym さんのプレゼンテーションでした。まるで TED トークのような情熱あふれる素晴らしいプレゼンテーションで、自分もいつか郡山さんのようなプレゼンテーションをしてみたい、と強くインスパイアされました。そのおかげで RubyKaigi 2014 の CFP に応募する一歩を踏み出せましたし、本番が近づくにつれプレッシャーで追いつめられた気持ちになったときも、あのときの感動を思い出して勇気づけられました。


英語が流暢に喋れるわけでもないのに英語でスピーチをすることについては葛藤がありました。 Semi International Conference とはいえ大多数の参加者は日本人ですし、日本語スピーチについてはプロの翻訳チームによる英語への同時通訳が提供されるのですから、下手な英語で喋るより日本語で喋ったほうが、誰にとってもメリットが大きいはずです。それをわかった上であえて英語を選ぶのは勇気がいることでした。オーガナイザーチームの皆さんがそれを認めてくれたことはとても嬉しく、同時に責任の重大さも強く感じました。

発表前日 @kakutani さんから「(言語は)どっちでもいいと思っている。日本人が英語で喋っても、外国人が日本語で喋っても、好きにやってもらえれば」とおっしゃっていただいたおかげで、ここまできたらあとはやれるだけのことをやるだけだ、と気持ちが吹っ切れました。

発表直後には、翌日の発表を控えた @remore さんから「自分も英語でスピーチする予定なので、(日本人である僕が英語で喋っているのを)みれてよかった」と言っていただき、やってよかった、と救われた気持ちになりました。

英語スピーチの準備をするのは日本語のときと比べるとずっと大変で、逃げ出したくなったときもありましたが、貴重な経験になりました。この経験を糧とし、今後はより大きな目標にチャレンジしていきたいです。

helm-ghq で Searching for program: No such file or directory, ghq エラーが出るときの対処法

ghq コマンドに Emacs からパスが通っていないので、 exec-path に追加する。

(add-to-list 'exec-path "/Users/kyanny/gocode/bin")

GUI 版 Emacs.app を使っているとシェルの rc ファイルでエクスポートした環境変数が引き継がれないのでこういうことがよくある。

自分の場合 ghq/Users/kyanny/gocode/bin/ghq にインストールされていた。環境変数 $GOPATH$HOME/gocode にしているためと思われる。

環境によってホームディレクトリのパスや gocode の部分はかわるので、適時よみかえること。

masutaka/emacs-helm-ghq · GitHub

ghn v2.0.0 released

http://rubygems.org/gems/ghn/versions/2.0.0

ChangeLog from previous stable version:

  • New Features:
    • Add open subcommand (support open(1) alternative commands at some platforms)
    • Add --all (-a) global option to list/open all unread notifications
    • Add aliases for username/reponame shot form
    • Add Follow issuecomment anchor option
  • Deleted Features:
    • --open option is removed
    • --mark-as-read option is removed
  • Bugfixes:
    • Support Release type notification

Thank you very much for Contributors!


ghn v2.0.0 をリリースしました。変更点は上記またはリリースノートをご覧ください(内容は同じです)

過去のバージョンも含め、パッチを送ってくれたりバグ報告をしてくれたコントリビューターの皆さん、ありがとうございました。


うっかりメジャーバージョンを 2 にあげてしまったけど、 pre リリースを除いた一番最新のリリースバージョンは v0.1.0 で、バージョン 1 を飛ばしてしまった。次に何か作るときは最初のリリースから v1.0.0 として出すようにするべきだなと思った。

今回バージョンアップするにあたって、内部のコードをごっそり書き換えた。なぜか自前でサブコマンドやコマンドラインオプションの処理をしていたのを thor を使うようにしたのと、 GitHub API クライアントを github_api から octokit に変更した。

前者は hub のようにファイル一個を配布すれば使えるようにと依存ライブラリを減らしたかった名残だ(当初は GitHub の API も net/http か open-uri を使って自前で叩いていた覚えがある)しかし自分が使うぶんには gem という配布形式で不便しないし、そういうツールも増えてきたように思う。そもそも Ruby が必要な時点で単体配布向きではないかもしれない。配布の容易さにこだわるなら Go で書くべきなのかもしれない。気が向いたら移植してみたい。

後者は sawyer が url という属性を風変わりに扱う問題への対処方法を知らずに苦肉の策で別ライブラリを採用した名残だ。公式の強みで仕事等でも octokit を使う機会は多く、わざわざ似てるけどちょっと違うものを使う意味もないと思って定番に乗り換えた。残念だったのは Octokit. auto_paginate が Notifications API ではうまく動かなかったこと(Link ヘッダが無いため) auto_paginate があれば --all オプションはすぐ実装できると思ってやり始めたので使えなくて拍子抜けだった。自前実装でとりあえずどうにかなってよかった。

Video: GoGaRuCo 2013 - Measuring Ruby by Sam Saffron and Jeff Atwood

GoGaRuCo 2013 - Measuring Ruby by Sam Saffron and Jeff Atwood - YouTube

YouTube の Watch Later に入ってたのを消化した。硬派なパフォーマンスチューニングの話。以下視聴メモ。

  • Discourse のパフォーマンスチューニング、特に Ruby プログラム部分の話
  • 前半でクヌースの「早すぎる最適化は悪」を引用しつつ、サイトが遅い原因の大半はフロントエンドにあると指摘
  • しかしフロントエンド最適化の話はせず(おそらくそれは踏まえた上でなおサーバーサイドを限界までチューンする話、だったのだろう)
  • dtrace の扱いづらさ(?自信なし)を経て rbtrace に触れる
  • rack_mini_profiler の使い方に触れる、 /?pp=help とすると裏コマンドがいろいろ見られる
  • memory_profiler gem を使うとメモリについて詳しいことがわかる、オブジェクトが作られた数とかそれによって消費したバイト数とか(動画内では ruby-head が必要とあるけど一年前の動画だから。 2014 年現在はふつうに最新リリース版の 2.1 系で使える)
  • あと flamegraph オプションを使うとコールスタックがカラフルなグラフで見れる
  • それらを踏まえてオブジェクト生成コストを減らすコーディング指南とか、常に実行可能なベンチマークコードを持っておいてライブラリの新しいバージョンに対して実行し改善や悪化を計測可能にするとか

僕はこう思ったッス

  • 動画のタイトル見たとき「まさかあの Jeff Atwood なわけないよなー、同姓同名の人なんだろうけど気の毒だなー」と思ったら本人でびっくりした
  • 大規模ハイトラフィックサイトにおけるハイパフォーマンス Ruby プログラミングという感じでためになった
  • 個人的にパフォーマンスへの関心が薄くてベンチマークの類いにもあんまり興味が無いのだけど、技術者としてやっていく上でそれはマイナスに働きそうだなという懸念が以前からあったので、たまにこういうのをみると刺激されてよかった
  • とはいえ個人的には消費メモリを節約するためにオブジェクトの属性をハッシュに詰め直す、みたいなコーディングの工夫でがんばる方向性にはやっぱり賛成できなくて、だったらもっとメモリ効率の良い、用途に適した言語で書けばいいのに、と思ってしまう(もちろん習得コストとかいろいろあるけど、必要に迫られたらできるはず)
  • とはいえ遅いと言うだけよりはコードとデータで示したほうがよっぽどいいし、そういう動きがないと処理系を作る側にも伝わらないだろうから、やっぱこういうことをする人はそれはそれで偉いと思った
  • script/bench.rb で Rails edge とかに対して Discourse のベンチを走らせて継続的にパフォーマンスの変化をチェックする、というのはちゃんと人柱になっててえらいなーと思った。ノブレス・オブリージュっぽさを感じた
  • flamegraph というものを初めて見たけど youpy さんっぽいなと思った

Video: OSCON 2014: How Instagram.com Works; Pete Hunt

OSCON 2014: How Instagram.com Works; Pete Hunt - YouTube

YouTube で Facebook Developers チャンネルを購読してたら新着動画のお知らせメールに載ってたので視聴した。以下メモ。

  • instagram.com は React を使った Single Page Application
  • ユーザーエクスペリエンスを最優先した結果 SPA を選択した
  • 初回ロード時間はリクエスト数 x 転送バイト数で決まるので .js/.css ファイルを一個に結合するのは良くない
  • エントリポイントごとにモジュールを分けて、モジュール単位で一個に結合、 minify/gzip などすると効率が良い
  • .js/.css は CommonJS の require を使って(?自信なし)ロードする。サイズの小さい画像も DataURI を require して img 要素を作る
  • このような特殊なファイル読み込み手法のため CSS の読み込み順序が不定になりセレクタ名の衝突・上書きで見た目が崩れるので命名規約とかいろいろ使い方を工夫する
  • ファイルの編成には browserify や grunt gulp 等ではなく、依存関係の扱いに長けた(?自信なし) webpack がオススメ。ブラウザのファイルロード・読み込み速度が 250ms -> 120ms に改善した

僕はこう思ったッス

  • ブラウザパフォーマンスも考えた上でモジュールシステムを決めたりしててさすが Facebook だなと思った。 Rails とかでやってると何も考えず一個にまとめているけど、考え無しでやるだけは良くない
  • 「オレは CSS が嫌いだ」には同情するけどセレクタの衝突でややこしくなったりするのは自分らがわざわざ特殊なやり方でファイル読み込みしているせいじゃん...と思った
  • 「Facebook は巨大なベヒーモス」とか所々で笑いをとろうとしてるのに会場の笑い声が一切録音されてなくて気の毒だった。でも会場が広いのとマイクの集音性能が優秀なせいかもしれない
  • webpack って初めて知ったなーと思ったら数ヶ月前に日本語でも紹介されていてアンテナの低さが身にしみた
  • 40分枠のうちほぼ30分ぴったりに収まるトークと10分の質疑応答でほぼ40分ぴったりで終わっててすごいと思った。プレゼン慣れしてるのだろうし、準備や練習も相当してるのだろう