RubyKaigi 2019 Day 3 (written by r-furukawa)

RubyKaigi 2019 Day 3

はじめまして、株式会社ねこじゃらし エンジニアの古川です。

今回福岡にて行われた RubyKaigi の Day 3 report を行わせていただきます。

私は今回が RubyKaigi が初参加でしたので、初参加なりの感想 (もしかしたらいつもの RubyKaigi どおり、かもしれませんが) を書かせていただきます。

Sessions

今回 report する session の一覧です

Ruby Committers の session で、主に参加者からの質問や、現状構想中の ruby information に関して

アジャイル開発型企業特有の、無意味なコードが膨大に増えてきたときの refactoring 方法 (その手引き)

今後 Ruby に実装される予定 (正確には外部実装だが) の目玉 rbi type checking の実装に関して

現状 rubyist たちがこぞって入れている bundler を RubyGems と共に ruby に梱包しようと言う取り組みに関して

-> 飛行機に乗る都合で最後の session は聞くことはできませんでした...

Ruby Committers vs the World

質問 (抜粋)

  • 最近 ruby は保守的 (非互換性に対して気にしすぎ) なのでは?

これに関しては、 matz 氏以外では大多数の人が もっと攻めた実装を行って欲しい との意見だったよう。かく言う私もそのような意見でした。しかしながら、それを実現するためには様々な施策 (安定板サポート期間の延長・拡大等) が必要だが、そのための人員不足や知識を持った人が行う必要性など、考慮すべき問題点が複数存在する。とは言っても、

しかしながら、 keyword 引数に関しては、後方互換性など考えずに、どうにかする必要性がある。

とのことで、どこかのタイミングで大きく既存の仕様を変更する必要がありそう。

また、今回様々な session とも関係する Ruby 3.0.0 の実装では、

後方互換性を意識して、本来の美しい仕様を壊してしまった。

とのこと。

それも含め、既存の仕様からの変更は 4.0.0 に着手することには、初めていきたい、とのこと。

  • 特定のライブラリなどでメンテナンスが行き届いていないのでは?

しかしながら、メンテナンスが行き届いていない上で bug が見つかっていないのは、誰にも使われていない証拠なのでは?とのこと。誰にも使われないような機能に対して、メンテナンスの為の人員を投入するのは人的リソースが厳しいらしい。

しかしながら、今後の実装 (GVL・MJIT の一部) に関しては、現状メイン開発者がメンテナンスをする気がないらしい。

また、 JSONCSV 等の非常に使用率の高い汎用公式 gem に関しても、メンテナーとの連絡がつきづらく、少し不安なよう。

Time に関しては、どんどん仕様が曖昧になっているようで、今回の議題としては Time.parse '123' が error してくれなくなった、とのこと。これはつまり、 123 という string に対し、 Ruby に何を求めているのか、 ruby committer もユーザも曖昧な状態を指している。

これを受け matz 氏は、

人間が時間を曖昧に捉えていることの表れ

とし、ある意味 developer friendly の現れなのかもしれない そんなことないか...

また、余談だが、 Ruby 本体の repository が SVN から git に移動する予定の様 githubには、歴史的背景により行かない様だ

開発者会議

  • |>

ある意味観客の興味を一番引かせた内容であったかもしれないのが新 syntax である |> だ。

これは、 matz 氏の構想レベルの話で、まだ仕様などは決まっていないらしく、それを相談することも会議の一部の様だ。

今まで ruby の記法での

b(a(x))

x |> a |> b

として記述する syntax で、 Elixir から着想を得た様です。

また、この様な新 syntax の実装の際に話題となる、 @ の扱いに関して、今回も使用したく無いとのこと。

また、上記記法で実行順番が右辺への代入を行っている為、最終的な戻り値も右辺への代入で記述できる syntax の方がいいのでは?とのこと。

その為、

x |> a |> b => y

の様な右代入式で y への代入も行える様に仕様修正も行うかもしれないらしい。

  • Numbered parameter

@1 の様な記法を用いた、簡略記法の提案で、こちらも matz 氏からのもの。

1.times do |i ,| p i end
1.times do p @1 end

上記コードは共に同様の結果を出力するもので、この様な動作を期待するコードが書かれがちであるために考案したとのこと。

