<?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: Ismael Ramon</title>
    <description>The latest articles on DEV Community by Ismael Ramon (@desko27).</description>
    <link>https://dev.to/desko27</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%2F117269%2F985ef3f2-7497-40b9-84f2-7d8cb9837d9a.jpeg</url>
      <title>DEV Community: Ismael Ramon</title>
      <link>https://dev.to/desko27</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/desko27"/>
    <language>en</language>
    <item>
      <title>AB Testing en el Frontend con React</title>
      <dc:creator>Ismael Ramon</dc:creator>
      <pubDate>Tue, 17 Nov 2020 08:22:31 +0000</pubDate>
      <link>https://dev.to/adevintaspain/ab-testing-en-el-frontend-con-react-43nf</link>
      <guid>https://dev.to/adevintaspain/ab-testing-en-el-frontend-con-react-43nf</guid>
      <description>&lt;p&gt;¡Hola Frontender@! ✨ Si has oído hablar antes del &lt;em&gt;AB Testing&lt;/em&gt; o incluso si lo has puesto ya en práctica, sabrás que se trata de una &lt;strong&gt;metodología para determinar si tu flamante nueva idea de producto gusta&lt;/strong&gt; o no a tus usuarios, averiguar cómo impacta en las métricas de tu negocio y, en definitiva, si te conviene conservarla o no.&lt;/p&gt;

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

&lt;p&gt;Trabajo como 👨🏻‍💻 Desarrollador Frontend en &lt;strong&gt;Adevinta Spain&lt;/strong&gt;, donde cualquier cambio que llega a producción acaba rápidamente en manos de millones de usuarios. Bajo estas condiciones, subir un desarrollo sin medir su impacto podría ser un desastre, así que esta técnica resulta imprescindible.&lt;/p&gt;

&lt;p&gt;Para hacer &lt;em&gt;AB Testing&lt;/em&gt;, necesitas una plataforma que cubra la gestión de los datos. Para eso existen &lt;a href="https://www.ventureharbour.com/best-a-b-testing-tools/" rel="noopener noreferrer"&gt;varias opciones&lt;/a&gt;, nosotros usamos &lt;strong&gt;Optimizely&lt;/strong&gt;. Todas ofrecen cosas similares y no vamos a entrar en eso, pues el foco del artículo es la parte en React.&lt;/p&gt;

&lt;p&gt;Dicho esto, hablemos de ⚛️ &lt;strong&gt;React&lt;/strong&gt;. Me gustaría compartir contigo la experiencia que hemos vivido desde la perspectiva Frontend, dificultades que hemos afrontado y, como consecuencia, cómo hemos iterado nuestra primera solución hasta llegar a la que utilizamos hoy día.&lt;/p&gt;

&lt;h2&gt;
  
  
  La primera solución
&lt;/h2&gt;

&lt;p&gt;Vamos a poner un ejemplo sencillo. Imagina que quieres medir el impacto de &lt;strong&gt;cambiar el texto de un botón&lt;/strong&gt; porque tienes la hipótesis de que, con ese otro texto, el botón puede ser más atractivo para el usuario.&lt;/p&gt;

&lt;p&gt;En Optimizely configurarías algo como lo siguiente y &lt;strong&gt;obtendrías unos IDs&lt;/strong&gt;.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Experimento&lt;/th&gt;
&lt;th&gt;ID&lt;/th&gt;
&lt;th&gt;Tráfico&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Mejorar botón&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;123&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;100%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Variantes&lt;/th&gt;
&lt;th&gt;ID&lt;/th&gt;
&lt;th&gt;Tráfico&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Variante A&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;1116&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;50%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Variante B&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;1117&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;50%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Nuestro primer enfoque fue diseñar &lt;strong&gt;un componente&lt;/strong&gt; al que le pasabas el render de cada variante como un hijo, y te &lt;strong&gt;renderizaba automáticamente&lt;/strong&gt; el que correspondía a &lt;strong&gt;la variante asignada al usuario&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Experiment&lt;/span&gt; &lt;span class="na"&gt;experimentId&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;123&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;variationId&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;1116&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;defaultVariation&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Comprar&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;variationId&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;1117&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;¡Compra ya!&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Experiment&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;La variante original tiene una prop adicional llamada &lt;code&gt;defaultVariation&lt;/code&gt; que la identifica como la que se ha de mostrar por defecto.&lt;/p&gt;

