¡Muy buenas a todos! Cuánto tiempo, ¿no?. Quizás te preguntes, ¿qué te ha pasado Alberto? La verdad es que llevo años (y lo digo en serio) queriendo acompañar mis posts con videos en YouTube y me prometí que el siguiente post llevaría un vídeo sí o sí… ¡lo que no anticipaba es que me costaría tanto! Básicamente esta autoimposición me sacaba totalmente de mi zona de confort y más que nada me ha costado por vergüenza y por mi habitual perfeccionismo que siempre tiene el efecto secundario de bloquearme, así que al final he asumido que mis primeros vídeos no serán la capilla Sixtina, que se verán cutres y que lo que digo en ellos, igual que lo que digo en mis posts, mejoraré poco a poco con el tiempo según voy aprendiendo. En mi caso desde luego lo que necesito es empezar, aunque sea de cualquier manera, en lugar de seguir más años rumiando la misma matraca.

Hoy voy a hablaros de qué pinta tienen los service objects con los que puedo trabajar en mi día a día trabajando con Ruby on Rails.

¿Qué es un service object en Rails?

Si ahora mismo estás pensando… “pero, ¿qué es eso de service object?, ¡si eso no sale en Rails por ninguna parte!” Tranquilidad. No encontrarás ningún service object en la estructura por defecto de Ruby on Rails, pero eso no quiere decir que no se puedan usar, es más, muchas empresas los usan… ¡Tanto que hasta tienen su mención en la guía de Autoloading de Rails!

Los services objects, también conocidos como action objects o workflow objects, son unos objetos que sirven para modelar lógica de negocio de tu aplicación que típicamente en una aplicación Rails estaría repartida entre el controlador y el modelo, ya sea mediante métodos o callbacks. En lugar de tener toda la lógica de negocio esparcida por ahí la tienes en un sitio claro, bonito y conciso.

¿Cuándo usar los service objects?

La respuesta, como en muchas cosas en el desarrollo de software, es que depende de gustos. Yo he estado en equipos en los que los usaban siempre, hasta el extremo, es decir, la acción del controlador era una única línea de código que instanciaba el service object y le mandaba un mensaje, y por otro lado, también he estado en equipos que decían que de eso nada, aquí todo en modelos, controladores y callbacks que así es como se hace en Basecamp. En mi caso me gusta usarlos cuando la lógica de negocio es compleja y siento que no pertenece al modelo, cuando me parece que tenerla en callbacks puede complicar otros flujos o simplemente cuando el hecho de extraerla en un objeto propio me permitirá tener una mayor legibilidad del código o reutilizarlo en un futuro.

Nombrado

Nombre del servicio

Respecto al nombre, ¿qué nombre le ponemos? Personalmente me gusta utilizar nombres derivados de un verbo como por ejemplo Orders::Builder para crear un pedido por ejemplo una tienda en la que el proceso es complejo, requiere de validaciones, etc.

Nombre del método principal

Sobre este aspecto me gusta un nombre del método que revele la intención de lo que va a ocurrir en él. Para el ejemplo anterior, lo más trivial sería usar build, pero si tenemos diferentes sabores o alternativas como fetch_or_build_by podremos expresarlo perfectamente con este tipo de convención. Mucha gente, entre los que quizás te encuentres, adoptan la convención de nombrar a este método call. Personalmente la idea de utilizar este nombre para todos los servicios a piñón no me seduce. Sinceramente no me gusta porque, además de que en cierta manera te obliga a tener un único método por servicio, pierdes toda expresividad y posibilidad de ayudar al lector de tu código a entender qué hace este método concreto de tu servicio. Además, el nombre call ya se usa en Ruby para procs y lambdas, y el hecho de ver call como nombre de un método siempre despista a mi cabeza llevándola a pensar que está tratando con procs o lambdas.

¿Dónde colocar los service objects en tu aplicación Rails?

En este paso sigo la convención más aceptada y que he visto en todas partes en las que he trabajado sin excepción, y es, bajo app/services, que como ya vimos antes, aparece mencionada así en la guía de Autoloading de Rails.

Otras alternativas a los service objects en Rails

Como ya mencioné anteriormente, la alternativa más común en una aplicación de Rails es tener toda esta lógica de negocio distribuida en métodos y callbacks de controladores y modelos, pero además existe otra alternativa, llamada process objects, de los que hablaremos en otra ocasión.