vscode-rubocop 0.2.0 をリリースした

RuboCop を標準搭載した LSP 向けの VS Code 拡張である vscode-rubocop の 0.2.0 をリリースしました。いわゆる肉の日リリースです。

marketplace.visualstudio.com

Ruby 製の言語サーバーをターゲットにした、LSP クライアントを見てみると、どうも YJIT を有効にするようにしていることに気がつきました。

LSP クライアントは LSP サーバーを起動して、LSP サーバーは起動したままなので高速なわけですが、それなら YJIT を有効にしておけば速いのではというのは、自然な発想になっていそう。

というわけで vscode-rubocop でも世の中のムーブメントに乗って、デフォルトで YJIT を有効にした設定を追加しました。

裏側でやっていることは LSP クライアントから LSP サーバーの起動コマンドに環境変数 RUBY_YJIT_ENABLE=true をつけることで、LSP サーバーを YJIT 有効な状態で起動しているだけです。論理的には LSP サーバー側で RubyVM::YJIT.enabled? による確認をすると true が返る仕組み。

いろいろと言っていますが、要は vscode-rubocop 0.2.0 へのアップグレード、あるいはインストールをするとデフォルトで RuboCop 標準の LSP サーバーが YJIT で起動するということ (もちろん YJIT が導入された Ruby 3.1 以上の場合に限る) 。

この VS Code 拡張についてもう少し概念的な話を書いておくと、Ruby 環境に対する VS Code 拡張の LSP はいくつか出ていますが、vscode-rubocop が目指すのはいまのところ以下の3つとしています。

当面は vscode-rubocop 0.5.0 くらいまでロードマップのイメージができているので、RuboCop の言語サーバー機能とあわせて、たびたびアップデートしていくと思います。お楽しみに。

RuboCop に標準搭載した LSP の基本については以下を参照してください。

koic.hatenablog.com

そして偶然ですがこの日、Visual Studio Marketplace の VS Code 拡張でトレンド入りしていた記念スクショです。

しかし、ユーザーの利便性を考えて VS Code 拡張の LSP クライアントを開発をしていたら、VS Code の推し活みたいになってきたなあ。

勤務先で『高橋メソッド』の書籍紹介をした

勤務先のおすすめ書籍の紹介イベントで、『でかいプレゼン 高橋メソッドの本』を題材にした話をした。

当日のスライドは以下。

高橋メソッドそのものに関する Web 文献は高橋会長のサイトなどを参照してください。

www.rubycolor.org

単に高橋メソッドの紹介になると、本を読みましょうとか、上記 Web 媒体を見ましょうになるので、自分が受けた影響と活動への反映についてまとめることにしてみました。今回作ったスライドでも部分的に高橋メソッドの薫りのするページがあると思います。個人的には、角谷さんのプレゼンとスライド (特に中期作品) にはとても影響を受けていて、そういったあたりもかつて研究家 (誰?) なんかは感じ取れられていると聞いたことがあるようなないような。

ザザッと今回の発表は記憶から掘り起こしながら作ったのですが、プロポーザルを書くポイントは「審査員がワクワクするような内容を」とかモリスさんから聞いたと思っていたけれど、ジョーカーさんだったかも、、、みたいな感じ。Asakusa.rb で聞いたのは間違いないんだけれど、純粋記憶が残って習慣的記憶が怪しいのは仕方ないところかもしれない。

それはそれとして、自分が実践しているプレゼンについてまとめる形にはなったので、何かしら参考になる人がいれば幸いです。

勤務先の 43 期一年間を通して書籍紹介を 4 回するというコーナーでのトークでしたが、ちょうど 4 回終わったところで、取り挙げた 4 冊をリストアップしておきます。

プレゼンに慣れるにはプレゼンをするのが一番というか「修せざれば現れず」なので、やっていきましょう。

RuboCopにLSPを標準搭載した

タイトルのとおり。RuboCop 1.53 で LSP (言語サーバー) を標準搭載しました。

最初に3行まとめを書いておきます。

  • RuboCop を使っているけれど LSP を使っていない場合は、高速なリアルタイム性で開発体験が変わると思います。速い!
  • VS Code ユーザーを使っている方は、後述する vscode-rubocop という VS Code 拡張をインストールすれば OK です。
  • Emacs や Vi などのユーザーは、LSP クライアントの設定で rubocop --lsp を起動するように LSP 設定してください (VS Code では不要) 。

公式の使い方としては以下のドキュメントを更新していくことになるものの、実装者が自分なのでこちらに軽く書き記します。

