<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Sergio</title>
    <description>The latest articles on DEV Community by Sergio (@imsergiobernal).</description>
    <link>https://dev.to/imsergiobernal</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F106108%2F1a88dd76-5aff-4905-be1e-1f7279542368.jpg</url>
      <title>DEV Community: Sergio</title>
      <link>https://dev.to/imsergiobernal</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/imsergiobernal"/>
    <language>en</language>
    <item>
      <title>Unir diseño con traducción: hasta dónde.</title>
      <dc:creator>Sergio</dc:creator>
      <pubDate>Tue, 18 Jul 2023 11:00:31 +0000</pubDate>
      <link>https://dev.to/imsergiobernal/unir-diseno-con-traduccion-hasta-donde-19cm</link>
      <guid>https://dev.to/imsergiobernal/unir-diseno-con-traduccion-hasta-donde-19cm</guid>
      <description>&lt;p&gt;En este artículo explicaré por qué probé a introducir a los diseñadores de UI a formar parte de las traducciones, y por qué he llegado a la conclusión de que &lt;strong&gt;no es, al menos, el momento&lt;/strong&gt; de hacer integraciones entre sus herramientas y las de traducción.&lt;/p&gt;

&lt;h2&gt;
  
  
  Índice
&lt;/h2&gt;

&lt;p&gt; 1. De dónde surge la idea&lt;br&gt;
 2. Veía potenciales procesos a plantear&lt;br&gt;
 3. Entonces, ¿los diseñadores dan de alta las palabras?&lt;br&gt;
 4. ¿Puedo integrar mi herramienta de diseño con el TMS?&lt;br&gt;
       4.1. Sólo un idioma en la app de diseño de UI, y todo a texto plano (como toda la vida)&lt;br&gt;
       4.2. Los diseñadores establecen las cadenas de texto, y los programadores las cargan en el TMS.&lt;br&gt;
       4.3. Lo que nos ahorremos en establecer integraciones aquí, lo podremos emplear en otros procesos&lt;br&gt;
 5. Conclusión&lt;br&gt;
   &lt;/p&gt;

&lt;h2&gt;
  
  
  De dónde surge la idea
&lt;/h2&gt;

&lt;p&gt;Los diseñadores son probablemente las personas en una empresa que más conocen el valor de un Design System junto con los programadores front-end. Normalmente en estos Design System hay un apartado que trata cosas como el &lt;em&gt;tono de voz&lt;/em&gt; y la personalidad.&lt;/p&gt;

&lt;p&gt;¿Cuántos de vosotros no estáis hasta las 👃 de que diferentes personas os estén diciendo de cambiar los textos/copies de la interfaz o mensajes? 😀&lt;/p&gt;

&lt;p&gt;Bueno, pues estas reglas del Design System establecen cómo han de ser los copies para mejorar la calidad y reducir la fricción de los procesos.&lt;/p&gt;

&lt;p&gt;Entonces pensé: en las operaciones de diseño habrá que hacer algo.&lt;/p&gt;

&lt;p&gt;  &lt;/p&gt;

&lt;h2&gt;
  
  
  Veía potenciales procesos a plantear
&lt;/h2&gt;

&lt;p&gt;Unas herramientas claves en esto son las &lt;strong&gt;Translations Management Systems/Software&lt;/strong&gt; o &lt;strong&gt;TMS&lt;/strong&gt;, que permiten tener un punto central donde gestionar prácticamente todo el ciclo de vida de las traducciones.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--KHpKuNK5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/waxh55iua42dzioloi6x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KHpKuNK5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/waxh55iua42dzioloi6x.png" width="800" height="424"&gt;&lt;/a&gt;&lt;br&gt;Operaciones ligadas a las traducciones. Fuente: &lt;a href="https://phrase.com/blog/posts/translation-management-system-how-it-works/"&gt;Phrase&lt;/a&gt;
  &lt;/p&gt;

&lt;p&gt;Otro punto importante es tener un idioma base para todos los procesos del proyecto, ya que las cadenas de texto necesitan de un idioma base para ser traducidas al resto (luego puedes crear otros flujos de traducción para optimizar costes pero no viene al tema).&lt;/p&gt;

&lt;p&gt;Veía que los diseñadores suelen tener un montón de páginas en herramientas como Figma, exponiendo las mismas "vistas"/"componentes" (V/C en adelante) y cuando se cambiaba alguna palabra, otras V/C quedaban desactualizadas. Luego, si había que hacer una revisión para ver que todo estaba bien, había que estar preguntando: "oye, ¿es este el copy o es este otro?"&lt;/p&gt;

&lt;p&gt;Imagina a alguien que acaba de entrar, que no se entera de la película, viendo como hay textos distintos en la aplicación y, que en muchas ocasiones, te ahorras preguntar ya que el coste de desconcentrar a otras personas por algo así no compensa. Pero esa imagen de desorden y falta de integridad está en la calidad de proyecto y de la app. Esta problemática se encuentra más en proyectos en los que no hay un Design System.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--lMXlgJsU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dhno5okoiiwtvugqtxhd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--lMXlgJsU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dhno5okoiiwtvugqtxhd.png" width="800" height="786"&gt;&lt;/a&gt;&lt;br&gt;Ejemplo de cómo se pueden crear falta de integridad en la herramienta de diseño y en las apps finales
  &lt;/p&gt;

&lt;p&gt;Por eso pensé que podría haber alguna manera de que los diseñadores pudieran vincular las cadenas de texto del TMS con las que hay en los mocks/prototipos (llámese como desee) para que se viera exactamente igual en todas las V/C y también en la app, que de ser multiplataforma, entonces en todas las apps.&lt;/p&gt;

&lt;p&gt;Esto también permitiría ver los mocks/prototipos en &lt;strong&gt;distintos idiomas&lt;/strong&gt; (conforme vayan traduciéndose en el TMS), así como escalar el trabajo si se utiliza una arquitectura de componentes.&lt;/p&gt;

&lt;p&gt;De una manera simple de dibujar, el escenario quedaría en algo tal que así (perdonad el serif del número 1 😅):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--HUKULedP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ey03zx09pv2av5z5apxx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--HUKULedP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ey03zx09pv2av5z5apxx.png" width="800" height="535"&gt;&lt;/a&gt;&lt;br&gt;La función del TMS en esta operativa a grosso modo
  &lt;/p&gt;

&lt;p&gt;La duda que te puede saltar ahora es: ¿dónde dan de alta esas traducciones? ¿En Figma, en el TMS? ¿Acaso lo tienen que hacer ellos?&lt;br&gt;
   &lt;/p&gt;

&lt;h2&gt;
  
  
  Entonces, ¿los diseñadores dan de alta las palabras?
&lt;/h2&gt;

&lt;p&gt;En resumidas cuentas: sí. Creo que los diseñadores darán de alta el 99% de copies y serán responsables de optimizar el uso de estos.&lt;/p&gt;

&lt;p&gt;Pero claro, ¿dónde los dan de alta? ¿En Figma, o en el TMS? ¿Cómo hacen cambios y dónde?&lt;/p&gt;