しかしながら、ここでも @ の扱いについて討論が始まり、様々な意見が出た。

感想

  • 最近 ruby は保守的 (非互換性に対して気にしすぎ) なのでは?

私としても、 matz 氏の提案する様な新しい syntax が多く取り入れられた方がいいと思うし、それ以外にも後方互換性を多少度外視した実装が存在してもいいと思っています。

しかしながら、職業で Ruby を使用している以上、やはり互換性の問題は常に付きまとい、心ではそう思いながらも、実際に大幅な仕様変更があった場合自分に降ってくるのは明白…

なんとも言い難い状況ですが、それでも新機能・新 syntax に関してはどんどん追加してもらった方が嬉しいかな、とは思います。

  • |>

この仕様に関して、私としては非常に面白いのでは無いか?と思っています。

その理由として、 Ruby では主に右辺の戻り値を元に左辺の評価を開始する記法が多く、その逆を用いることはコードの幅を広げるのでは無いかと考えている為です。

後置 if など、その式に最も会う記法を選択できのは Ruby の特徴でもある為、この様な選択肢の拡張は非常に好感が持てます。

  • Numbered parameter

これに関して、議論の中ででた 扱える変数を一つに限定して it (他の妥当な単語でも可) とする と言う案に共感しています。

と言うのも、正直この様な記法を用いることが多い部分では、複数の値を操作したいことはあまり無い。単数を持つことが多いのであれば、不必要に多くの可能性 (nil が帰ってきそうな後続の変数名) を増やす必要は無い。と考えている為です。

開発者会議の内容に関しては、特に興味を引くもの (主に syntax) が多く、今後の Ruby version に対しても期待を持てる内容でした。

Cleaning up a huge ruby application

着手理由

cookpad エンジニアの Sangyong Sim 氏は、 cookpad サービスの基盤となっている cookpad_all の Ruby on Rails コードに対して、 bug を消すと bug が増える, 既存の gem 等を patch している為、期待通りの動作修正が行えない, test がいつになっても終わらない 等のことから、不要なコード削除の必要性があるとのこと。

また、不要なコード削除の必要性として、

読むコードは少なくなり、修正を行う際の効率にも関わる。 gem への patch での不必要な依存性や、 test の実行速度の改善に役立つのでは。

と説明しています。

  • なぜ進まないのか?

しかしながら、実際にその様な活動 (不要なコード削除) を始めたところで一向にコードを削除できなかった、とのこと。

なぜなら、コードを削除するためには、 そのコードが、全体に対して不必要であることの証明 が必要であると、語っていました。

また、 Ruby 特有の自由性によって method を全文検索したところで、証明できない ことも語っていました。 Ruby では、 alias_method_chainsend の様な、 method 名を隠して実行する様な操作も可能であるため、証明が難しいとのこと。

しかしながら、これを行う必要性があることは確信しているため、この問題の優先順位を上げ、継続的に行う仕組みを作成することが必要であると提起していました。

解決方法

この問題において、本 session で上げられた内容は主に 継続的に行う仕組み不必要の証明 です。

そのため、二つの方法を試行した様ですが、結果的に現状使われているのは Coverage を用いた方法のよう。

  • Coverage.start oneshot_lines: true

CoverageRuby 2.6 系でサポートされたライブラリで、 load した Ruby ファイルのコードに対して行レベルで実行の hook を行います。

これを用いることで、対象のコードに対して コードのどの部分が実行されたか を result として受け取ることができる様になります。

また、 oneshot_lines option は、この hook を最初の一回のみに限定するもので、これを用いることで log 収集の overhead を大幅に削減できます。

この手法を用い、実行情報を NoSQL へ保存し、実行されることのなかったコードを抽出する様な仕組みとなっている様です。

また、この様なやり方にした理由として、他の方法では overhead も考えると cruby への patch を当てる必要があった。とのことでした。

また、この Coverage では、そもそも行レベルでの情報を収集できるため、結果も細かく読み取ることができる様になる。とのこと。

感想

この様な不必要なコード削除は、弊社でも問題となっています。

その為、この session の内容はかなり興味深く、実際に取り入れる場合の模索なども行いました。

