Módulo 8: Project Validate Mercados Recommendations

Paso 1: convierte la suposición en una hipótesis falsable

Descripción

Todo lo que sigue en este módulo depende de este primer paso, así que vale la pena empezar despacio, aunque ya lo hayas visto en el módulo 4. La suposición riesgosa de recommendations —"los usuarios van a comprar más si ven recomendaciones personalizadas"— llegó desde product-thinking-for-engineers-guide como una frase suelta, con un risk: 0.6 y un impact: 5 que la marcan como la más urgente del backlog, pero sin ninguna forma todavía de saber si es cierta. Antes de diseñar cualquier test, cualquier entrevista, cualquier fake door, esta lección la convierte en una hipótesis falsable: una afirmación con una condición de fracaso explícita, escrita antes de recoger ningún dato.

Conexión con el módulo. Esta lección reutiliza isFalsifiable(hypothesis) exactamente como quedó en el módulo 4, sin ningún cambio. No hay ningún modelo nuevo aquí — lo que hace este paso es fijar, por escrito y verificado, el punto de partida sobre el que se apoyan los seis pasos siguientes: si la hipótesis de esta lección estuviera mal formada, pickTest() (lección 3) elegiría un test para refutar la afirmación equivocada, el guion de entrevista (lección 4) preguntaría por la cosa equivocada, y la decisión final (lección 7) no tendría ningún fundamento sólido debajo. Todo el pipeline de este módulo descansa sobre que este primer paso quede bien hecho.

Una analogía: la apuesta que puedes perder, no la que no puedes

Un apostador serio nunca apuesta "creo que va a ganar el mejor equipo" — esa frase no se puede perder, porque cualquier resultado se puede reinterpretar como "sí, ganó el mejor equipo". Apuesta algo concreto: "el equipo A gana por más de 1.5 goles", una afirmación que, si el resultado sale distinto, pierde de forma inequívoca. La diferencia entre las dos frases no es de entusiasmo ni de convicción — es de si existe, de antemano, un resultado observable que probaría la apuesta equivocada. La hipótesis de esta lección hace exactamente eso con recommendations: no "creemos que a los usuarios les va a gustar" (no se puede perder), sino una cifra concreta que, si no se alcanza, deja la suposición oficialmente refutada.

Ejemplo trabajado: isFalsifiable() sobre dos versiones de la misma creencia

Empezamos con la versión que, en una reunión con prisa, es fácil escribir sin darse cuenta del problema: una creencia razonable, pero sin ninguna condición de fracaso. Reutilizamos isFalsifiable() exactamente como quedó en el módulo 4:

// L2 (M8): isFalsifiable() sobre dos versiones de la misma creencia -- la
// version vaga que casi se escribe por defecto, y la version falsable que
// este paso deja lista para el resto del pipeline. Funcion EXACTA del modulo 4.
function isFalsifiable(hypothesis) {
  const hasBelief = typeof hypothesis.believe === 'string' && hypothesis.believe.trim().length > 0;
  const hasFailureCondition = typeof hypothesis.wrongIf === 'string' && hypothesis.wrongIf.trim().length > 0;
  if (!hasBelief) {
    return { ...hypothesis, falsifiable: false, reason: 'no declara una creencia clara (believe) -- no hay nada que probar' };
  }
  if (!hasFailureCondition) {
    return { ...hypothesis, falsifiable: false, reason: 'no declara una condicion de fracaso (wrongIf) -- no se puede refutar' };
  }
  return { ...hypothesis, falsifiable: true, reason: 'tiene creencia y condicion de fracaso, ambas observables' };
}

console.log('=== Version vaga, la que casi se escribe por defecto ===\n');
const vagueVersion = {
  believe: 'Los usuarios van a comprar mas si ven recomendaciones personalizadas',
  weWillKnowIf: 'lo vamos a notar en el comportamiento de compra',
};
const vagueCheck = isFalsifiable(vagueVersion);
console.log('falsifiable: ' + vagueCheck.falsifiable + ' -> ' + vagueCheck.reason);