&lt;p&gt;Pues para responder a eso, hay que ver primero la escena actual de integraciones.&lt;/p&gt;

&lt;p&gt;  &lt;/p&gt;

&lt;h2&gt;
  
  
  ¿Puedo integrar mi herramienta de diseño con el TMS?
&lt;/h2&gt;

&lt;p&gt;Cómo hay pocos TMS (ironía), y encima no hay todavía un estándar común en estos procesos, las integraciones terminan dejando dudas. Algunas incluso ni funcionan.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--XTCjiUck--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jftp38703vrfwpe8efe1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--XTCjiUck--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jftp38703vrfwpe8efe1.png" width="800" height="609"&gt;&lt;/a&gt;&lt;br&gt;Una pequeña demostración del listado de integraciones que he probado para Figma
  &lt;/p&gt;

&lt;p&gt;He revisado más de 10 TMS y más de 30 integraciones y la conclusión es la que planteo en los siguientes puntos:&lt;/p&gt;

&lt;p&gt;  &lt;/p&gt;

&lt;h3&gt;
  
  
  Sólo un idioma en la app de diseño de UI, y todo a texto plano (como toda la vida)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;No hace falta más.&lt;/strong&gt; Los mocks tienen que servir para que los programadores y personal de producto cuenten con una fuente de información que les permita ver cómo tiene que quedar un desarrollo.&lt;/p&gt;

&lt;p&gt;Entre las complicaciones, nos encontramos con cómo introducir contenido dinámico (título de películas a ejemplo del mock), cómo introducir texto con placeholders (variables), plurales, ordinales, cómo mantener la app de UI rápida y ligera, cómo mantener el versionado de los diseños y cómo mantener actualizados ciertos cambios de manera bidireccional.&lt;/p&gt;

&lt;p&gt;Se que cuesta quitar azúcar, pero el proyecto irá perfectamente aun sin disponer mocks en múltiples idiomas. Esto reducirá muchísimo la toma de decisiones que hay que hacer y por eso, este artículo será más breve 😎&lt;/p&gt;

&lt;p&gt;  &lt;/p&gt;

&lt;h3&gt;
  
  
  Los diseñadores establecen las cadenas de texto, y los programadores las cargan en el TMS.
&lt;/h3&gt;

&lt;p&gt;Los diseñadores dictaminarán las palabras en texto plano, como han hecho siempre, pero también tendrán que ser responsables de su reutilización.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Así que: colleja al que utilice "Atrás" cuando ya existe un "Volver atrás" en toda la app.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Los diseñadores tendrán un glosario de términos, donde existirán términos de tipo "actions". Serán responsables de reutilizarlos.&lt;/p&gt;

&lt;p&gt;Y los programadores, utilizando herramientas de CI y frameworks de i18n, serán los que carguen esas cadenas de texto en el TMS para que los traductores dispongan de trabajo.&lt;/p&gt;

&lt;p&gt;Con esta reglas básicas, los desarrolladores también podrán añadir cadenas de texto que los diseñadores no hayan tenido en cuenta por cualquier motivo. Cosas tales como plurales o asuntos relacionados con ICU. Así mismo, a ser posible, los diseñadores reflejarán estas cadenas de texto faltantes una vez sean conscientes.&lt;/p&gt;

&lt;p&gt;  &lt;/p&gt;

&lt;h3&gt;
  
  
  Lo que nos ahorremos en establecer integraciones aquí, lo podremos emplear en otros procesos
&lt;/h3&gt;

&lt;p&gt;Aún nos falta meter otras cosas en este puzzle, como por ejemplo el versionado en Figma, el versionado en el TMS, Storybooks, etc. donde sí que podemos hacer cosas muy potentes.&lt;/p&gt;

&lt;p&gt;  &lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusión
&lt;/h2&gt;

&lt;p&gt;En referencia a este aspecto de la i18n y la fase de diseño, estableceremos unas normas básicas que no requerirán de integraciones programáticas y podremos lograr integrar i18n con mucha efectividad.&lt;/p&gt;

&lt;p&gt;Espero que te haya sido de utilidad.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://softwers.dev"&gt;https://softwers.dev&lt;/a&gt;&lt;/p&gt;

</description>
      <category>i18n</category>
      <category>ops</category>
      <category>design</category>
      <category>devops</category>
    </item>
    <item>
      <title>BDD automated-testing con Gherkin y Jest en Node.js 🦄</title>
      <dc:creator>Sergio</dc:creator>
      <pubDate>Sun, 08 Dec 2019 02:30:24 +0000</pubDate>
      <link>https://dev.to/imsergiobernal/bdd-automated-testing-con-gherkin-y-jest-en-node-js-3hjg</link>
      <guid>https://dev.to/imsergiobernal/bdd-automated-testing-con-gherkin-y-jest-en-node-js-3hjg</guid>
      <description>&lt;p&gt;Creo que los test en una aplicación son la mejor documentación que podemos crear. No solo son pruebas, también pueden narrar el comportamiento de la aplicación y sus restricciones.&lt;/p&gt;

&lt;p&gt;Además, es un buen punto donde las necesidades de negocio y el QA se pueden acercar al nivel de desarrollo.&lt;/p&gt;

&lt;p&gt;Pero gestionar el testing de una aplicación no es tarea fácil, porque las necesidades se transforman en el tiempo y se nos requiere mantener toda la estructura de tests que tenemos desarrollada. Por si fuera poco, también tenemos que mantener la documentación, arquitectura de la aplicación, etc.&lt;/p&gt;

