Skip to content

Instantly share code, notes, and snippets.

@dpaez
Last active February 27, 2018 14:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dpaez/754155ef38e2c7c800b68c292660f440 to your computer and use it in GitHub Desktop.
Save dpaez/754155ef38e2c7c800b68c292660f440 to your computer and use it in GitHub Desktop.
dk writing a blog post about choo and composing choo apps? choo apps as plugins? wat?

Componiendo choo apps.

TLDR

En este articulo vamos a ver los conceptos de composición y plugin. Vamos a relacionarlos usando el framework Choo teniendo como objetivo la creación de un componente nuevo que otrxs tal vez pueden usar.

Intro

Choo es un framework para construir aplicaciones web (otro mas 😁), que tiene como objetivo simplificar el desarrollo e incluso hacerlo divertido. Esto lo podemos ver reflejado en su filosofia [Ref: Choo#Philosophy]. Pero ¿Cómo logra choo simplificar este proceso? Bueno, alguna de las estrategias que Yoshua Wuyts (autor, desarrollador principal) y colaboradores eligen son: mantener una base de código pequeña (1 solo archivo, con dependencias por supuesto), apoyarse en un sistema de eventos y mantener una superficie de API reducida. Pero estas son tan solo algunas características, si desean conocer mas sobre choo hace un tiempo dí una charla llamada: Choo, el pequeño framework que puede que funciona como una introducción al framework (con algunos ejemplos incluidos).

En este articulo vamos a asumir que el lector tiene conocimientos básicos sobre Choo y que participó en el desarrollo de alguna aplicación web.

Composición & Plugines

Posiblemente estamos acostumbrados a descomponer problemas pero, sorprendentemente, no somos tan conscientes de usar la composición de distintas partes para obtener una solución. En este árticulo vamos a centrarnos en composición a través de funciones, algo que JavaScript nos permite hacer de forma muy simple [Ref: Composing Software: An Introduction].

Por ejemplo, con un poco de JS idiomático podemos representar una simple composición de funciones:

const logger = formatFn => {
  return text => console.log(formatFn(text))
}

// y luego podemos usarlo así

const myFormat = text => `⚠️ :: ${text}`

const myLogger = logger(myFormat)

myLogger('hello world')

Antes de seguir avanzando quiero recordar que cuando estamos desarrollando, hay muchas formas de obtener un mismo resultado. Teniendo eso en cuenta, usaré mi experiencia trabajando con otras tecnologias, puntualmente me refiero al framework para crear servicios, Hapi.js.

En el ecosistema de Hapi.js la creación de plugines para extender el framework y adecuarlo a nuestros casos de uso es una practica habitual y probada (pueden ver el ecosistema oficial). Simplemente, para que estemos todos en la misma pagina ¿qué entendemos por plugin?. Podemos decir que se trata de un componente que agrega una funcionalidad especifica a otro componente. [Ref: wikipedia]

En Hapi.js un plugin tiene la siguiente forma [Ref: Plugins]:

const plugin = {
    name: 'test',
    version: '1.0.0',
    register: function (server, options) {

        server.route({
            method: 'GET',
            path: '/test',
            handler: function (request, h) {

                return 'ok';
            }
        });
    }
};

Entonces ¿cómo conectamos estos dos conceptos, composición y plugines? Creo que ustedes ya tienen la respuesta. Puedo agregar que usar composición como mecanismo para extender de manera uniforme (plugin) un componente de software es una estrategia que funciona (eg, estamos separando responsabilidades en distintos plugines) y es facil de comprender (eg, porque siempre hacemos lo mismo para extender nuestro sistema).

Contexto

Para bajar estos conceptos voy a agregar un problema real o mejor dicho un caso de uso. Luego de hacer algunas pruebas con choo me decidi por armar una charla al respecto y dije, "hey, ¿y si hago las slides usando choo?". Eso fue el disparador. Armé las slides pero quedo todo en un solo proyecto, o sea si alguien quería usarlo no podia, tenia q manualmente separarlo del código de mi presentación, no era un plugin per se. Un dia en el canal de IRC de choo ví que uno de los usuarios compartió las slides y consegui algunos buenos comentarios, les dije que estaba pensando separar las slides y publicarlas como un modulo en npm y obtuve algo de interes. Eso fue la motivación. 👍 🎉

En ese momento empecé a trabajar en choo-slides. La idea es agregar una feature a una aplicación choo, que sea capaz de ser usada como motor de presentación. Es decir, podes crear tus slides usando HTML, JS y CSS y tenes algunas funcionalidades como soporte para notas, saltar a una slide en particular y obviamente poder moverte adelante y atras. Tambien pensé que seria bueno agregar estas funcionalidades sin que tu app deje de ser una app. Quiero decir que el usuario siga teniendo el control y pueda extender esto a otros escenarios que no contemplé inicialmente. Es una forma mas relajada y no menos responsable de desarrollar.

Manos a la obra

Primero estuve revisando el ecosistema de choo y no encontre proyectos similares. Choo es una comunidad nueva y muy interesante, hay usuarios de todo tipo como el mítico substack, pero bueno, al ser nueva no hay muchos modulos, lo que representa una excelente oportunidad para crecer, aportar y contribuir. Volviendo al tema, no encontre modulos similares, en particular lo que buscaba era verificar si habia una forma de extender una aplicación. Tenia una idea en mente pero buscaba validarla. Como no encontré una forma en particular, recordé esto que mencionaba antes: "hay muchas formas de llegar a un resultado".

La idea es extender una app choo como si fuera un plugin. El mecanismo que provee la API de choo es el método use(fn). Como podemos observar recibe como parámetro una función, a esta función la va a invocar con los siguientes parametros: state, emitter, app. state se refiere al estado actual de la aplicación, emitter es el mecanismo que tenemos para disparar acciones como un render y finalmente recibimos una instancia de la app que nos hostea. Esto último lo relacioné con mi experiencia trabajando con Hapi.js e inmediatamente me pareció el punto de extensión que estaba buscando para mi nuevo plugin.

Este plugin iba a agregar nuevas funcionalidades (como nuevas rutas y eventos), modificando así la aplicación que lo fuera a usar (aka, host), por eso era interesante contar con una instancia de la app. Cabe destacar que para hacer estas modificaciones sobre un host, hay que tener ciertos cuidados, como usar namespaces para evitar colisiones, documentar estas extensiones o modificaciones claramente y tratar de minimizarlas (preguntarnos dos veces antes de hacer algun cambio).

Entonces, para crear un plugin usando choo, podemos hacer algo así:

module.exports = myPlugin

function myPlugin(options){
  // validar options, podemos usar [assert](https://nodejs.org/api/assert.html)
  
  // tambien podes crear lo que necesitemos compartir con la función de retorno, ya que este es nuestro closure.
  
  const store = (state, emitter, app) => {
    // acá tenemos efectivamente el state, emitter y la instancia de la app host.
    // nuestras modificaciones o extensiones las hacemos desde este punto usando la API de choo.
  }
  
  store.storeName = 'myPlugin' // es una buena práctica identificar a nuestros plugins 
  
  return store; // finalmente retornamos la función que la app host va a invocar.
}

Con este pseudo snippet cubrimos lo necesario para extender una aplicación choo, el resto corre por nuestra cuenta (imaginación).

Desde el lado de la app host la invocación sería algo asi:

const choo = require('choo')
const myPlugin = require('myplugin')

// creo mi app choo
const app = choo()
// conecto con myPlugin
app.use(myPlugin({ ...opciones }))

// finalmente monto la app al dom
app.mount('body')

No hay nada nuevo y eso es bueno. ¡Estamos usando una estrategia uniforme para extender nuestras apps choo! 🆒

Conclusiones

Hemos visto una forma posible para extender una aplicación choo. Esta forma involucra los conceptos de composición y plugin. Para esto vimos como crear un plugin choo y como conectarlo a otro componente host a través de un mecanismo simple de composición de funciones. Dicho mecanismo es provisto por el framework: app.use(fn).

Espero que algunos de los conceptos que vimos les sirvan y puedan aplicarlos en sus proyectos. Les recomiendo, si aun no lo han hecho, probar choo, es una herramienta simple y poderosa con una comunidad y ecosistema en crecimiento. Y hablando de comunidad, si tienen alguna duda o comentario o simplemente quieren compartir experiencias de desarrollo en JS con otrxs pares, los invito a sumarse al slack de LaPlataJS (slackin). Eso es todo, gracias por leer! 👋 DK

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment