A Pythonist in Rubyland

La verdad es que no pensaba que a estas alturas de la película hubiese programado en Ruby. ¿Porque? Porque soy un fanboy de Python y programando en Python no tiene ningun sentido hacerlo en Ruby, ya que son lenguajes que ocupan el mismo nicho. Pero es mas…, Python está aumentando su uso gracias a la comunidad científica, mientras que Ruby está estancado. Hay una migración real de desarrolladores de Ruby/Rails a Elixir.

Dicho esto, al menos en Madrid y en el mundo startapil, RoR se usa mucho. De hecho me está sorprendiendo todo lo que se usa frente a Python, ya que tenía la idea de que Python iba aumentando. Esto confirma que la popularidad de Python viene por el campo de data science.

Sólo hay un motivo intrínseco para usar Ruby IMO, que es que quieras probar Rails. El otro motivo es extrínseco, y es que te veas forzado.

Yo soy de la opinión de que el lenguaje da igual, al final es una herramienta para resolver un problema. Lo importante es el problema y darle solución. El lenguaje es lo de menos… Al final es una herramienta para definir la solución aplicando todo el know-how transversal que como desarrolladores tenemos.

Hay mucha información el la web comparándolos, por lo que no tiene sentido que yo lo haga. Pongo un enlace random reciente de ejemplo por completitud… ;p

De lo que sí que quiero hablar es de mis impresiones totalmente subjetivas… Son un conjunto de ‘Random Notes’. No me limitaré sólo al lenguaje, sino también al ecosistema.

Un par de disclaimers:

  • Considero que tampoco he estado programando lo suficiente para tener unos criterios más madurados
  • Sólo he manejado una base de código, pero sí que es cierto que he trabajado con desarrolladores experimentados

Sobre el ecosistema

  • Hoy en día está extendido el uso de bundler. Cuando en el pasado lo toqué por obligación de refilón no era así. Para un newbie es confuso que el comando sea bundle pero la gema sea bundler.

  • Rspec nació en la comunidad Ruby. Esto hace que tengan muy documentado como hacer mejores specs. A mi particularmente no me gusta del todo es estilo de specs que recomiendan porque no me parece muy BDD. Van al detalle de describir métodos, que no me parece correcto. Quitando ese detalle, está muy bien.

  • Puedes usar Active Record sin usar rails. Me ha parecido muy potente… He usado Django, pero no lo suficiente como para poderlos comparar bien. Desde el desconocimiento me ha parecido más potente, y me gusta que esté desacoplado del Framework. Cosas curiosas que he visto:

    • scopes: En Django puedes hacer lo mismo que haces con los scopes con los db managers, pero su uso es muchísimo mas engorroso.
    • Polymorphic models. ref implementation in django.
    • Enums. Permite hacer uso de métodos que se crean automáticamente [ref].
    • El forzar que se ejecuten las validaciones o no, dependiendo de si el método acaba con '!'. Es decir save() vs save!().
    • Encontré también las validaciones muy potentes.
  • Para procesamiento de tareas en background sidekiq está muy bien. Es muy sencillo poder lanzar una tarea en background o no, e incluso tiene extensiones muy útiles como por ejemplo para ejecutar batches.

  • Parece que hay una correlación entre proyectos Ruby y el uso de CircleCI. Personalmente no me ha gustado el uso que he visto (al estilo de la doc). Siento no poder extenderme más aquí, pero no tengo ya ejemplos. Si tu ya estás montando una imagen de docker en desarrollo, ¿que sentido tiene que hagas lo mismo, pero usando una sintaxis propietaria? Para eso ya tienes el Dockerfile….

  • Usamos Rollbar. No lo conocía y me gustó. Normalmente he usado Sentry.

  • Parece se usa bastante FactoryBot. Un DSL para crear datos de prueba. Está muy bien…

Sobre el lenguaje