docs.rubocop.org

rubocop --lsp コマンドは直接ユーザーが手動実行するものではなく、以下のような LSP クライアント (設定) にて実行するものなので、コマンドラインからの手動での起動は不要です。例えば、VS Code 拡張の vscode-rubocop 内部で rubocop --lsp を起動します。本記事で例示しているような Emacs で自前で LSP クライアント設定を書く場合などに知っておくコマンドです。

ここからは LSP を使えるようにするための、それぞれのインストール方法を中心に記します。

VS Code

VS Code ユーザー向けに、VS Code 拡張の LSP クライアントを用意しています。

marketplace.visualstudio.com

Visual Studio Marketplace にリリース済みなので、VS Code の「Install Extensions」で「vscode-rubocop」を検索するか、Marketplace から直接などでインストール可能です。

もちろんエディタ上からオートコレクトの実行も可能です。vscode-rubocop の README 記載を参照してください。

とりわけ Format on Safe は有効にしておくと便利だと思います。 デフォルトで有効にするかどうかも悩んだのですが、いちおうテキストファイルに変更を加える振る舞いの性質から、ユーザーに意図的にチェックしたもらった方が良いかなと、デフォルトで無効にしています。

おまけ情報としては、LSP を策定しているのが Microsoft ということで一番相性 (LSP クライアントとしての出来栄え?) が良いと思います。自分の中で引き続き言語サーバー機能を拡張する計画が立っているので、この VS Code 拡張については言語サーバーにあわせて引き続きアップデートしていく予定です。

手元で今後の PoC を試すのはこちら。LSP 開発では Microsoft ということで手厚いんですよね。

他のエディタでの LSP クライアント設定は以下です。LSP クライアントからの bundle exec rubocop --lsp での起動をベースとした例ですが、見つからなかった際はグローバルの rubocop --lsp としたいなどあれば、適宜用途にあわせて編集してください。

Emacs (Eglot)

全体設定の .emacs/init.el あるいは、対象リポジトリ固有の .dir-locals.el に以下のような設定を足すことで有効にできます。

(require 'eglot)

(add-to-list 'eglot-server-programs '(ruby-mode . ("bundle" "exec" "rubocop" "--lsp")))
(add-hook 'ruby-mode-hook 'eglot-ensure)

保存時に autocorrect を掛けたい場合は以下のような設定を足してください。

(add-hook 'ruby-mode-hook (lambda () (add-hook 'before-save-hook 'eglot-format-buffer nil 'local)))

Emacs 29 で標準搭載になるらしい Eglot でのみ確認しているため、他の LSP クライアントはわかりません。自分は Emacs 28 なので別途 Eglot をインストールしています。

こちらはあくまでベースとなる設定例のため、それぞれ良い感じの使い勝手に elisp 設定して下さい。M-x forever。

2023年12月22日追記

tmtms さんが、RuboCop の LSP と他の LSP を共存可能な LSP ルーターを実装されました。LSP を併用したいケースで参照してみてください。

blog.tmtms.net

Emacs (LSP Mode)

LSP Mode には、以下の PR が取り込まれています。

github.com

MELPA から lsp-mode パッケージを入手してください。

詳しくは以下のドキュメントを参照してください。

emacs-lsp.github.io

Vim, Neovim (coc.nvim)

coc-settings.json への設定例です。

{
  "languageserver": {
    "rubocop": {
      "command": "bundle",
      "args" : ["exec", "rubocop", "--lsp"],
      "filetypes": ["ruby"],
      "rootPatterns": [".git", "Gemfile"],
      "requireRootPattern": true
    }
  }
}

保存時に autocorrect を掛けたい場合は以下のような設定を足してください。

{
  "coc.preferences.formatOnSave": true
}

coc.vim は Neovim で動作確認したのみなので Neovim 向けとしていますが、Vim でも動くと思います。 (2023年7月20日更新) Vim でも動作検証した。

Neovim (nvim-lspconfig)

~/.config/nvim/init.lua の編集例です。

vim.opt.signcolumn = "yes"
vim.api.nvim_create_autocmd("FileType", {
  pattern = "ruby",
  callback = function()
    vim.lsp.start {
      name = "rubocop",
      cmd = { "bundle", "exec", "rubocop", "--lsp" },
    }
  end,
})

Below is an example of additional setting for autocorrecting on save:

vim.api.nvim_create_autocmd("BufWritePre", {
  pattern = "ruby",
  callback = function()
    vim.lsp.buf.format()
  end,
})

保存時に autocorrect を掛けたい場合は以下のような設定を足してください。

