¿Cuáles son algunos malos hábitos típicos de los ingenieros de Ruby?

Mutación incontrolada y efectos secundarios.

Veamos una línea de código de un carrito de compras en línea:

fin.finalizar

¿Puedes adivinar qué llamará este método? ¿Actualizará el objeto Order? ¿Actualizarlo en la base de datos? Crear más registros? ¿Seleccionará LineItems de la base de datos? ¿Actualizar un total en caché en el objeto Order? ¿Envía un correo electrónico al usuario que realizó el pedido? ¿Inicia trabajos en segundo plano, vacia cachés, importa un módulo? ¿Qué hace este método que ni siquiera hemos considerado?

No podemos adivinar. Tenemos que buscar en el código para averiguarlo, y cada método llamado requiere más preguntas abiertas.

Las pruebas no nos salvarán. Son lentos, tal vez fallan o pasan cuando no deberían, y los cambios aparentemente triviales causan docenas de fallas. Es posible que las especificaciones aspiren a especificarse, pero nos estamos moviendo de un lado a otro entre las fábricas y las que intentan descubrir un doble de prueba en particular para acelerar una prueba o asegurarnos de que se envíe un correo electrónico. Y eso asumiendo que existen en absoluto; es una triste realidad que la mayoría de las veces las pruebas faltan en las funciones complejas para las que más las queremos.

Es imposible razonar acerca de un programa cuando no tiene una base sólida, ya que todo lo que haces puede rechazar un cambio en otra parte del sistema. La funcionalidad migra a devoluciones de llamada porque no hay control sobre los ciclos de vida de los objetos. Las pruebas se convierten en “demasiados problemas” cuando tiene que apagar la funcionalidad aparentemente desconectada para el rendimiento o para evitar la creación de instancias de docenas de objetos. Los objetos a menudo son “parcialmente válidos”, lo que desencadena un acoplamiento temporal o, lo que es peor, proporciona un caldo de cultivo para las dependencias cíclicas.

El control de la mutabilidad nos da valores para evitar la obsesión primitiva, valores que pueden pasarse de manera segura como argumentos sin ninguna posibilidad de que sean modificados por algún sub-sub-sub-método.

Controlar los efectos secundarios nos da una jerarquía. En el nivel más alto, describimos de dónde provienen los datos y sin tener que temer que algún objeto escondido actualizará el estado global. En los niveles más bajos escribimos lógica empresarial pura.


Entré en detalles sobre cómo lidiar con esto en mi charla de RailsConf 2015. La mayor parte del texto anterior es un extracto de mi libro de Ruby en progreso; puede unirse a la lista de correo electrónico en esa página para obtener más extractos y recursos a medida que la complete.

Copie y pegue el código que ha encontrado en el desbordamiento de pila en lugar de entender la respuesta y crear su propio código.

Es metaprogramación. Cuando los métodos se mezclan dinámicamente, no hay un controlador de métodos, etc. Toda esta magia es excelente para DSL, pero es realmente difícil depurar dicha aplicación e investigar problemas.