RubyKaigi 2019 Day 3 (written by t-okuaki)

株式会社ねこじゃらしの奥秋です。

このたび福岡で開催された RubyKaigi 2019 に参加してきました。参加された方々、お疲れ様でした!参加した感想と 3 日目に聞いたセッションのメモを下記に残しておきます。

感想

RubyKaigi への参加は初めてでした。これまでは「行っても話についていけないのでは」という不安から参加のハードルが高く、参加を見送っていましたが、今回思い切って参加しました。会社から旅費や参加費を出してもらえたのはありがたかったです。

参加して、Ruby という言語が目の前で作られていくのを見られたのはよい体験でした。講演の内容はやはりというか難しいものが多かったです。Ruby を作る(より良くする)話がメインなので、普段 Ruby を使うだけの私が、聞いてその場で理解するのは難しかったです。一緒に参加したメンバーは理解していたようなのでぐぬぬ...となりました。精進します。しかしなんとなく理解できたものだけでも面白かったです。Ruby は楽しく書けるようにするため、ある程度自由な書き方を許し、裏でよしなにやってくれますが、その「よしなにやってくれる部分」を実装するのにコミッターの方々が苦労されていることがわかりました。セッションの随所で「つらい」と話されていたのが印象的でした。

セッション以外でも盛り上がっていて、各スポンサーが様々な企画をされていて、楽しませていただきました。ちなみにねこじゃらしもシルバースポンサーだったりします。Official Party もすごかったです。商店街を貸し切るとか 正気の沙汰ではない 素晴らしい企画でした。

参加して得られたモチベーションをもとに今後もやっていこうと思います。最近は JavaScript と格闘することが多いですが...。

セッションメモ

下記は 3 日目に奥秋が聞いたセッションのメモです。 セッション中のメモを多少手直ししてそのまま載せています。雰囲気が伝われば幸いです。ふわっとしているところは私の理解が追いついていないところです...。おかしなところがあればご指摘ください。

💭:私の思ったこと、つぶやき

Ruby Committers vs the World - by CRuby Committers

💭 非常に面白かった。感想で書いた「Ruby という言語が目の前で作られていくのを見られた」というのはまさにこのセッションで思ったこと。

注意喚起

  • RubyGems のパスワード変更のお願い

質疑応答タイム

M: Matz C: Committer

  • 「非互換の変更に対して慎重。もっと攻めてほしい。Ruby は保守的になっていくことにどう思うか?」
    • 今の Matz の方針に賛成か?
      • (挙手を求めた結果)保守:攻める = 1:1
    • C: 古いコードを壊すのは NG
    • M: 投票は信じるな
      • キーワード引数はしょうがない
      • 福岡まで ruby の勉強しにくるひとはそもそもアグレッシブなのでそこで過半数だったとしても、採用したら炎上するよね。そして責任取るのは自分。
    • C: キーワード引数
      • 壊したほうがきれいな仕様だよね
      • ruby 3 はこれでいいとして、今後は...
        • M: 1.8 を使ってる人もいないだろうし、10 年単位とかなら古いのを壊してもいいかもしれません...ね
          • 1.8 使ってる人?(挙手を求める)... ちらほらいる
            • C: (バージョン)上げたほうがいいですよ
  • 「この辺の分野やライブラリで、担当メンテナがいると嬉しい、みたいなところってありますか?」
    • C: あんま使われてないものはそっとしておけばいいのでは。windows 対応は足りてない。
    • C: ドキュメントの Contribution がほしい
    • C: JSON のライブラリ
      • C: オリジナルな作者の反応がないので、長期的にどうしようか
    • C: Date ライブラリ
      • C: 長期的には Date を削除して Time と統合することを勧めている
        • M: 賛成
        • C: Time.parse の仕様がぼんやりしてる
          • M: (ぼんやりした仕様で)使いたいのでは
          • C: Time.parse('123') がエラーにならないのはどうなのか
      • DateTime
        • C: Rails ではカスタマイズして使われている。ActiveSupport に実装し直してもらえば...。
      • 「お客様の中で TimeZone に詳しいかたはいらっしゃいますか?」
    • C: Ruby core からライブラリに切り出している物が多いので、だれでも contributes できる
      • 本体も Git(cgit)に入りそう
    • OSS Gate というのがあるよ