なお公式でのサポートも進めてくれているようです。

github.com

未だ検証できていませんが、そちらを取り込めば以下で行けるようです。

require("lspconfig").rubocop.setup {}

@delphinus さんに教えてもらいました。情報ありがとうございます!

Helix

helix 23.05 (7f5940be) 時点での、~/.config/helix/languages.toml への設定例です。

[[language]]
name = "ruby"
language-server = { command = "bundle", args = ["exec", "rubocop", "--lsp"] }
auto-format = true

詳しくは Helix のドキュメントを参照してください。 https://docs.helix-editor.com/languages.html

他のエディター

LSP の仕様から Sublime Text などのエディタでも動くと思いますが、自分が普段使いのエディターではないので、環境を整えるところということでまだ見れていません。

開発後記

LSP 実装は以前から考えていて、RubyKaigi 2023 でジャスティンと話しをしたのが最終的に進めるモチベーションになったもの。LSP の話は帰りの松本駅で偶然ジャスティンと会ったときに話したような。

実装としては Standard に組み込まれた LSP がベースになっていて、さらに LSP を実現するあたっては RubyKaigi 2017 で発表されている mtsmfmlanguage_server-protocol を使っています。RubyKaigi は発表動画がアップロードされているので、後追い視聴できて開発が捗って良いですね (現地でも見ていますが何年も経つと忘れている部分があったり、当時理解が追いついていない部分があったりするので) 。

インストールの注意点として、language_server-protocol は Steep なんかでも使われているので、bundle update rubocop で RuboCop のアップデートが 1.53 にアップデートされない場合は、bundle update rubocop language_server-protocol として language_server-protocol もあわせてアップデートしてみてください。

RuboCop を使っているけれど LSP を使っていない場合は、高速なリアルタイム性で開発体験が変わると思います。ご活用ください。

RubyKaigi 2023 に登壇した

RubyKaigi 2023 に登壇しました。現地での登壇は3年ぶりです。

rubykaigi.org

当日の発表スライドは以下です。スライドのコード中に出てくる ennd なんかは typo ではなく、松田さんのスライドテクニックで、end がネストしている場合、ネスト分 ennnndとしてコードを圧縮しています。

また例年 yahonda さんに英文レビューをしてもらっていたところ、今回は勤務先の事業部でメンバー全員 ChatGPT Plus がサポートされている流れで、GPT 4 を使ったレビューをベースにしたあたり時代背景としてのひとつの変化かもしれません。

speakerdeck.com

スライド 100 枚を 30 分で話す競技にしてしまったのですが、いま流行りの『タイパ』は良かったかもしれません (通訳さんありがとうございました) 。

本編

すごくざっと話すと、「並列テストランナーとは何か?」から「並列テストランナーの種類」、「並列テストランナーの現在と今後」といった構成で作っています。

とりわけ「並列テストランナーの種類」について、現状で Ruby で実装されているメジャーどころの並列テストランナーのそれぞれの概略と、設計のポイントをまとめておきました。本編で話したのですが、並列テストランナーの機構自体を RSpec などのテスティングフレームワーク自体でサポートできると良いのではというひとつの考えが自分の中であり、そういったコントリビューションを各テスティングフレームワークにしていこうという人がいれば、そのヒントになると良いなあと思っています。

とっかかりとしては本編で話した Minitest と Rails 関係は何らかのヒントになるかもしれません。

そんな感じで、来年の RubyKaigi に登壇に向けてオープンなコードを書くことに目覚める人が増えるきっかけになるといいなあというのが、表紙のサブタイトル "The Force Awakens" に込めたもの。事前打ち合わせで通訳さんから聞かれたものですが、まあ、さすがに読み取れるものではないのでここでの補足としておきます。

プロダクトとしての test-queue

test-queue 自体が様々なテスティングフレームワークの各バージョンをサポートしているのですが、あまりに古い RSpec 2 と Minitest 4 はドロップしたいなあと思っていたところで、会場でアンケートを取ることにしていました。結果として会期中にリリースしたのが、The RubyKaigi 2023 Edition となる test-queue 0.9.0 です。

github.com

0.8.0 の機能はそのままで、新しい Ruby とその周辺環境で使う分には問題がないと思うので、ご活用ください。test-queue 自体は今回でひと区切りつけることができたと思うので、しばらく大きな非互換的な変化はないんじゃないかなと思います。

スローテストは設計改善へのヒント説

