Skip to main content

Mejores prácticas para administrar dependencias de Java

Escrito por
hero presentation

26 de agosto de 2022

0 minutos de lectura

Crear aplicaciones Java es excelente y hay muchos recursos disponibles. Para acelerar el desarrollo, muchas personas usan frameworks y bibliotecas que hacen gran parte del trabajo. Al observar las aplicaciones Java modernas, casi todas contienen dependencias de bibliotecas desarrolladas por otras personas.

Las dependencias representan alrededor del 80 al 90 % del binario, así que debemos cuidarlas bien al crear un proyecto Java. En este artículo, te daré algunos consejos y mejores prácticas para manejar las dependencias de Java en tu proyecto.

Por qué debes prestar más atención a tus dependencias de Java

Cuando se trata de administrar contribuciones de código, por lo general recurrimos a un proceso como las revisiones de código como primera medida de control de calidad, antes de fusionar código nuevo en nuestra rama principal. Consulta nuestra guía sobre herramientas de revisión de código Java para obtener más información. La programación en pareja es otra forma de llevar a cabo este proceso de control de calidad.

Sin embargo, la forma en que tratamos las dependencias es muy diferente de cómo tratamos nuestro propio código. En muchas ocasiones, se usan dependencias sin ningún tipo de validación. Además, esas dependencias de nivel superior incorporan dependencias transitivas, que pueden tener varios niveles de profundidad. Por ejemplo, una aplicación de Spring de 200 líneas con cinco dependencias directas puede terminar usando 60 dependencias en total, lo que equivale a casi medio millón de líneas de código que se envían a producción.

Actualizar dependencias de Java en proyectos heredados puede ser un desafío. Si están desactualizadas, tendrás un efecto dominó de problemas de compatibilidad, y actualizar una sola biblioteca podría implicar actualizar varias por un error o problema de seguridad. Si estas dependencias de Java cambian su API, tendrías que reescribir toda tu aplicación.

Además, en muchas aplicaciones empresariales importantes, las dependencias permanecen en el archivo de manifiesto, aunque ya no se usen en el código. Estas dependencias sin usar siguen disponibles en tu programa.

Todo esto puede provocar lo siguiente:

  • Binarios más grandes que consumen más recursos o tardan más en iniciar

  • Posibles conflictos entre bibliotecas al agregar dependencias nuevas.

  • Bibliotecas desactualizadas que contienen errores o problemas de seguridad

  • Problemas de compatibilidad al actualizar bibliotecas

  • Y más

Administrar dependencias de Java

Una de las mejores prácticas para usar repositorios como Maven Central de forma amplia es configurar tu propio administrador de repositorios. Se trata de un servidor proxy dedicado entre tu entorno de desarrollo interno y los repositorios públicos. No solo te ofrecerá compilaciones más rápidas y estables, sino que también te permitirá definir políticas para los paquetes de Java. Por ejemplo, puedes bloquear ciertas versiones para que no se puedan descargar ni usar en tus aplicaciones.

Para obtener más información sobre los administradores de repositorios y una lista de posibles productos, consulta la documentación de Maven.

Incluir dependencias nuevas en tu proyecto Java

Cuando necesitas resolver un problema y existe una biblioteca que puede ayudarte, es probable que quieras incluirla en los archivos de manifiesto de dependencias de Java. Sin embargo, antes de incluirla, deberías considerar lo siguiente: 

¿Resuelve el problema?

La razón principal para importar un paquete es resolver tu problema. La pregunta es si la dependencia que elegiste puede hacerlo. Además, ¿resuelve todo el problema sin generar nuevos desafíos? Si no es así, quizá haya mejores soluciones.

¿Necesito el paquete completo?

¿Vale la pena importar una dependencia grande, con muchas funciones y tipos de datos, si solo necesitas una función? A veces, puede ser más fácil y manejable escribir esa función tú mismo. Por ejemplo, ¿tiene sentido incluir toda Eclipse Collections si solo quiero usar el tipo de datos Tuple? Probablemente no.

Una consulta rápida en mvnrepository.com me muestra que este paquete ocupa unos 10 MB

Página de MvnRepository para Eclipse Collections Main Library versión 11.1.0, que muestra la licencia, las etiquetas, los archivos, el repositorio, las clasificaciones y el uso.

También verifica si las dependencias que ya tienes pueden resolver el problema. Es posible que algunas funciones o tipos de datos similares ya estén disponibles. Por otro lado, incluir una biblioteca nueva y extensa puede ayudarte a resolver varios problemas a la vez; todo depende de la situación.

¿Cuántas personas contribuyen?

El factor de bus puede ser bastante bajo si la dependencia de Java que usas tiene solo uno o unos pocos mantenedores. ¿Qué ocurre si el mantenedor decide dejar el proyecto o no tiene tiempo para corregir un error? Como alternativa, también puedes contribuir al proyecto y hacerlo más seguro para todas las personas involucradas.

