# Comparando el estilo “clásico orientado a clases” con el estilo Ruby-idiomático, funcional y modular

Vamos a **aterrizar la idea de Dave Thomas con código Ruby real**, comparando el estilo “clásico orientado a clases” con el estilo **Ruby-idiomático, funcional y modular**, y viendo *por qué* el segundo suele envejecer mejor.

No es una religión. Es ingeniería pragmática.

## 1. El punto de partida clásico (el reflejo Java)

![Comparando el estilo “clásico orientado a clases” con el estilo Ruby-idiom�](fig-01.webp)

Imagina un caso típico: procesar un pedido.

### Enfoque habitual con clases

```ruby
class Order
  attr_reader :items, :customer

  def initialize(items:, customer:)
    @items = items
    @customer = customer
  end

  def total_price
    items.sum(&:price)
  end

  def valid?
    items.any? && customer.active?
  end
end

class OrderProcessor
  def initialize(order)
    @order = order
  end

  def process
    raise "Invalid order" unless @order.valid?

    charge_customer
    send_confirmation
  end

  private

  def charge_customer
    PaymentGateway.charge(@order.customer, @order.total_price)
  end

  def send_confirmation
    Mailer.order_confirmation(@order)
  end
end
```

Esto es correcto. También es **más estructura de la necesaria**.

Problemas sutiles:

 - Las clases no modelan cosas del mundo real, sino **pasos de un flujo**
 - La lógica está dispersa
 - Probar `OrderProcessor` implica instanciar `Order`
 - La clase existe *solo* para agrupar métodos

## 2. La propuesta de Dave Thomas: empieza por acciones

Ruby no te obliga a empezar pensando en “objetos”.
Puedes empezar pensando en **verbos**.

### Enfoque funcional y plano

```ruby
def total_price(items)
  items.sum(&:price)
end

def valid_order?(items, customer)
  items.any? && customer.active?
end

def process_order(items:, customer:)
  raise "Invalid order" unless valid_order?(items, customer)

  PaymentGateway.charge(customer, total_price(items))
  Mailer.order_confirmation(items, customer)
end
```

Observa algo importante:

 - No hay *estado implícito*
 - Cada función hace **una cosa**
 - Las dependencias son explícitas
 - Es trivial testear cada función

Esto **ya es Ruby de primera clase**, no un atajo.

## 3. “Pero esto queda desordenado”: módulos al rescate

![Comparando el estilo “clásico orientado a clases” con el estilo R](fig-02.webp)

Aquí es donde mucha gente se pone nerviosa.
Dave Thomas dice: *no saltes a clases, usa módulos*.

```ruby
module Orders
  module Pricing
    def self.total(items)
      items.sum(&:price)
    end
  end

  module Validation
    def self.valid?(items, customer)
      items.any? && customer.active?
    end
  end

  module Processing
    def self.process(items:, customer:)
      raise "Invalid order" unless Validation.valid?(items, customer)

      PaymentGateway.charge(customer, Pricing.total(items))
      Mailer.order_confirmation(items, customer)
    end
  end
end
```

Esto aporta:

 - Namespacing claro
 - Ningún estado oculto
 - Ninguna jerarquía artificial
 - Código legible como un **mapa mental del dominio**

## 4. ¿Cuándo sí aparece una clase?

Dave Thomas no es anti-clases.
Las clases **aparecen cuando hay identidad y estado duradero**.

Ejemplo: un `Money`, un `User`, un `Session`.

```ruby
class Money
  attr_reader :amount, :currency

  def initialize(amount, currency)
    @amount = amount
    @currency = currency
  end

  def +(other)
    raise "Currency mismatch" unless currency == other.currency
    Money.new(amount + other.amount, currency)
  end
end
```

Aquí la clase tiene sentido porque:

 - Tiene identidad
 - Encapsula invariantes
 - Protege reglas internas

Lo que Dave Thomas critica es crear clases **solo para colgar métodos**.

## 5. Un ejemplo muy Rails-real (Service Objects)

![Comparando el estilo “clásico orientado a clases” con el estilo R](fig-03.webp)

El patrón clásico Rails:

```ruby
class CreateUser
  def initialize(params)
    @params = params
  end

  def call
    user = User.new(@params)
    user.save!
    Mailer.welcome(user)
    user
  end
end
```

La versión “Ruby puro”:

```ruby
module Users
  def self.create(params)
    user = User.create!(params)
    Mailer.welcome(user)
    user
  end
end
```

Pregunta incómoda:
👉 ¿qué aporta realmente la clase `CreateUser`?

Respuesta honesta: **nada**, salvo ceremonia.

## 6. Beneficios reales (no filosóficos)

Después de años, este estilo suele ganar porque:

 - El código crece **horizontalmente**, no en jerarquías
 - Refactorizar es más fácil
 - Las dependencias están a la vista
 - Los tests no requieren dobles complejos
 - El dominio se expresa como lenguaje, no como UML

Esto es muy Ruby y muy Pragmatic Programmer.

## 7. La idea profunda del vídeo (la que no sale en el código)

La charla no va de clases.
Va de esto:

**No diseñes por anticipación la forma final del sistema.
Deja que la estructura emerja del uso real.**

Las clases son una **decisión tardía**, no el punto de partida.