開発者会議

💭 hackmd 使ってた

次回

  • 2019/05/22 13:00- pixiv

新機能の議論

新しい呼び出し(パイプ)
  • Elixir にインスパイア
  • |> :今は SyntaxError にならないから後方互換 OK
## elixir
x |> func1 |> func2
func2(func1(x))

## ruby
x |> method(1) |> method2(2)
x.method(1).method2(2)

右代入

  • M: @ だけはやめて!
  • :::
    • M: あんまりコロンが並ぶと集合体恐怖症の人が...
## ruby
x |> method(1) |> method2(2) 👉 y
x |> method(1) |> method2(2) =| y
  • 2.6 で大文字が constant、小文字が local variable
  • 3.0 で新しい呼び出しと右代入が入る...?
  • Matz にっき
    • 「バージョン上げたほうがいいですよ」
Numbered Parameters
1.times do |i,| p i end
1.times do p @1 end
1.times do p ① end
## などなど
  • 懸念
    1. 想定された動きか?
    2. @ がインスタンス変数を想起するため見にくい
      • 人間慣れるから大丈夫では
    3. 使いたいのは一要素だけのときだけなんじゃないか
  • it 使うと RSpec が...

Cleaning up a huge ruby application - by Sangyong Sim さん

はなすこと

  • cookpad_all というシステムのコードを消す話

cookpad_all

  • rails になってから 10 年
  • ruby コード 50 万行...
  • shared をベースに web, api, batch, admin, mobile がある

巨大なプロダクトだと

  • バグを治すとバグが生まれる
  • Gem が古い
  • 期待動作をしない
  • => 生産性の低下

何を消すか

  • 不要なコード
  • 不要かわからないコード
    • 実行できるが意味のないコード
    • not executed code

なぜ消すか

  • 理解するコードをへらす
  • ライブラリー依存をへらせる
  • => 生産性上がる

困難

  • コストが高い
    • ほんとに消していいかの判断
    • ruby が自由
      • alias_method_chain などで名前がかわる
    • => 取り組みは以下
  • low priority
    • => 優先度をあげる
  • どんどん glow していく
    • ほこりのようなもの
    • => 継続的に削除していく

取り組み:継続的に削除するしくみづくり

  • 「KitchenCleaner」
  • 自動検知して、issue 自動作成

取り組み:IseqLogger

  • iseq: instructionSequence
  • 何が実行されたかをログにする
  • vm_core rb_iseq_check にパッチをあてる
  • performance への影響もあまりない
  • 💭 新しい言葉が多くわからなくなってきている
  • どの iseq が使われているのか
  • 💭 どのコードが使われてるかをいい感じに調べるということか
  • ログをどう使うか
    • 💭 ログ収集中にコードが変わることがあるということかな
    • 「そんなに頑張らなくても消せるものはたくさんあるだろう」という考えでやっている
  • Good
    • template も検知できる
  • Bad
    • Ruby にパッチを当てる必要がある
    • こまかい単位での削除には向いてない
      • ファイル単位での削除に向いていた

取り組み:Oneshot coverage

  • 各行が 1 回でも実行されたかを検知する
    • Coverage.start oneshot_lines: true
  • 工夫
    • ログ送信 / 1 h
  • Good
    • Ruby 2.6 にすればパッチなしで使える
  • Bad
    • データ量が多い
    • 未使用コードがパッと分かりづらい
  • coverband gem
  • oneshot_coverage gem
    • シンプル

成果

  • 起動時間が 1.5 s 早くなるまでになった

まとめ

  • 上記困難を参照

結論

  • まあまあ頑張れば消せる

