Las dependencias de código son el demonio.

Tus dependencias te quemarán siempre.
"El cambio es la única constante ..." - Heráclito (filósofo)

Las herramientas, bibliotecas y marcos que usamos para construir nuestras aplicaciones web hoy son drásticamente diferentes de los que usamos hace unos pocos años.

En unos pocos años a partir de ahora, la mayoría de estas tecnologías habrán cambiado drásticamente nuevamente. Sin embargo, muchos de nosotros hacemos de estos una parte central e inextricable de nuestras aplicaciones.

Importamos, usamos y heredamos de los marcos del sabor del mes como si todos estuvieran presentes y sin cambios para siempre. Bueno ... no lo son. Y eso es un problema.

Después de más de 20 años de desarrollo, diseño y arquitectura de aplicaciones web, he llegado a apreciar dos verdades importantes:

  1. Las dependencias externas representan una gran amenaza para la estabilidad y la viabilidad a largo plazo de cualquier aplicación.
  2. Cada vez es más difícil, si no imposible, construir cualquier tipo de aplicación no trivial sin aprovechar las dependencias externas.

Este artículo trata sobre la reconciliación de estas dos verdades para que nuestras aplicaciones tengan la mayor posibilidad de supervivencia a largo plazo.

La madriguera del conejo es muy profunda.

Si comenzamos a pensar en todas las cosas de las que dependen nuestras aplicaciones web, es fácil pensar en una docena o más incluso antes de llegar al código:

  • Poder
  • Conectividad
  • Cortafuegos
  • DNS
  • Hardware del servidor (CPU, disco, RAM, ...)
  • Enfriamiento
  • Plataforma de virtualización
  • Plataforma de contenedores
  • Sistema operativo
  • Plataforma de servidor web
  • Plataforma del servidor de aplicaciones
  • Navegador web

Como desarrolladores, es bueno estar al tanto de estas cosas, pero a menudo no hay mucho que podamos hacer al respecto. Entonces, ignorémoslos por ahora y hablemos solo sobre el código.

En el código, hay tres tipos de dependencias:

1. Dependencias que controlamos

Este es un código escrito y de nuestra propiedad o de nuestra organización.

2. Dependencias que no controlamos

Este es un código escrito por un proveedor externo o comunidad de software de código abierto.

3. Dependencias una vez eliminadas

Estas son las dependencias de código de las que dependen nuestras dependencias de código de terceros. (¡Dilo tres veces rápido!)

Vamos a hablar principalmente sobre dependencias que no controlamos.

Las dependencias que controlamos y las dependencias una vez eliminadas aún pueden causar dolores de cabeza, pero en el caso de las dependencias que controlamos, deberíamos poder intervenir directamente y mitigar cualquier problema.

En el caso de las dependencias una vez eliminadas, generalmente podemos confiar en que un tercero se encargará de nosotros, ya que también dependen de ellas.

Por qué las dependencias de código de terceros son buenas

Existe una gran parte de su aplicación web para resolver problemas comunes: autenticación, autorización, acceso a datos, manejo de errores, navegación, registro, cifrado, visualización de una lista de elementos, validación de entradas de formularios, etc.

Independientemente de la pila de tecnología que utilice, existe una buena posibilidad de que existan soluciones comunes a estos problemas, y estén disponibles como bibliotecas que puede adquirir y conectar fácilmente a su base de código. Escribir cualquiera de estas cosas completamente desde cero es generalmente una pérdida de tiempo.

Desea concentrarse en el código que resuelve un problema poco común o resuelve un problema común de una manera poco común. Eso es lo que hace que su aplicación sea valiosa: el código que implementa las reglas de negocios que son exclusivas de su aplicación, la "salsa secreta".

El algoritmo de búsqueda y clasificación de páginas de Google, el filtro de línea de tiempo de Facebook, la sección "recomendado para usted" de Netflix y los algoritmos de compresión de datos: el código detrás de todas estas características es "salsa secreta".

El código de terceros, en forma de bibliotecas, le permite implementar rápidamente esas características comercializadas de su aplicación, para que pueda concentrarse en su "salsa secreta".

Por qué las dependencias de código de terceros son malas

Eche un vistazo a cualquier aplicación web no trivial construida en los últimos años y quedará absolutamente asombrado por la cantidad de código que en realidad proviene de una biblioteca de terceros. ¿Qué sucede si una o más de esas bibliotecas de terceros cambian drásticamente, desaparecen o se rompen?

Si es de código abierto, tal vez pueda arreglarlo usted mismo. Pero, ¿qué tan bien entiendes todo el código de esa biblioteca que no tienes? Una gran razón por la que utiliza una biblioteca en primer lugar es para obtener los beneficios del código sin tener que preocuparse por todos los detalles. Pero ahora estás atrapado. Has atado completamente tu fortuna a estas dependencias que no tienes ni controlas.

No se preocupe, al final de este artículo, encontrará una nueva esperanza.