&lt;p&gt;Por lo demás, el código es bastante declarativo y resulta en lo siguiente.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Render&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Si caigo en variante A&lt;/td&gt;
&lt;td&gt;Comprar&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Si caigo en variante B&lt;/td&gt;
&lt;td&gt;¡Compra ya!&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Esto está muy bien y funciona, pero conforme fuimos haciendo &lt;strong&gt;experimentos más ambiciosos&lt;/strong&gt; y variados, el uso invitó a una reflexión sobre &lt;strong&gt;algunas limitaciones&lt;/strong&gt; de esta aproximación que tienen que ver con &lt;strong&gt;la experiencia de desarrollo&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  ⚠️ Limitación #1 – Probar variantes en local
&lt;/h3&gt;

&lt;p&gt;La limitación más tonta es que, para probar las variantes en local, &lt;strong&gt;no quedaba más remedio que ir moviendo la prop&lt;/strong&gt; &lt;code&gt;defaultVariation&lt;/code&gt; de una variante a otra.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Experiment&lt;/span&gt; &lt;span class="na"&gt;experimentId&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;123&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;variationId&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;1116&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Comprar&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;variationId&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;1117&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;defaultVariation&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;¡Compra ya!&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Experiment&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Los problemas de esto:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Esa prop no fue diseñada para hacer eso.&lt;/li&gt;
&lt;li&gt;Puedes commitearla por error en una posición equivocada.&lt;/li&gt;
&lt;li&gt;Por motivos que explicaré luego, no estás emulando lo que realmente pasa en la activación real de una variación, con lo que estás comprobando tu desarrollo con un comportamiento distinto al que se dará en producción.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  ⚠️ Limitación #2 – Zonas distantes en mismo render
&lt;/h3&gt;

&lt;p&gt;La segunda limitación entra cuando quieres afectar a zonas distantes dentro del mismo render, porque la única manera razonable de hacerlo es metiendo el componente allí donde haga falta, &lt;strong&gt;con la estructura de IDs y variantes repetida&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"product-detail"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Experiment&lt;/span&gt; &lt;span class="na"&gt;experimentId&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;123&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;variationId&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;1116&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;defaultVariation&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Comprar&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;variationId&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;1117&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;¡Compra ya!&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Experiment&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  ...
  ...
  ...
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Experiment&lt;/span&gt; &lt;span class="na"&gt;experimentId&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;123&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;variationId&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;1116&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;defaultVariation&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Favorito&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;variationId&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;1117&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;¡A favoritos!&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Experiment&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Problema de esto: estoy duplicando información.&lt;/p&gt;

&lt;p&gt;El problema se agrava bastante cuando tengo variantes que participan en diferentes componentes y repositorios para el mismo experimento.&lt;/p&gt;

&lt;h3&gt;
  
  
  ⚠️ Limitación #3 – Desde componente padre a hijos
&lt;/h3&gt;

&lt;p&gt;La tercera limitación entra en juego cuando quieres afectar a los hijos desde el componente padre, porque lo que haces entonces es pasar props, y son &lt;strong&gt;props que su única motivación es la existencia del experimento&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Experiment&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  ...
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ParentVariation&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    ↳ &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;DescendantA&lt;/span&gt; &lt;span class="na"&gt;isExperiment&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt; 😱
      ↳ &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;DescendantB&lt;/span&gt; &lt;span class="na"&gt;isExperiment&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt; 😱
        ↳ &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;DescendantC&lt;/span&gt; &lt;span class="na"&gt;isExperiment&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt; 😱
          ↳ &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;DescendantD&lt;/span&gt; &lt;span class="na"&gt;isExperiment&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt; 😱
            ↳ &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;DescendantE&lt;/span&gt; &lt;span class="na"&gt;isExperiment&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt; 😱
              ↳ &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;DescendantF&lt;/span&gt; &lt;span class="na"&gt;isExperiment&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt; 😱
                ↳ ...
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Experiment&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Problemas de pasar props:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Puede ser costoso, sobretodo cuando hay muchos niveles en la jerarquía.&lt;/li&gt;
&lt;li&gt;Los componentes se llenan de props que no forman parte de su contrato.&lt;/li&gt;
&lt;li&gt;Luego, cuando decidas quedarte con una variante, se hace muy difícil quitar los restos del experimento, has de ir recogiendo todas esas migas.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  ⚠️ Limitación #4 – Fuera de la zona de render
&lt;/h3&gt;

