$shibayu36->blog;

クラスター株式会社のソフトウェアエンジニアです。エンジニアリングや読書などについて書いています。

vscode-rdbg(debug.gem)でのRubyデバッグが便利すぎる

最近Rubyを学び直したり、アルゴリズムの基礎練をしたりしているのだが、debug.gemおよびvscode-rdbgが便利すぎるので紹介。

debug.gemやvscode-rdbgとは

debug.gem( https://github.com/ruby/debug )とは最近のRubyのモダンなdebugger。これまでlib/debug.rbやbyebug、debaseなどがあったが、それらのいくつかの課題を解決したdebuggerとなっている。Ruby 3.1 の debug.gem を自慢したい - クックパッド開発者ブログ に背景や基本的な使い方が詳しく載っている。

またRubyKaigi 2022のruby/debug - The best investment for your productivity - RubyKaigi 2022でも紹介された。Scriptable Breakpointsという仕組みを使えばデバッグ体験をシェアできるという話に感動したことを覚えている。

vscode-rdbgとは、debug.gemの機能をVS Code上で使いやすくしたもの。これの体験が良すぎると思ったので今回記事を書いている。

最初に設定しておくと便利なこと

vscode-rdbgを使うにあたって、settings.jsonに以下のような設定を入れておくことをお勧めする。これを入れておくことで、どのワークスペースでもrdbgを通したrubyスクリプト実行ができるようになる。またuseTerminalをtrueにしておくことでSTDINを使いたいプログラムにも対応できる。

  "launch": {
    "version": "0.2.0",
    "configurations": [
      {
        "type": "rdbg",
        "name": "Debug current file with rdbg",
        "request": "launch",
        "script": "${file}",
        "args": [],
        "askParameters": true,
        "useTerminal": true
      }
    ]
  }

ワークスペースでlaunch設定を共有したい話についてはVSCodeで全ワークスペースで使うdebug launch設定をする - $shibayu36->blog;にも書いた。

続いて最近公開したRubyで迷路探索を幅優先探索で解く - $shibayu36->blog;のプログラムを参考にvscode-rdbgを使ってみる。

VS Code上でブレークポイントを設定してデバッグする

まずは単純にブレークポイントを設定してデバッグしてみる。VS Codeで他言語のデバッグと同様のインターフェースでブレークポイントを設定すればデバッグできる。これだけでも便利。

Watchを設定し、見たいものに着目しながらデバッグする

さらにWatchの部分で見たいものを設定しておけば、そこに着目しながらデバッグができる。見たい部分だけ集中して見れるので、状況がわかりやすい。

rescue any exceptionを設定しておけばエラーになった時にdebuggerを起動できる!

この機能が超便利。Rubyスクリプトにバグがあって落ちてしまった時に、その時点でdebuggerが起動するので落ちた時の状況が把握しやすい。

例えば以下のように境界チェックを忘れるというバグを入れてみる。

diff --git a/ruby/lib/maze.rb b/ruby/lib/maze.rb
index 263e546..a4fa272 100644
--- a/ruby/lib/maze.rb
+++ b/ruby/lib/maze.rb
@@ -35,8 +35,8 @@ class SolveMaze
         next_y = cur_y + dy
 
         # outbound
-        next if next_x < 0 || next_x >= @maze_width
-        next if next_y < 0 || next_y >= @maze_height
+        # next if next_x < 0 || next_x >= @maze_width
+        # next if next_y < 0 || next_y >= @maze_height
         next if @maze_struct[next_x][next_y] == '#' # wall
         next if @maze_dist[next_x][next_y] # already visited
 

そうするとスクリプトを実行すると以下のように落ちる。

/Users/yuki.shibazaki/development/src/github.com/shibayu36/algorithms/ruby/lib/maze.rb:40:in `block in calc_by_bfs': undefined method `[]' for nil:NilClass (NoMethodError)
        from /Users/yuki.shibazaki/development/src/github.com/shibayu36/algorithms/ruby/lib/maze.rb:33:in `each'
        from /Users/yuki.shibazaki/development/src/github.com/shibayu36/algorithms/ruby/lib/maze.rb:33:in `calc_by_bfs'
        from /Users/yuki.shibazaki/development/src/github.com/shibayu36/algorithms/ruby/lib/maze.rb:85:in `<main>'

この状態でrdbgを通してスクリプトを実行すると、以下のようにdebuggerが立ち上がり、状況を把握しやすくなる。

Debug Consoleで詳細に追いかける

VS Codeでdebuggerが立ち上がった状態で、Debug Consoleを見るとdebug.gemと直接やりとりができる。直接やりとりできる分、debug.gemのすべての機能が使えるので便利。

まとめ

debug.gemおよびvscode-rdbgを使うと非常に便利で、最近の開発に不可欠となっている。特に境界がややこしいコードとかを書くときに大活躍している。非常に便利なのでみんな使いましょう。

参考