&lt;p&gt;Es por eso que la automatización se vuelve un enclave vital para mantener nuestro proyecto lo más ágil (sí, &lt;em&gt;agile&lt;/em&gt; en Español) posible.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fvvnln8o2dkbanq55f9hp.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fvvnln8o2dkbanq55f9hp.jpg" alt="BDD TDD"&gt;&lt;/a&gt;&lt;/p&gt;
[Image Source](https://blog.testlodge.com/tdd-vs-bdd)




&lt;p&gt;Aquí es donde &lt;strong&gt;vamos a entrar en juego&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Caso en un entorno Agile&lt;/strong&gt;
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Todo comienza por una necesidad.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Vamos a suponer que formamos parte de un equipo de 3 desarrolladores emprendedores los cuales nos hemos repartido roles en el de desarrollo de software. Nosotros (usted lector y yo) nos vamos a encargar de las soluciones más abstractas del proyecto.&lt;/p&gt;

&lt;p&gt;Uno de los compañeros quiere que desarrollemos la implementación de una estructura de datos de una &lt;strong&gt;Lista Enlazada&lt;/strong&gt;. Él no se quiere encargar de dicha abstracción, por que está dedicado su tiempo a concreciones de más alto nivel para el negocio. Sin embargo, esta necesidad es importante porque un error en la implementación podría suponer un gran coste y un sin fin de problemas. Además pensamos utilizarla en varias partes del proyecto.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Realmente él habría hecho el mismo proceso de Descubrimiento, Formulación, Automatización que vamos a narrar en este artículo pero con un lenguaje más de producto y no tanto de ciencias de la computación.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Para el que no lo sepa, una Lista Enlazada tiene la siguiente estructura. &lt;a href="https://www.geeksforgeeks.org/linked-list-set-1-introduction/" rel="noopener noreferrer"&gt;Aquí podrás encontrar más información&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F953%2F1%2ADnMUy7SEP31IRXq1zbMwWA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F953%2F1%2ADnMUy7SEP31IRXq1zbMwWA.png" alt="Lista Enlazada"&gt;&lt;/a&gt;&lt;/p&gt;
Forma visual de una Lista Enlazada



&lt;p&gt;Quien se dedique a implementar algoritmos y estructuras de datos sabrá que es fácil &lt;em&gt;colarse&lt;/em&gt; por algún lado. Es importante sentarse previamente a definir cómo funcionará, aunque normalmente todos vamos corriendo al código 😌. En este caso, la Lista Enlazada ya está más que definida porque es muy popular y muy sencilla.&lt;/p&gt;

&lt;p&gt;Practicamos un poco de BDD y nos sentamos con nuestro compañero emprendedor para desarrollar la historia de usuario.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcucumber.io%2Fimg%2Fbdd-practices-diagram.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcucumber.io%2Fimg%2Fbdd-practices-diagram.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Descubrimiento: lo que podría hacer&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Nos pide que necesita la implementación de la Lista Enlazada.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Como desarrollador de componentes de la aplicación, quiero crear una lista enlaza con la secuencia de teclas que pulsamos en el teclado para poder implementar la lógica de un historial de comandos.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fhelpx.adobe.com%2Fcontent%2Fdam%2Fhelp%2Fes%2Fphotoshop%2Fusing%2Fundo-history%2F_jcr_content%2Fmain-pars%2Fimage_0%2Fwa_17.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fhelpx.adobe.com%2Fcontent%2Fdam%2Fhelp%2Fes%2Fphotoshop%2Fusing%2Fundo-history%2F_jcr_content%2Fmain-pars%2Fimage_0%2Fwa_17.png" alt="Historial de comandos de Photoshop"&gt;&lt;/a&gt;&lt;/p&gt;
Sería algo parecido al historial de comandos de Photoshop



&lt;p&gt;Conversando con nuestro compañero, descubrimos que para lo que necesita ahora, con la siguiente serie de requerimientos podemos empezar:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Requerimientos&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Poder instanciar una lista&lt;/li&gt;
&lt;li&gt;La lista estará vacía por defecto&lt;/li&gt;
&lt;li&gt;La lista tendrá una longitud&lt;/li&gt;
&lt;li&gt;La lista ha de tener un HEAD y un TAIL&lt;/li&gt;
&lt;li&gt;Poder añadir elementos al final de la lista&lt;/li&gt;
&lt;li&gt;Los elementos guardarán un puntero al siguiente elemento&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Formulación: Qué debe de hacer&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Sabemos lo que nuestro &lt;em&gt;cliente&lt;/em&gt; quiere, ahora vamos a escribir los requerimientos en lenguaje &lt;a href="https://cucumber.io/docs/gherkin/" rel="noopener noreferrer"&gt;Gherkin&lt;/a&gt; para sacar juguito a lo que vamos a ver después 🧃.&lt;/p&gt;

&lt;p&gt;Gherkin es un Domain-specific language (DSL) / sintáxis que permite definir muy explícitamente el &lt;strong&gt;comportamiento&lt;/strong&gt; de una &lt;em&gt;Feature&lt;/em&gt; y los &lt;strong&gt;criterios de aceptación&lt;/strong&gt;. Se puede utilizar para &lt;strong&gt;todos los niveles de testing&lt;/strong&gt; sin restricción, dado que el &lt;strong&gt;dominio&lt;/strong&gt; dará el contexto.&lt;/p&gt;

&lt;p&gt;El objetivo de este artículo &lt;strong&gt;no es explicar o entrar en detalle sobre Gherkin&lt;/strong&gt;, pero si tienes algun comentario de mejora o quieres que profundice en más detalle, házlo saber en los comentarios ✍.&lt;/p&gt;

&lt;p&gt;Tendremos que hacer un ejercicio por &lt;strong&gt;desarrollar los escenarios&lt;/strong&gt; en base a la información que hemos extraído en el &lt;strong&gt;proceso de Descubrimiento previo&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight gherkin"&gt;&lt;code&gt;&lt;span class="err"&gt;//&lt;/span&gt; &lt;span class="err"&gt;file&lt;/span&gt; &lt;span class="err"&gt;'lib/data-structures/features/singly-linked-list.feature'&lt;/span&gt;
&lt;span class="kd"&gt;Feature&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; Singly Linked List

  &lt;span class="kn"&gt;Scenario&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; Instancing a list
    &lt;span class="nf"&gt;Given &lt;/span&gt;no instance
    &lt;span class="nf"&gt;When &lt;/span&gt;instancing a new Singly Linked List
    &lt;span class="nf"&gt;Then &lt;/span&gt;initial head must be null
    &lt;span class="nf"&gt;And &lt;/span&gt;initial tail must be null
    &lt;span class="nf"&gt;And &lt;/span&gt;length must be 0

  &lt;span class="kn"&gt;Scenario&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; Pushing a value on a empty list
    &lt;span class="nf"&gt;Given &lt;/span&gt;an Empty Singly Linked List with 0 nodes
    &lt;span class="nf"&gt;When &lt;/span&gt;pushing 'First Node' as node value
    &lt;span class="nf"&gt;Then &lt;/span&gt;head value becomes 'First Node'
    &lt;span class="nf"&gt;And &lt;/span&gt;tail value becomes 'First Node'
    &lt;span class="nf"&gt;And &lt;/span&gt;the list length becomes 1

  &lt;span class="kn"&gt;Scenario&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; Pushing values on a list with a single node
    &lt;span class="nf"&gt;Given &lt;/span&gt;a Singly Linked List with a single node as 'First Node' as value
    &lt;span class="nf"&gt;When &lt;/span&gt;pushing the following values
    &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nv"&gt;NodeValue&lt;/span&gt;   &lt;span class="p"&gt;|&lt;/span&gt;
    &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Second&lt;/span&gt; &lt;span class="n"&gt;Node&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt;
    &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Third&lt;/span&gt; &lt;span class="n"&gt;Node&lt;/span&gt;  &lt;span class="p"&gt;|&lt;/span&gt;
    &lt;span class="nf"&gt;Then &lt;/span&gt;list length gets incremented to 3
    &lt;span class="nf"&gt;And &lt;/span&gt;tail value becomes 'Third Node'
    &lt;span class="nf"&gt;But &lt;/span&gt;head value still equals to 'First Node'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Opcionalmente le pasamos dicho fichero al compañero para que nos compruebe que hemos entendido correctamente sus necesidades. Si hubiese sido un cliente sin habilidades técnicas &lt;strong&gt;también sería capaz de entender este lenguaje&lt;/strong&gt;, y ese es unos de los principios y beneficios de Gherkin.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Cuando uses Gherkin, describe el comportamiento requerido, no el cómo.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Escribir este tipo de textos no es tarea fácil al principio. No obstante es una disciplina que hay que entrenar y que aumentará la calidad de tus entregas y tu pensamiento como desarrollador. Existen buenas y malas prácticas.&lt;/p&gt;

&lt;blockquote&gt;
&lt;h2&gt;
  
  
  Sufre el dolor de la disciplina o sufre el dolor del arrepentimiento.
&lt;/h2&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Automatización: Qué es lo que realmente hace&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Aquí viene lo sexy 😏. El principal coste que tiene trabajar con Gherkin es que &lt;strong&gt;hay que mantener dos cosas&lt;/strong&gt;: la definición de la feature y los tests.&lt;/p&gt;

&lt;p&gt;Pero amigo mio, vamos a hacer que mantener las dos cosas sea muy liviano, porque definiones y tests &lt;strong&gt;estarán enlazados explícitamente&lt;/strong&gt; a través de &lt;a href="https://www.npmjs.com/package/jest" rel="noopener noreferrer"&gt;jest&lt;/a&gt; + &lt;a href="https://www.npmjs.com/package/jest-cucumber" rel="noopener noreferrer"&gt;jest-cucumber&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fcgk55ldqcl8iad5s23jj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fcgk55ldqcl8iad5s23jj.png" alt="Jest 💗 Cucumber"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Instalemos ambos paquetes&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm i &lt;span class="nt"&gt;-D&lt;/span&gt; jest jest-cucumber
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;La conexión entre los tests y los ficheros de definición de &lt;code&gt;.feature&lt;/code&gt; es &lt;strong&gt;bidireccional&lt;/strong&gt; y muy práctica.&lt;/p&gt;

&lt;p&gt;Cuando hagamos un mínimo cambio en el fichero &lt;code&gt;singly-linked-list.feature&lt;/code&gt;, el fichero &lt;code&gt;singly-linked-list.steps.js&lt;/code&gt; fallará 🚨 para avisarnos de que hay adaptaciones por hacer. Sólo así lograremos lo que se denomina una &lt;strong&gt;Documentacion viva&lt;/strong&gt; real.&lt;/p&gt;

&lt;p&gt;Hay que entender que si el fichero &lt;code&gt;singly-linked-list.feature&lt;/code&gt; cambia, es porque han habido &lt;strong&gt;cambios de negocio&lt;/strong&gt;. De haber habido cambios en el negocio, nunca estará de más que queden explícitos. Esto lo hacemos a través de dicho fichero. Esto permitirá que el software escale mucho más, sobretodo con la &lt;strong&gt;incorporación de nuevas personas al equipo&lt;/strong&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Si recién te incorporas a un proyecto, te darás cuenta que hacer TDD puede ser casi imposible. Con la ayuda semántica de los ficheros .feature a través de BDD este proceso se hace mucho más armonioso.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Por otra parte, si el título de alguno de los tests no es exacto a la definición, también fallará. Vamos a poner esto a prueba.&lt;/p&gt;

&lt;p&gt;Vamos a crear el siguiente steps test &lt;strong&gt;incompleto&lt;/strong&gt; y vamos a cargar la &lt;code&gt;.feature&lt;/code&gt; a través de la función &lt;code&gt;loadFeature()&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// file 'lib/data-structures/features/steps/singly-linked-list.steps.js'&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;loadFeature&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;defineFeature&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;jest-cucumber&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;SinglyLinkedList&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./SinglyLinkedList&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;feature&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;loadFeature&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./SinglyLinkedList.feature&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;loadRelativePath&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;errors&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nf"&gt;defineFeature&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;feature&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;test&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Instancing a list&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;given&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;when&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;and&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

        &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;list&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="nf"&gt;given&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;no instance&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;list&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;toBeUndefined&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;

        &lt;span class="nf"&gt;when&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;instancing a new Singly Linked List&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;list&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;SinglyLinkedList&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;

        &lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;initial head must be null&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;head&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
        &lt;span class="nf"&gt;and&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;initial tail must be null&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tail&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
        &lt;span class="nf"&gt;and&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;length must be 0&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Pushing a value on a empty list&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;given&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;when&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;and&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

        &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;list&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="nf"&gt;given&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/^an Empty Singly Linked List with &lt;/span&gt;&lt;span class="se"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;.*&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="sr"&gt; nodes$/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arg0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;list&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;SinglyLinkedList&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

            &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parseInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arg0&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;

        &lt;span class="nf"&gt;when&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/^pushing &lt;/span&gt;&lt;span class="se"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;.*&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="sr"&gt; as node value$/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arg0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arg0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;

        &lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/^head value becomes &lt;/span&gt;&lt;span class="se"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;.*&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="sr"&gt;$/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arg0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;head&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arg0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
        &lt;span class="nf"&gt;and&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/^tail value becomes &lt;/span&gt;&lt;span class="se"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;.*&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="sr"&gt;$/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arg0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tail&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arg0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
        &lt;span class="nf"&gt;and&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/^the list length becomes &lt;/span&gt;&lt;span class="se"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;.*&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="sr"&gt;$/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arg0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parseInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arg0&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ahora corremos Jest para que compruebe los test y obtendríamos el siguiente resultado:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ npx jest
 PASS  19. Singled Linked List/SinglyLinkedList.steps.js  Singly Linked List
    √ Instancing a list (5ms)
    √ Pushing a value on a empty list (1ms)
    √ Pushing values on a list with a single node (1ms)

 FAIL  19. Singled Linked List/SinglyLinkedList-demo.steps.js
  Singly Linked List
    × encountered a declaration exception (9ms)

  ● Singly Linked List › encountered a declaration exception

Feature file has a scenario titled "Pushing values on a list with a single node", but no match found in step definitions. Try adding the following code:

test('Pushing values on a list with a single node', ({ given, when, then, and, but }) =&amp;gt; {
  given('a Singly Linked List with a single node as \'First Node\' as value', () =&amp;gt; {

   });

    when('pushing the following values', (table) =&amp;gt; {

    });

    then(/^list length gets incremented to (.*)$/, (arg0) =&amp;gt; {

    });

    and('tail value becomes \'Third Node\'', () =&amp;gt; {

    });

    but('head value still equals to \'First Node\'', () =&amp;gt; {

    });
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Como has podido observar, falta el &lt;code&gt;Scenario: Pushing values on a list with a single node&lt;/code&gt; y Jest nos está regalando un precioso copy-paste con el que podremos salir del apuro y ahorrar tiempo. Es una plantilla que se puede mejorar si así lo deseamos; vamos a desarrollar la implementación y hacer que los &lt;code&gt;Third Node&lt;/code&gt; y &lt;code&gt;First Node&lt;/code&gt; se pasen como argumentos para que el test sea más explícito. El fichero final quedará así:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// file 'lib/data-structures/features/steps/singly-linked-list.steps.js'&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;
    &lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Pushing values on a list with a single node&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;given&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;when&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;and&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;but&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

        &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;list&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="nf"&gt;given&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/^a Singly Linked List with a single node as '&lt;/span&gt;&lt;span class="se"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;.*&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="sr"&gt;' as value$/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arg0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;list&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;SinglyLinkedList&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
            &lt;span class="nx"&gt;list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arg0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

            &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;

        &lt;span class="nf"&gt;when&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pushing the following values&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;table&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;table&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;row&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nx"&gt;list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;row&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;NodeValue&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="p"&gt;});&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;

        &lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/^list length gets incremented to &lt;/span&gt;&lt;span class="se"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;.*&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="sr"&gt;$/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arg0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parseInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arg0&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
        &lt;span class="c1"&gt;// Utilizo Regex para determinar qué valor será pasado a través de arg0&lt;/span&gt;
        &lt;span class="nf"&gt;and&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/^tail value becomes '&lt;/span&gt;&lt;span class="se"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;.*&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="sr"&gt;'$/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arg0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tail&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arg0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
        &lt;span class="c1"&gt;// Utilizo Regex para determinar qué valor será pasado a través de arg0&lt;/span&gt;
        &lt;span class="nf"&gt;but&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/^head value still equals to '&lt;/span&gt;&lt;span class="se"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;.*&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="sr"&gt;'$/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arg0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;head&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arg0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Y ahora sí, los tests serán 💚.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bonus: Extensiones de VSCode
&lt;/h2&gt;

&lt;p&gt;Voy a mencionar dos extensiones que pueden llevar esto a otro nivel de productividad&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://marketplace.visualstudio.com/items?itemName=Orta.vscode-jest" rel="noopener noreferrer"&gt;Jest&lt;/a&gt;&lt;br&gt;
VSCode estará corriendo los tests de fondo y permitirá ver en tiempo real el resultado de ellos, así como debuggear de manera individual.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F48m795hy3osk409lkuaw.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F48m795hy3osk409lkuaw.gif" alt="Jest demo"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://marketplace.visualstudio.com/items?itemName=alexkrechik.cucumberautocomplete" rel="noopener noreferrer"&gt;Cucumber (Gherkin) Full Support&lt;/a&gt;&lt;br&gt;
Syntax highligther, gherkin-to-test copy paste converter, autocompletion ... Una maravilla.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fp7tpl2wj6ygellv0956s.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fp7tpl2wj6ygellv0956s.gif" alt="Cucumber demo"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;¿Qué te ha parecido el tema tratado? ¿Te puedo ayudar en algo 🐱‍👓? Muchas gracias por dedicar tu tiempo a leer este artículo y nos vemos en el siguiente.&lt;/p&gt;

</description>
      <category>bdd</category>
      <category>node</category>
      <category>gherkin</category>
      <category>jest</category>
    </item>
    <item>
      <title>No olvides exportar los providers en NestJS</title>
      <dc:creator>Sergio</dc:creator>
      <pubDate>Mon, 04 Nov 2019 19:40:57 +0000</pubDate>
      <link>https://dev.to/imsergiobernal/no-olvides-exportar-los-providers-en-nestjs-4980</link>
      <guid>https://dev.to/imsergiobernal/no-olvides-exportar-los-providers-en-nestjs-4980</guid>
      <description>&lt;p&gt;Si ya conoces NestJS, sabrás que tiene mucha similitud con el framework de front-end Angular. Y no es pura casualidad, dado que NestJS basa gran parte de su arquitectura en librerías del propio Angular.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--DQcSbyQ0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://miro.medium.com/max/2124/1%2AbYHZw5xC3g4o3-2S9rMC9A.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--DQcSbyQ0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://miro.medium.com/max/2124/1%2AbYHZw5xC3g4o3-2S9rMC9A.png" alt="" width="880" height="510"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Si estás comenzando con NestJS, &lt;strong&gt;es muy importante que centres energías en aprender cómo funciona el mecanismo de contenedores de Inversión de Control&lt;/strong&gt;. A su vez, has de saber que se parece bastante al mecanismo de Angular &lt;strong&gt;pero no son exactamente iguales&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--YVkAyzZ8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.tutorialsteacher.com/Content/images/ioc/principles-and-patterns.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--YVkAyzZ8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.tutorialsteacher.com/Content/images/ioc/principles-and-patterns.png" alt="" width="602" height="241"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Por ejemplo, en Angular encontramos un artefacto llamado Component (decorador @component) mientras que en Nest tenemos un artefacto llamado Controller (decorador @controller) que vendría a ser un parecido. Esto se debe a que &lt;strong&gt;Nest no tiene que lidiar con temas de view rendering&lt;/strong&gt; y se centra directamente en el concepto de controlador.&lt;/p&gt;

&lt;p&gt;Vamos a hacer un repaso a la interfaz que tienen los decoradores @NgModule y @Module en cada framework —Angular y Nest respectivamente.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Angular front-end AdminModule&lt;/span&gt;
&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;NgModule&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;declarations&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;MyComponent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;MyDirective&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;MyPipe&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;entryComponents&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
  &lt;span class="na"&gt;providers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;MyService&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="c1"&gt;// imported and auto-public for everyone&lt;/span&gt;
  &lt;span class="na"&gt;imports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;AdminDashboardModule&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;MyComponent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;MyDirective&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;MyPipe&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;AdminModule&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;

&lt;span class="c1"&gt;// Nest back-end AdminModule&lt;/span&gt;
&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Module&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;providers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;MyService&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;MyRepository&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;MyFactory&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;MyHelper&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;controllers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;AdminController&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;imports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;CoreModule&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;AdminService&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;MyService&lt;/span&gt;&lt;span class="cm"&gt;/*re-export needed to be public for the enquirer*/&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;AdminModule&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Comparando interfaces de los módulos en Angular y Nest&lt;/p&gt;

&lt;p&gt;Vamos a hablar en concreto de la propiedad &lt;em&gt;exports&lt;/em&gt; en ambos frameworks.&lt;/p&gt;

&lt;h1&gt;
  
  
  Propiedad exports
&lt;/h1&gt;

&lt;p&gt;En Nest, la propiedad &lt;em&gt;export&lt;/em&gt; en un @Module define qué &lt;em&gt;Providers&lt;/em&gt; serán expuestos hacia el módulo que lo está importando, también llamado &lt;em&gt;enquirer&lt;/em&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;  &lt;span class="p"&gt;...&lt;/span&gt;
  &lt;span class="nx"&gt;providers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;MyService&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;MyRepository&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;MyFactory&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;MyHelper&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;MyService&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;MyRepository&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="c1"&gt;// Es necesario exportar para hacerlo público&lt;/span&gt;
  &lt;span class="p"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Recordemos. Un &lt;em&gt;Provider&lt;/em&gt; es aquel elemento que puede ser inyectado como dependencia. Ejemplos de &lt;em&gt;Providers&lt;/em&gt; son: servicios, repositorios, factories, helpers, etc.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Mientras que en Angular, la propiedad &lt;em&gt;export&lt;/em&gt; en un @NgModule permite listar qué declaraciones—componentes, directivas y pipes— serán expuestas. Todo &lt;em&gt;Provider&lt;/em&gt; en la propiedad providers será público y accesible en toda la aplicación bootstrapeada.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;  &lt;span class="p"&gt;...&lt;/span&gt;
  &lt;span class="nx"&gt;providers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;MyService&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="c1"&gt;// Serán públicos automáticamente&lt;/span&gt;
  &lt;span class="p"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Exceptuando aquel módulo que sea Lazy Loaded dado que tendrá su propio lazy loaded injector.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Lo importante de esto es que sepas que en Nest has de especificar qué &lt;em&gt;Providers&lt;/em&gt; quieres que sean públicos, ya que &lt;strong&gt;por defecto no se exportará ninguno&lt;/strong&gt;. Esto es una gran diferencia con Angular por que en dicho framework, los &lt;em&gt;Providers&lt;/em&gt; &lt;strong&gt;son registrados en el módulo root/root injector de toda la aplicación&lt;/strong&gt;—accesible por lo tanto por todos los módulos—.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;El objetivo en Nest es encapsular y aislar 📦 por completo todos los Providers del Module. Pero, si quieres que alguno sea público para quien importe dicho módulo, entonces deberás especificarlo en la propiedad &lt;em&gt;exports&lt;/em&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;cats&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kr"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ts&lt;/span&gt; &lt;span class="err"&gt;🐈&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Module&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@nestjs/common&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;CatsController&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./cats.controller&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;CatsService&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./cats.service&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Module&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;controllers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;CatsController&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;providers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;CatsService&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;CatsService&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="c1"&gt;// hago CatsService público!&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;CatsModule&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Espero que este recordatorio y explicación te sean de utilidad en tu proyecto de Nest 🧐.&lt;/p&gt;

</description>
      <category>nestjs</category>
      <category>typescript</category>
      <category>di</category>
    </item>
    <item>
      <title>¿Para qué sirven los métodos .call() y .apply() en JavaScript?</title>
      <dc:creator>Sergio</dc:creator>
      <pubDate>Thu, 31 Oct 2019 23:35:09 +0000</pubDate>
      <link>https://dev.to/imsergiobernal/para-que-sirven-los-metodos-call-y-apply-en-javascript-4bj2</link>
      <guid>https://dev.to/imsergiobernal/para-que-sirven-los-metodos-call-y-apply-en-javascript-4bj2</guid>
      <description>&lt;p&gt;He de admitir que el desconocimiento de estos métodos, junto con la sintáxis Class fueron los mayores desencadenantes de querer profundizar más en los fundamentos del lenguaje.&lt;/p&gt;

&lt;p&gt;Ahora que te los he mencionado, los comenzarás a ver en todas partes. En realidad ya estaban ahí pero, ¿sabías que hacen?. Pues son muy populares, y mucho más en proyectos ES5 y previos.&lt;/p&gt;

&lt;p&gt;Estos métodos forman parte de la base de la programación orientada a objetos de JavaScript, y son cruciales para entender el lenguaje y es una pena que las sintáxis como Class y la keyword new los estén dejando en deshuso. Y digo que es una pena porque son fundamentales y muy importantes en el sistema de herencia prototipal, mientras que los otros son sugar syntax que lo único que hacen es oscurecer el lenguaje.&lt;/p&gt;

&lt;p&gt;Antes de comenzar, estos dos métodos están disponibles en el prototype del objeto global Function:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Function.prototype.call&lt;br&gt;
  Function.prototype.apply&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;En este post mostraré ejemplos de uso para que lo entiendas y pongas a prueba.&lt;/p&gt;

&lt;h1&gt;
  
  
  Métodos call() y apply()
&lt;/h1&gt;

&lt;p&gt;Antes de nada y te voy a ahorrar dolores de cabeza, son exactamente lo mismo. &lt;strong&gt;La única diferencia reside en el segundo argumento&lt;/strong&gt;, donde call() será un listado de argumentos infinito y apply() será un array.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;arg1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;arg2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;arg3&lt;/span&gt;&lt;span class="p"&gt;...)&lt;/span&gt;
&lt;span class="nx"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;apply&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;arg1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;arg2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;arg3&lt;/span&gt;&lt;span class="p"&gt;...])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Un tip que me ayuda a recodar cuál es cuál es la letra C de call, la cual &lt;strong&gt;me recuerda a comas&lt;/strong&gt;; la a de apply, &lt;strong&gt;me recuerda a array&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Vamos a un ejemplo con call(). Vamos a crear una pseudoherencia clásica. Se trata de una pseudoherencia clásica porque estamos definiendo la estructura del objeto final, "instancia" de Person.&lt;/p&gt;


