Se está instando a los desarrolladores que construyen aplicaciones Laravel a abandonar la palabra clave new dentro de sus controladores y cambiar al patrón Factory Method. Al trasladar la creación de objetos a fábricas dedicadas, el código se vuelve más fácil de extender, probar y mantener; beneficios que cobran importancia a medida que los proyectos crecen más allá de un puñado de endpoints.
Por qué la palabra clave new es un riesgo oculto
Cuando un controlador contiene una línea como
$processor = new StripePaymentProcessor($config);
el controlador queda estrechamente acoplado a la clase StripePaymentProcessor. Cada lugar que necesite un procesador de pagos repite esa línea, dispersando la lógica de construcción por todo el código base. Si más adelante el procesador requiere un logger, un gestor de caché o un formato de configuración diferente, cada uno de esos puntos debe actualizarse. El resultado es un código frágil que se resiste al cambio y es difícil de simular (mock) en pruebas unitarias.
El patrón Factory Method entra en acción
El patrón Factory Method reemplaza la instanciación directa con un método que devuelve una instancia de una interfaz determinada. El controlador depende de la interfaz, mientras que una clase fábrica sabe qué clase concreta construir y cómo ensamblar sus dependencias. Toda la lógica de creación reside en un solo lugar, por lo que añadir una nueva dependencia o intercambiar implementaciones solo afecta a la fábrica.
Ventajas principales
- Acoplamiento débil – Los controladores trabajan con abstracciones, no con clases concretas.
- Construcción centralizada – Cambiar el proceso de construcción requiere editar un único archivo.
- Testeabilidad – Las fábricas pueden ser sustituidas por stubs o mocks, lo que permite realizar pruebas de controladores aisladas.
- Principio de Abierto/Cerrado – Se pueden añadir nuevas funcionalidades (por ejemplo, una nueva pasarela de pago) sin tocar el código existente del controlador.
Una analogía de una cafetería
Imagina a un barista que debe moler los granos, vaporizar la leche y verter el agua manualmente para cada pedido, utilizando una larga serie de sentencias if-else. Si la receta del latte cambia, cada barista debe volver a aprender los pasos. Una máquina de café que recibe un tipo de pedido y gestiona la preparación internamente resuelve el problema: el barista simplemente le dice a la máquina lo que se necesita, y la máquina encapsula todos los pasos. Actualizar la receta ahora significa ajustar la máquina, no a cada barista.
Laravel ya se apoya en las fábricas
Los propios componentes principales de Laravel ilustran el patrón en acción:
- Base de datos –
ConnectionFactorydecide si construir una conexión MySQL o PostgreSQL. - Colas (Queues) –
QueueManagercrea drivers para Redis, SQS u otros back-ends. - Sistema de archivos –
FilesystemManagerproduce instancias de discos locales o S3. - Correo (Mail) –
MailManagerresuelve drivers de SMTP, Mailgun u otros.
Si el framework confía en las fábricas para estos servicios críticos, el código personalizado debería hacer lo mismo.
Cuándo introducir una fábrica
Usa una fábrica cuando:
- La creación de objetos implica múltiples pasos de configuración o servicios externos.
- Existen varias implementaciones intercambiables (diferentes pasarelas de pago, proveedores de almacenamiento, etc.).
- Se espera que la lista de posibles implementaciones crezca.
Evita una fábrica cuando:
- La construcción es una única llamada
newinmutable sin configuración adicional. - Solo se utilizará una implementación, lo que convierte la abstracción adicional en una sobrecarga innecesaria.
Guía rápida: refactorización de un controlador de pagos
- Define una interfaz –
PaymentProcessorInterfacecon un métodoprocess(array $data). - Implementa clases concretas –
StripePaymentProcessor,PayPalPaymentProcessor, cada una cumpliendo con la interfaz. - Crea una fábrica –
PaymentProcessorFactorycon un métodomake(string $driver): PaymentProcessorInterface. En su interior, utiliza unswitcho un mapa para devolver la clase adecuada, inyectando cualquier servicio requerido desde el contenedor de servicios de Laravel. - Inyecta la fábrica – En el constructor del controlador, utiliza el type-hint
PaymentProcessorFactory. Laravel la resolverá automáticamente. - Usa la fábrica –
$processor = $this->processorFactory->make('stripe'); $processor->process($request->all());
Ahora el controlador nunca menciona new ni un procesador concreto. Añadir una nueva pasarela significa crear una clase y extender el mapa de la fábrica, sin realizar cambios en el controlador.
Posibles desventajas y cómo mitigarlas
La principal crítica hacia las fábricas es la indirección añadida, lo que puede resultar verboso para objetos triviales. El exceso de ingeniería en un servicio simple puede inflar la base de código sin un beneficio real. La clave está en evaluar la complejidad de la construcción: si un objeto es un simple contenedor de datos sin dependencias, un new directo puede ser aceptable. Además, las fábricas pueden convertirse en un vertedero de lógica no relacionada. Mantener las fábricas enfocadas en la creación de objetos y delegar la configuración a proveedores de servicios dedicados preserva la claridad.
Qué tener en cuenta a continuación
- Vinculaciones del contenedor de servicios – El contenedor de Laravel puede resolver fábricas automáticamente si vinculas la interfaz a la clase de la fábrica en un service provider.
- Autodescubrimiento – Algunos paquetes exponen sus propias fábricas; ten cuidado con las colisiones de nombres.
- Estrategias de prueba – Al realizar pruebas unitarias de controladores, reemplaza la fábrica con un mock que devuelva un procesador simulado (stubbed), asegurando que las pruebas sigan siendo rápidas y aisladas.
Conclusión
Reemplazar las llamadas new dispersas con una fábrica bien ubicada centraliza la construcción, reduce el acoplamiento y alinea el código personalizado con la propia filosofía de diseño de Laravel. Para equipos que anticipan crecimiento —nuevos proveedores de pago, back-ends de almacenamiento o cualquier componente de tipo plug-in— el patrón Factory Method es una inversión de bajo costo que rinde frutos en flexibilidad y confianza. Tu "yo" del futuro, y cualquiera que herede el código, te lo agradecerá.