Pero antes de incluir dependencias en tu proyecto, asegúrate de revisar el repositorio principal y ver cuántos mantenedores activos tiene.

Encabezado del repositorio de GitHub que muestra 1173 confirmaciones, 10 ramas, 0 paquetes, 40 versiones y 66 colaboradores

¿Sigue recibiendo mantenimiento?

Si un paquete ya no recibe mantenimiento, definitivamente no querrás depender de él. Antes de integrarlo, verifica si hay nuevas confirmaciones en el repositorio de GitHub y revisa su ciclo de lanzamiento. Esto te dará una idea de qué tan bien se mantiene el paquete.

Interfaz del repositorio que muestra un commit de hace 2 horas, resaltado con una flecha rosa, y dos carpetas debajo

¿Cuál es la versión más reciente del paquete?

Los ejemplos de código pueden darte información muy útil sobre una dependencia de Java en particular. Sin embargo, estos ejemplos podrían estar desactualizados y el paquete en cuestión podría haberse actualizado. Considera usar la versión estable más reciente. En el caso de Eclipse Collections, vemos en mvnpackage.com que la versión estable más reciente es la 11.1.0, del 5 de julio de 2022. Considera usar esa versión.

Ten en cuenta que en esta imagen también aparece la versión 11.1.0.M2. Claramente, es una versión preliminar. Solo deberías incluir versiones estables en tu aplicación de producción, a menos que tengas plena certeza. Como regla general, no incluyas versiones con calificadores como:

  • alpha o a

  • beta o b

  • milestone o m

  • rc o cr

  • snapshot

Si una dependencia de Java tiene el calificador GA o final, por lo general puedes considerarla una versión estable.

Tabla con las versiones de Java, la cantidad de vulnerabilidades, enlaces al repositorio Central, cifras de uso y fechas de lanzamiento.

¿Tiene vulnerabilidades de seguridad?

Antes de depender activamente de un paquete de Java, asegúrate de analizarlo para detectar vulnerabilidades conocidas. Snyk CLI es una excelente herramienta para analizar tus archivos Maven o Gradle. Si tu biblioteca contiene una vulnerabilidad de seguridad, quizá te convenga elegir otro paquete.

Actualizar tus dependencias de Java

¿Hay versiones más nuevas disponibles?

No querrás revisar manualmente cada dependencia de Java para ver si hay versiones más nuevas disponibles. Por suerte, hay formas más sencillas de hacerlo. Con los plugins de tu administrador de paquetes, puedes verificar tus dependencias automáticamente con la frecuencia que quieras; por ejemplo, en cada compilación.

Ten en cuenta que tus herramientas podrían recomendarte versiones beta o preliminares. Se recomienda encarecidamente usar solo versiones estables de una biblioteca.

Ejemplo de Maven

En Maven, puedes usar el plugin versions como se muestra a continuación. No es necesario agregar nada específico a tu pom.xml

mvn versions:display-dependency-updates
La salida de la terminal del complemento Maven Versions muestra las actualizaciones disponibles de dependencias e indica que la compilación se realizó correctamente.

Ejemplo de Gradle

En Gradle, tenemos que incluir un plugin, como el plugin versions de ben-manes.

plugins {
  id "com.github.ben-manes.versions" version "0.42.0"
}

Ahora podemos ejecutar un comando similar para mostrar versiones más nuevas de tus bibliotecas.

gradle dependencyUpdates -Drevision=release
Salida de terminal titulada “Actualizaciones de dependencias del proyecto” que muestra dependencias de Java con sus versiones actuales y posteriores.

IntelliJ IDEA

Si usas IntelliJ IDEA, las dependencias que se pueden actualizar aparecerán subrayadas cuando haya versiones más nuevas. Esto funciona tanto con proyectos Maven como Gradle.

XML de dependencias de Java Maven que muestra org.eclipse.collections y una sugerencia del IDE para actualizar eclipse-collections-api de la versión 10.3.0 a la 11.1.0.

Snyk

Al conectar tu repositorio de GitHub con tu cuenta de Snyk, podemos ofrecerte correcciones o actualizaciones recomendadas en cada pull request. Esto, junto con nuestros completos consejos de seguridad, puede ayudarte a mantener actualizadas tus dependencias de Java.

pull request de GitHub de Snyk que propone actualizar org.eclipse.collections:eclipse-collections de la versión 10.3.0 a la 11.1.0.

¿Los paquetes que usas siguen recibiendo mantenimiento?

Es recomendable volver a revisar el repositorio de GitHub o mvnpackage.com para ver si hay actualizaciones y confirmaciones recientes. Si parece que un paquete ya no recibe un buen mantenimiento, puedes encargarte de mantenerlo o migrar a otra biblioteca mejor actualizada.

