Tech Racho エンジニアの「?」を「!」に。
  • Ruby / Rails関連

Ruby: byebugからruby/debugへの移行ガイド(翻訳)

概要

原著者の許諾を得て翻訳・公開いたします。

Ruby: byebugからruby/debugへの移行ガイド(翻訳)

新しいデバッガに乗り換えてデバッグプロセスを変更するのがつい億劫になることもあるでしょう。本記事によって、皆さんがruby/debugに親しんでスムーズに移行する助けになることを願っています。

ruby/debug - GitHub

以下、debugruby/debugを指します。

免責事項

  • 著者はdebugと比べてbyebugの経験があまりありません。不正確な情報や古い情報がありましたらぜひお知らせください
  • 本記事の目的は高度なレベルで比較を行うことです。debugの特定の利用方法については公式ドキュメントを参照してください。
  • 本記事はすべての機能を網羅しているわけではありませんが、ほとんどの機能をカバーしているはずです。

🔗 debugを使うメリット

個別の機能を解説する前に、debugを使うメリットについて簡単に触れておきたいと思います。

1. 出力がカラー化されている

2. メソッドやブロックの引数をバックトレースできる

3. Zeitwerkとの互換性問題は解決済み

4. ブレークポイントやトレーサーが強力

5. リモートデバッグ機能やVSCode統合が便利

詳しくは以下の別記事をどうぞ。

参考: Setup ruby/debug with VSCode

🔗 debugの現在のデメリット

  • スレッド制御があまり柔軟でない
  • Fiberとの連携がまだ弱い
  • pry-byebugのようなpry統合がまだない
  • プロジェクト単位のコンフィグは利用不可(セキュリティ上の理由)

byebugdebugの比較は以下のとおりです。

🔗 インストール

原注

Ruby 3.1にはdebug v1.4が付属していますが、常に最新リリースを使うことをおすすめします。

byebug debug
サポートするRubyバージョン 2.5以降 2.6以降
gemのインストールコマンド gem install byebug gem install debug
Bundlerでの記法 gem "byebug" gem "debug"
依存関係 なし irb
reline
C拡張 利用可能 利用可能
最新バージョン 11.1.3(2020/04/23) 1.6.2(2022/08/10)

🔗 デバッガの起動方法

byebug debug
シェルでの起動 byebug foo.rb rdbg foo.rb
デバッガ構文での起動 byebug binding.break
binding.b
debugger
(いずれも同じ)
requireでの起動 なし require "debug/start"

🔗 ユーザーエクスペリエンス機能

byebug debug
カラー出力 なし あり
コマンド履歴 あり あり
ヘルプコマンド h
help
h
help
ソースファイル編集コマンド edit edit

🔗 評価

REPLでのコード評価方法はbyebugdebugでだいたい同じです。

  • 式がコンソールコマンドと一致しない場合(my_method(arg)など)、Rubyコードとして評価される
  • 式がコンソールコマンドと一致する場合(nなど)、コンソールコマンドで評価を実行できる
byebug debug
デバッガ実行コマンド <コマンド> <コマンド>
式とコマンドの衝突回避方法 eval <式> pp <式>
p <式>
eval <式>

🔗 フロー制御とフレーム移動

debugのステップコマンドはbyebugと同じなので、byebugユーザーは新しい操作を学ばずにdebugに乗り換えられます。

byebug debug
ステップイン s
step
s
step
ステップオーバー n
next
n
next
終了 fin
finish
fin
finish
<id>フレームに移動 f <id>
frame <id>
f <id>
frame <id>
上のフレームに移動 up up
下のフレームに移動 down down
nフレーム上に移動 up <n> なし
nフレーム下に移動 down <n> なし
プログラムを継続実行 c
continue
c
continue
デバッガ終了 q
quit
q
quit
プログラムを強制終了 kill kill

🔗 スレッド制御

上述したように、debugはサスペンド中にすべてのスレッドを停止するので、現時点ではスレッド単位の管理はできません。そのため、スレッドについてはよりシンプルなコマンドが用意されています。

byebug debug
サスペンド時のスレッド 現在のスレッドのみ すべてのスレッド
すべてのスレッドをリスト表示 th l
thread l
th
thread
スレッドidに切り替える th switch <id>
thread switch <id>
th <id>
thread <id>
スレッドを停止する th stop <id>
thread stop <id>
なし
スレッドを再開する th resume <id>
thread resume <id>
なし

🔗 ブレークポイント

byebugも適切なブレークポイントをサポートしていますが、debugは以下のようにさらにレベルアップしています。

  • pre:オプションやdo:オプションを用いてブレークポイントでコマンドを実行できる
  • path:オプションを用いて呼び出し元ベースの条件付きトリガーをサポート
  • 特殊なcatchブレークポイントやwatchブレークポイントをサポート

🔗 1. ブレークポイントの設定

