El lanzamiento de Laravel 4 (también conocido como Illuminate), representó un gran cambio con respecto a la versión anterior. Laravel 4 reemplazó un framework que estaba construido mayormente por métodos estáticos, con otro que usa el poder de la inyección de dependencias, además de otros conceptos como los proveedores de servicio (o service providers) y, por supuesto, Composer. Sin embargo, a través del uso de Facades, se mantuvo el uso de los llamados como Route::get, View::make, etc.
Por lo tanto la versión 4, aunque incluyó muchos features, fue más, en mi opinión, un cambio de estructura por dentro, que de cara al usuario. Es decir, instalas Laravel 4 y aún puedes ver las mismas carpetas app/controllers, app/models/, y las mismas rutas en routes.php que tenías en Laravel 3:
Ahora, Laravel 5, además de nuevos features que amo como la inyección de dependencias dentro de los métodos, y otros que no me gustan tanto como las anotaciones en los controladores, es un cambio más hacia al usuario, la infraestructura del framework sigue siendo muy similar, pero el cambio se le plantea al usuario. Comenzando con un directorio de carpetas completamente nuevo:
¿Dónde está mi carpeta de modelos?
Si bien el patrón MVC (con el lanzamiento de frameworks como Ruby on Rails o CakePHP, que buscaba emular a Rails) le hizo mucho bien a nuestra forma de programar hace ya casi una década, hoy en día nos está perjudicando, de hecho, desde hace un tiempo el mismo Taylor Otwell en su libro From Apprentice To Artisan, nos recomienda eliminar la carpeta models/ y buscar un nuevo enfoque para estructurar nuestra aplicación.
– Ok, pero ¿Dónde coloco mis modelos?
Un modelo es un concepto muy genérico. Se supone que representa la lógica de negocio de nuestra aplicación, pero, al menos que estemos haciendo un sencillo sistema de noticias, nuestra aplicación puede resultar muy compleja para encapsularla en una sola capa.
Por ejemplo, veamos el siguiente modelo:
Pueden notar que sólo estamos viendo el encabezado de cada método mas no su contenido? Ahora, probablemente este usuario tendrá más relaciones, diferentes reglas dependiendo si se está registrando o actualizando, muchos más getters, y muchos queries para poder acceder a diferentes tipos de usuarios, además de muchísima más lógica de negocios, etc.
Fácilmente en una aplicación de mediano tamaño tendríamos 5 veces más métodos, y una clase con 1000 o 2500 líneas, ¡En un mismo archivo!
Este escenario hace que nuestro código se vuelva realmente difícil de manejar, depurar, probar, refactorizar, reusar, etc. Además es una clara violación del Single Responsability Principle, que es uno de los 5 principios básicos de la programación orientada a objetos, introducidos por Robert Martin (también conocido como «Uncle Bob») y que nos indica que una clase debe tener una única responsabilidad o razón de existir.
¿Cuál es la responsabilidad del objeto User descrito arriba? ¿Cuál es la responsabilidad de la última clase que creaste en tu proyecto? Si te encuentras a ti mismo definiendo una clase usando la conjunción «y», probablemente has roto este principio. Por ejemplo, la clase User descrita más arriba, define una entidad de usuarios, pero además hace consultas, valida y activa usuarios, etc. Demasiadas responsabilidades.
Al eliminar la carpeta models/ nos obligamos a pensar cómo estructurar nuestra aplicación. ¿Queremos hacer una consulta para traer usuarios de la base de datos? Quizás necesitemos un repositorio. ¿Queremos validar un usuario? Quizás necesitemos crear una clase Validator, Request o Manager. ¿Necesitamos definir lógica para activar un usuario incluyendo el envío de emails, etc.? Quizás debamos crear una capa adicional para ello.
Para que tengan una idea, les comparto la estructura de carpetas del proyecto en el que estoy trabajando:
Al principio puede parecer demasiado, pero con el tiempo te darás cuenta que tener clases pequeñas con responsabilidades únicas hacen tu código mucho más fácil de manejar, y tu proyecto muchísimo más ordenado.
A pesar de ello mi modelo de Usuario en este proyecto tiene unas 200 líneas de código. Imaginen cuantas tendrían si no fuera por esta separación.
Estructura por módulo y no por tipo
Otra forma de estructurar tu aplicación es hacerlo por módulos en vez de por tipos, es decir en vez de crear una carpeta repositories y otra entities, crea una carpeta Section (suponiendo que estamos desarrollando un módulo de secciones) y dentro de Section entonces crea Section.php (sería la entidad) y SectionRepo.php (sería el repositorio) y así sucesivamente, como puedes ver en esta imagen:
¿Cómo Laravel carga mis clases automáticamente?
Buena pregunta, anteriormente estábamos en la consola ejecutando composer dump-autoload cada 5 minutos, no es muy práctico, sin embargo ahora podemos usar PSR-4, supongamos que estamos creando un proyecto llamado Acme y crearemos las clases del proyecto dentro de app/Acme/ entonces en el archivo composer.json agregamos lo siguiente:
"autoload": { "psr-4": { "Acme\\": "app/Acme" } }
Luego ejecutamos composer dump-autoload una única vez y con esto ya Composer y Laravel sabrán cómo cargar nuestras clases de aquí hasta el fin del proyecto. Sólo debes tener en cuenta que si agregas una clase en app/Acme/User/UserRepo.php la clase debe llamarse UserRepo (tal como el nombre del archivo sin la extensión .php) y debe tener un namespace de Acme\User tal como las carpetas donde se encuentra, es decir, de esta forma:
Conclusión
Al eliminar la carpeta models e incluir PSR-4 por defecto, Laravel 5 obliga a los usuarios a pensar en la estructura de su aplicación. Si estás trabajando con Laravel 4, puedes dar un paso y eliminar tú mismo la carpeta de modelos y hacer una estructura similar a la de Laravel 5, tal como te explique en este post. Si lo haces o para quienes ya trabajan así el cambio de versión de Laravel será no sólo mucho más fácil de manejar, sino también bastante esperado.
¿Listo para aprender Laravel 5? Aquí tenemos un curso completo para ti.
Regístrate hoy en Styde y obtén acceso a todo nuestro contenido.