console.log('\n=== Version falsable, la que usa el resto del modulo ===\n');
const recommendationsHypothesis = {
  believe: 'Los usuarios van a comprar mas si ven recomendaciones personalizadas',
  weWillKnowIf: 'al menos el 8% de los usuarios que ven una recomendacion la agregan al carrito',
  wrongIf: 'menos del 8% de los usuarios que ven una recomendacion la agrega al carrito, incluso despues de dos semanas de exposicion',
};
const falsifiabilityCheck = isFalsifiable(recommendationsHypothesis);
console.log('creemos que: "' + recommendationsHypothesis.believe + '"');
console.log('lo sabremos si: "' + recommendationsHypothesis.weWillKnowIf + '"');
console.log('estaremos equivocados si: "' + recommendationsHypothesis.wrongIf + '"');
console.log('falsifiable: ' + falsifiabilityCheck.falsifiable + ' -> ' + falsifiabilityCheck.reason);

Qué esperar. Al correr el archivo con Node, la salida es exactamente esta:

=== Version vaga, la que casi se escribe por defecto ===

falsifiable: false -> no declara una condicion de fracaso (wrongIf) -- no se puede refutar

=== Version falsable, la que usa el resto del modulo ===

creemos que: "Los usuarios van a comprar mas si ven recomendaciones personalizadas"
lo sabremos si: "al menos el 8% de los usuarios que ven una recomendacion la agregan al carrito"
estaremos equivocados si: "menos del 8% de los usuarios que ven una recomendacion la agrega al carrito, incluso despues de dos semanas de exposicion"
falsifiable: true -> tiene creencia y condicion de fracaso, ambas observables

Mira con cuidado la diferencia entre las dos versiones: ambas comparten exactamente el mismo believe — la creencia de fondo no cambió en absoluto. Lo único que separa a la versión vaga de la versión falsable es una sola línea, wrongIf, y esa línea es la que hace todo el trabajo. "Lo vamos a notar en el comportamiento de compra" suena razonable en una reunión, pero no dice cuánto comportamiento cuenta como "notarlo" — cualquier resultado, alto o bajo, se puede reinterpretar después como si hubiera confirmado la creencia. "Menos del 8%... incluso después de dos semanas" no deja ese espacio: es una cifra concreta, con un plazo concreto, que un resultado real puede violar sin ambigüedad.

Fíjate también en el detalle del plazo — "incluso después de dos semanas de exposición" — que la versión vaga no tiene. Sin ese plazo, alguien podría defender la hipótesis indefinidamente diciendo "todavía no le dimos tiempo suficiente", sin que exista nunca un momento en el que la hipótesis pueda darse por refutada. El plazo cierra esa salida: dos semanas es el tiempo que el equipo acordó, de antemano, como razonable para que el comportamiento se estabilice, y después de ese plazo, el número manda, sin excusas nuevas.

Por qué el umbral se fija antes de ver cualquier dato

El 8% de weWillKnowIf no es un número que salga de una fórmula — es una decisión del equipo, tomada antes de correr ningún test, sobre cuánta señal hace falta para justificar seguir invirtiendo en recommendations. Podría haber sido 5% o 12%; lo que importa no es el número exacto, sino que quedó fijado antes de que existiera ningún dato que pudiera influir en la elección. Esta es la misma disciplina que viste con el umbral del fake door en el módulo 5 (5% de clic-through, acordado antes de la semana de medición) — y no es casualidad que se repita aquí: es la defensa más simple y más efectiva contra el sesgo de confirmación que el módulo 6 nombró en detalle. Un equipo que fija el umbral después de ver el resultado puede, sin darse cuenta, mover la barra exactamente hasta donde el número que ya tiene la deja pasar.

                    ANTES de ver datos          DESPUES de ver datos
                    ───────────────────         ──────────────────────
Umbral fijado       "8%, decidido hoy"          "el numero que salga es
                                                  el umbral, ajustado a
                                                  gusto"