本編中で話した仮説です。テストスイートについて、ワーカーが処理する時間が短ければ短いだけ、ワーカーがロックする時間は短いです。つまりテストスイートが速く完了すればするだけ、ワーカー間全体としてスループットが上がるはず。モデル単位でいえばテストスイートとプロダクトコードは大体 1 対 1 の関係なので、スローテストのテストスイートはそもそも Fat モデルだったりするのではというのが起点。E2E テストも適切に分割されていると、理論的には全体のスループット向上に影響する気がします。このあたりのヒントは『プログラマーのための CPU 入門』に書かれているスーパースカラ、スーパーパイプラインからアイデアを触発されたものです。

本編で直接の言及をしていませんし、本発表とは直接的な繋がりはないものの、この書籍からはコンピュータの仕組みという観点からマルチコアを活かした並列での高速化へのヒントを得られるかもしれないので、こちらで言及をしておきます。

その後の会話やフィードバック

その後の会期中に自分の発表への会話で印象に残ったものです。

  • hirocaster さんからは、test-queue のワーカーを数百単位で稼働させて事例を聞けたのは面白かったです。ビルドの足回りだと AWS CodeBuild の 72 Cores がなかなかの量だと思っていたところ、自前で用意しての大型のビルド環境構築は印象的な事例でした。彼からも RSpec 2 はドロップして良さそうという声を聞けたのはちょっとした後押しでした。
  • moro さんは熟練の Rails エンジニア、かつ Cucumber の書籍も書いていたこともあり、test-queue の Cucumber が新しいバージョンで動かない点で困りそうなことはないか聞いてみたところ、いまは Cucumber は使っていないということで、そちらはまあ急がなくて良いかなというのが私個人のメンテナーとしての現状です。そんな感じで UA 起点での E2E テストでは RDBMS に限らず、chromedriver なども並列分起動してマシンリソース使いますね的な話をしていました。そして、E2E はスローテストになりがちなので、ゴールデンパスを中心とするような E2E と、細かな条件分岐とするユニットテスト、それぞれの領域でテストを使い分けるの大事だねみたいな話をしていました。
  • ledsun さんとは、各テスティングフレームワークに並列テストランナーを持つのであれば、それは独自インタフェースではなく、Web サーバー/フレームワークにおける Rack のような中間層のインタフェースを設けると良いのではという話をしました。いやあ、たしかにそれができると良さそう。一方で各テスティングフレームワークにその中間層を売り込みに行く作戦などは立てておけると良いかも?現状の Minitest / Rails あたりがヒントになるのかなあ。少なくとも RubyKaigi 2024 までの間に自分が手を出すことはない気がするので、興味のある人がいればアイデアとしてどうぞ!
  • m_seki さんからは、「そもそもそんなにテストするのが良くないんじゃない?」みたいな話があり、さすが本質を突いてもらいました。テスティングとチェッキングは違うよというものだと思うのですが、たしかに何年も失敗していないテストを毎回実行させる必要はないんですよねえ。このあたり onk なんかとも、毎回のビルドで実行するテストと、1日1回だけビルドするテストは分けて良いかもというような話をしました (つまり常のフルビルドではなくてよいのでは) 。それと何年も落ちていないテスト、もう落ちることないかもですが、ビジネスの先によってアプリケーションの変更がどうなるか予測不可能な部分もあって、 (ものにもよるものの) なかなか捨てるに踏み切れないんですよねえ。

発表後にこういったいろいろな会話をできるのは、オンラインの間はできなかったことで良かったです。特に会場のリアクションは現地で話す際の醍醐味だったので、test-queue 0.9.0 はそういった意味でも "The RubyKaigi 2023 Edition" としてメモリアルカットしています。

最後に、通訳さん、オンライン配信業者さん、そして 1,200 人もの国際大規模イベントを運営されたスタッフのみなさんありがとうございました!

RubyKaigi 2024 に向けてハックを続けましょう!

『研鑽Rubyプログラミング』をレビュアー献本いただいた

『研鑽Rubyプログラミング』をレビュアー献本いただきました。角谷さん、ラムダノートさん出版おめでとうございます & ご献本いただきありがとうございました。

記憶によると勤務先で出展していた『Kaigi on Rails 2021』のオンラインスポンサーブースで、角谷さんから「Jeremy Evans の『Polished Ruby Programming』を翻訳しているんだけど、レビュアーとして参加しない?」と声を掛けていただいたのが切っ掛けだったと思います。とりわけ「第6章 コードを読みやすくフォーマットする」で登場する RuboCop のパートの研鑽へのお手伝いが期待されていることかなと思いながら参加させてもらいました。

