La importancia de encapsular las librerías de terceros

Hace poco comenzamos a migrar una aplicación de Vue 2 a Vue 3, y uno de los problemas que nos encontramos que la librería vue-resource había quedado obsoleta y debíamos sustituirla por fetch. Entonces vimos que se utilizaba en un gritón de sitios y la API de fetch no es ni parecida.

Refactorizar cada uso de vue-resource en la aplicación no era una opción, pues se trata de una aplicación muy grande, y nos hubiera llevado demasiado tiempo. Por lo que decidimos crear una librería propia que respeta la API de vue-resource, pero que utiliza fetch por debajo.

Esta solución fue posible porque vue-resource se utiliza desde la instancia de Vue, y simplemente sustituimos una por otra al instanciar Vue, pero puede haber casos más complejos en los que no sea tan sencillo.

Uso de librerías de terceros

Usar librerías de terceros nos aporta muchas ventajas. Nos ahorra tiempo, nos proporciona funcionalidades que no sabríamos implementar o tendrían un coste inasumible, y nos permite no reinventar la rueda y centrarnos en resolver los problemas de negocio.

Sin embargo, del mismo modo, usar estas librerías nos está atando a ellas y a las decisiones de sus creadores.

El día menos pensado, el desarrollador de esa librería que utilizas en tu aplicación para crear PDFs, decide que ya no tiene tiempo o motivación para mantenerla, o decide que va a cambiar el API, y tu aplicación se encuentra con que no funciona ningún PDF.

Encapsula las librerías externas en una tuya

Proteger tu aplicación de estos cambios es muy sencillo, y en la mayoría de casos tiene un coste ínfimo durante la creación del proyecto.

A partir de ese momento, si el día de mañana la librería deja de tener mantenimiento, cambia su API, o simplemente encuentras una que te gusta más, solo tienes que cambiar la implementación de tu librería, y tu aplicación seguirá funcionando como si nada.

Ejemplo de encapsulamiento

Imaginamos que tenemos una librería que nos permite crear PDFs, que contiene la función que nos interesa, createPdf con esta API.

// vendorPdf.js
function createPdf(html, name, paperSize, orientation) {
    // ...
}

Podríamos usarla en nuestro código de esta forma, y en principio no habría ningún problema.

// myCode.js
const html = '<h1>My title</h1><p>My paragraph</p>';
const name = 'my-file.pdf';
const paperSize = 'A4';
const orientation = 'portrait';

createPdf(html, name, paperSize, orientation);

Sin embargo, si mañana encontramos una librería más eficiente, y quereos cambiarla, tendríamos que cambiar todas las llamadas a createPdf en nuestra aplicación. Un verdadero rollo.

En lugar de eso, podemos crear una librería propia, que encapsule la librería externa, y además, aprovecharemos para adaptar la API a nuestras necesidades. Consiguiendo no solo estar protegidos ante cambios, sino que además, podemos simplificar su uso.

Por ejemplo, en nuestro caso, sabemos que nuestra aplicación siempre saca los PDF en A4 y en vertical, por lo que los parámetros paperSize y orientation son siempre los mismos.

Podríamos crear una libería con esta API.

// myPdfLibrary.js
function makePdf(html, name) {
  const paperSize = 'A4';
  const orientation = 'portrait';
  
  createPdf(html, name, paperSize, orientation);
}

Ahora, si queremos usar la nueva librería SuperPDF, con esta API.

// SuperPDF.js
class SuperPDF {
  constructor(paperSize, orientation) {
    // ...
  }
  
  create(html, name) {
    // ...
  }
}

Simplemente modificamos nuestra librería.

// myPdfLibrary.js
function makePdf(html, name) {
  const paperSize = 'A4';
  const orientation = 'portrait';
  
  const superPdf = new SuperPDF(paperSize, orientation);
  
  superPdf.create(html, name);
}

Como veis, protegernos de los cambios de API y librerías es muy sencillo y fácil de hacer, así que te recomiendo que siempre que vayas a empezar a usar una librería externa, crees la tuya que te proporcione una API estable para el futuro.

Perderás unos minutos en la primera implementación, pero ahorrarás mcuho tiempo y disgustos en el futuro.