Best practices in web API client development - by Go Sueyoshi さん

スライド

自己紹介

  • sue445 さん
  • pixiv
  • gem
    • rubicure
  • SRE: site reliability engeneer

Goal

  • 失敗しない API クライアントの設計

API クライアント

  • 4 パターン

1. Public APIs made by ourselves

  • 使う側は便利
  • 作る側は大変

2. Private APIs made by ourselves

  • 「作ったこの gem を入れといて」ができる
  • dogfooding

3. Public APIs made by others

  • マイナーなやつは自分で作るしかない

4. Private APIs made by others

  • ドキュメントはエクセル、次に PDF

どこに API クライアントを作るか

  • 1 つのアプリしか使わないとしても Gem 化したほうがいい
  • Gem 化しないと
    • 密結合になってしまう
    • CI が大変
  • Gem として切り出すと
    • アプリ本体と疎結合
    • CI が早く終わる
    • シンプル

APi クライアントの責務

  • single responsibility principle (SRP)

API クライアントで作るもの

  • パラメータの変換機能(は API の責務)
    • 時刻の変換
  • Ruby クラスに エラーコードをラップ
    • faraday gem
    • サンドイッチメソッド(書籍:refactoring: ruby edition)
  • OAuth2 access token の自動更新

API クライアントでつくるべきでないもの

  • API response を一定時間キャッシュすること
    • memcached
    • メンテが大変
    • アプリ側に作るべき
  • request params validation

いままで作った API クライアントとその TIPS

  • pixela
    • pixela の api
    • データを "草化" できる
    • Tips
      • keyword args を使う(引数 1, 2 個でも)
        • アプリ側の変更に柔軟に対応しやすい
  • chatwork-ruby
    • ChatWork の API クライアント
    • Tips

7 good patterns

  1. 依存をなるべく少なく
  2. Faraday は銀の弾丸
    • faraday_boolean gem
  3. 主題を目立たせる
  4. prefer keyword args to hash args
  5. パラメータオブジェクトの導入
    • 引数に配列やハッシュを渡すと、コメントが書きにくい
    • パラメータオブジェクトなら
      • YARD でコメント書きやすい
      • パラメータオブジェクトにメソッドをもたせられる
      • テストを書ける
  6. メソッドでアクセス可能なレスポンス
  7. curl は万国共通

The future of the Bundled Bundler with RubyGems - by Hiroshi SHIBATA さん

  • 💭 登壇者に Asakusa.rb に参加されている方が多い気がする。

なんで bundler を Ruby にマージしたいか

  • 「最初に入れる Gem は Bundler」をやめたい
  • 去年の進捗
    • マージは進捗なし
    • RubyGems 3 が ruby 2.2 未満のサポートを切る
    • Bundler 2 をリリース
  • RubyGems 2.7 には Bundler が integrate される
  • Ruby 2.6 以降は必ず Bundler がある

Ruby 2.6

  • RubyGems 3
    • 2 ファクター認証対応
    • deprecated なコードを削除
  • Bundler 2
    • Gemfile から gems.rb にする案はなしになった
    • ruby 2.2 未満のサポートを切った
    • build matrix が小さくなった
  • ruby 本体にマージするため
    • bundler のテストを miniruby で実行できるようにした
      • これで RSpecRuby 本体に入れられる
      • すごいこと
  • Bundler のテストが大変
    • 外から叩いてエラーをパースして... みたいな感じ(?)
      • => 実行時間が長い
    • どうしても正しい結果が得られないテスト
      • Ruby がインストールされている前提のテスト
        • miniruby で実行しないといけないので
        • そういうのはスキップ
  • the location fo execution wrapper
    • gem wrapper と original executable
    • gem update で Bundler の「オリジナルファイル」が消え去る
  • Update BundlerVersionFinder
    • e.g. 1.17.1 なら 1.x.y がマッチ