byebug debug
行を指定して設定 b <行>
break <行>
b <行>
break <行>
ファイルと行を指定して設定 b <ファイル>:<行>
break <ファイル>:<行>
b <ファイル>:<行>
break <ファイル>:<行>
メソッドに設定 b <クラス名>#<メソッド名>
break <クラス名>#<メソッド名>
b <クラス名>#<メソッド名>
break <クラス名>#<メソッド名>
条件を指定して設定 b ... if <式>
break ... if <式>
b ... if <式>
break ... if <式>
パスの条件を指定して設定 なし b ... path: /パス/
break ... path: /パス/
指定のコマンドを実行して継続 なし b ... do: <コマンド>
break ... do: <コマンド>
停止前に指定のコマンドを実行 なし b ... pre: <コマンド>
break ... pre: <コマンド>
例外にブレークポイントを設定 なし catch <例外クラス>
インスタンス変数を監視するブレークポイント なし watch <@インスタンス変数>

🔗 2. ブレークポイントの管理

byebug debug
ブレークポイントをすべて表示 info breakpoints b
break
ブレークポイントを設定 b ...
break ...
b ...
break ...
ブレークポイントを削除 del <id>
delete <id>
del <id>
delete <id>
すべてのブレークポイントを削除 del
delete
del
delete

🔗 情報表示

🔗 1. バックトレース

debugのバックトレースには、メソッド呼び出しの値やブロック引数の値が含まれます。このちょっとした改良のおかげで、フレーム間で値を手動でinspectせずに済みます。

フィルタ機能を活用することで、フレームワークやライブラリのフレームを無視して、関連するフレームだけを表示できます。

byebug debug
バックトレースを表示 where
backtrace
bt
backtrace
bt
バックトレース内でメソッドやブロックの引数を表示 なし あり
バックトレースのフィルタ なし bt /正規表現/
バックトレースの上限数を指定 なし bt <n>

🔗 2. 変数・定数

byebug debug
ローカル変数を表示 var local info l
インスタンス変数を表示 var instance info i
グローバル変数を表示 var global info g
定数を表示 var const info c
引数のみを表示 var args なし
info lでできる)
変数・定数を名前でフィルタ なし info ... /正規表現/

🔗 3. メソッド

debugにはオブジェクトのメソッドをリスト表示する専用のコマンドはありませんが、irbやpryに似たlsコマンドが利用できます。

byebug debug
obj.methods method instance obj なし
obj.methods(false) method obj.class ls obj

🔗 トレース機能

debugのトレース機能については別途記事を書くつもりですが、それまでのつなぎとして、特に以下のトレース機能を折に触れて試してみることをおすすめします。

  • trace exception: コードで発生する例外を監視します。アプリケーション内部で発生する例外がrescueされる様子を見たら驚くでしょう。
  • trace object <式>: オブジェクトがメソッド呼び出しを受信する様子や、オブジェクトがメソッド呼び出しに渡されるなどの活動を監視します。 

byebug debug
行トレーサー set linetrace trace line
グローバル変数トレーサー tarcevar なし
複数のトレーサーを利用する なし あり
メソッド呼び出しトレーサー なし trace call
例外トレーサー なし trace exception
Rubyオブジェクトトレーサー なし trace object <式>
トレース出力のフィルタ なし trace ... /正規表現/
トレーサーを無効にする set linetrace false trace off [トレーサー種別]
idを指定してトレーサーを無効にする なし trace off <id>

🔗 コンフィグ

debugではニーズに応じてさまざまなコンフィグ機能を利用できます。ただしセキュリティ問題が懸念されるため、プロジェクト単位でのrcファイルはサポートしていません。

byebug debug
コンフィグをすべて表示 なし config
特定のコンフィグを表示 show <コンフィグ名> config show <コンフィグ名>
コンフィグを設定 set <コンフィグ名> <値> config set <コンフィグ名> <value>
RCファイル名 .byebugrc .rdbgrc
(またはRubyスクリプト形式の.rdbgrc.rb
RCファイルの置き場所 $HOMEおよびプロジェクトルート $HOME

🔗 リモートデバッグ

開発環境をコンテナ化すると標準I/O(stdio)に常にアクセスできるとは限らなくなるので、リモートデバッグ機能が非常に重要になってきます。リモートデバッグ機能は、VSCodeやChromeなどのさまざまなデバッグクライアントに接続するうえでも重要です。

リモートデバッグ機能が必要なら、debugに乗り換えるのがベストです。

byebug debug
TCP/IP接続 あり あり
Unixドメインソケット接続 なし あり
Debug Adapter Protocol(DAP)経由のVSCode統合 なし あり
Chrome DevTools Protocol(CDP)経由のChrome統合 なし あり

まとめ

多くの開発者にとって、byebugからdebugへの乗り換えはほとんど手間がかからないはずです。しかもdebugに乗り換えることでかなりの生産性向上が見込めます。

もちろんbyebugは素晴らしいデバッガであり、長年コミュニティに大きく貢献してきました。しかし近年は開発のテンポが低下しており(最後のリリースは2年前です)、debugはRubyコアチームによって定期的に更新されているので、両者のギャップは開く一方です。

そういうわけで、debugを手元に常備して強力な機能を知っておくと、長期的に生産性を高めるための大きな投資となります。

参考資料

関連記事

ruby/debugのChrome Devtools連携をRailsで動かす


CONTACT

TechRachoでは、パートナーシップをご検討いただける方からの
ご連絡をお待ちしております。ぜひお気軽にご意見・ご相談ください。