Las dependencias de código son el diablo.

"El cambio es la única constante ..." - Heráclito (Filósofo)

Las herramientas, bibliotecas y marcos que usamos para construir nuestras aplicaciones web en la actualidad son drásticamente diferentes de las 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 vuelto a cambiar drásticamente. Sin embargo, muchos de nosotros hacemos de estos una parte central e inextricable de nuestras aplicaciones.

Importamos, usamos y heredamos de los marcos de trabajo del tipo 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 desarrollar, diseñar y diseñar aplicaciones web, he llegado a apreciar dos verdades importantes:

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

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

La madriguera del conejo es muy profunda.

Si empezamos 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 de 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 propiedad de nosotros o de nuestra organización.

2. Dependencias que no controlamos

Este es un código escrito por un proveedor externo o una 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!)

Hablaremos principalmente de las dependencias que no controlamos .

Las dependencias que controlamos y las dependencias una vez eliminadas todavía 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, normalmente podemos confiar en un tercero para que se encargue de ellas, ya que ellos también dependen de estos.

Por que las dependencias de código de terceros son buenas

Una gran parte de su aplicación web existe 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, es muy probable que existan soluciones comunes para estos problemas y que 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 comerciales que son exclusivas de su aplicación únicamente: la "salsa secreta".

El algoritmo de búsqueda y clasificación de páginas de Google, el filtrado de la 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 funciones es "salsa secreta".

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

Por que las dependencias de código de terceros son malas

Eche un vistazo a cualquier aplicación web no trivial creada 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é pasa si una o más de esas bibliotecas de terceros cambia drásticamente, o desaparece o se rompe?

Si es de código abierto, quizás puedas arreglarlo tú mismo. Pero, ¿qué tan bien comprende todo el código de esa biblioteca que no posee? 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 atascado. Ha atado completamente su fortuna a estas dependencias que no posee ni controla.

Quizás pienses que estoy exagerando o hablo desde un punto de vista puramente académico. Déjame asegurarte: tengo docenas de ejemplos de clientes que se burlaron por completo al incrustar código de terceros con demasiada fuerza en su aplicación. Aquí hay solo un ejemplo reciente ...

Un antiguo cliente mío creó su aplicación utilizando un proveedor de backend-as-a-Service propiedad de Facebook, llamado Parse. Utilizaron una biblioteca cliente de JavaScript proporcionada por Parse para consumir el servicio Parse. En el proceso, acoplaron 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 empezaron a tener una buena tracción con clientes reales que pagaban, Parse anunció que cerraría.

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

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

Equilibrando lo bueno y lo malo

Hace varios años, mi solución de referencia para superar los riesgos y al mismo tiempo conservar los beneficios de las bibliotecas de terceros era envolverlas con el patrón de adaptador.

Esencialmente, envuelve el código de terceros en una clase de adaptador o módulo que ha escrito. Esto luego 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 corregir un poco de código del adaptador. El resto de su aplicación permanece intacta.

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

¿Te imaginas tener que empaquetar toda la biblioteca de React (incluido JSX) antes de usarla? ¿Qué tal empaquetar jQuery, Angular o Spring Framework 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 código base, evalúe el nivel de riesgo que presentará multiplicando dos factores:

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

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

  • 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 conocida.

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

  • Solo se usa en una pequeña parte 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é antes.
  • Eliminarlo requiere cambios mínimos en su código base.
  • Toda su aplicación es muy pequeña y se puede reescribir rápidamente. (Tenga cuidado con este, rara vez es cierto durante mucho tiempo).

Cuanto más riesgoso sea algo, más probable será que lo envuelva o lo evite por completo.

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

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

Hablando de diversión, échale un vistazo a esto ...

La imagen de arriba es el gráfico de dependencia de 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 presentan sus dependencias. He reunido una lista de herramientas gratuitas para generar gráficos similares a los anteriores en una variedad de lenguajes, incluidos 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 olvide obtener su lista de generadores de gráficos de dependencia gratuitos aquí.