6章で個人的に気に入っているのが「詩人」と「哲人」のメタファー。RuboCop の使い方として Jeremy Evans としては DisabledByDefault: true から始めることをオススメ (いうなれば激推し) していて、Jeremy の書籍なのでそこは著者の意思としても、RuboCop コミッターの私としてはデフォルトが使いづらいという声は耳にしています (し個人としてもそれはそう思う) ので DisabledByDefault: true から始めてチームで引っ掛かった Cop を有効にする書籍に載っているアプローチはもちろん有効なひとつ。とはいえゼロベースで有効化してくのも手間という場合は rubocop-rails_config や Standard gem みたいなものに乗るのも選択肢です。この「好みの違いを受け入れる」 RuboCop の哲学については Ruby30 でも話しているのでご参考まで。

@yahonda さんの感想にある「議論を起こす価値のある本」になりえているパートのひとつかもしれません。

また、レビューの最中に RuboCop 本体に対して気づいたバグがあり、RuboCop に以下のパッチをあてたりしていました。

github.com

github.com

github.com

6 章に登場する RuboCop に関する訳注は、書籍レビューが元になったこのパッチの結果によるフィードバックがきっかけになっています。Ruby エコシステムを研鑽するきっかけにもなっててすごい。

そんなわけで Jeremy Evans という本物の超人が執筆した書籍というだけで価値ある書籍ですが、日本語版はプロの Ruby コミッターや現役で Active Record ならびに RDBMS に強い Rails コミッター、Ruby コミュニティで活躍している Rubyist のフィードバックも反映されており、原書にはない付加価値の付いた最高に研鑽された翻訳書です。

最後に TBA になると思いますが、角谷さんと RubyKaigi に向けた販促に関する話をしていて、著者の Jeremy Evans も来日登壇する RubyKaigi 2023 での賑わいのひとつになるかもしれません。とにかくおすすめ!

RubyKaigi 2023 に登壇します

RubyKaigi 2023 に『The Resurrection of 
the Fast Parallel Test Runner』というタイトルで登壇します。そして久しぶりの現地登壇です (3年以上ぶり?) 。

私の登壇は2日目である 2023年5月12日(金) の 13:30-14:00 の予定です。

rubykaigi.org

昨年コミット権を持った test-queue をベースにした、並列テスティングについての話です。ある意味で去年の『Make RuboCop super fast』に続く、リアルワールドプロジェクトでの開発ツールの速度改善に繋がる話です (つまりお役立ち) 。

github.com

並列テスティングへのなぜ何から始まり、並列テストを実現するテストランナーの設計や並列テストランナー界 (?) への今後の展望を主題に、利用者として知っておくと良さそうな話なんかも含めて話す予定です。あと Gem メンテナーを引き継いだ際に行うことやその気持ちなども交えるので、OSS 開発というものに興味のある人にも何かしら持ち帰れるような内容になると思います。

そんなわけで、実プロジェクトで役立つ知識だったり、そうでないマニアな知識を抽出したストーリーを鋭意作成中です。

また、今年の RubyKaigi には勤務先の永和システムマネジメントから同僚の @ima1zumi も登壇します。お楽しみに。

勤務先で『ソフトウェア職人気質』の書籍紹介をした

勤務先のおすすめ書籍の紹介イベントで、『ソフトウェア職人気質』を題材にした話をした。

当日のスライドは以下。

『ソフトウェア職人気質』は『エクストリームプログラミング』の第一版 (たぶん 2023 年現在の世間で広まっていない方) のような、ゼロ年代に台頭していた尖った書籍のうちの一冊。書籍そのものの内容というよりは、その内容と現実世界の仕事とのリンクについて取り上げなどしていた。 発表の話としては前半パートと後半パートで分かれていて、前半パートは自分の前の発表者だった @fkino と話していることが色々と被っていて、なんなら自分の 5 ページ目のスライドはだいたい同じデザイン構成で「示し合わせもなく、なんだこれ?w」展開で面白かった。

後半はいま話題の GPT に関連する話としていて、GPT との共生への展望みたいなことを書いているものの、本編では時間が足りず結構端折って話していた。

個人的には今後パラダイムシフトが起きるとしても、いまの仕事で行っている熟練度がゼロリセットされるものではないと見ているので『ソフトウェア職人』として研鑽していきましょうという感じで締めくくり。アジャイルマニフェストには署名がないものの、XP のシリーズ書籍の著者のひとりであるピート・マクブリーンさんのソフトウェア開発への考え方について、知られる機会になっているといいなあと思っている。