Saltar al contenido principal

Selección y Evaluación de Dependencias

El principio — "No reinventar la rueda" con criterio

Reutilizar código probado es casi siempre mejor que escribirlo desde cero. Pero agregar una dependencia no es gratis — cada librería que entra al proyecto es una superficie de ataque, una obligación de mantenimiento, un riesgo de supply chain y una posible fuente de incompatibilidades futuras.

La regla en Wiedii: antes de agregar cualquier dependencia, hacerse dos preguntas en orden:

1. ¿Realmente la necesito? 2. Si la necesito, ¿esta es la correcta?

Nadie debería agregar una librería porque "está buena" o "la usé antes". Toda dependencia que entra al proyecto tiene que justificarse.


Pregunta 1 — ¿Realmente la necesito?

Cuándo SÍ usar una librería

  • La funcionalidad es compleja, tiene edge cases no obvios y está bien resuelta en el ecosistema (parsers, criptografía, validación, dates, i18n, ORM)
  • Implementarla correctamente requiere conocimiento especializado que el equipo no tiene (algoritmos de seguridad, protocolos de red, compresión)
  • La librería tiene tests extensos, documentación y comunidad activa que reducen el riesgo de bugs
  • El tiempo de implementación propia superaría el beneficio

Cuándo NO usar una librería

  • La funcionalidad cabe en menos de 30-50 líneas sin mantenimiento complejo
  • La API nativa del lenguaje o runtime ya lo resuelve (fetch vs axios para requests simples, Array.from vs lodash para muchas operaciones)
  • Solo se van a usar 1-2 funciones de una librería de 50KB
  • La librería añade muchas dependencias transitivas para resolver algo trivial
// ❌ No instalar lodash solo para esto:
import _ from 'lodash'
const result = _.get(obj, 'a.b.c', 'default')

// ✅ Hacerlo nativo:
const result = obj?.a?.b?.c ?? 'default'

El árbol de decisión

¿Necesito esta funcionalidad?

├── SÍ → ¿La plataforma/lenguaje ya la provee de forma nativa?
│ ├── SÍ → Usar la nativa. Fin.
│ └── NO → ¿Puedo implementarlo en <50 líneas sin mantenimiento complejo?
│ ├── SÍ → Implementarlo. Fin.
│ └── NO → Evaluar librería externa → ver Checklist de evaluación

└── NO → No agregar nada.

Pregunta 2 — ¿Esta librería es la correcta?

Health check de 2 minutos — los 6 criterios

Antes de instalar cualquier paquete, revisar estos seis puntos. Si alguno falla, buscar alternativa o escalar al Tech Lead.

1. Tendencia de descargas (no el número absoluto)

La tendencia dice hacia dónde va la comunidad — el número absoluto solo dice dónde estuvo.

# Consultar en: npmtrends.com | pkgpulse.com/compare | npmjs.com (stats tab)

✅ Creciendo o estable con alto volumen
⚠️ Plana por 12+ meses → posiblemente estancada
⚠️ Declinando 20%+ año a año → la comunidad se está yendo
❌ Caída abrupta → problema grave o abandono

Ejemplo clásico: moment.js tiene 14M descargas/semana pero declina cada trimestre. date-fns tiene 50M/semana y crece. Si empiezas un proyecto hoy, ¿a cuál le apuestas para los próximos 3 años?

2. Último release

< 3 meses → mantenimiento activo
3-12 meses → cadencia saludable
⚠️ 12-24 meses → investigar si es intencional (libs estables pueden tener esto)
2+ años → casi seguro abandonada (a menos que sea intencionalmente estable como ms, uuid)
❌ Para librerías de seguridad: > 12 meses sin release = señal de alerta roja

3. Issues abiertos vs cerrados

# GitHub → Issues tab
✅ Issues triageados en < 2 semanas
✅ Ratio open:closed menor a 1:3
✅ Vulnerabilidades de seguridad resueltas rápido
⚠️ Issues sin respuesta por 60+ días
❌ Vulnerabilidades conocidas sin patch
❌ Último comentario del maintainer fue hace 8 meses

4. Tamaño y dependencias transitivas

# Consultar en: bundlephobia.com | pkg-size.dev
✅ Tamaño proporcional a lo que hace
✅ Tree-shakeable (solo pagas por lo que usas)
✅ Pocas o cero dependencias propias
⚠️ Una utilidad pequeña que trae 15 dependencias transitivas
❌ 100KB para parsear fechas → hay alternativas más pequeñas

# Por referencia:
# Utilidades simples: < 5KB gzipped
# Validación: 5-15KB
# State manager: 2-30KB
# ORM: varía (Prisma es grande pero es codegen)

5. Soporte TypeScript

✅ Tipos nativos en el paquete (campo "types" en package.json)
✅ @types/ activo y sincronizado
⚠️ @types/ existe pero va meses atrás del paquete
❌ Sin tipos → terminarás haciendo cast a `any` en todos lados

6. Licencia

✅ MIT → uso irrestricto en código propietario
✅ Apache-2.0 → similar a MIT + grant explícito de patentes
✅ BSD-2-Clause, BSD-3-Clause → permisivas
⚠️ GPL-2.0 / GPL-3.0 → copyleft: tu código puede requerir ser open source
⚠️ AGPL-3.0 → copyleft fuerte (incluye uso en red/SaaS)
❌ BUSL-1.1 (Business Source License) → no es open source para uso comercial
❌ Propietaria → leer los términos con Legal antes de usar

# Verificar licencias de todo el árbol de dependencias:
bun x license-checker --summary # JS/TS
composer licenses # PHP
pip-licenses # Python
go-licenses report ./... # Go