Resultado: 6%       Hipotesis REFUTADA           "6% ya es bastante bueno,
                    (por debajo del umbral)       llamemoslo exito"
Quien decide        El equipo, con la mente      El equipo, ya con el
                    despejada                     resultado frente a los
                                                   ojos, tentado a leerlo
                                                   como quiere

Errores comunes

Escribir weWillKnowIf sin escribir wrongIf. Qué pasa: alguien completa la plantilla con una condición de éxito ("lo sabremos si el 8% agrega al carrito") pero nunca escribe explícitamente la condición de fracaso, asumiendo que es la misma frase "al revés" y que no hace falta escribirla aparte. Por qué pasa: parece redundante escribir dos veces, en dos direcciones, lo que se siente como la misma idea. Cómo detectarlo: pídele a quien escribió la hipótesis que recite, de memoria, el wrongIf exacto — si duda, o lo improvisa en el momento, la hipótesis nunca tuvo una condición de fracaso de verdad, solo una de éxito con la que todos estaban cómodos. Cómo corregirlo: escribe las dos frases por separado, cada una con su propio umbral y su propio plazo — como viste en el ejemplo de hoy, wrongIf agregó el plazo de "dos semanas" que weWillKnowIf no tenía, y ese detalle solo aparece cuando alguien se obliga a escribir la condición de fracaso de forma explícita, no como espejo automático de la de éxito.

Elegir un umbral cómodo en vez de un umbral honesto. Qué pasa: al fijar el 8% (o cualquier número), el equipo, sin decirlo en voz alta, elige uno que sabe que va a ser fácil de superar, en vez de uno que refleje de verdad cuánta señal necesita el negocio para justificar construir el motor completo. Por qué pasa: un umbral fácil de pasar se siente como una apuesta más segura — nadie quiere ser quien fijó la barra tan alto que el proyecto "fracasó" en la evaluación. Cómo detectarlo: pregunta qué pasaría si el número real cae justo por debajo del umbral elegido — si la respuesta instintiva es "igual seguiríamos adelante", el umbral no estaba fijado con honestidad. Cómo corregirlo: el umbral tiene que reflejar el costo real de construir la versión completa (build_the_engine, 40 person-days según el módulo 4) versus el valor que aporta — no la comodidad de quien lo escribe. Si dudas de qué número usar, vuelve al opportunitySize de product-thinking-for-engineers-guide para anclar el umbral en el negocio real, no en la sensación de "algo parece razonable".

Ejercicios

Ejercicio 1 — Encuentra el wrongIf faltante. Un compañero de equipo escribe esta hipótesis para una apuesta distinta, sellerTools: { believe: 'Mejores herramientas hacen que los vendedores suban mas productos', weWillKnowIf: 'el catalogo de los vendedores piloto crece mas rapido que el del grupo de control' }. Sin ejecutar Node, ¿qué devolvería isFalsifiable() sobre este objeto, y por qué?

Ver solución

Devolvería { falsifiable: false, reason: 'no declara una condicion de fracaso (wrongIf) -- no se puede refutar' }. El objeto tiene un believe con contenido (pasa el primer chequeo), pero no tiene ninguna propiedad wrongIf en absoluto — hypothesis.wrongIf sería undefined, y typeof undefined === 'string' es false, así que hasFailureCondition queda en false y la función se detiene en el segundo if. Este ejercicio confirma algo importante sobre isFalsifiable(): no evalúa si la condición de éxito está bien escrita — solo verifica que exista una condición de fracaso, explícita y separada. Una hipótesis puede tener el mejor weWillKnowIf del mundo y seguir siendo falsifiable: false si nunca se molestó en escribir lo contrario.

Ejercicio 2 — Ajusta el umbral y razona el impacto. Si el equipo decidiera que 12% (en vez de 8%) es el umbral correcto para recommendations —razonando que el motor completo cuesta 40 person-days y necesita una señal más fuerte para justificar esa inversión—, reescribe weWillKnowIf y wrongIf con ese nuevo umbral. ¿Cambia esto si la hipótesis es falsifiable según isFalsifiable()?

