Usando la nueva gema debug para 'debuggear' en Ruby

Publicado el Jueves, 8 de junio de 2023

Desde hace poco empecé a usar el debugger nuevo en Ruby 3: debug. Tengo un vago recuerdo de que cuando empecé a programar con Ruby, el debugger era medio complicado. Si no recuerdo mal debug o ruby-debug era el debugger original, pero después cayó en desuso (o el código no se mantenía) y empecé a usar byebug. Pero esto pasó hace más de 10 años así que no confío mucho en mis recuerdos vagos (que no es lo mismo que "no confío mucho en mis recuerdos, vagos").

Leyendo sobre debug en el blog de Koichi Sasada, su programador principal, parece que mi memoria no está tan mal: debug.gem es un debugger para Ruby. Es un nuevo reemplazo de lib/debug.rb el cual está instalado desde el anciano Ruby 1.3.1 (!!). Sin embargo, lib/debug.rb no ha sido bien mantenido con el tiempo y nadie lo usa.

La nueva gema debug apareció con Ruby 3.1 (diciembre de 2021). Al instalarla con gem install debug, reemplaza a lib/debug.rb de la biblioteca estándar de Ruby. En su README, lista algunas ventajas: es rápida, permite debugging remoto con soporte nativo (UNIX domain socket (UDS), TCP/IP, integración con frontends de debugging), extensible, soporta hilos (casi terminado) y ractors (eventualmente), y más.

Hace tiempo que quería empezar a usarlo, pero cuesta sacarse la costumbre después de años usando byebug. Por suerte, la transición no me costó casi nada. Para usar debug, definimos "breakpoints" en nuestro código y al ejecutarlo el debugger nos va a proveer una consola de "debugueo" (qué difícil el Espanglish). La verdad que funciona y se ve muy bien, y no he encontrado nada que hacía con byebug que no pueda hacer con debug. Lo vengo usando a diario desde hace un tiempo y todo bien.

Para invocar al debugger en nuestro código, tenemos que requerir "debug" y llamar al método binding.break, que a su vez tiene dos alias que pueden resultar más cómodos: binding.b y debugger.

En la consola de debug, tenemos varios comandos útiles para analizar el código. Éstos son los comandos que uso generalmente:

  • info muestra información del código que estamos ejecutando.
  • bt o backtrace para ver información del backtrace actual.
  • l o list muestra el código fuente actual.
  • n o next "step over", sigue ejecutando el código siguiente.
  • s o step "step in", ingresa al código (por ejemplo de una función).
  • c o continue resume el código.
  • q o Ctrl + D Salir.

Mi entorno de desarrollo con Ruby consiste de Emacs y la terminal. Ejecuto tests y código Ruby siempre desde la terminal. De repente en algún momento intento probar si hay una integración de Emacs con debugger (Koichi Sasada dice que se puede), pero ese es un camino sólo de ida que todavía no empecé a caminar. Hay un montón de características más que no he tenido la necesidad de probar, pero como actualización a byebug, funciona perfectamente.

Mini pique Emacs:

De cuando usaba byebug, tengo una función en mi configuración de Emacs para llamar al debugger con un atajo de teclado en cualquier parte de mi código Ruby:

;; Require byebug
(defun add-byebug()
  (interactive)
  (beginning-of-line)
  (insert "require 'byebug'; byebug")
  (indent-according-to-mode)
  (newline-and-indent)
  )

Esto agrega el código require 'byebug'; byebug donde se encuentra el cursor. Lo llamaba con las teclas C-c y:

(global-set-key (kbd "C-c y") 'add-byebug)

Para debug hice lo mismo, pero agregando require 'debug'; binding.break:

(defun add-binding-break()
  (interactive)
  (beginning-of-line)
  (insert "require 'debug'; binding.break")
  (indent-according-to-mode)
  (newline-and-indent)
  )

2 comentarios en este post

Feed de comentarios
  1. Avatar

    grilix 8 junio. 2023 - 09:42

    Opi, el debugue remoto puede estar bueno para cuando corremos la app en containers, que a veces da dolores de asno. Integrar el debug con el IDE está sobrevalorado, igual que la horrible palabra DEPURACIÓN. Buen contenido, sigue así!

Dejar un comentario

Toasty!