Quizás pienses que estoy exagerando o hablando desde un punto de vista puramente académico. Permítame asegurarle: tengo docenas de ejemplos de clientes que se burlaron por completo incrustando demasiado código de terceros en su aplicación. Aquí hay solo un ejemplo reciente ...

Un antiguo cliente mío construyó su aplicación utilizando un proveedor de Back-end como servicio propiedad de Facebook, llamado Parse. Utilizaron una biblioteca de cliente JavaScript proporcionada por Parse para consumir el servicio Parse. En el proceso, unieron estrechamente todo su código, incluido el código de "salsa secreta", a esta biblioteca.

Tres meses después del lanzamiento inicial del producto de mi cliente, justo cuando comenzaron a obtener una buena tracción con clientes reales y pagadores, Parse anunció que se estaba cerrando.

Ahora, en lugar de centrarme en iterar en su producto y aumentar su base de clientes, mi cliente tuvo que descubrir cómo migrar a una versión de código abierto autohospedado de Parse o reemplazarlo por completo.

La interrupción que esto causó para una aplicación joven e incipiente fue tan grande que mi cliente finalmente desechó la aplicación por completo.

Balanceando lo bueno y lo malo

Hace varios años, mi solución para superar los riesgos y al mismo tiempo conservar los beneficios de las bibliotecas de terceros fue envolverlos usando el Patrón Adaptador.

Esencialmente, envuelve el código de terceros en una clase de adaptador o módulo que ha escrito. Esto funciona para exponer las funciones de las bibliotecas de terceros de una manera que usted controla.

Con este patrón, si una biblioteca o marco de terceros cambia, o desaparece, solo tiene que arreglar un poco de código de adaptador. El resto de su aplicación permanece intacta.

Diagrama del patrón del adaptador de Dofactory.com

Esto suena bien en papel. Cuando tiene dependencias autónomas que solo proporcionan algunas funciones, esto será suficiente. Pero las cosas pueden ponerse feas rápidamente.

¿Te imaginas tener que envolver toda la biblioteca React (incluida JSX) antes de usarla? ¿Qué tal envolver jQuery, o Angular, o el framework Spring en Java? Esto rápidamente se convierte en una pesadilla.

En estos días recomiendo un enfoque más matizado ...

Para cada dependencia que desee agregar a su base de código, evalúe el nivel de riesgo que introducirá multiplicando dos factores:

  1. La probabilidad de que la dependencia cambie de manera material.
  2. La cantidad de daño que un cambio material a la dependencia le haría a su aplicación.

Es menos probable que una biblioteca o marco de terceros cambie cuando algunas o todas las siguientes cosas son verdaderas:

  • Ha existido durante varios años y ha tenido varios lanzamientos importantes.
  • Es ampliamente utilizado por muchas aplicaciones comerciales.
  • Cuenta con el apoyo activo de una gran organización, preferiblemente una empresa o institución de renombre.

Una biblioteca o marco de terceros hará menos daño a su aplicación cuando algunas o todas las siguientes cosas sean ciertas:

  • Solo lo usa una pequeña porción de su aplicación, en lugar de usarse en todas partes.
  • El código que depende de él no es parte de esa "salsa secreta" de la que hablé anteriormente.
  • Eliminarlo requiere cambios mínimos en su base de código.
  • Toda su aplicación es muy pequeña y puede reescribirse rápidamente. (Tenga cuidado con este, rara vez es cierto por mucho tiempo).

Cuanto más arriesgado es, más probabilidades hay de que lo envuelva o lo evite por completo.

Cuando se trata del código que es realmente central para la propuesta de valor de su aplicación, su "salsa secreta", debe ser extremadamente protector con él. Haga que el código sea lo más independiente posible. Si absolutamente necesita usar una dependencia, considere inyectarla en lugar de hacer referencia directa a ella. Incluso entonces, ten cuidado.

A veces esto significa decir "no" a una biblioteca de terceros que crees que es genial, o que realmente quieres usar por una razón u otra. Sé fuerte. Confía en mí, valdrá la pena. Solo pregúnteles a todas aquellas personas que invirtieron mucho en la primera versión de Angular, o a mi antiguo cliente que usó Parse en todas partes. No es divertido Créame.

Hablando de diversión, mira esto ...

Gráfico de dependencia para el explorador TinyTag

La imagen de arriba es el gráfico de dependencia para una aplicación llamada TinyTag Explorer.

Generar un gráfico de dependencia para sus aplicaciones existentes es una excelente manera de comprender el nivel de riesgo que introducen sus dependencias. He reunido una lista de herramientas gratuitas para generar gráficos similares a los anteriores en una variedad de lenguajes que incluyen JavaScript, C #, Java, PHP y Python. Puedes obtenerlo aqui.

Ayúdame a ayudar a otros

Quiero ayudar a tantos desarrolladores como pueda compartiendo mi conocimiento y experiencia con ellos. Ayúdame haciendo clic en el botón ❤ recomendar (corazón verde) a continuación.

Finalmente, no olvides tomar tu lista de generadores de gráficos de dependencia gratuitos aquí.