Formas de organizar el código

Excepto las prácticas de primero de carrera y algunos scripts muy simples, cualquier aplicación acaba constando de un montón de ficheros que necesitamos organizar de alguna manera en carpetas para poder manejarlos sin volvernos locos.

Existen muchas formas de organizar el código y en ellas influye mucho el gusto de cada uno o las convenciones aplicadas por cada equipo de desarrollo, pero eso no quita que también haya formas más o menos estándar, cada una de ellas centrada en mejorar determinados aspectos.

En este post vamos a ver dos filosofías distintas a la hora de organizar el código y veremos qué nos puede aportar cada una.

Organización por roles tecnológicos

La organización por roles es una de las más extendidas actualmente en el desarrollo de software. Probablemente uno de los proyectos que más hizo por este tipo de organización fue Ruby on Rails con su convención sobre configuración basada en la ubicación física en disco de sus modelos, vistas y controladores, y que luego ha sido copiada por otros frameworks como ASP.NET MVC.

Esta organización se basa en agrupar los ficheros en base al rol tecnológico que desempeña en el sistema. De esta forma, si en la capa de presentación estamos aplicando un patrón MVC, tendremos carpetas con Models, Views y Controllers o si tenemos un modelo de dominio estilo DDD, tendremos carpetas con Entities, Repositories, Factories.

Algo parecido a esto:

organización de código por roles

La organización por roles tecnológicos fomenta una forma de pensar homogénea y centrada en aspectos técnicos. Al definir tanto los roles y hacerlos tan explícitos con las carpetas independientes, sirve para remarcar mucho la arquitectura del sistema y eso nos lleva a encajar las nuevas funcionalidades dentro de esa arquitectura.

La principal ventaja de esto es que el diseño del sistema tiende a mantenerse muy homogéneo y la estructura de carpetas actúa como guía al implementar nuevas funcionalidades.

Si quieres montar una nueva funcionalidad para gestionar clientes potenciales en tu aplicación web, te crearás la entidad cliente potencial en la carpeta Entities, el repositorio en la carpeta Repositories, el controlador en Controllers, etc.

Es una buena opción cuando se está trabajando con equipos de desarrollo grandes en los que hay más rotación de personal, porque marca unas pautas muy claras de cómo hacer las cosas y el resultado final resulta más predecible.

Precisamente esta homogeneización se puede convertir en uno de los inconvenientes de esta forma de organizar el código, porque lleva a intentar encajar todas las funcionalidades del sistema en una serie de roles que, a veces, no son necesarios o no son necesariamente la mejor forma de implementar una funcionalidad concreta.

Es algo parecido a lo que ocurre con los diseños de N capas tradicionales, en los cuales puedes acabar creando capas que no aportan ningún valor sólo para mantener el diseño uniforme.

Además, al organizar el código por roles, tendemos a pensar sólo en términos de esos roles. Hay ocasiones en que la mejor forma de implementar algo es utilizando una clase o una función que no encaja en ninguno de los roles, pero como la estructura de carpetas sólo nos habla de controladores, vistas y modelos, acabaremos implementándolo como una de esas cosas. Es frecuente encontrar proyectos en los que todo es un NoSeQuéController, NoSeQuéView o NoSeQuéModel.

Otro problema (menor, si estás usando un IDE moderno con un sistema de navegación potente), es que el código necesario para comprender una funcionalidad queda repartido en muchas carpetas y es difícil saber realmente cuánto código está relacionado con una funcionalidad concreta.

Organización por funcionalidades

La organización por funcionalidades (features) se basa en primar el aspecto funcional sobre el técnico a la hora de decidir dónde colocar cada fichero.

En lugar de agrupar los ficheros por el rol que tienen (Controlador, Repository, ViewModel, Directive…), los agrupamos en base a la funcionalidad que implementan.

Más o menos así:

Organización de código por funcionalidad

Por ejemplo, en una aplicación web MVC que tiene una parte para gestionar clientes podríamos tener una carpeta customers que incluyese el modelo, la vista, el controlador y el resto de cosas que necesitemos.

Llevado al extremo, en cada carpeta tendríamos un slice vertical completo de la aplicación, desde el UI hasta la persistencia, pero normalmente no se llega a tanto, y podemos tener una carpeta customers con el código javascript y html de la nuestra aplicación SPA hecha con angularjs, y en alguna otra parte otra carpeta customers con el código C# de un proyecto WebAPI, con su controlador, servicios para cargar datos, etc.

Si la organización basada en roles tenía cierto parecido con las arquitecturas N capas, podríamos decir que la organización basada en funcionalidades se asemeja más (salvando las enormes distancias) al concepto de microservicios que está tan de moda ahora, porque fomenta el minimizar las dependencias entre unas carpetas y otras para tener funcionalidades lo más cohesivas e independientes posibles.

Esta forma de organizar el código evita los inconvenientes de la organización por roles. Con ella todo el código relativo a una funcionalidad está físicamente cerca, ayudando a saber mejor qué código está ligado a esa funcionalidad y a navegar por él.

Además facilita la navegación por la aplicación a un nivel más alto. Cuando ves carpetas llamadas Customers, Orders o Catalogue, es más fácil hacerse a la idea de qué hace la aplicación que si ves carpetas llamadas Controllers, Views y Models.