No me limito sólo al lenguaje tal cual, ya que incluyo comentarios sobre puntos de estilo recomendados.

  • Es un lenguaje orientado a objetos al 100%. Todos los tipos son objetos. Esto te permite hacer cosas tal que:
    10.times do
        # multi-line body omitted
    end
  • Mola mucho, pero mucho mucho, lo fácil que es hacer DSL’s con él. Esto hace a que muchas de las herramientas que uses en el día a día realmente sean DSL’s.

  • Es un poco coñazo que los atributos de una clase sean privados. Al final te lleva a hacer uso de attr accesors.

  • Viniendo de un mundo donde hay una mejor forma de hacer las cosas la multitud de opciones que te da Ruby no me gusta. Está genial para por ejemplo hacer DSL’s pero si no usas un linter te puedes encontrar con una base de código muy variada. Supongo que esto ha llegado a la creación tardía de Ruby Style Guide y a su chequeo por Rubocop.

  • Prefiero identar con cuatro espacios.

  • Interesante el concepto de symbol

  • Interesante y potente que if y case sean expresiones.

  • ¿En serio tanto cuesta poner un return? Prefiero ser explícito y poner returns (en ruby no es necesario)

  • Tiene unless (if not). Realmente no me he acostumbrado a su uso… Me rallaba mucho.

  • Puedes poner un if al final de una expresión. Al principio cuesta acostumbrarse pero acaba molando…:

    raise("Failed to save document!") unless document.save
  • No se recomienda el uso de self. A mi personalmente me parece que el código es mucho más claro.

  • Mola poder tener '?' al final de metodos

  • ¿En serio se necesita nil?, blank?, y empty? [ref]?

  • No hay help() [ref].

  • No debugger integrado. Pero todo el mundo usa [pry]. Está muy bien.

Sobre rspec y testing

No sólo existe rspec, también hay bastante uso de minitest, porque es más rápido. Pero yo sólo he usado rspec.

  • No se usa inyección de dependencias y se ‘monky patchea’ a saco en los tests (rspec te lo pone muy fácil). El ‘monky patcheo’ se elimina cuando se acaba el contexto. Ejemplo (extracto):
    # simulate a not found resource
    context "when not found" do
      before { allow(Resource).to receive(:where).with(created_from: params[:id]).and_return(false) }
      it { is_expected.to respond_with 404 }
    end
  • Una de las mayores rayadas que me encontré al principio es que quería comprobar que estaba haciendo un test y me iba a la base de datos (de test), y no veía nada. Al final resultó que en el contexto de rspec no se estaba haciendo el commit de las transacciones. Vamos nunca se estaba escribiendo en la BD realmente. En relación a esto decir que hay que tener cuidado con los before.all y before.each. Pero ahora mismo no puedo elaborarlo más… Es una autonota. Tendría que probarlo de nuevo…

Sobre prácticas de los desarrolladores

  • Están muy acostumbrados a la consola. Te diría que mucho más que los de python. Me da la sensación que los pythoneros son mas de script y los de ruby más de consola (la de rails). Creo que el porqué, es por la unión de estos factores:

    • La potencia de active record
    • El no uso de inyección de dependencias
    • El autoload de rails

    Esto hace que con cuatro tecleos puedas hacer muchas cosas. Ejemplo:

    > Service1.new(key:'01-06-2018', model1_id: Model1.find_by_code('a_code').id).save()
    > AModule::Service2.run Service1.find(Service1.last.id)
  • Me han parecido menos pragmáticos en general que los pythoneros. Supongo que la filosofía del lenguaje para el deleite del programador tiene también este efecto. He visto más ‘cleveradas’ en código de lo que estoy acostumbrado.

  • Me he encontrado alineamiento de código. En un ejemplo sería tal que:

    a_hash = {
      one:   1,
      two:   2,
      three: 3
    }
  • Ruby te permite tener una sección privada en una clase, pero he visto poco uso de marcadores visuales como el típico prefijo usado en python, el underscore. Me parece que queda mucho más claro el código.

Recursos

Cuando pedí a amigos recursos para aprender me recomendaron:

Un recurso extra:

Cesar Ortiz

Read more posts by this author.

Madrid, Spain