また Sangyong Sim 氏が、やり方など以上に特に推していたことが この様な対応の優先順位を上げること だそうで、実際に直近のメリットが感じ辛い対応である為、実践する必要がある様に感じました。

The challenges behind Ruby type checking

内容

この session では Ruby 3 系に追加される予定である、外部 type checker である .rbi ファイルの syntax などに関する経過報告です。

type checker を今回実装するにあたって、 ruby では重きを置いている Duck Typing に影響が無いか。も重点的に考慮している様です。

Ruby では type checker の種類が多岐に渡り、実際に運用するのが他の言語と比べて難しい理由として、 eval, has_many (active_record) などの様なコードの仕様が変更される meta-programming が多く存在している為であると説明されていました。

また、現状開発済みである .rbi の syntax として、以下の様なものを発表していました。

Integer # instance
singleton(Integer) # signleton
Array[Integer] # generic
Hash[Symbol, String] # generic
Integer | String # union
any # dynamic
nil # Base types
bool # Base types
void # Base types
Integer? # optional
1, :hello, 'world' # singleton type
[Integer, String] # Tuple
{name: String, email: String?} # record
^(Integer, String) -> void # Proc

また、 Demo として実際に IO.open.rbi にて type check する場合の記述も公開。

しかしながら、実際の .rbi ファイルを IO.open に適用すると、考慮すべき対象が多すぎ、非常に大量なコーディングが必要な様。

既存の gem (Rails など) に対して type check を付与した gem を公開できる機構も必要であるとのことでした。

  • sorbet, steep

既存の type checker である sorbetsteep に対してもサポートする予定である様で、それぞれの内で存在する公理を満たす様に設計する必要があるとのこと。

感想

.rbi ファイルに関しては以前から話に出ていましたが、実際の syntax をコードレベルで公開されるのは初めて?の様で、今後のコーディングパターンを想像しやすく、有用な session でした。

また、既存の type checker に対してのサポートなどを鑑みるに、今から sorbet などを利用することもアリなのでは…と

私の方で最も心配していたのが既存 gem への対応で、今回 session では type checker も内包した状態の gem を公開する様な仕組みに関しても言及していた為、うまく使っていければかなり有用になるのではないか、と感じました。

The future of the Bundled Bundler with RubyGems

内容

RubyKaigi 会場であった Ruby で最初に入れる tool 投票 で見事一位になった bundler のお話。

また、上記投票からのフィードバックを含め SHIBATA 氏は、

Ruby を入れて最初に install するのが bundler であるならば、それは Ruby に含まれている方がいいのでは

とのことでした。

それも踏まえ、 RubyGems, bundler が古い gem に対する support を切ったことを皮切りに、すでに Ruby に内包されている RubyGems の様に bundler も cruby へ merge する様に作業したとのこと。

また、これらはそれぞれが Ruby の内外に存在している為、使用する変数に差異が出てしまったりする。しかし、どちらも Ruby に merge されている状態になれば、 bundler 特有のエラーなども起きず RubyGems との摩擦も軽減できるはずであると、このプロジェクトの必要性を説明していました。

感想

実際のところ私も bundler は Ruby のお供として、常に使用している為 Ruby に内包されていた方がいいのは自明であると考えています。

また、 bundler が意味不明なエラーを吐くことも Ruby 外部の tool であることが原因の一つで、この問題が早く解決されるのであれば非常に嬉しいと思っています。

全体の感想

今回の RubyKaigi では、やはり Ruby 3 系へ向けての session が多かった様で、特に type checker などの設計は sorbet からも説明がありました。

私としては、新しい syntax も興味がありますが、 MJIT, Guild などの改善要素にも興味があり、現状弊社で使用している Ruby の version up も検討しています。

Ruby 3 系への乗り換えは、非常に困難を強いることになる様な気もしますが、なるべくならば、最新安定版を使用できる用にしたいと考えていますので、今後の発表にも注目しなくては、と思いました。

また、 Ruby 3 系では、上記に挙げた様な改善要素が複数入っている為、コード全体のリファクタリングなどを行い、 Ruby 3 系に適したコードにしていく様な展開もできればなぁ、と思っています。 できるかは別として

ってかそもそも今の最新安定板にversion-upする仕事があるのですが...