Planear compilar dependencias para la canalización

Completado

En esta unidad, obtendrá información sobre cómo empaquetar código para que resulte más fácil compartirlo. Descubrirá por qué debería hacer paquetes, los tipos de paquetes que puede crear, dónde puede hospedarlos y cómo puede acceder a ellos una vez que están hospedados. También obtendrá información sobre el control de versiones del paquete.

Los códigos base siempre aumentan de tamaño y se vuelven más complejos. No es habitual que un equipo escriba todo el código que usa su aplicación. En su lugar, el equipo incluye código existente escrito por otros desarrolladores. Puede haber muchos paquetes, o dependencias, de este tipo en una aplicación. Es importante administrar activamente estas dependencias para poder mantenerlas correctamente y asegurarse de que cumplen los requisitos de seguridad.

Veamos cómo le va al equipo. Andy ha reunido al equipo para hablar sobre un cambio potencial en el código que ayudaría a otro equipo.

Reunión de equipo

Andy: Hola a todos. Estuve hablando con el equipo que trabaja en el sistema de back-end para Space Game. Podrían usar los modelos que usamos para el sitio web en una aplicación de back-end que planean escribir.

Amita: ¿A qué te refieres con los modelos?

Andy: Como sabéis, el sitio web de Space Game es una aplicación de ASP.NET Core. Usa el patrón Modelo-Vista-Controlador (MVC) para separar los datos de cómo se muestran dichos datos en la interfaz de usuario. Estaba pensando que podríamos crear un paquete que contenga nuestras clases de modelo para que las pueda usar cualquier aplicación.

Amita: ¿Cuál es exactamente el objetivo?

Andy: Que ambos equipos compartamos la misma base de datos. El juego envía las puntuaciones más altas de la base de datos; nosotros leemos estas puntuaciones para mostrarlas en la tabla de clasificación.

Amita: Tiene sentido. ¿Y cómo creamos este paquete?

Andy: Por eso quería hablar con vosotros. Tenemos algunas opciones, y estoy buscando ideas.

Tim: Me encantaría ayudar, pero primero tengo algunas preguntas. Soy nuevo en esto y quiero entender cómo funciona todo.

¿Qué es un paquete?

Un paquete contiene código reutilizable que otros desarrolladores pueden usar en sus propios proyectos, aunque no escribirlo.

En el caso de los lenguajes compilados, un paquete contiene normalmente el código binario compilado, como archivos .dll en .NET o .class en Java. Para los lenguajes interpretados en lugar de compilados, como JavaScript o Python, un paquete puede incluir código fuente.

En cualquier caso, los paquetes normalmente se comprimen en formato ZIP o similar. Los sistemas de paquetes suelen definir una extensión de archivo única como .nupkg o .jar para hacer que el uso del paquete sea claro. La compresión puede ayudar a reducir el tiempo de descarga y también genera un único archivo para simplificar la administración.

Los paquetes también suelen contener uno o varios archivos que proporcionan metadatos o información sobre el paquete. Estos metadatos podrían describir lo que hace el paquete, especificar sus términos de licencia, la información de contacto del autor y la versión del paquete.

¿Por qué debería crear un paquete?

Compilar un paquete en lugar de duplicar el código tiene sus ventajas.

Una razón para crear un paquete en lugar de duplicar el código es evitar el desfase. Cuando se duplica el código, cada copia puede desviarse rápidamente para satisfacer los requisitos de una aplicación determinada. Resulta difícil migrar los cambios desde una copia a las otras. En otras palabras, se pierde la capacidad de mejorar el código de manera que beneficie a todo el mundo.

Los paquetes también agrupan funciones relacionadas en un componente reutilizable. En función del lenguaje de programación, un paquete puede proporcionar aplicaciones con acceso a determinados tipos y funciones, a la vez que restringe el acceso a los detalles de implementación.

Otro motivo para compilar un paquete es proporcionar una manera coherente de compilar y probar la funcionalidad de dicho paquete. Cuando se duplica el código, cada aplicación podría compilar y probar el código de diferentes maneras. Un conjunto de pruebas puede incluir comprobaciones cuyas ventajas podría aprovechar otro conjunto.

Una desventaja es que tiene que probar y mantener otro código base con un paquete. También debe tener cuidado al agregar características. Por lo general, un paquete debería contener características que beneficien a muchos tipos de aplicaciones. Por ejemplo, Json.NET es un paquete popular de NuGet para .NET que permite trabajar con archivos JSON. Json.NET es de código abierto, por lo que la comunidad puede proponer mejoras y notificar problemas.

