開発は、コードを書いている時間よりデバッグをしている時間のほうが長くなります。 デバッグの快適さは開発の楽しさにかなり直結します。 Rubyはこの環境が恐ろしく整備されています。
Rubyは、文化的にかなりみっちりテストを書きます。 特にRailsのような足元が整備されビジネスロジックだけに集中できるフレームワークの場合、一切アプリケーションを実行すること無く テストだけで開発できてしまいます。
テストは rspec
や minitest
などを使いますが、
直接実行するよりも guard
という ファイル監視ツール から実行できるようにすることがほとんどです。
Railsは規約が強いフレームワークなので、 app/controllers/users_controller.rb
が更新されると対応するテストである spec/controllers/users_controller_spec.rb
を実行したりもできます。
ここまで、基本的に一切の作業をすること無く rspec --init
と guard init
だけでこの環境が作れます。
さて、テストが落ちた時Rubyistはどうするのでしょう。
なんと、おもむろにコード上に binding.pry
と書きます。
するとどうでしょう、guard
で回っているテストの該当箇所で REPL が起動します。
この pry
というREPLが異常に優秀で、その場でRubyのコードが実行できるだけでなく、
ls x
で 変数が持つメソッド一覧 を見たり、 $ x.foo
で メソッドの実装 を見たりできます。
メソッドの実装がその場で読めるのでデバッグに非常に役立ちます。
Railsなどの複雑なGemの場合、実装を読むだけではそれでも動きが理解できない場合がありますが、
そういう場合でも、Rubyはただのテキストファイルなので、手元にあるGemのコードに直接 binding.pry
を書いてしまえば良いのです。
この binding.pry
は ただのRubyのメソッド呼び出し なので、もちろんRubyの文法が自由に使えます。
例えば特定のケースだけでテストが落ちる時、
def foo(arg)
binding.pry if arg == 100
...
と書けます。
他の言語にもこのようなデバッガのようなものは多々ありますが、Rubyの場合は非常に高度に独立していると言えます。
ただ binding.pry
を書けばいいだけなので、特定のIDEなどのツールに依存しません。
多くの言語のデバッガは ブレイクポイント を設定するのにGUIを使わざるを得ず、だいたいIDEが必須になってきます。
それに比べRubyでは好きなエディタと好きなシェルだけで自由自在にデバッグできるのです。
また、多くの言語が デバッガからプログラムを起動する や、
デバッグモードでプログラムを起動する など少し特殊な方法でプログラムを起動するのに対し、
Rubyの場合はただのRubyコードなので、いつもと同じようにRubyを動かせばいいだけというのは大きな利点です。
すなわち、 ruby foo.rb
でも、 rspec foo_spec.rb
でも、 rake spec
でも、guard
の中でも、
はたまたRailsアプリにブラウザでアクセスしたときでも、どんなときでもその場で pry
のコンソールに落ちます。
例えばJavaScriptには debugger
という構文がありますが、ブラウザでは止まりますが node
では止まりません。
Rubyは必ず同じ方法で同じように止まるのです。
JavaScriptのデバッグは、 ブラウザ という最も馴染み深いデバッガを使うところが最大の利点です。しかし、上述したようにテストランナーの中で止めることはできません。
実際コードを動かす場所はほぼブラウザであり、テストツールでブラウザを完璧にエミュレートしているわけではないので、最終的にブラウザで動かしてみる以上のデバッグは不可能なんじゃないかと思います。
また、メソッドの中身を見ようとしたら f () { [native code] }
と言われて悲しい気持ちになることも多々あります。
JavaScriptの世界では、コードが変更されたら何かをするというのはかなり一般的です。
なのでテストやビルドを自動的に回し続けたりすることは可能です。
ただし、guard
のように監視ツールがまとめて面倒見てくれるのではなく、ツールごとに --watch
のオプションを実装しているパターンがほとんどです。
Pythonでは pdb
というデバッガが存在するらしいですが使われているんでしょうか?
特に機械学習やデータ処理系の人は Jupyter Notebook というコードが実行できるドキュメントシステムを使うことが多いようです。
たぶん彼らは python
コマンドの使い方を知らないんでしょう。
GOやJavaは昔ながらのデバッガを使うようです。
GOでは delve
というのが人気らしいです。
PHPにはデバッグという概念は存在しません。
Rubyはテストが書きやすく、テストを回しやすく、そして何より テストを止めやすい という点でデバッグ能力がめちゃめちゃ優れています。
いつも開発するときは binding.pry
で止めてコード読むので、
型が必要だとかドキュメントが必要だとか感じたことが全然ありません。
その場でほとんどのコードにアクセスできるのは本当に快適です。
とにかく他の言語でも止まって欲しい。
止まって、中身を見せて欲しい。
一番の問題は避けては通れないJavaScriptです。 特に最近は トランスパイル や 難読化 が必ず行われるので、ソースコードを読むことが非常に大変です。 ブラウザでしかデバッグできないのに、ブラウザが読み込んでいるのは難読化されたコードという地獄に陥ったりします。 とてもつらい。