&lt;p&gt;Finalmente, la última limitación aparece cuando te das cuenta de que &lt;strong&gt;quieres hacer cosas fuera del render&lt;/strong&gt; para cuando se carga determinada variante.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Actions&lt;/span&gt; &lt;span class="o"&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="c1"&gt;// ❌👇 Aquí no puedo saber en qué variante estoy&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;someData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getSomeData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="cm"&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;handleClick&lt;/span&gt; &lt;span class="o"&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="cm"&gt;/* ... */&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Experiment&lt;/span&gt; &lt;span class="na"&gt;experimentId&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;123&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;variationId&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;1116&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;defaultVariation&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Comprar&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;variationId&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;1117&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;¡Compra ya!&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Experiment&lt;/span&gt;&lt;span class="p"&gt;&amp;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;Yo no puedo llegar ahí con un componente. ¿Qué es lo que sí puedo hacer? Bueno, si tu componente es pequeño como este, es verdad que puedes subir el experimento al componente padre para que te lleguen props.&lt;/p&gt;

&lt;p&gt;Por otro lado, si tu componente es grande y complejo el refactor se te puede complicar.&lt;/p&gt;

&lt;h2&gt;
  
  
  Análisis de Experiencia de Desarrollo
&lt;/h2&gt;

&lt;h4&gt;
  
  
  Problemas
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;❌ La lentitud y fallos producto de probar las variantes en local.&lt;/li&gt;
&lt;li&gt;❌ La persecución de la información duplicada, esparcida por los lugares más inhóspitos.&lt;/li&gt;
&lt;li&gt;❌ El cambio de contrato no deseado en mis componentes.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Soluciones
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;✅ Definir una API concreta para probar las variantes en local.&lt;/li&gt;
&lt;li&gt;✅ Reducir la fuente de la verdad para cada experimento.&lt;/li&gt;
&lt;li&gt;✅ Proveer maneras de ampliar el alcance sin generar ruido, es decir, que esa fuente de la verdad llegue más lejos con las mínimas afectaciones posibles en mi infraestructura.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  La iteración
&lt;/h2&gt;

&lt;p&gt;Queremos que nuestras herramientas nos ayuden y sabemos que una misma solución no funciona para siempre, porque las cosas cambian. Por eso, tras el análisis anterior, empezó un proceso de mejora de las herramientas.&lt;/p&gt;

&lt;h3&gt;
  
  
  🆕 Props para probar variantes
&lt;/h3&gt;

&lt;p&gt;Se añaden nuevas props que pueden usarse en el componente del experimento: &lt;code&gt;forceVariation&lt;/code&gt; y &lt;code&gt;forceActivation&lt;/code&gt;. Ambas props aceptan los mismos valores: el &lt;strong&gt;ID de la variante&lt;/strong&gt; que quieres forzar o &lt;strong&gt;una letra del abecedario&lt;/strong&gt; que corresponda al orden en que están presentadas &lt;strong&gt;las variantes&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Por ejemplo, si le enchufo una “B” se va a estar refiriendo a la segunda variante, y así no tengo que poner el ID completo que suele ser bastante largo.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Experiment&lt;/span&gt; &lt;span class="na"&gt;experimentId&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;123&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;forceActivation&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"B"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;variationId&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;1116&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;defaultVariation&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Comprar&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;variationId&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;1117&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;¡Compra ya!&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Experiment&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;La diferencia entre &lt;code&gt;forceVariation&lt;/code&gt; y &lt;code&gt;forceActivation&lt;/code&gt; es que &lt;strong&gt;&lt;code&gt;forceVariation&lt;/code&gt;&lt;/strong&gt; va a obligar a la variante especificada a comportarse &lt;strong&gt;como si fuera la variante por defecto&lt;/strong&gt;, mostrándose en el primer render.&lt;/p&gt;

&lt;p&gt;En cambio, &lt;strong&gt;&lt;code&gt;forceActivation&lt;/code&gt;&lt;/strong&gt; mantendrá la variante por defecto en el primer render, y &lt;strong&gt;simulará una activación como la que hace Optimizely, haciendo un segundo render&lt;/strong&gt; con la variante especificada. Esto permite detectar problemas que antes no podíamos ver hasta configurar el experimento completo en Optimizely.&lt;/p&gt;

&lt;p&gt;En general, &lt;strong&gt;se reduce la dificultad de probar variantes en local&lt;/strong&gt;, y si se colaran en una revisión de código por error, que sería muy difícil, no pasaría nada porque están diseñadas a propósito para que en producción se ignoren, por si las moscas.&lt;/p&gt;

&lt;h3&gt;
  
  
  🆕 Contexto para experimentos
&lt;/h3&gt;