Cuando varias aplicaciones pueden aprovecharse del mismo código, las ventajas superan con creces a los inconvenientes. Solo hay un código base, un único conjunto de pruebas, y solo un proceso de compilación que administrar.

¿Cómo se pueden identificar las dependencias?

Si el objetivo es reorganizar el código en componentes independientes, debe identificar las partes de la aplicación que se pueden quitar, empaquetar para que se puedan reutilizar, almacenar en una ubicación central y de las que se puedan crear versiones. Incluso puede que quiera reemplazar su propio código por componentes de terceros que sean de código abierto o de los que tenga licencia.

Hay muchas maneras de identificar las posibles dependencias en el código base. Entre ellas se incluye el examen del código para los patrones de reutilización y el análisis de la arquitectura de la solución. Aquí se indican algunas maneras de identificar las dependencias:

  • Código duplicado.

    Si determinados fragmentos de código aparecen en varios lugares, es una buena indicación de que puede volver a usar el código. Centralice estos fragmentos de código duplicados y reempaquételos de forma adecuada.

  • Cohesión alta y acoplamiento bajo.

    Un segundo enfoque consiste en buscar elementos de código que tengan una cohesión alta entre sí y un acoplamiento bajo con otras partes del código. Básicamente, la cohesión alta significa mantener partes de un código base que están relacionadas entre sí en un único lugar. Al mismo tiempo, el acoplamiento bajo consiste en separar las partes no relacionadas del código base lo máximo posible.

  • Ciclo de vida individual.

    Busque partes del código que tengan un ciclo de vida similar que pueda implementar y publicar de manera individual. Si este código lo puede mantener un equipo independiente, es una buena indicación de que se puede empaquetar como un componente fuera de la solución.

  • Partes estables.

    Algunas partes del código base podrían ser estables y cambiar con poca frecuencia. Compruebe el repositorio de código para buscar código con una frecuencia de cambio baja.

  • Código y componentes independientes.

    Siempre que el código y los componentes sean independientes y no estén relacionados con otras partes del sistema, puede aislarlos en dependencias independientes.

Se pueden usar varias herramientas para permitirle analizar y examinar el código base. Estos van desde herramientas que examinan el código duplicado y dibujan gráficos de dependencia de la solución hasta herramientas que pueden calcular métricas para el acoplamiento y la cohesión.

¿Qué tipos de paquetes existen?

Cada lenguaje de programación o marco de trabajo proporciona su propia forma de compilar paquetes. Los sistemas de paquetes populares proporcionan documentación sobre cómo funciona el proceso.

Es posible que ya esté familiarizado con estos sistemas de paquetes populares:

  • NuGet: paquetes de bibliotecas de .NET
  • NPM: paquetes de bibliotecas de JavaScript
  • Maven: paquetes de bibliotecas de Java
  • Docker: empaqueta software en unidades aisladas denominadas contenedores

¿Dónde se hospedan los paquetes?

Puede hospedar paquetes en su propia red o usar un servicio de hospedaje. Un servicio de hospedaje se suele denominar un repositorio de paquetes o registro de paquetes. Muchos de estos servicios proporcionan hospedaje gratuito para proyectos de código abierto.

Aquí se indican algunos servicios de hospedaje populares para los tipos de paquete que acabamos de describir:

  • Galería de NuGet

    Los paquetes NuGet se usan para los artefactos de código .NET. Estos artefactos incluyen ensamblados .NET y archivos relacionados, herramientas y, a veces, metadatos. NuGet define la forma en que se crean, almacenan y consumen los paquetes. Un paquete NuGet es básicamente una estructura de carpetas comprimida con archivos en formato ZIP y que tiene la extensión .nupkg.

  • NPM

    Se usa un paquete de NPM para JavaScript. Un paquete de NPM es un archivo o carpeta que contiene archivos JavaScript, y un archivo package.json que describe los metadatos del paquete. En el caso de node.js, el paquete normalmente contiene uno o más módulos que se pueden cargar una vez consumido el paquete.

  • Repositorio central de Maven

    Maven se usa para proyectos basados en Java. Cada paquete tiene un archivo de Modelo de objetos del proyecto que describe los metadatos del proyecto y es la unidad básica para definir un paquete y trabajar con él.

  • Docker Hub

    Los paquetes de Docker se denominan "imágenes" e incluyen implementaciones completas e independientes. Normalmente, una imagen de Docker representa un componente de software que se puede hospedar y ejecutar por sí mismo, sin dependencias en otras imágenes. Las imágenes de Docker están en capas y pueden depender de otras imágenes.

