Reinventar la rueda

¿Has tenido que repetir alguna vez un mismo desarrollo, pero de forma diferente para una nueva aplicación? ¿Cuántas formas diferentes de utilizar un mismo componente (dropdown, checkbox, …) has usado? ¿Tiemblas al pensar en lo que supone migrar a una nueva tecnología y rehacer los desarrollos que ya funcionan?

Estamos en el momento cumbre de uso de Javascript, y en realidad avanzamos hacia atrás…

No hace mucho asistí a una presentación, en la que se enseñaba un nuevo desarrollo. Se trataba de un desarrollo paralelo al de producción, pero usando una nueva tecnología de desarrollo. Esto debía sustituir en el futuro a lo que tenían actualmente. El ponente dijo satisfecho:

‘Os presento el futuro…’

Y asistimos a una presentación en la que se enseñaron nuevos menús desplegables, nuevos dropdowns, nuevos checkboxes, nuevos tooltips…

La gente más técnica asentía con la cabeza. Claro, es que estamos usando componentes. React, Vue, Polymer… Con esto todo irá mucho más rápido.

Pero la gente de negocio se miraba un poco extrañada. ¿Qué tiene esto de innovador? Son los mismos componentes que ya conocemos.

¿Esto va a suponer una mejora? Probablemente sí, pero es difícil de explicar que vaya a suponer un beneficio tener a un equipo trabajando semanas en algo que ya existe.

¿Por qué no unificar esfuerzos?

Se ha avanzado mucho en lo últimos años en materia de componentes, pero la sensación que yo tengo es que los avances van cada uno por un camino diferente.

Sí, existe un estándar con los Web Components, pero en la práctica tampoco es necesariamente la mejor solución.

A la hora de personalizar un elemento (que siempre es necesario) hay que entrar en el ‘mundo javascript’, y tiene sus limitaciones (https://dmitriid.com/blog/2017/03/the-broken-promise-of-web-components/)

Es cierto que la idea de los componentes se ha consolidado y parece que los esfuerzos han avanzado en esa dirección y ha habido mucha mejoría, pero la realidad es que se siguen repitiendo una y otra vez los mismos patrones:

  • se define la arquitectura
  • se utiliza un framework para resolver problemas conocidos
  • se personalizan los componentes para ajustarse a los requisitos

Al pasar los años volvemos a definir nuevas arquitecturas, aprender nuevos frameworks, personalizar los componentes…, otra vez lo mismo.

Además, todas las arquitecturas pasan por los mismos problemas inherentes a la web: datos asíncronos que vienen de servidor, cambios dinámicos en el DOM, respuesta a eventos, diferentes dispositivos, diferentes visualizaciones.

¿No sería más fácil que hubiera un camino igual para todos? ¿Por qué no simplificar la forma de llevarlo a cabo sin tener que aprender con cada proyecto una nueva forma de hacer lo mismo? Y sobre todo, que tu código base sea el mismo independientemente de la tecnología.

Yo pienso que no es tan complicado.

¿No existen transpilers que convierten cualquier dialecto de js en un lenguaje entendible por los navegadores? ¿Y si pudiéramos utilizar algo similar para cualquier framework usando una misma forma de utilizarlo para todos?

¿Qué podríamos hacer para comunicarnos con cualquier framework de la misma forma?

Por poner un ejemplo, la forma de aglutinar todo esto y mirar desde un punto de vista común podría ser usando lo más universal que comparten todos: JS y JSON

Vamos a un ejemplo de componente simple, como por ejemplo un checkbox.

<input type="checkbox">

Un checkbox es un elemento en el que el usuario puede marcar o desmarcar su valor. Podemos complicarlo un poco, el elemento puede estar deshabilitado para impedir que el usuario lo cambie, podemos asociarle un evento para indicarnos que ha cambiado su valor. No mucho más.

¿Qué necesito para utilizar cualquier checkbox genérico?

  • Método get/set
  • Evento change
  • Enable/disable
  • Valor por defecto

¿Y si yo definiera una interfaz en la que se inicialice mi checkbox con un JSON simple

miObjeto = new Element({ type: 'checkbox', default: false});
o
<div data-element="{ type: 'checkbox', default: false}">

y pudiera utilizar los métodos siempre de la misma forma:

miObjeto.get()
miObjeto.set(true)
miObjeto.on('change', fn)

pero por dentro le digo que utilice para ese get/set/change la tecnología que yo quiera:

jQuery

<input type="checkbox">

get -> $('input').val()
set -> $('input').val(true)
change -> $('input').on('change', fn)

Angular

<input type="checkbox" ng-model="myValue" ng-change="myFunc()">

get -> return $scope.myValue
set -> $scope.myValue = true
change -> $scope.myFunc = fn

Polymer

<dom-module id="custom-element">
    <template>
      <input type="checkbox" checked="{{checked::change}}">
    </template>
    <script>
      Polymer({
        is: 'custom-element',
        properties: {
          checked: {
            type: Boolean,
            value: true,
            observer: 'changeHandler'
          }
        },
        changeHandler: function (value) {
            this.fire('change', {value: value}));
        }
      });
    </script>
</dom-module>
<custom-element></custom-element>

get -> customElement.checked;
set -> customElement.checked = true;
change -> customElement.addEventListener('change',function (e) {
  fn(e.detail.value)
});

Entre medias haría falta un plugin o transpiler que convierta esa definición JSON en código diferente para cada framework.

De este modo, podríamos cambiar de tecnología sin modificar el código base de la aplicación.

Si pensamos en el trabajo conseguido con Material Design de cara al diseño y experiencia de usuario, esto sería algo similar pero enfocado a la capa de desarrollo. Una definición abstracta de componentes de uso común, con una interfaz única e independiente de lo que haya por debajo, ¿por qué no?