&lt;div class="runkit-element"&gt;
  &lt;code&gt;
    
  &lt;/code&gt;
  &lt;code&gt;
    
function Human(gender) {
  this.gender = gender;
  this.isAlive = true;
}

function Person(gender, age) {
  // this = {}
  Human.call(this, gender);
  // this = { gender: 'male', isAlive: true }
  this.age = age;
  // this = { gender: 'male', isAlive: true, age: 18 }
  return this;
}

const alberto = Person.call({}, 'male', 18);

console.log(alberto);
process.exit(0)

  &lt;/code&gt;
&lt;/div&gt;



&lt;p&gt;De manera sencilla, llamamos a la función Person a la cual le pasamos primero un objeto vacío como &lt;em&gt;this&lt;/em&gt;, y a continuación &lt;strong&gt;los argumentos necesarios por la función&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;alberto&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;call&lt;/span&gt;&lt;span class="p"&gt;({},&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;male&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;¿Sabes que habría pasado si en vez de poner {} hubiésemos puesto &lt;em&gt;this&lt;/em&gt;? Habría pasado lo siguiente:&lt;/p&gt;


&lt;div class="runkit-element"&gt;
  &lt;code&gt;
    
  &lt;/code&gt;
  &lt;code&gt;
    
function Human(gender) {
  this.gender = gender;
  this.isAlive = true;
}

function Person(gender, age) {
  // this = global: { ... }
  Human.call(this, gender);
  // this = global: { ..., gender: 'male', isAlive: true }
  this.age = age;
  // this = global: { ..., gender: 'male', isAlive: true, age: 18 }
  return this;
}

const alberto = Person.call(this, 'male', 18);

console.log(alberto);
process.exit(0)

  &lt;/code&gt;
&lt;/div&gt;



&lt;p&gt;Como puedes ver alberto ahora tiene un montón de propiedades nuevas, y esto se debe a que &lt;em&gt;this&lt;/em&gt; en el momento de ser ejecutado con .call hace referencia al objeto window del navegador (o global si estamos en Node como es el caso), y por lo tanto estaríamos pasando como contexto a Person un objeto no deseado.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/t8m0LMOd4nmKs/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/t8m0LMOd4nmKs/giphy.gif" alt="" width="320" height="240"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;¿Y si en vez de usar &lt;em&gt;this&lt;/em&gt; y call(), llamo a la función directamente?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;Human&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;gender&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;gender&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;gender&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isAlive&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;person&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;gender&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;age&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Está recibiendo un this implícito&lt;/span&gt;
  &lt;span class="c1"&gt;// this = global: { ... }&lt;/span&gt;
  &lt;span class="nx"&gt;Human&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;gender&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="c1"&gt;// this = global: { ..., gender: 'male', isAlive: true }&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;age&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;age&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="c1"&gt;// this = global: { ..., gender: 'male', isAlive: true, age: 18 }&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;alberto&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;person&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;male&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Invocando a la función sin call()&lt;/span&gt;
&lt;span class="cm"&gt;/*
Es lo mismo! La transformación la ejecuta el parser de JS (internals)
  person('male', 18) 'implícito' === 'explícito' person.call(this, 'male', 18)
*/&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;alberto&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Sucedería exactamente lo mismo. Podrás observar varias cosas:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;No he usado el sandbox porque por lo visto tiene algún mecanismo de seguridad para prevenir esta práctica, dado que supone un riesgo de seguridad. Puedes probarlo en tu navegador o en Node.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;He renombrado Person a person, y eso se debe a lo mismo. Se creó una regla para que no se pueda llamar a las funciones directamente si comienzan en letra capital, dado que puede darse el caso de que un desarrollador llame a la función directamente y el &lt;em&gt;this&lt;/em&gt; quede referenciado al global/window.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Hay que andarse con ojo a la hora de usar &lt;em&gt;this&lt;/em&gt; .&lt;/strong&gt; Y este es uno de los principales motivos por los que se empiezan a crear nuevos mecanismos como new y Class, para evitar equivocaciones y proveer de una opción más sencilla a los desarrolladores que vienen de lenguajes OOP de clases.&lt;/p&gt;

&lt;p&gt;Ahora toca el turno a explicar qué sucede dentro de Person. Retomamos el primer ejemplo. Como puedes ver volvemos a hacer uso de call()^2, pero esta vez en vez de {} usamos la palabra &lt;em&gt;this&lt;/em&gt;^3. El &lt;em&gt;this&lt;/em&gt; siempre depende del contexto desde el cual se ha ejecutado, y en este caso proviene del call(&lt;em&gt;this&lt;/em&gt;)^1 de &lt;strong&gt;alberto&lt;/strong&gt;, que es {}.&lt;/p&gt;

&lt;p&gt;(el símbolo &amp;gt; lo uso para que podáis encontrar lo que digo)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;gender&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;age&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// this = {}&lt;/span&gt;
  &lt;span class="nx"&gt;Human&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;gender&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;alberto&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{},&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;male&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Por lo tanto, continuando la llamada, Human continúa recibiendo el objeto vacío a través del contexto^3 que estamos enviando explícitamente a través de call(this)^2&lt;/p&gt;

&lt;p&gt;Aprovecho para mencionar, que es usual decir &lt;em&gt;contexto&lt;/em&gt; y referirnos a &lt;em&gt;this&lt;/em&gt;, dado que todo &lt;em&gt;this&lt;/em&gt; dependerá del contexto desde el que se le llame.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Todo &lt;strong&gt;this&lt;/strong&gt; dependerá del contexto desde el que se le llame. Es por lo tanto una referencia contextual.&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;Human&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;gender&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="c1"&gt;// this = {} ( proviene de Human.call(this, gender) )&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;gender&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;gender&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isAlive&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;gender&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;age&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// this = {}&lt;/span&gt;
  &lt;span class="nx"&gt;Human&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;gender&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;alberto&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{},&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;male&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ahora viene lo bonito 💕❤🌹🎉en JavaScript existe una técnica llamada Aumentación. Es más fácil leerla y encontrarla como "Augmentation", su variante inglesa.&lt;/p&gt;

&lt;p&gt;Lo que está haciendo Human es aumentar el contexto desde el que se le llama. En otras palabras, aumentar el &lt;em&gt;this&lt;/em&gt;, añadirle más propiedades (también podrían ser métodos).&lt;/p&gt;

&lt;p&gt;Y ahora lo no tan bonito 👺, si queremos aprovechar el potencial de JavaScript, hay que saber cuándo aumentar el contexto. Lo digo porque al final, acaba convirtiéndose en una composición que no aprovecha los prototypes. Digamos que el call() sería como un super(). Pero esto es para otro tema.&lt;/p&gt;

&lt;p&gt;Ahora, el contexto tendrá dos propiedades nuevas, que son &lt;strong&gt;gender&lt;/strong&gt; y &lt;strong&gt;isAlive&lt;/strong&gt;. El this que hay en person ha aumentado. Volvemos a aumentar el contexto añadiendo la propiedad age^1. Y finalmente retornamos^2 el contexto aumentado.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;gender&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;age&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="p"&gt;...&lt;/span&gt;
  &lt;span class="c1"&gt;// this = { gender: 'male', isAlive: true }&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;age&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;age&lt;/span&gt;&lt;span class="o"&gt;^&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="c1"&gt;// this = { gender: 'male', isAlive: true, age: 18 }&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;^&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;¿Has entendido las diferencias entre estos dos métodos? ¿Me animo a crear un post con más ejemplos?&lt;/p&gt;

&lt;p&gt;Espero tus comentarios y que te haya sido de utilidad. &lt;/p&gt;

</description>
      <category>javascript</category>
      <category>oop</category>
    </item>
    <item>
      <title>Mediator design pattern: En dos aplicaciones</title>
      <dc:creator>Sergio</dc:creator>
      <pubDate>Tue, 22 Oct 2019 10:54:34 +0000</pubDate>
      <link>https://dev.to/imsergiobernal/mediator-design-pattern-en-dos-aplicaciones-3j9k</link>
      <guid>https://dev.to/imsergiobernal/mediator-design-pattern-en-dos-aplicaciones-3j9k</guid>
      <description>&lt;p&gt;El patrón de diseño Mediador (Mediator design pattern) es un patrón de comportamiento que permite crear interacciones entre objetos reduciendo un excesivo acoplamiento.&lt;/p&gt;

&lt;p&gt;Según definición en Wikipedia&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"El patrón mediador define un objeto que encapsula cómo un conjunto de objetos interactúan. Este patrón de diseño está considerado como un patrón de comportamiento debido al hecho de que puede alterar el comportamiento del programa en ejecución."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Dsdvqlmq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://www.dofactory.com/images/diagrams/net/mediator.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Dsdvqlmq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://www.dofactory.com/images/diagrams/net/mediator.gif" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
Esquema básico UML de clases del patrón Mediator



&lt;p&gt;Cuando indagué más sobre este patrón, me encontré con una potente herramienta con la que contar a la hora de solucionar problemas como los que describiré en este artículo.&lt;/p&gt;

&lt;h1&gt;
  
  
  Ejemplo básico
&lt;/h1&gt;

&lt;p&gt;Un ejemplo sería una sala de chat, donde existen múltiples usuarios que pueden comunicarse públicamente o de manera privada (mensaje privado). La clave está en delegar al Mediador la responsabilidad de los sucesos, desacoplando la interacción entre el resto de instancias.&lt;/p&gt;

&lt;p&gt;Un user(User) recibirá la interfaz de Chatroom y podrá ordenarle:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Quiero enviar un mensaje global&lt;/li&gt;
&lt;li&gt;Quiero enviar un mensaje a un usuario en concreto&lt;/li&gt;
&lt;li&gt;Quiero mutear los mensajes que provean de estos usuarios&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Y un chatroom(Chatroom) sabrá procesar estas peticiones. Si esta petición involucra a otras entidades relacionadas con el Mediador, una acción colateral se verá ejecutada de manera invisible al user(User)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// 'chatroom.js'&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;Chatroom&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;mutes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;Chatroom&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prototype&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;register&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;nickname&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;chatroom&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;Chatroom&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prototype&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;unregister&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// this.users ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;Chatroom&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prototype&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;deliver&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;hasMuted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;// Comprueba si existe un muteo y envía un mensaje privado&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;receive&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;// Comprueba si existe un muteo y envía un mensaje a todos los usuarios&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;hasMuted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;receive&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;Chatroom&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prototype&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;mute&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;receiver&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;sender&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Prohibe a 'sender' enviar mensajes a 'receiver'&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;Chatroom&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prototype&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;hasMuted&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;receiver&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;sender&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Comprueba si 'receiver' tiene muteado a 'sender'&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;





&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// 'user.js'&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;nickname&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;nickname&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;nickname&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;chatroom&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prototype&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;send&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;chatroom&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;deliver&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;nickname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prototype&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;receive&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`(&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;nickname&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;) [&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;]: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prototype&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;muteFrom&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// this.chatroom.mute ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prototype&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;disconnect&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// this.chatroom.unregister ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;





&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// 'main.js'&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mainChatroom&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Chatroom&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;offTopicChatroom&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Chatroom&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sergio&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Sergio999&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;mainChatroom&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sergio&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;jose&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;x0s3&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;mainChatroom&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;jose&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;manel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;manel&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;mainChatroom&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;manel&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;sergio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hola a todos&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// (x0s3) [Sergio999]: Hola a todos&lt;/span&gt;
&lt;span class="c1"&gt;// (manel) [Sergio999]: Hola a todos&lt;/span&gt;

&lt;span class="nx"&gt;sergio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hola Manel!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;manel&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// (manel) [Sergio999]: Hola Manel!&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Me gusta imaginar el patrón &lt;strong&gt;como un mensajero&lt;/strong&gt;, y qué mejor ejemplo. El usuario sabe qué acciones puede realizar, pero el mensajero (Mediador) es el que sabe cómo realizarlas. Es como entregarle un bulto con una información y decirle: "Ya sabes lo que toca hacer", o bien preguntarle cualquier cosa que sea capaz de responderte.&lt;/p&gt;

&lt;p&gt;En el anterior ejemplo, se intercomunican instancias del mismo tipo (User). Sin embargo podrían ser de cualquier otro tipo, como por ejemplo una torre de control donde pueden comunicarse tanto Aviones, Pilotos, Operarios de tierra, etc...&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--LoXHlmY---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://www.aerobcn.com/wp-content/uploads/2014/07/atc-003.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--LoXHlmY---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://www.aerobcn.com/wp-content/uploads/2014/07/atc-003.jpg" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
Aquí todavía no ha llegado Tsunami Democratic



&lt;p&gt;No voy a detallar una implementación de la torre de control, dado que sería muy parecido. Voy a pasar a otro caso de uso muy destacable.&lt;/p&gt;

&lt;h1&gt;
  
  
  Uso como Workflow de eventos
&lt;/h1&gt;

&lt;p&gt;Otro uso que se le puede dar al patrón Mediator es como desarrollo de un workflow, dado de que se parte del concepto de Mediator como una figura que toma el control de acciones para inter-desacoplar los objetos asociados a él.&lt;/p&gt;

&lt;p&gt;En el siguiente ejemplo tomamos VideoProcessorWorkflow como el mediador de los eventos. Sus &lt;em&gt;colleages&lt;/em&gt; (elemento en el UML de Mediator Design Pattern) serán instancias de módulos con lógica totalmente encapsulada y aislada a través de cada una de sus interfaces:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// 'videoprocessor.workflow.js'&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;VideoProcessorWorkflow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;video&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;videoConverter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;videoFXApplier&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;videoUploader&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="nx"&gt;opts&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;on&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;once&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;EventEmitter&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="c1"&gt;// Exposing public members&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;on&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;on&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;once&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;once&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// Defining the workflow. Callback style for the glory&lt;/span&gt;
    &lt;span class="nx"&gt;videoConverter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;video&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;opts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;converter&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;once&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;video/converted&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;video&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;videoFXApplier&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;video&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;opts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fx&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;once&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;video/fxed&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;video&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;videoUploader&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;video&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;opts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;upload&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;once&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;video/uploaded&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;link&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="c1"&gt;// Workflow emits a result event&lt;/span&gt;
                &lt;span class="nx"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;videoProcessorWorkflow/completed&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;link&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="p"&gt;});&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;VideoProcessorWorkflow será una función constructora que expondrá los métodos .on() y .once() a los que poder añadir handlers.&lt;/p&gt;

&lt;p&gt;Por otra parte tenemos features/componentes/modulos que contienen lógica totalmente aislada, pero que podemos utilizar a través de un proceso como el Workflow que acabamos de desarrollar.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// 'modules/index.js'&lt;/span&gt;

&lt;span class="cm"&gt;/**
 * Módulos totalmente desacoplados que emiten eventos
 */&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;VideoConverterModule&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;video&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;opts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Implementation&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;VideoFXApplierModule&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;video&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;opts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Implementation&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;VideoUploaderModule&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;video&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;opts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Implementation&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Y finalmente lo que vendría a ser el main(), contenedor principal o controlador que orquesta el workflow y sus dependencias.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// 'main.js'&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;video&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;file.avi&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;modules&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;videoConverter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;VideoConverterModule&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="na"&gt;videoFXApplier&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;VideoFXApplierModule&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="na"&gt;videoUploader&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;VideoUploaderModule&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;opts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;converter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;outputFormat&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;mp4&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;fx&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;bright&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;upload&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;to&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;youtube&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;...&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;


&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;videoProcessorWorkflow&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;VideoProcessorWorkflow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;video&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;modules&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;opts&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;videoProcessorWorkflow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;videoProcessorWorkflow/completed&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;link&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Video uploaded to: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;link&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Con este patrón se podrían seguir creando más Workflows para la digestión de eventos, como por ejemplo sería un VideoProcessorErrorWorkflow que encadene una serie de sucesos a raíz de un error en alguno de los módulos.&lt;/p&gt;

&lt;p&gt;Hasta aquí mi aportación del día, espero que te haya sido de utilidad!&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>architecture</category>
      <category>designpatterns</category>
      <category>node</category>
    </item>
    <item>
      <title>What's your thought about pseudoclassical OOP in JS?</title>
      <dc:creator>Sergio</dc:creator>
      <pubDate>Sat, 19 Oct 2019 12:19:59 +0000</pubDate>
      <link>https://dev.to/imsergiobernal/what-s-your-thought-about-pseudoclassical-oop-in-js-280</link>
      <guid>https://dev.to/imsergiobernal/what-s-your-thought-about-pseudoclassical-oop-in-js-280</guid>
      <description>&lt;p&gt;Hi, I'm a JavaScript beginner and I found pseudoclassical inheritance a bad tool for Javascript, because why going for something pseudo when you can go directly for PHP (for instance)?.&lt;/p&gt;

&lt;p&gt;Have you tried to work with pseudoclassical OOP style? Did you worked with pure prototypal inheritance focus? What's your learning about?&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>javascript</category>
    </item>
  </channel>
</rss>
