Monorepositorio con C#: organización del código en la práctica
\n\nEn el desarrollo moderno con C# (.NET), cada vez más surge la pregunta de elegir entre un monorepositorio (monorepo) y un multirepositorio (multirepo). Un monorepositorio es un enfoque en el que todo el código de varios proyectos, bibliotecas y servicios se almacena en un único repositorio de Git. En este artículo, analizaremos cómo organizar un monorepositorio para soluciones de C#, veremos ejemplos prácticos de estructura, configuración de compilación y gestión de dependencias.
\n\nVentajas del monorepositorio para C#
\n\nEl monorepositorio es especialmente útil cuando tienes varios proyectos relacionados: API web, aplicaciones de consola, bibliotecas de clases y pruebas. Las principales ventajas son:
\n- \n
- Versión única de dependencias — todos los proyectos utilizan la misma versión de paquetes NuGet y bibliotecas internas. \n
- Refactorización simplificada — un cambio de API en una biblioteca se ve inmediatamente en todos los consumidores. \n
- CI/CD centralizado — un único pipeline para compilar, probar y desplegar todos los componentes. \n
- Reducción de duplicación — los modelos, utilidades y configuraciones comunes se trasladan a proyectos compartidos. \n
Sin embargo, también hay que considerar las desventajas: el aumento del tamaño del repositorio, el mayor tiempo de clonación (si no se usa sparse checkout) y la necesidad de un sistema de permisos de acceso bien pensado.
\n\nEstructura del monorepositorio en C#
\n\nConsideremos una estructura típica de monorepositorio para un proyecto .NET. Supongamos que tenemos los microservicios AuthService, OrderService y una biblioteca común Shared.
MyMonorepo/\n├── .github/\n│ └── workflows/\n│ └── ci.yml\n├── src/\n│ ├── AuthService/\n│ │ ├── AuthService.Api/\n│ │ │ ├── Controllers/\n│ │ │ ├── Program.cs\n│ │ │ └── AuthService.Api.csproj\n│ │ └── AuthService.Tests/\n│ │ └── AuthService.Tests.csproj\n│ ├── OrderService/\n│ │ ├── OrderService.Api/\n│ │ │ └── OrderService.Api.csproj\n│ │ └── OrderService.Tests/\n│ │ └── OrderService.Tests.csproj\n│ └── Shared/\n│ ├── Shared.Models/\n│ │ └── Shared.Models.csproj\n│ └── Shared.Utils/\n│ └── Shared.Utils.csproj\n├── tests/\n│ └── IntegrationTests/\n│ └── IntegrationTests.csproj\n├── MyMonorepo.sln\n├── Directory.Build.props\n├── Directory.Packages.props\n├── .gitignore\n└── README.md\n\nElementos clave:
\n- \n
- src/ — carpeta principal con el código fuente. \n
- tests/ — pruebas de integración, si no están vinculadas a un servicio específico. \n
- Directory.Build.props — configuración común de MSBuild para todos los proyectos. \n
- Directory.Packages.props — gestión centralizada de versiones de paquetes NuGet (modo Central Package Management). \n
- .sln — archivo de solución que agrupa todos los proyectos. \n
Configuración de la gestión centralizada de dependencias
\n\nEn .NET 6+ se introdujo el soporte integrado para Central Package Management (CPM). Esto es ideal para un monorepositorio. Cree el archivo Directory.Packages.props en la raíz:
<Project>\n <PropertyGroup>\n <ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>\n </PropertyGroup>\n <ItemGroup>\n <PackageVersion Include="Microsoft.AspNetCore.App" Version="8.0.0" />\n <PackageVersion Include="Microsoft.EntityFrameworkCore" Version="8.0.0" />\n <PackageVersion Include="xunit" Version="2.7.0" />\n </ItemGroup>\n</Project>\n\nAhora, en cada .csproj solo es necesario indicar el nombre del paquete sin la versión:
<Project Sdk="Microsoft.NET.Sdk.Web">\n <PropertyGroup>\n <TargetFramework>n