Sin embargo, si encuentras un problema en una dependencia fundamental para tu aplicación, considera resolverlo por tu cuenta y contribuir con la corrección al proyecto de código abierto. Será muy apreciado y, a menudo, más rápido que enviar informes de problemas e insistir para que el mantenedor los corrija.

¿Hay problemas de seguridad en mis dependencias de Java?

Aunque tu aplicación no tenga vulnerabilidades ahora, eso no significa que vaya a seguir así para siempre. Todos los días se descubren y divulgan nuevas vulnerabilidades y exploits. Por eso, debes volver a analizar tus bibliotecas con regularidad para asegurarte de que sigan libres de vulnerabilidades.

Snyk te ofrece varias formas de integrar el análisis de dependencias en tu ciclo de desarrollo. En tu equipo local, puedes usar Snyk CLI o las integraciones para IntelliJ, Eclipse o VS Code para analizar vulnerabilidades. También puedes analizar durante el ciclo de compilación con el plugin de Maven o Gradle (no oficial), o elegir una de las integraciones para pipelines de CI. Como alternativa, puedes agregar tu repositorio de Git a Snyk para que analicemos y actualicemos tus proyectos a diario.

Informe de vulnerabilidades de Snyk que muestra problemas críticos de Apache Struts, incluidos hallazgos de ejecución de código arbitraria y remota con puntuaciones de gravedad.

Eliminar dependencias de Java de tu proyecto

¿El paquete todavía se usa?

Si ya no se usa una dependencia de Java, debemos eliminarla del archivo de manifiesto. Cada paquete de ese archivo forma parte del binario y está disponible en el classpath. Eliminar dependencias sin usar reducirá el tamaño del binario y hará que el inicio y las descargas sean más rápidos, además de mejorar la seguridad. Reducir al mínimo las dependencias en tu classpath es fundamental para protegerte contra ataques como una cadena de gadgets de deserialización.

Mantener el escritorio limpio —o, en este caso, la aplicación— siempre es muy recomendable. Por suerte, los administradores de paquetes pueden ayudarte a identificar estas dependencias de Java sin usar.

Ejemplo de Maven

En Maven, puedo usar el plugin dependency para analizar mis dependencias. Este plugin verifica si las dependencias de Java que declaro también se usan en mi código.

En este caso, no quiero que me molesten las dependencias provided o test, así que uso el indicador ignoreNonCompile.

mvn dependency:analyze -DignoreNonCompile
Advertencia de la terminal que muestra dependencias declaradas sin usar: Apache Commons Lang 3.9 y Apache Struts 2.5.10.

Ejemplo de Gradle

En Gradle, tenemos que agregar otro plugin para analizar las dependencias. En este caso, usaremos el plugin nebula.lint. Este linter de Gradle puede analizar las dependencias de Java que incluiste y detectar si hay alguna sin usar.

plugins {
   id "nebula.lint" version "17.7.0"
}

Tengo que configurar el plugin para definir gradleLint.rules. Puedes hacerlo en tu archivo de Gradle o como parámetro de línea de comandos. En el ejemplo a continuación, elijo esta última opción. Consulta la documentación del plugin para obtener más información sobre cómo configurarlo para tu aplicación.

gradle lintGradle -PgradleLint.rules=unused-dependency
Salida de terminal que muestra advertencias de lint por dependencias sin usar de Apache Commons Lang y Struts en build.gradle.

Crea una estrategia sólida para administrar las dependencias de tus aplicaciones Java

Al desarrollar aplicaciones Java y usar dependencias como bibliotecas o frameworks, es recomendable crear una estrategia para manejarlas. Saber cómo seleccionar, actualizar y eliminar dependencias de Java de nuestra aplicación es esencial para la seguridad. Al crear una estrategia clara, evitamos sorpresas cuando un problema de seguridad de alta prioridad nos obliga a actualizar un paquete.

Consulta este artículo para obtener más información sobre cómo administrar dependencias de código abierto.

Empieza con los desafíos de Capture the Flag

Aprende a resolver desafíos de captura la bandera con nuestro taller virtual introductorio a pedido.

Leer más

Blog

Los modelos de frontera encontraron las vulnerabilidades. Solo el atacante encontró las cadenas.

El análisis estático encontró las fallas, pero solo las pruebas de ataque en vivo demostraron cómo podían encadenarse para provocar brechas. Una comparación de Evo COS, Claude Security y Claude Code Security.

feature insights context
Blog

Los ataques autónomos ya están aquí. La defensa debe estar a su altura.

Los atacantes autónomos están reduciendo el tiempo disponible para defenderse. Descubre cómo el descubrimiento, la corrección, la validación y la prevención continuos pueden ayudar a los equipos de seguridad a seguirles el ritmo.

Blog

Por qué los agentes de programación con IA siguen generando fallas de control de acceso

Los agentes de programación con IA pueden generar lógica de autorización que compila y supera la revisión, pero expone los datos de un inquilino a otro. Descubre por qué es difícil detectar el control de acceso roto y cómo prevenirlo.