# 🚩 Ejercicio 7 · El controller que hace todo

**Clase 7 — Servicios e inyección de dependencias**
· Dificultad: 🔴 alto · Tiempo estimado: 75–90 min

---

## La situación

El Liquidador tiene que emitir recibos. Hay dos formas de calcular el neto
—una simple y una detallada— y el sistema debería poder cambiar de una a otra
**sin tocar el código que liquida**.

Hoy no puede: el controller fabrica sus propias dependencias con `new` y elige a
mano qué calculadora usar.

```php
$servicio = new LiquidacionService();     // ❌ acoplado
```

Y el `LiquidacionService` está vacío: la lógica de negocio todavía vive en
ningún lado.

## Lo que hace especial a este ejercicio

Cada corrida te muestra **el árbol que arma el container** cuando le pedís una
sola cosa:

```
  Pediste: ReciboController

  ReciboController
      ↳ LiquidacionService
          ↳ CalculadoraNeto → CalculadoraDetallada
          ↳ EmpleadoRepository

  Ni un solo `new` escrito por vos.
```

Eso es la "magia" de Laravel, desarmada: el container lee los **tipos** que
declarás en los constructores y va construyendo hacia abajo. Está implementado
en `src/nucleo/Contenedor.php`, en unas 60 líneas que se leen de una sentada.

Y al final te muestra la prueba del desacople:

```
  ligar(CalculadoraNeto::class, CalculadoraDetallada)  →  neto  $996.000,00
  ligar(CalculadoraNeto::class, CalculadoraBasica)     →  neto  $890.000,00
```

**Una línea** cambia el resultado de toda la aplicación.

## Tus tres tareas

| # | Dónde | Qué |
|---|---|---|
| 1 | `proveedor.php` | Registrar la **ligadura** del contrato |
| 2 | `app/Servicios/LiquidacionService.php` | Recibir las dependencias e implementar la lógica |
| 3 | `app/Controllers/ReciboController.php` | Sacar los `new`: recibir el service **por constructor** |

(Son tres archivos, pero se verifican cinco cosas: las dos últimas son
consecuencias que solo se cumplen si lo anterior está bien hecho.)

## Cómo correrlo

```bash
docker compose run --rm ejercicio
```

Con los cinco pasos en verde aparece tu bandera `ipap{c07-xxxxxxxxxx}`.

> **Sin Docker:** `cd src && php index.php`

## Lo que vas a practicar

| Paso | Concepto de la clase |
|------|----------------------|
| 1 | **Service Provider** y **bindings**: dónde se decide qué implementación se usa |
| 2 | **Service Layer** e **inyección por constructor** |
| 3 | **Service Container**: pedir en vez de fabricar |
| 4 | Que el **Repository** aísle el acceso a datos |
| 5 | **Desacoplamiento**, medido de verdad |

## Dos pasos que no se pueden falsear

Este ejercicio verifica cosas distintas a las de los anteriores. No alcanza con
que el resultado esté bien: tiene que estar bien **por el motivo correcto**.

**Paso 3.** Se liga un `LiquidacionService` impostor y se mira si tu controller
lo usa. Si el controller hace `new` adentro, nunca se va a enterar del impostor
—aunque el recibo salga perfecto—. Es la única forma de probar que de verdad le
pide al container.

**Paso 5.** Se corre lo mismo dos veces cambiando **solo la ligadura**. Si los
resultados son distintos, el desacople es real. Si son iguales, hay una clase
concreta escrita a mano en algún lugar del camino.

Por eso no sirve "hacer que funcione": hay que hacerlo bien.

## Si te trabás

1. **La ligadura.** Una línea en `proveedor.php`. El error del container te dice
   exactamente qué contrato no sabe resolver.
2. **El constructor del service.** Declaralos **con su tipo completo**: el
   container resuelve por el tipo, así que sin tipo no puede hacer nada.
   La promoción de propiedades de PHP 8 (`private Tipo $x` en el constructor)
   te ahorra escribir las asignaciones.
3. **El controller.** Cuando termines, este archivo **no debería nombrar ninguna
   calculadora ni el repositorio**. Solo el service. Si todavía los menciona,
   algo quedó acoplado.
4. **Ojo con el orden.** El paso 2 no puede dar verde si el paso 1 no está: el
   container no puede armar el service si no sabe qué calculadora entregarle.

---

## Lo interesante

Cuando termines, buscá en todo el proyecto la palabra `CalculadoraDetallada`.
Va a aparecer **en un solo lugar**: `proveedor.php`.

Eso es lo que se gana. Mañana Contaduría pide una tercera forma de calcular:
se agrega una clase que cumpla el contrato y se cambia esa línea. El controller,
el service y el repositorio no se enteran.

Y hay un beneficio que se ve menos pero pesa más: **como el container decide qué
instancia entrega, en un test podés pedirle que entregue una falsa.** Es
exactamente lo que hace el paso 3 de este verificador — y es la razón por la que
en la Clase 12 vamos a poder testear la lógica de liquidación sin base de datos.

> Una advertencia honesta, la misma que está en la diapositiva: estos patrones
> **no son obligatorios**. En una aplicación chica pueden ser puro ruido. Se
> justifican cuando la lógica se repite, cuando hay más de una implementación
> posible, o cuando hace falta testear. Criterio antes que dogma.