&lt;p&gt;Se implementa un contexto exclusivo para todos los experimentos, en el que viene un &lt;strong&gt;objeto con toda la información sobre el estado del experimento&lt;/strong&gt;, incluyendo unos booleanos muy chulos para saber en qué variante estamos.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Experiment&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; 🚀
  ...
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ParentVariation&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    ↳ &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;DescendantA&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      ↳ &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;DescendantB&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        ↳ &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;DescendantC&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
          ↳ &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;DescendantD&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
            ↳ &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;DescendantE&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
              ↳ &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;DescendantF&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt; ← useExperiment() 😍
                ↳ ...
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Experiment&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Este contexto se provee automáticamente a través del componente de React y &lt;strong&gt;se puede consumir mediante el nuevo hook &lt;code&gt;useExperiment&lt;/code&gt;&lt;/strong&gt; en cualquier punto descendiente de la jerarquía.&lt;/p&gt;

&lt;p&gt;De esta manera, se empieza a &lt;strong&gt;ampliar el alcance de un experimento&lt;/strong&gt; evitando ruido en mis componentes. Ya no necesitamos aquel interminable taladro de props, porque ahora la información relevante viaja sin intermediarios desde la fuente de la verdad hasta allí donde se invoque.&lt;/p&gt;

&lt;h3&gt;
  
  
  🆕 Hook como origen de experimento
&lt;/h3&gt;

&lt;p&gt;La zona prohibida fuera del render deja de ser prohibida, porque &lt;strong&gt;el hook gana la capacidad de actuar como origen y gestor del estado del experimento si le pasas su configuración&lt;/strong&gt;, algo que antes solo podía hacer el componente, y devuelve la misma información que se recibía al consumir el contexto, con los booleanos para saber en qué variante estamos.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Actions&lt;/span&gt; &lt;span class="o"&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="c1"&gt;// 1️⃣👇 Creamos el experimento con el hook...&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;isVariationB&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useExperiment&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;experimentId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;123&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;variations&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1116&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;isDefault&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="mi"&gt;1117&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;

  &lt;span class="c1"&gt;// 2️⃣👇 Y ya puedo saber aquí en qué variante estoy ✅&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;someData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getSomeData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="cm"&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;handleClick&lt;/span&gt; &lt;span class="o"&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="cm"&gt;/* ... */&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;isVariationB&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;¡Compra ya!&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;Comprar&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;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;Además, &lt;strong&gt;si queremos seguir propagando el contexto&lt;/strong&gt; hacia abajo para tener ocasión de consumirlo, por definición los hooks no pueden hacerlo, pero &lt;strong&gt;podemos envolver el render con el componente Experiment y obligarlo a actuar solamente de proveedor&lt;/strong&gt; pasándole solo la prop feed con lo que devuelve el hook de useExperiment. De esta manera actuará exclusivamente de proveedor de contexto, y podremos consumir en niveles inferiores la información del experimento.&lt;/p&gt;

&lt;p&gt;Gracias a esta última iteración, &lt;strong&gt;ningún experimento está limitado al área del render&lt;/strong&gt;, llevando las herramientas de &lt;em&gt;AB Testing&lt;/em&gt; a un grado de alcance bastante potente.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusiones
&lt;/h2&gt;

&lt;p&gt;A día de hoy estamos muy contentos con &lt;strong&gt;estas mejoras&lt;/strong&gt; y realmente &lt;strong&gt;nos ayudan a ser mucho más ágiles&lt;/strong&gt; haciendo &lt;em&gt;AB Tests&lt;/em&gt;. Pero las tratadas en este artículo no son las únicas, ¡más adelante hablaremos de otros retos afrontados!&lt;/p&gt;

&lt;p&gt;También, es importante destacar que todos estos cambios vinieron de forma progresiva para que la adopción fuera asequible y, más importante, &lt;strong&gt;totalmente retrocompatible con la solución anterior&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;¡Eso es todo! Estas herramientas son opensource y &lt;a href="https://github.com/SUI-Components/adevinta-spain-components/tree/master/components/abtesting/optimizelyXExperiment" rel="noopener noreferrer"&gt;están documentadas&lt;/a&gt; y testeadas. Te invito a que les eches un vistazo y quedamos siempre abiertos a cualquier aportación. 🙌🏻&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fisqb2jkqow5832mug3i4.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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fisqb2jkqow5832mug3i4.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>react</category>
      <category>abtesting</category>
      <category>javascript</category>
      <category>frontend</category>
    </item>
  </channel>
</rss>
