RubyKaigi2016に参加してきました
2016年9月8日から10日にかけて国立京都国際会館にてRubyKaigi2016が開催されました。地域Ruby会議ではなくThe Ruby Kaigiが関西圏で開催されるのは初めてだと思います。RubyKaigi2015はスケジュールの関係で参加することができませんでしたが、今回は岡山から近いこともあり3日間参加してきました。 印象に残ったセッションについて感想を書いておこうと思います。
1日目
Ruby3 Typing(Yukihiro "Matz" Matsumoto)
基調講演はRubyのパパであるまつもとゆきひろさんから、主にRubyの型についてのお話でした。Javaのようにきっちりと型を指定せずとも型推論等を用いて、ストレス無く静的型付けの恩恵をうけることができる言語が最近増えてきています。それを受けて完全な動的型付けであるRubyが今後どのように進化を遂げようとしているのか、その方向性を示す内容でした。
静的型付けのように何度も型を書くのはDRYではないので、絶対にやりたくない。しかし、動的型付けは実行してみるまでエラーが発生しない。静的型付けのような型チェックもできるけど、動的型付けのような柔軟性もほしい。そのために、実行結果を記録し型データベースのようなものを作ってはどうかとのこと。 確かにこの方法であれば完璧ではないにしろ、静的型付けの恩恵は受けることができそうです。私の想像ですがGemで提供されるライブラリにも型データベースが添付される時代が来るのかもしれません。
「前に進むことについてはなんでもやる」と力強く言われていたのがとても印象的なキーノートでした。
dRuby in the last century.(Masatoshi SEKI)
Rubyの分散オブジェクト技術であるdRubyの歴史についてのお話でした。個人的にはRails開発でかつて利用していたSporkで使われていた技術という認識でしかありませんでしたが、分かりやすいデモを交えた発表内容でよく理解できました。前職では.NET リモーティングを使ったプログラム開発を行っていたのですが、dRubyはそのRuby版という印象を受けました。10年ほど前は「ネットワーク経由で遠隔地のオブジェクトをオブジェクトのまま扱いたい」っていう需要もしくはブームがあったのかな? 遠隔でRubyを操作というとAPIサーバー立てて、httpで操作させるかな...という発想になりがちですが、改めてdRubyの利便性を感じることができました。
Unifying Fixnum and Bignum into Integer(Tanaka Akira)
Ruby2.4系からFixnumとBignumがIntegerに統合されることについての説明でした。
(手元のRuby2.3.1と2.4.0devで検証した結果)
# v2.3.1 p 1.class => Fixnum p 4611686018427387904.class => Bignum
# v2.4.x p 1.class => Integer p 4611686018427387904.class => Integer
変更の理由としては
- 32bit/64bitのCRuby/JRuby実装によってFixnumの範囲が異なる
- ISO/JISの規格では明確に範囲が決まっていない
といったことが挙げられます。現実的にはBignumとFixnumはプログラマはあまり区別すること無く利用していたわけです。また次のように互換性も保持されているようです。 (手元の2.4.0devで検証した結果)
1.class == Fixnum => true
このためコードの変換は基本的には不要だと思われますが、自作のGem等は早めの対策を行って欲しいとのこと。その際にメジャーバージョン(1.2.3の1の部分)ではなくマイナーバージョン(1.2.3の2の部分)をバージョンアップするように要望がありました。
メジャーバージョンだとGemfileで~>で指定している場合にバージョンアップされないし、仕様変更を嫌ってなかなか導入されないためだそうです。仕様変更を行った際に、こういった細かな気遣いを同時に行うことで変更を世に広める事ができるんだなと妙に納得してしまいました。
2日目
Fearlessly Refactoring Legacy Ruby(Justin Searls)
sutureというgemのお話でした。 メソッドの実行状況を一度DBに保存し、下位互換性をチェックしながら新しいコードに差し替えていくという手法でレガシーコードをリファクタリングしていくことができるようです。実況状況を保存するという手法は、外部へのhttpアクセスを保存して、それをテストで利用するvcr.gemに似てると思ったのですが、対象が外部アクセスではなくRubyのメソッドで、かつテストだけではなく開発環境や本番環境で利用できるのが面白いと感じました。
How DSL works on Ruby(SHIBATA Hiroshi)
Rakeを取り上げ、RubyでDSLがどのように実装されているかの解説でした。DSLとは特定のドメイン領域の問題解決に特化した言語だそうです。Rakeは当初Ruby版Makeを作る思想で作られたそうです。普段RailsでRakeタスクを定義している時にタスクごとの依存関係を簡単に解決できるので、なるほどこれが「特定のドメイン領域か」と理解できました。メタプログラミングを利用してDSLをどのように定義することができるのか初心者にもわかりやすく解説されていたのが印象的でした。
Ruby Reference Manual 2016 Autumn(okkez)
Rubyのリファレンスマニュアルであるるりまのお話でした。Ruby2.4.0では次の点が大きく変更となるようです。
- Tk関連の組み込みライブラリのGem化
- FixnumとBignumの統合
特にFixnumとBignumの統合はドキュメントのメンテが大変に感じました。
Modern Black Mages Fighting in the Real World(Satoshi "moris" Tagomori)
「現代の黒魔術師が現実世界で戦う」というタイトルです。ここでいう「黒魔術」とはダックタイピングの事。Fluentdの0.12から0.14へのバージョンアップでいかにして下位互換性を保持したままNameSpaceを整理していったかという話でした。この黒魔術のおかげでv0.12用に作成されたプラグインはv0.14で問題なく利用できるそうです。 Twitterで「バージョンを1に変更して下位互換性を切り捨てれば?」という意見もありましたが、Fluentdほど無停止が要求され多くの環境で利用されている仕組みにとって、互換性はとても重要なのだと思います。
ただ、個人的にはv0.14でv0.12のプラグインを利用している時には何らかのWARNINGを出さないといつまでもv0.12のプラグインが利用されてしまうような気がしました。私のプロジェクトでも言えますが、メンテが難解な黒魔術を今後どうやって取り除いていくかが課題となる気がしました。
3日目
Ruby Committers vs the World
Rubyコミッターによる座談会でした。様々な話題が飛び出したのですが私が気になったのは次の3点です。
Stringリテラルのデフォルトをfreezeにしないのか?
Ruby2.3から次のようなマジックコメントをファイルの先頭に書けばデフォルトでStringオブジェクトがfreezeされた状態となります。
# frozen_string_literal: true
会場からこの動きをデフォルト動作にしないのかという質問がされましたが、会場に「このコメントを普段書いている人」と手を上げてもらったところ、大多数の人が書いていないという状態でした。 おそらく大多数の人が書くようになればfreezeがデフォルトとなるのでしょう。
Githubで開発はしないのか?
たとえソースの管理がGithubに移ったとしてもisssueは使わないとのことでした。すでにredmineとsvnの間でいくつもの連携スクリプトが動作しており、そこを自分たちで変更してまで移行するメリットが見いだせないとのお話でした。
Ruby3では並行性・並列性のサポートをしてほしい
Rubyコミッターの笹田さんからの要望でした。同RubyKaigiで新しい並列実行モデルであるGuildの発表をされています。まつもとゆきひろさん曰く「何らかのサポートは取り入れていきたいが、それがGuildになるかどうかは分からない」とのことでした。
Web Clients for Ruby and What they should be in the future(Toru Kawamura)
同氏が2014年のRubyKaigiで発表されていたHypermedia: the Missing Element to Building Adaptable Web APIs in Rails はサーバー側のアーキテクチャに関係するものでしたが、今回はAPIにアクセスするクライアントに関係するお話でした。現在FacebookやTwitterなどWebサービスごとに様々なクライアントGemが存在しています。使い方はGem毎に異なり、それぞれのドキュメントを読む必要があります。その理由としてはWeb APIごとのJSON構造の違いや4xxより細かいWebAPI固有のエラーがあります。またAPIを1回呼び出すことと、機能を実行することにはギャップがあり、機能が使いたいわけであってAPIを呼び出したいわけじゃないとの事です。
これを打破するためには状態管理が必要なWebクライアントが必要とのこと。この発表ではFaradayを用いてミドルウェアを作成し、サービス固有のGemを作成せず汎用的な設計にするテクニックが紹介されました。
It's More Fun to Compute(Julian Cheal)
Rubyを用いてコードで音を奏でる発表を行われていました。まず、様々な波形による音の違いが説明されFM音源世代のおじさんたちは大喜びでした。バブルソートとクイックソートのアルゴリズムの違いを音で表現したのは素晴らしかったです。
まとめ
今回は会場の素晴らしさが印象に残るRubyKaigi2016でした。毎年ですがスタッフのホスピタリティあふれる活躍のおかげで3日間楽しく過ごすことができました。
さて昨今、言語仕様としては多言語に押され気味なRubyですが新しい並列実行モデルや、動的型付けのカジュアルさを引き継いだ型推論の考えなどまだまだネタに尽きないなぁと思い安心しました。今後どのようにRubyが進化していくのか楽しみです。
Kansai RubyKaigi 06に参加してきた
参加してきた!
7月11日 (土)にKansai RubyKaigi 06がエムオーテックス新大阪ビルで開催されました。場所はビルの名前の通り新大阪駅近くで、非常に便利の良い場所です。 セッションは映画館みたいな大会議室で行われました。参加者は200名以上で大変な盛り上がりでした!
以下、気になったセッションのメモです。
Rubyにみるプログラミングスタイルの進化(まつもとゆきひろさん)
早口のMatzのセッションにしては珍しく、スライド上でうさぎがカメを追いかけてる状態が長かったです。I/Oを読んでる17歳の時の写真から始まり、ポケコン、紙のノート上でのプログラミング、SONY NEWSワークステーションでのRuby開発の話とMatz自身の人生を垣間見ることができました。 印象的だったのがGitの利便性についてMatzの口から説明があったこと。これって珍しいですよね。 あとは、静的型付けの話。型があるのが嫌なわけではなく、いちいち書くのがめんどくさいとのこと。この辺りの話は「オープンソースの代弁者」としてセミナーでスーツ組に対して話をする白Matzとは異なり、いきいきしていました(笑)。 今でもRubyMineなどのIDEではかなりいい感じにコード補完がされるので、さらにPCの処理能力が進化し、言語側から型情報のサポートを受けることができれば、さらに楽ちんなプログラミングができる世界がやってくるのでは、と感じることができたセッションでした。
Readable RSpec(株式会社spice life)
LT枠でのお話でした。RSpecの書き方についてのあれやこれや。 let(:user)をどこで定義するのかは確かに難しいですね。私はスコープが狭くなることになるべくこだわりたいので、同じ定義を2箇所で書いてしまうこともあります。DRYに書けるのがRSpecの利点と思いますが、見通しが悪くなるくらいならDRYは捨てます!
Railsガイドを支える技術(@yasulabさん)
Railsガイドを和訳したときのノウハウについて。Gitのコミットログをスキャンして変更点を探し出すという手法が素晴らしかった。私自身、この手のガイドは1箇所でも情報が古ければ全体的に古く感じてしまうこともあり、情報の鮮度へのこだわりをひしひしと感じました。
スモウルビー1.0:小学3年生から始めるRubyプログラミング(@takaokoujiさん)
Scratchベースのプログラミングツール「スモウルビー」でプログラミング少年団という活動を行っているお話。素のScratchはブロックを組み合わせるだけで、その後のアップグレードパスが用意されていないけど、スモウルビーを動かすためにはRuby + Railsが必須なので、より複雑なプログラミングを行う環境が自然にできあがるとのことでした。 我々も同じことが言えて勉強会で意識が高まったけど、家や会社で試そうとすると環境構築でつまずいてしまうパターンが多いので、この取組はとても理にかなっていると思います。スモウルビーはScratchをRubyのコードに変換することもできたと思うので、そのあたりデモンストレーションで見たかった気もします。
RSpec、Minitest、使うならどっち?(伊藤 淳一さん)
偉い人がRSpecを使いたがらない風潮は私も以前から感じていました。今回の発表では機能やスピードをわかりやすく比較してRSpecに優位性があることが証明されました(って理解でOKよね?)。とはいえ、Githubでプルリク出したりForkしたソフトウェアの修正時にMinitestの知識が必要になってくることもあるので、基本的なことは抑えておこうと思いました。 余談ですがMinitestがランダムな順序でテストを実行するがデフォルト動作なのは良いことですね!「手元で動かしてOKで、CIでコケる」というテスト組み合わせ問題の単純な解決方法になりそうです。
API server/client development using JSON Schema(@izumin5210さん)
単なるテキストファイルであるJSONに制約を付けてバリデーションを行うことができる仕組みを「JSON Schema」と言うそうです。今回はじめて知りました。私自身、仕事でAPIを作ることが多いので調べてみようと思います。 発表の中で「RailsではStrong parameterがあるのに JSON Schema必要?」みたいな話があったのですが、JSON Schemaの一番の利点はクライアント・サーバー両方のテストが容易に書けることだそうです。 具体的なコードが少なく話しの後半はちょっとついて行けてなかったのであとで調べてみます。
キーワードパラメータを支える技術(笹田 耕一さん)
Ruby2.1から2.2に変わったタイミングでキーワード引数が大幅にスピードアップしたそうです。今回の発表ではどのような取り組みで高速化したのかをわかりやすく説明されていました。 通常Rubyの高速化の話はC言語で語られることが多く、私にはチンプンカンプンなのですが今回はRubyで作られた擬似コードによる説明で非常に分かりやすかったです。
def f3 3 end def foo(k1: 1, k2: eval(“k3”)), k3: f3()) p k1, k2, k3 end foo
この場合、一見
1, 3, 3
と表示さそうですが、Rubyのコードは左から実行されるのが大原則なので、
1, nil, 3
と表示されるべきなのだそうです。めったに書かれないこのコードを実現するために複雑な処理が入っているとのこと。
懇親会の居酒屋でもノートPCを開いてこの点を丁寧に説明して下さり、より理解が深まりました。ビール片手にRubyコミッターから言語の仕様の話を聞かせてもらえるという貴重な体験ができました。
まとめ
大阪や東京で開催されるRubyイベントに何度か顔を出すうちに、親しくお話させてもらえる方も増えてきました。こういったイベントでの話はブログやSNSでは得られない生の声を聞くことができるので楽しいですね。 最後になりましたがスタッフの皆さんお疲れ様でした。楽しい時間をありがとう! 来年はOkayamaRubyKaigiを開催しようかな?
RubyKaigi2014に参加してきた(2日目、3日目)
2日目
Coming soon…(Yukihiro "Matz” Matsumoto)
- 2001年にRuby2の話をしている
- VirtualMachineが入る
- 6年後
- 笹田さんがきちんと実装してくれた
- M17N
- Native thread
- Generational GC
- VirtualMachineが入る
- RubyConf 2005
- Stabby lambda ( -> )
- RubyConf 2006
- 22のアイデアのうち7つは入らなかった
- オープンソースコミュニティはサメのようなものなので泳ぎ続けないと死んでしまう
- 燃料を投下したい
- Ruby 3.0のアイデア
- 最近登場した言語はスクリプト言語でありながら静的な型を持っている
感想:Ruby3.0に導入されるかもしれない機能のお話。私はPythonのように、制約はないけどDocumentとして引数の型を書いておくという手法はアリかなと思う。けど、まつもとさんはとにかくコード量を減らしたい仕様にしたいみたい。コードの文脈からしてこのメソッドの引数にはintが入るであろうことは、言語が判断すべき。わざわざ型を指定しなくても、文脈で判断できるのが良いコードという認識なんだと思った。現在RubyMineとかのコード補完やチェックはかなりのレベル(ホント、どうやってるのか不思議なくらい)まで来ているので、言語側がサポートしてくれればより精度の高いコーディング補助が可能になると思う。今後Rubyがどのような進化をとげるのか楽しみ!
<%= link_to "bundle", "update" %> - Make "bundle update" more fun to review(Kensuke Nagae)
- bundle update
- Gemfile.lockが更新されるが、各Gemがどんな変更が行われているかを見たい。
- Compare Linker
- GithubからCompare Linkerがwebhookを受け取る
感想: bundle updateする→Gemfile.lockがなんか更新されてる→いつ更新してるんだろうとRubyGemsを見に行く→何が変わってるんだろうとGithubを見に行く... という流れは私もよく体験する。これを自動化してGithubに変更点のDiffを見ることができるリンクをpushする仕組みを作ったお話。3回同じことをやったら自動化しろとはよく聞くが、この複雑な処理を自動化したのは素晴らしい。
ServerEngine: a framework for multiprocess servers in Ruby(Masahiro Nakagawa)
- fruentd
- ログ収集ソフトウェアのメイン開発
- System programs
- Chef
- Serverspec
- Apache Deltacloud
- Network server
- starling
- unicorn
- Log Server
- Fluentd
- サーバープログラミングで考慮すべきこと
- マルチプロセス、マルチスレッド
- エラーハンドリング
- ログ
- ServerEngineを作った
- 何ができるか
- Unicornみたいなサーバーを簡単に作れる
- Worker moduleとServer moduleをユーザーが作る
- 3層構造
- USR2 signalでリロードできる
感想: 操作感はまさに慣れ親しんだunicornそのもの!webrickも非常に便利なWebサーバーだが、ServerEngineを使えば大規模アクセスにも対応したunicornライクなサーバーを作ることができそうだ。
3日目
おはようRails
- (あまりの面白さにメモ取ってなかった)
感想: tubolinksはみんな消してるんだなー、とか今の若い子は「Railsは業務で使うもの」だと思ってるとかなかなか刺激的な内容だった。正直、私はあまりサービス志向のプログラマじゃないので(社会人としてそれはどうなんだというのはさておき...)Rails使ってサービスを素早く立ち上げるって点はあまり興味ないかも。自分が楽しめる仕事をやっていきたいなーと思っております。
Speeding up Rails 4.2(Aaron Patterson)
- ManageIQ
- 仮想マシン管理ソフトウェア
- Rails no one commiter
- Rackはもう終わり。楽じゃない
- Rack 2.0
- the_metalはrack2.0のプロジェクト
- Rack 1.xの問題
- hashのkey
- ストリーミングの制御がめんどくさい
- Adequate Record
- URL PATHは短いほうが速い
- 配列的な構造を定数に変換することでスピードアップ
感想: たこ焼き仮面ことAaronの日本語での発表はとても楽しく聞くことができた。特にスライド内のジョークを日本人のセンスに合わせているところがGood! 発表内容としてはAaronさんの地道なRails高速化についてのお話がメイン。長く運用するシステムでは長期的に見ると細かい点が積み重なり問題を引き起こすことがあるので、このような改善はとてもありがたい。「存在しないコードが一番速い」というのは名言だと思った。
Everything is Broken: A Story of Hope(Jonan Scheffler)
- 公開鍵暗号方式を色で表現していたのがわかりやすかった
感想: あまりRubyに関係がある内容では無かったが、公開鍵暗号の仕組みを色の混ぜあわせで解説する方法はとてもわかりやすかった。私も他人に説明するときは使わせてもらおう。
以上が3日間でビビッときた発表でした。 RubyKaigiはいつもネット上でしか交わらない方とリアルでお話することができる素晴らしいイベントです。この3日間の熱を冷まさないように、岡山での活動につなげていかねばっ!と思いました。
RubyKaigi2014に参加してきた(1日目)
▲3日目 おはよう Railsの様子
9月18-20日にタワーホール船堀にて開催されたRubyKaigi2014に参加してきました。 簡単ですが気になった発表について、感想を交えてレポートを書いておきます。
1日目
CRuby Commiters(Tomoyuki Chikanaga)
- CRubyのコミッタは80アカウント、実質50人ぐらいのアクティブなコミッタがいる
- RubyKaigiでスピーカーになっているのは15人
感想: ネット上やRubyKaigi会場で時々お見かけする方々が、どんな分野を担当してるか分かってよかった。
Building the Ruby interpreter -- What is easy and what is difficult?(Koichi Sasada)
- 10周年
- Rubyの開発は何が簡単で何が難しいかという話
- 何をやってきたか
- 本題
感想: 「なんとなく思いついたアイデアを実装するのは簡単。でも、まともに使えるようにするためには苦労が必要」という部分は、レイヤーは違えどどんなエンジニアにも共通なんだなと思った。私の仕事だとRubyで大量のデータを集計するバッチ処理を書くことが多くて、GCの遅さには悩まされてる。これが新バージョンのRubyで少しでも軽減されると助かる。
Controller Testing: You’re Doing It Wrong( Jonathan Mukai-Heidt)
- controllers
- bing action
- small details
- controllerはno logicであるべき
- テストが必要なロジックはコントローラに書くな
- before_filterを使う
- Little to no logic in controllers.
- shared examples cover the small details.
- 認証テストをまとめる
- 使いすぎるとどこでコケてるかわからなくなる
- テストはチェックリストのように
- 命令文ではなく平叙文的にテストをかけ
感想:「うーん。まぁそうだよね」と思う内容だった。shared examplesを使ってテストをまとめるとしても、やり過ぎるとテストが追いづらくなるし、可読性を求めて一箇所に書いてしまうとDRYじゃなくなりメンテしづらいしバランスが大切ということかな。「テストはバランスが大切」という話は3年ほど前からよく聞いてるし自分でも感じてるんだけど、これといって決定打が無いなとも思ってる。
Introduce Oracle enhanced adapter for ActiveRecord, another choice for your Rails database.(Yasuo Honda)
- Oracle enhanced adapter maintainer
- Oracle enhanced adapter
- 3rd party Activerecord adapter
- 標準にない機能
- Rubyの型とのマッチング
- 既存のテーブル設計をRailsに合わせるユースケースが多い
- 7つほど専用の命令が用意されている
- Oracleを使うことで何が良いか?
- オプティマイザが賢い
- プリペアードステートメントが賢い
- SQLインジェクションの対応に強い
- Oracle11g
- 1つのプリペアードステートメントで複数の実行計画を持つことができる
- User.where(:database => ‘oracle’).last.id
- ActiveRecord
- そのまま
- Oracle modified SQL
- 素のSQLではなく最適化されてる
- where文が書き換えられてる
- 実行計画を動的に変えてくれる
- where文で指定された列に該当する値が多ければフルスキャン
- そうでなければindexを使ってくれる
- 実行計画がメモリに蓄えられてシェアされる
- 素のSQLではなく最適化されてる
- ActiveRecord
- User.where(:database => ‘oracle’).last.id
- 問題点
- いくつかテストがコケる
- Empty string as NULL
- 長さ0の文字がNULLとして扱われる
- Identifier length <= 30 byte
- オブジェクト名は最大30文字
- “id” needs to set explicitly
- Oracleは明示的にidに入る値を書かなくてはならない
- No limit in sub queries
- limit句がサブクエリ内で書けない
- Empty string as NULL
- いくつかテストがコケる
- Rails4.2
- Adequate Record
- パフォーマンス改善
- Adequate Record
- Oracleとしての新しい機能
- 12cが最新機能
- 徐々に標準に近づけようとしている
- JSON Datatypeのサポート
- Better Top-N query support
- これのおかげでページネーションがまともに動くようになった。
- order_hacksというダーティーな処理を削除
- これのおかげでページネーションがまともに動くようになった。
- 12cが最新機能
- 環境作るのが大変だよね
- 1つのプリペアードステートメントで複数の実行計画を持つことができる
感想:発表前の会場挙手で意外とRailsでMySQLを使っている人が多かった。Oracleは普段使ってないけど、MySQLやPostgreSQLと比較して独特の仕様が多いように思う。その反面「Oracle modified SQL」で適切なSQLに書き換えれば高速に動作するところが素晴らしい。単に「ActiveRecordをOracleに対応させましたよ」というだけでなくOracleの旨味を引き出していた。メインで利用するDBとしての選択ではなく、外部システムとのやりとりで接続することを想定してActiveRecordに追加命令があるのもありがたい。複雑になりがちなRailsでの複数DB接続に希望が持てた。
Hypermedia: the Missing Element to Building Adaptable Web APIs in Rails(Toru Kawamura)
- Sendagaya.rb
- Web APIの話
- 蜘蛛の巣のようなAPI
- public
- どう使われるか分からない
- 蜘蛛の糸のようなAPI
- private
- どう使われるか分かってる
- APIをRestfulにするかどうかは要件次第
- 要件にあったAPIを
- 今回は蜘蛛の巣のようなAPIをどう作るかという話
- Breaking Changes are Harmful
- 壊す変更は有害
- クライアントがiOSアプリだと変更に時間が掛かる
- 人間が読めるドキュメントから作られるサービスがたくさんある
- 機械が読める説明書から作られるクライアントもある
- JSONで仕様を提供してコードを自動生成する
- APIの変更がクライアントに反映されるべき
- APIの説明を分割して各レスポンスに埋め込むのが良い
- 疎結合が良い
- APIコールのメタファーが危険
- クライアントが次に何をするかはAPIから返ってくるリンクをたどる。=HYPERMEDIA
- 普通のWebと一緒
- ワークフローがあるから破綻しない
- 人間は画面に表示される内容を目で見て判断して処理を行っている
- HTMLクローラー
- hypermicrodata gem
- HTMLをサーバーサイドでJSONに変換
- 状態遷移図を作って設定
- ブラウザと同じイメージで作ること
- HTMLじゃなくてJSONを書くときの注意
- まとめ
- Web APIはHTML Webアプリと同じように設計しよう
- RESTの制約・原則を意識するともっとうまくできる
感想:API設計で問題となる仕様変更についてのスマートな解決方法を学ぶことができた。クライアントが「次に読むべきURI」をアドレスではなくHTML内の文字で示すという考え方は面白い。「え?それってスクレイピングじゃ...?」という疑問に対しても「hypermicrodata.gem」という解決方法を準備してくれているのも素晴らしい。期限を設けてv1,v2...とバージョン番号で区切るしか無いと思っていたAPI仕様変更に対する問題に光明が差した気がした。
RubyistはWindowsに帰っておいで -Vagrantを使ったWindows開発環境-
Windowsマシンを組み立てたった!
自作PCなんて何年ぶりだ!? pic.twitter.com/AB3FStmPFR
— Yamamoto Kazuhisa (@kazuhisa1976) 2014, 6月 21
ASP.NETに興味が出てきたので久々にWindowsPCをアップグレードした。CPUはCore2QuadからCorei5(4590)に、OSはVistaからWindows8.1に変わった。特に大きなハマリも無くすんなりアップグレード完了。最近のマシンの起動は本当に速い。昔はBIOSでいろいろチェックしたのち立ち上がってたのに時代は変わったなぁ。
なぜRailsプログラマはMac OSを使うのか?
多くのRailsプログラマがなぜMacを使うか?それは「Unixのような環境」を使いたいためだと思う。HerokuやAWS Elastic BeanstalkのようなPaaSサービスが人気なのは確かだがデプロイされる先はUnix系OSであることに変わりはない。開発環境をデプロイ環境と揃えておくことは開発者としてごく自然の考えだし、デプロイ時のトラブルも少ない。もちろん私も4年以上MacでRails開発を行っている。
時代は変わった
本番環境と親和性の高いMacOSだが、最近は開発環境の複雑さによって環境を仮想化し、場合によって切り分ける動きが出てきた。
-
- PostgreSQL
- sidekiq.gem
- redis
プロジェクトB
- Mongoid.gem
- MongoDB
- Mongoid.gem
プロジェクトC
こんな状況で一台のMacに色々なアプリケーションをインストールして、プロジェクトに応じて起動したり停止したりするのはうんざりだ。今であれば普通にVagrantによる仮想環境で解決しようと思うはずだ。
ならWindowsでいいんじゃない?
はい。Windowsでいけちゃいます。
ポイントは次の通り。
Vagrantの共有ディレクトリは使わない
WindowsのファイルシステムをLinuxで使うのと、LinuxのファイルシステムをWindowsで使うのでは後者の方がオススメ。理由としては速度が速い事と、Rubyの組み込みライブラリであるFileクラスの動作不良*1が発生したため。
Sshfs Managerを使ってディレクトリを共有する
シェルはGit BashとConEmuを使う
https://code.google.com/p/conemu-maximus5/
多機能なコンソール。いい感じのフォントや色を設定しよう。
RubyMineはVagrant用の設定を使う
Ruby用IDEであるRubyMineを使うとGemの中のソースまでジャンプしてくれる。Railsのソースを読むのにとても便利だ。RubyMineはVagrantにも対応しておりVagrantfileを読み込ませることで、コードジャンプやIDEによるデバッグ実行が可能となる。
http://www.jetbrains.com/ruby/webhelp/configuring-remote-interpreters-via-virtual-boxes.html
Windows環境はできることが多い
私の場合、Windowsだと幸せが多い
DMMでダウンロードした動画(察して)
なんと、WindowsMediaPlayerとゆー、標準プレイヤーで観ることができる!先行き不安なSilverLightプレイヤーを使わなくていいのはありがたい。
RAW現像ソフトSilkypix Developer Studioの動作が爆速
「爆速」というか単純にMac版が遅すぎるって話なんだけどね...
ゲームができる
バナー広告でよく見かけるWorld of Tanksとかで遊べてしまう。
Visual Studioで.NETができる
あたりまえ。
IEで動作確認できる
まとめ
MacでVagrantを使って開発環境を切り替えつつRailsやってる人は、Windowsに戻ってきてもいいかもしれない。Windows8.1は表示もシンプルで動作も恐ろしく速く、OS自体のデキはMacOSと比較してとても良いと思う。この夏はぜひWindowsで視野を広げてみよう。
*1:File.exists("config/locales.")のような存在しないファイル/ディレクトリが存在することとして判断されてしまう
Railsのバッチ処理のコツ
はじめに
Railsでギョーミーな仕事を行う上で欠かせないのがバッチ処理です。 日々上位システムから送られてくる膨大なデータを迅速に取り込み、集計処理を行いDBに格納する。上位システムは何層も構成されており、我々が集計処理に使える時間はエンドユーザーが出社してくるまでの数時間... みたいなシチュエーション無いですか?
今回はバッチ処理を行うコツについて書いてみようと思います。
想定される処理
- CSVファイルの取り込み
- 集計処理
- 集計結果をDBに格納
普通にrake taskを書いて処理できてれば今回の記事は必要ありません。そっとブラウザを閉じて下さい。そうでない場合、多くの人が直面する問題は次のようなものが考えられます。
- IDのオーバーフロー
- メモリが食いつぶされてバッチ処理が停止
それでは順番に説明します。
IDのオーバーフロー
大量のデータを日々のバッチで取り込んでいる場合、IDがオーバーフローしてしまう可能性があります。IDの最大値はINT型で2147483647もあるので通常利用している範囲ではオーバーフローすることは考えなくても(※1)大丈夫です。しかし、データの取り込みは追記だけとは限りません。何かの条件でDELETE & INSERTする場合、ID列の寿命は思っていたより早く尽きてしまうでしょう。
※1 毎日10万件のデータを取り込んだとして58年持つ計算。
そんな場合は思い切ってID列を削除してしまいましょう。
# migrationの定義 create_table :sales, :id => false do |t| t.references :customer t.date :sales_date t.decimal :total_sales end add_index :sales, [:customer_id, :sales_date], unique: true
IDを削除することの弊害
IDを削除することで、IDのオーバーフローに怯える必要は無くなりました。ActiveRecord::Baseのwhereメソッドによる検索も普通に使えます。findメソッドによるID検索が使えないだけだと思っていると、大きな落とし穴が待ち構えています。それはUpdateができないことです。
この問題を解決するためにはcomposite_primary_keys
というgemを利用しましょう。
Modelに次のようにキーを定義することでUpdateが可能になります。
class Sales < ActiveRecord::Base self.primary_keys = :customer_id, :sales_date end
メモリが食いつぶされてバッチ処理が停止
初めは快調に処理が進んでいたのに、だんだん遅くなって停止してしまう。こんな経験はないでしょうか?
▲こうなるともうお手上げ
メモリの消費をチェック
Linuxであればfreeコマンドでメモリの消費をチェックしてみましょう。
$ watch free -m total used free shared buffers cached Mem: 8000 6998 1001 0 340 2346 -/+ buffers/cache: 4311 3688 Swap: 10063 414 9649
バッチ実行中にbuffers/cache
のfreeの値がどんどん減っていくようであれば、あなたのバッチ処理は何かがおかしいです。
大きなselectを行わない
Sale.all.each do |sale| # 略 end
全てのデータを一気に取得して処理するのではなく、可能であれば小さい単位に分割しましょう。
Shop.all.each do |shop| Sale.where(shop_id: shop.id).each do |sale| #略 end end
適切な粒度でバルクインサートを行う
このような処理はメモリを食いつぶす原因となります。
Sale.all.each do |sale| OtherSale.create!(total_sales: sale.total_sales, ...) end
ActiveRecord.importを利用してバルクインサートを行いましょう。その際に、全てのレコードをインサートするのではなく適切な粒度になるよう気をつけましょう。
Sale.find_in_batches do |sales| # 1,000件ずつ取り出す list = [] sales.each do |sale| list << OtherSale.new(total_sales: sale.total_sales, ...) end OtherSale.import list end
最後に
バッチ実行中にだんだん遅くなっていく現象は、テスト段階では気づきにくいものです。本番運用が始まる前にかならずダミーデータを作成して検証を行うようにしましょう。
Jenkinsでmaster-slave間の通信が不安定なときはslave.jarの起動オプションを疑え
現在、awsのspot instanceを利用してRailsプロジェクトのテストを並列実行しようと試行錯誤しています。
なぜだかmaster-slave間の通信が不安定で困っていたのですが、ようやく打開策を見つけました。
症状
- slave側のテストの状況がモニタリングできなくなる
- slaveの処理が止まっているわけではないみたい
- nodeの接続がすぐに切れるわけではないが、しばらくすると切れてしまう
ログの状況
- 不安定なときのnodeのログは次のようになっていました。
[04/24/14 20:29:44] [SSH] ip-172-16-2-101.ec2.internal:22とのSSHコネクションをオープン [04/24/14 20:29:44] [SSH] 認証成功 [04/24/14 20:29:45] [SSH] リモートユーザーの環境: AWS_AUTO_SCALING_HOME=/opt/aws/apitools/as AWS_CLOUDWATCH_HOME=/opt/aws/apitools/mon AWS_ELB_HOME=/opt/aws/apitools/elb AWS_IAM_HOME=/opt/aws/apitools/iam (略) [04/24/14 20:29:45] [SSH] javaのJavaバージョンをチェック [04/24/14 20:29:45] [SSH] java -version returned 1.7.0_55. [04/24/14 20:29:45] [SSH] sftpクライアントの開始 [04/24/14 20:29:45] [SSH] 最新のslave.jarをコピー中... [04/24/14 20:29:45] [SSH] 404,201 バイトコピー. Expanded the channel window size to 4MB [04/24/14 20:29:45] [SSH] スレーブのプロセスを開始: cd "/media/ephemeral0/jenkins" && java -jar slave.jar <===[JENKINS REMOTING CAPACITY]===>channel started Slave.jar version: 2.39 これはUnixのスレーブです。 Effective SlaveRestarter on ip-172-16-2-101.ec2.internal: null Slave successfully connected and online Apr 24, 2014 9:28:47 PM hudson.slaves.ChannelPinger$1 onDead INFO: Ping failed. Terminating the channel. java.util.concurrent.TimeoutException: Ping started on 1398342287626 hasn't completed at 1398342527626 at hudson.remoting.PingThread.ping(PingThread.java:120) at hudson.remoting.PingThread.run(PingThread.java:81)
Ping failed.
だそうです。
- 解決方法
- slave.jarの起動オプションに
-text
をつける。具体的には[Jenkinsの管理] - [ノードの管理] - (ノードを選択) - [設定] でSuffix Start Slave Command
に-text
をつける。頭にスペースを入れること!
- slave.jarの起動オプションに
- Distributed builds - 日本語 - Jenkins Wiki によると
スレーブ起動のために、telnetのような (バイナリデータを直接扱えない) binary-unsafe なリモート操作用のメカニズムを使っているなら、 slave.jar の実行時に -text オプションを追加して下さい。
とあります。うーん。Macでmaster-slave構成を組んでいた時は何も問題が無かったんだけどな。ともあれ、slaveとの通信が不安定なときはtextモードを試してみましょう。