Service Objects en Rails

Un pequeño ensayo a favor de los service objects

Fernando E. Silva Jacquier

fesilvajacquier

Tech Lead en Boxful
Consultor
Teacher en Le Wagon

Empecemos por las críticas

> The wrong object causes more trouble than no object at all
> Service Objects accumulate invisible inter-service coupling

Enough With the Service Objects Already by Avdi Grimm

> What does this mean? It means the service object pattern has no intrinsic ability to make your codebase easier to read, easier to maintain, simpler, or exhibit better separation of concerns.

Why Service Objects are an Anti-Pattern by Jared White

Entonces, ¿Por qué son tan populares los service objects?

La doctrina de de Rails dice: No one paradigm

> Rails isn't like that. It isn't a single, perfect cut of cloth. It's a quilt. A composite of many different ideas and even paradigms. Many that would usually be seen in conflict, if contrasted alone and one by one. But that's not what we're trying to do. It isn't a single championship of superior ideas where a sole winner must be declared.

Peeeeeeeero...

Patterns of Enterprise Application Architecture

En Rails Guides - Active Record Basics se hace mención directa a Patterns of Enterprise Application Architecture de Martin Fowler

Un libro donde se habla del Service Layer Pattern. Que propone una service layer que coordina domain objects

Domain Driven Design

En las guías de Rails no se menciona a Domain Driven Design pero muchas de sus ideas están presentes.

Por ejemplo, los conceptos de layered architecture (cómo en el patrón MVC) y domain objects.

Este es un libro donde se habla de una Application Layer que deber ser fina, no contener lógica de negocio (porque la lógica de negocio debería estar en los domain objects) y también habla del concepto de Services.

Yyyy...

MVC Architecture

En las guías de Rails no se menciona quién se encarga de coordinar a los domain objects

Acá la charla se podría bifurcar

Meme Paths

No usa Service Objects

> We don't distinguish application and domain layers

Code I Like - IV - Vanilla Rails is Plenty by Jorge Manrubia (37 signals)

No usa Service Objects

Maybe: The personal finance app for everyone

Usa Service Objects

Architecture Abstractions Layers

Layered Design for Ruby on Rails Applications by Vladimir Dementyev (Evil Martians)

Por qué usar service objects

Partamos de un ejemplo (casi) real

Subscription Versions Subscription Versions 1 Subscription Versions 2 Subscription Versions 3

Dónde va la lógica?

Dónde va la lógica? 0 Dónde va la lógica? 1 Dónde va la lógica? 2 Dónde va la lógica? 3

El principal beneficio...

Feels right

Otros beneficios


              class Subscription::RemoveCoupon
                include Interactor::Organizer

                before do
                  context.coupon_id = nil
                end

                delegate :subscription, :coupon_id, to: :context

                organize SubscriptionVersion::UpsertPending,
                         SubscriptionVersion::Process,
                         Subscription::UpdateUpcomingInvoice,
                         Customer::NotifyNewSubscriptionVersion
              end
            
Gema: Interactor

Cómo aplicarlos

Tenemos que evitar el problema real


              # Cómo se llaman?
              # subject + actor (entidad que ejecuta el verbo)
              User::PlanUpdater
              # subject + verb (+ object)
              User::UpdatePlan # -> user.update(plan)
            

              # Qué devuelven?
              result = User::UpdatePlan

              result.is_a?(User) # ???
              result.is_a?(TrueClass) # ???
              result.is_a?(FalseClass) # ???
              result.is_a?(ResultObject) # ???
            

Cómo se siente este problema?

La Plata Venecia

The name of the game is convention

Shape 0 Shape 1 Shape 2 Shape 3 Shape 4

Y también es importante desde dónde lo llamamos

Mermaid Diagram

The Fowler Evans Ruler de Ivan Nemytchenko

Principio Verifica
1. Sin estado (Stateless) No tiene variables de instancia ni estado interno
2. Nombrado por una actividad Nombre claro orientado a la acción
3. Representa una operación de negocio Expresa un proceso del mundo real
4. Coordina objetos del dominio Llama a métodos en entidades/value objects
5. Controla transacciones Cambia el estado del sistema
6. Tiene efectos secundarios Produce un impacto observable
7. Sin lógica de aplicación Separación clara de la interfaz y la infraestructura

No hace falta reinventar la rueda

Podemos usar alguna de las gemas que ya existen para esto.

¿Preguntas?

El código de la presentación está en https://github.com/fesilvajacquier/servisis
Y pueden ver las slides en https://fesilvajacquier.github.io/servisis/