Monorepositório com C#: organização de código na prática
\n\nNo desenvolvimento moderno com C# (.NET), a questão da escolha entre monorepositório (monorepo) e multirrepositório (multirepo) surge cada vez mais. Monorepositório é uma abordagem onde todo o código de vários projetos, bibliotecas e serviços é armazenado em um único repositório Git. Neste artigo, vamos analisar como organizar um monorepositório para soluções C#, examinar exemplos práticos de estrutura, configuração de compilação e gerenciamento de dependências.
\n\nVantagens do monorepositório para C#
\n\nO monorepositório é especialmente útil quando você tem vários projetos relacionados: APIs web, aplicativos de console, bibliotecas de classes e testes. Os principais benefícios são:
\n- \n
- Versão única de dependências — todos os projetos usam a mesma versão de pacotes NuGet e bibliotecas internas. \n
- Refatoração simplificada — alterações em uma API de biblioteca são imediatamente visíveis em todos os consumidores. \n
- CI/CD centralizado — um único pipeline para compilação, teste e implantação de todos os componentes.
- Redução de duplicação — modelos, utilitários e configurações comuns são extraídos para projetos compartilhados.
No entanto, também é preciso considerar as desvantagens: aumento do tamanho do repositório, maior tempo de clonagem (se não usar sparse checkout) e a necessidade de um sistema de controle de acesso bem planejado.
\n\nEstrutura do monorepositório em C#
\n\nVamos considerar uma estrutura típica de monorepositório para um projeto .NET. Suponha que temos os microsserviços AuthService, OrderService e uma biblioteca compartilhada 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-chave:
\n- \n
- src/ — pasta principal com o código-fonte. \n
- tests/ — testes de integração, se não estiverem vinculados a um serviço específico.
- Directory.Build.props — configurações comuns do MSBuild para todos os projetos.
- Directory.Packages.props — gerenciamento centralizado de versões de pacotes NuGet (modo Central Package Management).
- .sln — arquivo de solução que une todos os projetos.
Configuração do gerenciamento centralizado de dependências
\n\nNo .NET 6+, foi introduzido o suporte nativo ao Central Package Management (CPM). Isso é ideal para um monorepositório. Crie o arquivo Directory.Packages.props na raiz:
<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\nAgora, em cada .csproj, basta especificar apenas o nome do pacote sem a versão:
<Project Sdk="Microsoft.NET.Sdk.Web">\n <PropertyGroup>\n <TargetFramework>n