En el artículo anterior, analizamos cómo sobrevivir al infierno de las dependencias desde la perspectiva del consumidor. Sin embargo, el verdadero salto de calidad en una carrera técnica ocurre cuando dejas de ser quien descarga paquetes y te conviertes en quien los diseña.
El problema fundamental que resuelve NuGet no es simplemente "bajar DLLs", sino la violación del principio DRY (Don't Repeat Yourself) a nivel arquitectónico.
Imagina el escenario clásico donde tienes una clase AuditLog.cs o un StringUtils.cs. Al iniciar un nuevo microservicio, lo más "rápido" es copiar y pegar el archivo. Seis meses después, encuentras un bug crítico de seguridad en esa clase. Ahora te enfrentas a la pesadilla de auditar y parchear 10 repositorios distintos manualmente.
La solución profesional es empaquetarlo y vamos a descubrir como hacerlo con NuGet.
1. NuGet Library
Crear una librería no requiere magia, requiere metadatos. El archivo .csproj deja de ser un simple archivo de configuración para convertirse en el manifiesto del producto.
Si el
.dlles el producto, el.csprojes la etiqueta de envío; sin ella, nadie sabrá qué es, cómo se usa ni si es seguro.
Aquí tienes una configuración explicada:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<!-- MULTI-TARGETING -->
<!-- netstandard2.0 para compatibilidad máxima (Legacy) -->
<!-- net8.0 para optimizaciones modernas -->
<TargetFrameworks>netstandard2.0;net8.0</TargetFrameworks>
<!-- IDENTIDAD -->
<PackageId>MyCompany.Common</PackageId>
<Version>1.0.0</Version>
<Authors>Equipo de Arquitectura</Authors>
<Company>Mi Empresa S.A.</Company>
<Description>Librería base para validaciones y logs estandarizados.</Description>
<!-- ASSETS -->
<PackageIcon>icon.png</PackageIcon>
<PackageReadmeFile>README.md</PackageReadmeFile>
<!-- SEGURIDAD -->
<!-- Garantiza que el binario sea idéntico bit a bit en cada build -->
<ContinuousIntegrationBuild>true</ContinuousIntegrationBuild>
<!-- ORGANIZACIÓN -->
<PackageTags>logs;validation;common;architecture</PackageTags>
<PackageOutputPath>./nupkg</PackageOutputPath>
<!-- REPOSITORIO Y LICENCIA -->
<RepositoryUrl>https://github.com/mi-empresa/my-common-lib</RepositoryUrl>
<RepositoryType>git</RepositoryType>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<!-- BUILD -->
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<IncludeSymbols>true</IncludeSymbols>
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
</PropertyGroup>
<!-- DEPENDENCIAS -->
<ItemGroup>
<PackageReference Include="Serilog" Version="4.0.0" />
</ItemGroup>
<ItemGroup>
<!-- Empaquetamos los assets visuales dentro del nupkg -->
<None Include="..\images\icon.png" Pack="true" PackagePath="\" />
<None Include="..\README.md" Pack="true" PackagePath="\" />
</ItemGroup>
</Project>
¿Por qué cada línea importa?
🎯 El Dilema del Target (Multi-targeting)
¿Tu empresa tiene proyectos viejos en .NET Framework y nuevos en .NET 8? No elijas uno.
Usando <TargetFrameworks> (en plural), compilas para ambos.
- netstandard2.0: Corre en casi cualquier cosa (incluso .NET Framework 4.6.1+).
- net8.0: Aprovecha las optimizaciones modernas de rendimiento. NuGet entregará automáticamente la DLL correcta según el proyecto del consumidor.
📁 Assets (Icon & Readme)
Agrega personalización y documentación de tu package (al menos si será público).
- PackageIcon: Incluye tu logo (png 128x128).
-
PackageReadmeFile: El
README.mdse mostrará en la pestaña de NuGet en Visual Studio. Es tu oportunidad de explicar cómo usar la librería antes de que el dev se frustre y la desinstale.
🔒 Builds Deterministas
¿Te ha pasado que compilas lo mismo dos veces y el hash cambia?
<ContinuousIntegrationBuild>true</ContinuousIntegrationBuild> garantiza que si el código no cambia, el binario es idéntico bit a bit. Esto es crucial para validaciones de seguridad y cachés en entornos corporativos.
📦 Dependencias Transitivas
Al incluir Serilog en el ItemGroup, cualquiera que instale tu paquete lo recibirá automáticamente. ¡No obligues a tus usuarios a instalar dependencias manualmente!
🏷️ Etiquetas de repositorio
Si omites esto, tu paquete se verá "sospechoso" en los feeds. Vincular el código fuente demuestra profesionalismo y permite a los usuarios (o auditores) navegar al repo original con un clic.
🗂️ Estrategia de versionamiento
Si bien aquí usamos una versión estática (1.0.0), en entornos profesionales te sugiero automatizar esto con herramientas como MinVer, que calculan la versión semántica basándose en tus Git Tags.
⚖️ Licenciamiento Legal
-
Open Source: Usa
<PackageLicenseExpression>con códigos estándar como MIT, Apache-2.0, etc. -
Propietario/Empresarial: Usa
<PackageLicenseFile>y apunta a un archivo LICENSE.txt dentro del paquete para proteger la propiedad intelectual de tu empresa.
2. NuGet Tools
Mientras que las librerías se integran en tu aplicación, las NuGet Tools son aplicaciones que corren junto a tu aplicación. Piensa en herramientas como dotnet-ef.
Podemos crear nuestras propias herramientas corporativas (por ejemplo, un Scaffolder para crear microservicios con la arquitectura de la empresa) empaquetando una aplicación de consola.
PackAsTool
La diferencia técnica radica en la propiedad <PackAsTool>. Esto le dice a NuGet que el paquete contiene un ejecutable, no una librería para referenciar.
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net10.0</TargetFramework>
<!-- Convierte la consola en una herramienta distribuible -->
<PackAsTool>true</PackAsTool>
<!-- Este es el comando mágico que escribirás en la terminal -->
<ToolCommandName>my-scaffolder</ToolCommandName>
<PackageId>MyCompany.Scaffolder</PackageId>
<Version>1.0.0</Version>
<PackageOutputPath>./nupkg</PackageOutputPath>
</PropertyGroup>
</Project>
Cuando un desarrollador instala este paquete, el ejecutable se añade al PATH del sistema y queda disponible como un comando nativo.
# 1. Instalación Global
dotnet tool install -g MyCompany.Scaffolder
# 2. Ejecución
my-scaffolder "NuevoServicio"
💡 Para evitar la instalación global puedes usar Local Tools (
dotnet new tool-manifest) para asegurar que todos usen la misma versión mediantedotnet tool restore.
3. Estrategias de distribución
Tener el artefacto .nupkg es solo el primer paso. La decisión crítica es dónde debe alojarse.
Para publicar, necesitamos registrar los destinos en nuestro NuGet.config. Este archivo actúa como una "libreta de direcciones" bidireccional: sirve tanto para descargar (restore) como para subir (push).
<configuration>
<packageSources>
<clear />
<!-- Estrategia A: Cloud (GitHub, Azure, AWS) -->
<add key="github" value="https://nuget.pkg.github.com/TU_ORG/index.json" />
<!-- Estrategia B: Server NuGet Privado -->
<add key="baget" value="http://nuget-server:5555/v3/index.json" />
<!-- Estrategia C: Pública -->
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
<!-- Estrategia D: On-Premise con carpetas compartidas -->
<add key="shared" value="\\ServidorWindows\Nugets" />
</packageSources>
</configuration>
Aquí están las estrategias ordenadas por madurez empresarial:
Estrategia A: Cloud Providers
El estándar de oro, el código fuente vive junto a sus artefactos. Proveedores como GitHub Packages, Azure Artifacts o AWS CodeArtifacts permiten que tus paquetes sean públicos o privados, seguros y accesibles solo mediante autenticación.
La ventaja clave es la integración con CI/CD: un Pipeline ejecuta los tests y, si pasan, publica automáticamente la nueva versión.
# Publicar usando el alias "github" definido en el config
dotnet nuget push "./nupkg/MyCompany.Common.1.0.0.nupkg" --source "github" --api-key TU_TOKEN
Estrategia B: Server NuGet Privado
La evolución moderna para redes aisladas, levantar un servidor web dedicado como BaGet.
Esto ofrece indexado rápido, caché, interfaz web para buscar paquetes y compatibilidad con clientes que no son Windows.
# Publicar usando el alias "baget" definido en el config
dotnet nuget push "./nupkg/MyCompany.Common.1.0.0.nupkg" --source "baget" --api-key TU_API_KEY
Estrategia C: NuGet.org
Si tu librería resuelve un problema universal y no contiene lógica de negocio propietaria, el destino es nuget.org. Es el repositorio central del ecosistema .NET. Tu código será accesible globalmente.
dotnet nuget push "./nupkg/MyCompany.Common.1.0.0.nupkg" --source "nuget.org" --api-key TU_NUGET_API_KEY
Estrategia D: On-Premise con carpetas compartidas
La estrategia clásica "Old School" en entornos corporativos Windows. Antes de Docker y la Nube, simplemente creábamos una carpeta en un File Server (\\192.168.1.50\Librerias) y apuntábamos Visual Studio allí.
# Publicar usando el alias "shared" definido en el config
dotnet nuget push "./nupkg/MyCompany.Common.1.0.0.nupkg" --source "shared"
Conclusión
La madurez en el desarrollo .NET implica moverse de la duplicación a la modularización.
- Usa libraries bien etiquetadas (PackageTags) y licenciadas (PackageLicenseExpression) para centralizar la lógica.
- Usa Tools para distribuir utilidades que mejoren la experiencia de desarrollo (DX).
- Elige la estrategia de distribución que se alinee con tu infraestructura (Nube vs On-Premise).
Empaquetar tu código es una excelente forma de escalar tu impacto como desarrollador.
¡Happy coding! 🚀



Top comments (0)