Señales de alerta que requieren buscar alternativa

SeñalPor qué es problema
Un solo maintainer con > 12 meses sin actividadSi esa persona para, el proyecto muere
Transferencia reciente de ownership a org desconocidaVector documentado de supply chain attacks
> 15 dependencias transitivas para una utilidad simpleCada dep = superficie de ataque adicional
Script postinstall que descarga código de internetEjecución de código arbitrario en tu máquina
Paquete muy nuevo (< 6 meses) con descargas infladasPosible inflación artificial para parecer confiable
Vulnerabilidades de seguridad abiertas sin respuesta del maintainerNo serán parched — el riesgo es tuyo

Herramientas por stack

JavaScript / TypeScript (npm / bun)

# Explorar y comparar antes de instalar
# npmtrends.com/<paquete> — tendencia de descargas
# pkgpulse.com/compare/<a>-vs-<b> — comparación con health score
# bundlephobia.com — tamaño y dependencias

# Verificar seguridad ANTES de instalar
bun x npm-audit-fix # equivalente a npm audit

# Después de instalar — escanear todo el árbol
bun audit

# Licencias del árbol completo
bun x license-checker --summary

# Socket.dev (GitHub App) — análisis de comportamiento en PRs
# Detecta supply chain attacks que npm audit no ve

PHP / Composer

# Consultar: packagist.org — stats de descargas y abandono
# phpstan.org — compatibilidad con análisis estático

# Después de instalar
composer audit # vulnerabilidades conocidas

# Licencias
composer licenses

Python / pip

# Consultar: pypi.org — descargas, releases, maintainers

# Seguridad
pip-audit # escanea el entorno virtual actual
safety check # alternativa popular

# Licencias
pip-licenses --format=table

Go / modules

# Consultar: pkg.go.dev — documentación, versiones, dependencias

# Seguridad
govulncheck ./... # herramienta oficial de Go para vulnerabilidades

# Licencias
go-licenses report ./...

Checklist de pre-instalación

Completar este checklist antes de hacer merge de cualquier PR que agrega una nueva dependencia:

## Checklist: [nombre-del-paquete]

### Justificación
- [ ] ¿Qué problema resuelve? (describir en una línea)
- [ ] ¿Existe alternativa nativa de la plataforma? (si sí, por qué no usarla)
- [ ] ¿Se puede implementar en < 50 líneas sin mantenimiento complejo? (si sí, implementar)
- [ ] ¿Cuántas funciones vamos a usar de esta librería?

### Health check
- [ ] Tendencia de descargas: ______ (subiendo / estable / bajando)
- [ ] Último release: ______ (< 12 meses = ✅)
- [ ] Ratio issues open/closed: ______ (< 1:3 = ✅)
- [ ] Tamaño: ______ KB gzipped — Tree-shakeable: S/N
- [ ] TypeScript: nativo / @types / ninguno
- [ ] Licencia: ______ (MIT/Apache = ✅ para uso comercial)

### Seguridad
- [ ] `bun audit` / `composer audit` / `pip-audit` sin nuevas CVEs
- [ ] Sin scripts postinstall que descarguen código externo
- [ ] Maintainer activo y reputado (revisar historial de GitHub)
- [ ] Sin vulnerabilidades de seguridad abiertas sin respuesta

### Alternativas evaluadas
- [ ] Alternativa considerada: ______
- [ ] Razón para elegir la seleccionada: ______

### Decisión
- [ ] Aprobado para instalar: S/N
- [ ] Aprobación del Tech Lead requerida: S/N (requerir si algún punto falla)

Monitoreo continuo

Agregar una dependencia no es un evento único — es una relación a largo plazo. Las librerías cambian: maintainers se van, proyectos se abandonan, CVEs se descubren.

En Wiedii, el monitoreo continuo está cubierto principalmente por Renovate (ver renovate), que abre MRs automáticos con actualizaciones de dependencias. Esto cubre el caso de parches de seguridad y actualizaciones de versión.

Para el monitoreo de health score y abandono, hacer una revisión trimestral de las 10-15 dependencias más críticas del proyecto:

# JavaScript: revisar health en pkgpulse.com
# Cualquier librería que haya bajado > 15 puntos en health score = investigar

# Verificar si siguen teniendo maintainers activos en GitHub
# Revisar si hay alternativas que la comunidad haya adoptado

# Señal de migración urgente:
# - El proyecto fue archivado en GitHub
# - El maintainer anunció abandono
# - CVE crítica abierta > 30 días sin respuesta

Por qué las descargas altas no son suficiente

Un error común: elegir una librería porque "tiene muchas descargas" sin revisar la tendencia. Ejemplos del ecosistema:

  • request (npm): 14M descargas/semana en 2020, archivada en 2021. Muchos proyectos la usaban porque era "popular".
  • node-uuid: deprecada, reemplazada por uuid. Las descargas seguían altas porque proyectos legacy no migraban.
  • colors / faker (2022): maintainers sabotearon sus propias librerías introduciendo código malicioso. Solo el análisis de comportamiento (Socket.dev) lo detectó antes que npm audit.

La popularidad pasada no garantiza el mantenimiento futuro. La tendencia de los últimos 3-6 meses es el mejor indicador de hacia dónde va la comunidad.


Relación con otros principios de Wiedii

  • KISS — si puedo implementarlo simple, no necesito la dependencia
  • DRY — la librería provee abstracción reutilizable, pero solo si vale el costo
  • politicas-core — toda dependencia elegida va pinneada, sin rangos abiertos
  • renovate — el monitoreo y actualización continua es automático via Renovate

Referencias