Una fuente del paquete hace referencia al servidor de repositorio del paquete. Este servidor puede estar en Internet o detrás del firewall, en su red. Por ejemplo, puede hospedar sus propias fuentes de NuGet mediante productos de hospedaje, como Azure Artifacts y MyGet. También puede hospedar paquetes en un recurso compartido de archivos.

Al hospedar paquetes tras el firewall puede incluir fuentes para sus propios paquetes. También puede almacenar en caché los paquetes en los que confía en su red cuando los sistemas no puedan conectarse a Internet.

¿Qué elementos son una buena estrategia de administración de dependencias?

Una buena estrategia de administración de dependencias depende de estos tres elementos:

  • Estandarización.

    La estandarización de la forma de declarar y resolver las dependencias ayudará a que el proceso de versión automatizada siga siendo repetible y predecible.

  • Empaquetado de formatos y orígenes.

    Cada dependencia se debe empaquetar con el formato aplicable y almacenarse en una ubicación central.

  • Control de versiones.

    Debe realizar un seguimiento de los cambios que se producen con el tiempo en las dependencias, al igual que se hace con su propio código. Esto significa que se deben crear versiones de las dependencias.

¿Quién puede acceder a los paquetes?

Muchas fuentes de paquetes proporcionan acceso sin restricciones a los paquetes. Por ejemplo, puede descargar Json.NET de nuget.org sin necesidad de iniciar sesión ni autenticarse.

Otras fuentes de paquetes requieren autenticación. Puede autenticar el acceso a las fuentes de varias maneras. Por ejemplo, algunos tipos de fuentes requieren un nombre de usuario y una contraseña. Otras fuentes requieren un token de acceso, que suele ser una larga serie de caracteres que identifica quién es y a qué recursos tiene acceso. Puede establecer que los tokens de acceso expiren después de un período determinado.

¿Cómo se versionan los paquetes?

El esquema de versionamiento depende del sistema de empaquetado que utilice.

Por ejemplo, los paquetes de NuGet usan el versionamiento semántico.

El versionamiento semántico es un esquema de versionamiento popular. Este es el formato:

Principal.Secundaria.Revisión[-Sufijo]

Esto es lo que significa cada uno de estos parámetros:

  • Una versión principal nueva presenta cambios importantes. Las aplicaciones normalmente necesitan actualizar la forma en que usan el paquete para trabajar con una versión principal nueva.
  • Una versión secundaria nueva presenta características nuevas, pero es compatible con versiones anteriores.
  • Una revisión nueva incluye correcciones de errores compatibles con versiones anteriores, pero no características nuevas.
  • La parte -Sufijo es opcional e identifica el paquete como una versión preliminar. Por ejemplo, 1.0.0-beta1 podría identificar el paquete como la primera compilación de versión preliminar beta para el lanzamiento de la versión 1.0.0.

Cuando se hace referencia a un paquete se hace mediante el número de versión.

Aquí se muestra un ejemplo de cómo instalar un paquete mediante PowerShell y un número de versión específico:

Install-Package Newtonsoft.Json -Version 13.0.1

¿Qué ocurre cuando cambia el paquete?

Al hacer referencia a un paquete desde la aplicación, por lo general ancla, o especifica, la versión de ese paquete que quiere usar.

Muchos marcos de trabajo le permiten especificar rangos de versiones del paquete permitidos para instalar. Algunos también le permiten especificar caracteres comodín, lo que se llama una versión flotante.

Por ejemplo, en NuGet, versión "1.0" significa la primera versión que es igual o mayor que 1.0. "[1.0]" indica que se instale la versión 1.0 y no una versión más reciente.

Estos son algunos ejemplos más:

Esta notación: Selecciona:
(1.0,) La primera versión que es mayor que 1.
[1.0,2.0] La primera versión que es mayor o igual a 1.0, y menor o igual a 2.0.
(1.0,2.0) La primera versión que es mayor que 1.0, y menor que 2.0.
[1.0,2.0) La primera versión que es mayor o igual a 1.0, y menor que 2.0.

A medida que cada mantenedor lanza una versión nueva del paquete, puede evaluar qué ha cambiado y probar la aplicación en ella. Cuando esté listo, puede actualizar el número de versión del paquete en la configuración y enviar el cambio a la canalización de compilación.

Este es un ejemplo de cómo puede incluir el paquete Newtonsoft.Json en el archivo de proyecto de la aplicación de C# (.csproj). En este ejemplo se especifica la versión 13.0.1 de ese paquete:

<ItemGroup>
  <PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
</ItemGroup>

Comprobación de conocimientos

1.

¿Qué es un paquete?

2.

Supongamos que ha compilado un paquete que quiere compartir públicamente. ¿Cuál es la manera más fácil de hacerlo?