A la hora de implementar nuevas funcionalidades ayuda a considerarlas de forma independiente, por lo que resulta más sencillo «separarse» del diseño general y utilizar diseños más optimizados para cada funcionalidad concreta sin necesidad de ajustarnos a unos roles marcados previamente.

Esa libertad para implementar nuevas funcionalidades se convierte en un arma de doble filo si estás trabajando con gente que no es capaz de diseñar con un mínimo de sentido común, puesto que resulta más complicado fomentar el uso de buenas prácticas prácticas estandarizadas de diseño.

Mezclando ambas alternativas

Hasta ahora hemos visto dos formas de organizar el código que parten de ideas distintas y priorizan objetivos diferentes, pero no hace falta ser muy listo para darse cuenta de que en realidad estamos hablando de dos ejes distintos, roles técnicos y funcionalidades, y que en el fondo son dos conceptos ortogonales, por lo que podemos mezclarlos a nuesto antojo.

De hecho, lo normal es que cuando una aplicación se hace realmente compleja (cientos de ficheros) se acaben mezclado de una forma u otra.

Si se ha empezado organizando por roles técnicos, llega un momento en que tener 400 controladores de AngularJS en una sola carpeta se hace inmanejable y se acaba separándolos en distintas carpetas dentro de la carpeta controllers.

Igualmente, si cada funcionalidad de una aplicación con AngularJS acaba teniendo 3 directivas, 2 filtros, 4 controllers y 5 vistas, es razonable que terminemos particionando más los ficheros, ya sea mediante carpetas o alguna convención de nombres en los propios ficheros.

Conclusiones

La manera de organizar el código no sólo influye en dónde colocamos cada fichero, sino que también puede condicionarnos a la hora de diseñar el sistema o de implementar nuevas funcionalidades.

Si priorizamos el aspecto técnico organizando el código por roles, conseguiremos sistemas más homogéneos, con un código más estándarizado entre unas partes y otras de la aplicación, pero también nos puede hacer sentir una pérdida de libertad al implementar nuevas funcionalidades por intentar encajarlas en una estructura preestablecida.

Personalmente, hoy en día prefiero inclinarme hacia el lado de la organización por funcionalidad, incluso aunque luego el 80% de las funcionalidades tengan la misma estructura (y, por tanto, encajarían bien en una organización por roles). Pese a que esto requiere pensar más para decidir cómo implementar cada funcionalidad, a cambio permite pensar con más libertad en la forma de implementarla, y en mi opinión eso merece la pena.

4 comentarios en “Formas de organizar el código

  1. Hola Juanma,
    Gran post y además digerible un lunes por la mañana :)
    Yo por mi parte aporto este post (en el que tú también estuviste involucrado vía twitter) Convenciones de nombrado para ViewModels en ASP.NET MVC
    Me ha gustado mucho como lo has explicado, tengo que probar un día y hacer un «rol» vs «funcionalidad», ahora mismo tengo R# y me ayuda a navegar y localizar ficheros, pero reconozco que la separación clásica de ASP.NET MVC por rol técnico empieza a volverme un poco loco y además has dado en el clavo con el tema de querer encajar siempre cualquier fichero/componente/clase en un rol técnico, en mi caso a veces me resulta muy difícil (y a veces imposible) pero sigo queriendo hacerlo por cierta inercia, me has psicoanalizado muy bien!

  2. Yo estoy empezando con esto del ASP MVC y la verdad es que me parecía complicado manejarme con la forma de pensar. Desde la teoría me resulta complicado, pero lo veo complejo. ¿UNa carpeta Controladores para todo el proyecto? ¿Una de vistas para todo?. Me podría parecer normal que haya una de Modelos aparte, quizá, pero separar Controladores y Vistas para cada funcionalidad en carpetas diferentes se me antoja complicado de digerir.

    Quizás esa idea mixta, con carpetas por funcionalidad y dentro separar Controlador y Vistas, sería la mejor. ¿Y dónde irían los modelos? ¿También dentro de la carpeta por funcionalidad? ¿Como lo véis?

    Yo estoy empezando con esto y me confunde todo, pero no me ha gustado nada esa separación por roles. No le veo la utilidad en cuanto crezca el código.

    Y ya que estoy, de querer aplicar una estructura por funcionalidad con distintos niveles de anidación en dichas carpetas, ¿Cómo hacerlo? Apenas he visto que se pueden crear Áreas, pero solo a un nivel. Lo veo absurdo o probablemente aun no haya entendido las capacidades de ASP MVC.

    Un saludo y gran blog. Apuntado como fijo en mis lecturas. Claro, técnico y de temática interesante. Enhorabuena.

  3. Gracias Daniel, me alegro de que te resulte interesante el blog.

    Sobre las dudas que comentas, no soy un experto en ASP.NET MVC, pero puedes echarle un vistazo a estos posts en los que se profundiza en la parte técnica: http://timgthomas.com/2013/10/feature-folders-in-asp-net-mvc/

    En cuanto a los modelos, yo sí los colocaría junto a la vista y al controlador correspondiente, ya que esos modelos son específicos de cada «pantalla». Otra cosa es que tengas, en otra carpeta o en otro proyecto, el modelo de dominio (si es que lo usas en tu aplicación); ese modelo es independiente de las vistas concretas y creo que queda más claro mantenerlo separado.

    Un saludo,

    Juanma

Comentarios cerrados.