Ver solución

Una reescritura razonable: weWillKnowIf: 'al menos el 12% de los usuarios que ven una recomendacion la agregan al carrito', wrongIf: 'menos del 12% de los usuarios que ven una recomendacion la agrega al carrito, incluso despues de dos semanas de exposicion'. No, no cambia si es falsifiableisFalsifiable() solo verifica que believe y wrongIf existan y tengan contenido, sin importar cuál sea el número exacto del umbral. Esto es intencional: la función chequea la forma de la hipótesis (¿tiene una condición de fracaso concreta?), no si el umbral específico es el correcto para el negocio — esa segunda pregunta, sobre qué número es el correcto, es un juicio de negocio que el equipo tiene que hacer aparte, con datos como el opportunitySize de la guía hermana.

Ejercicio 3 — Escribe la hipótesis para una apuesta que nunca viste en esta guía. Imagina una apuesta nueva para Mercado: "agregar un botón de 'comprar de nuevo' en el historial de pedidos aumenta la frecuencia de recompra". Escribe la hipótesis completa (believe, weWillKnowIf, wrongIf), con un umbral y un plazo concretos, y verifica a mano que pasaría isFalsifiable().

Ver solución

Una hipótesis razonable: { believe: 'Agregar un boton de comprar de nuevo en el historial de pedidos aumenta la frecuencia de recompra', weWillKnowIf: 'al menos el 10% de los compradores que usan el boton hacen una segunda compra dentro de 30 dias, comparado con el grupo de control', wrongIf: 'menos del 10% de diferencia con el grupo de control, incluso despues de 30 dias de exposicion al boton' }. Pasa isFalsifiable(): tiene believe con contenido y wrongIf con contenido, ambos observables (una tasa de recompra medible, con un plazo concreto de 30 días). Fíjate en un detalle que este ejercicio deja ver con claridad: la hipótesis compara contra un grupo de control, no contra un número absoluto — una forma más rigurosa de escribir wrongIf, que descarta que la recompra hubiera subido de todas formas por razones ajenas al botón (estacionalidad, una campaña de marketing simultánea). No es obligatorio para pasar isFalsifiable(), pero es una práctica más sólida cuando el contexto lo permite.

Resumen y siguiente paso

En esta lección convertiste la suposición riesgosa de recommendations en una hipótesis falsable, con isFalsifiable() confirmando que tiene tanto una creencia clara como una condición de fracaso concreta y con plazo: menos del 8% de agregado al carrito después de dos semanas la refuta. Viste, comparando la versión vaga contra la versión falsable, que la diferencia entre ambas no está en el entusiasmo ni en la redacción general — está en una sola línea, escrita antes de ver cualquier dato, que decide de antemano qué resultado cuenta como fracaso.

Antes de avanzar deberías poder: escribir, para cualquier suposición nueva, una hipótesis con believe y wrongIf separados y concretos; y explicar por qué fijar el umbral antes de ver datos es una defensa activa contra el sesgo de confirmación.

La lección 3 toma esta hipótesis ya verificada y elige, con pickTest(), el test más barato que de verdad puede refutarla — entre varios candidatos legítimos, no entre el más cómodo y el resto.

Recursos

  • Karl Popper, entrada "Karl Popper" en la Stanford Encyclopedia of Philosophy — plato.stanford.edu/entries/popper. La fuente filosófica detrás de isFalsifiable() — para quien quiera el argumento completo detrás de "una buena hipótesis es la que se puede tumbar". En inglés.
  • Teresa Torres, "Assumption Testing: Everything You Need to Know to Get Started" — producttalk.org/assumption-testing. El artículo de referencia para seguir practicando la escritura de hipótesis falsables, más allá del caso de recommendations. En inglés.
  • David J. Bland y Alexander Osterwalder, resumen de Testing Business Ideasstrategyzer.com/library/testing-business-ideas-book-summary. Sobre por qué fijar el umbral de éxito antes de correr el test es una de las prácticas más citadas —y más saltadas— del diseño de experimentos de negocio. En inglés.