Ruby src に bundler をマージ

  • Heroku で問題
    • 当時 Heroku は Bundler 1 しかサポートしてなかった
      • 使う Bundler を 2 から 1 系に直してリリース
      • 今は Bundler 2 系も対応

リリース後の問題

  • LOAD_PATH が変になっている
  • The invalid gemspec generation issue
  • The bundler switcher issue of Heroku
    • 上記
  • Ruby 2.6.3 は最高
  • rubygems と bundler で SSL 証明書が重複 → fixed
  • rubygemsjson-2.1.9 を require すると 1.8.x が使えない

RubyGems 4 の展望

  • 非互換の変更
    • conservative option をデフォルトにしたい
      • インストールされていたらインストールしないオプション
    • default オプションの動作の変更
    • --user-install をデフォルトにしたい

Ruby 3 に向けて

Timezone API - by nobu さん

Timezone

  • UTC との差分を表現
  • TZ 環境変数
  • IANA tz dtabase が管理
    • "Area/Location" の形式

Time クラス

  • (C の)time_t のラッパー
  • 3 models
    • UTC
    • Local time (system 依存)
      • Time.now
      • Time.new, Time.local
      • Time.at
      • Time#getlocal
      • Time#getutc
      • Time#+, Time#=
    • Fixed offset
      • 1.9.2 から
      • Time.new( ... "+09:00")

2.5 まで

2.6

  • Time.find_timezone をユーザが定義すると Time.new( ... "Area/Location") とできるようにした(?)

interface

  • local_to_utc method
  • utc_to_local method
  • name
    • Marshal.dump/load (?)
  • abbr
    • Time#strftime の問題

質疑

  • in の命名について議論

The send-pop optimisation - by Urabe, Shyouhei

💭 初めて聞く概念が多くて正直わからなかった...。内容としては「メソッドの返り値が使わずに捨てられることをなくせばパフォーマンス上がるのでは?」という仮説を実証した話(のはず)。

結論

  • 「send-pop」を自動で検知して最適化して早くした

インストラクションシーケンス

  • send して pop している

ruby

  • 使われるかわからない戻り値
  • 使われない戻り値を捨てるとき send-pop
  • mame/optcarrot

mame/optcartot で測定

  • leave -> pop
  • 2-grams

最適化 first step

  • 意味のある値を返さなくてもいい
  • 戻り値が使われているかを呼び出し側に伝える
    • 伝えるためのフラグを用意
    • フラグをどのように使うか
    • 自動化
      • "pure" という概念
      • メソッドの末尾にある pure な部分があれば、....

C API

  • C で書かれている部分はコンパイルされていてどうしようもない
  • スペースを消す場合、スキャンしたスペースには興味が無いため、最適化の余地あり

無駄な pop を消したい

  • 常に可能ではない
    • 可能なものを区別するためのフラグを用意

return value を push しない

  • 3 つ の return value
    • C method retrun value
    • あと 2 つ
  • ブロックの中でリターンする場合が大変

ベンチマーク

  • make benchmark の結果
    • 一部項目で明らかに早くなっている
    • 明らかに遅くなっているものはない
  • mid-sized benchmarks
    • time make rdoc は若干遅くなった
    • optcarrot は若干早くなった
  • discourse/discourse (Rails application) ... アプリのなかにベンチマークがある
    • ちょっと早くなったか同じ

質疑

  • 遅くなる原因
    • rdoc だと、プロセスの起動で遅くなるなど

関連記事

RubyKaigi 2019 各日程のレポート

1 日目:中山村上 2 日目:市川 3 日目:古川、奥秋(本記事)

また例年動画で各セッションの様子が公開されているため、今年も公開されるか要チェックです。

ねこじゃらしについて

ねこじゃらしでは Ruby (Ruby on Rails) や JavaScript での開発経験がある Web エンジニア、また、ネイティブエンジニア、UI/UX デザイナを募集しております。

ご興味をお持ちいただけましたら、以下のリンクからお問い合わせください。

www.nekojarashi.com