Módulo 3: The Opportunity Solution Tree
Ramificar y podar el árbol
Descripción
Las lecciones anteriores construyeron el árbol de Mercado agregando ramas, una por una: cada oportunidad nueva, cada solución nueva, cada experimento candidato nuevo se sentía como progreso. Y lo es — pero solo hasta cierto punto. Un árbol real, con vida propia (no solo el diagrama de este módulo), tiende a crecer más rápido de lo que un equipo puede atender: cada semana de entrevistas trae oportunidades nuevas, cada sesión de brainstorming trae soluciones nuevas, y si nadie corta nada, el árbol se vuelve tan ancho que ningún equipo tiene tiempo de correr experimentos para todas sus ramas a la vez.
Esta lección le da nombre a las dos operaciones que mantienen un árbol útil: ramificar (agregar oportunidades y soluciones nuevas, lo que ya hiciste en las lecciones 5 y 6) y podar (decidir, con criterio explícito, qué ramas atacar primero y cuáles dejar sin tocar por ahora). Podar no es lo mismo que descartar para siempre — una rama podada sigue en el árbol, solo que no es la prioridad de esta semana. Vas a ver un modelo ejecutado que cuenta qué tan ancho está el árbol, y otro que lo poda usando un criterio que ya conoces de la guía anterior: el impact, uno de los cuatro factores de RICE.
Conexión con el módulo. Reutilizamos validateTree() de las lecciones 5 y 6 en espíritu — el árbol de hoy pasa por los mismos dos chequeos—, pero el foco de esta lección son dos modelos nuevos: countBranches(), que mide qué tan ancho está el árbol, y pruneTree(), que lo recorta a las oportunidades de mayor impact. No recalculamos RICE completo aquí —eso ya lo hiciste en product-thinking-for-engineers—; solo reutilizamos el campo impact para ilustrar qué significa, en la práctica, podar.
Una analogía cotidiana: el árbol frutal que nadie podó
Piensa en un árbol frutal de verdad —un limonero, por ejemplo— al que nadie le corta nunca ninguna rama. Con los años, crece en todas direcciones: docenas de ramas delgadas, cada una compitiendo por la misma cantidad de luz solar y de nutrientes que reciben las raíces. El resultado, casi siempre, no es más fruta — es fruta más chica y más débil, repartida entre demasiadas ramas, ninguna recibiendo lo suficiente para crecer bien. Un jardinero que sabe lo que hace corta, cada temporada, las ramas más débiles o menos prometedoras — no porque esas ramas sean "malas", sino porque el árbol entero da mejor fruta cuando concentra su energía en menos ramas, mejor elegidas.
El opportunity solution tree de un equipo de producto se comporta exactamente igual. Cada oportunidad nueva que agregas es una rama más compitiendo por el mismo recurso escaso: el tiempo del equipo para correr experimentos. Un árbol con siete oportunidades activas, todas "en progreso" al mismo tiempo, no produce siete aprendizajes sólidos — produce siete aprendizajes débiles, cada uno con menos atención de la que necesitaría para ser confiable. Podar —elegir, esta semana, dos o tres oportunidades para atacar en serio, y dejar el resto sin tocar por ahora— es lo que le permite al árbol, en el fondo, dar fruta de verdad.
Ejemplo trabajado: qué tan ancho está el árbol, y cómo se poda
Ampliamos el árbol de Mercado a siete oportunidades — las cinco que ya conoces, más dos nuevas: "no puedo pagar en cuotas sin tarjeta de crédito" y "el checkout tiene demasiados pasos y lo abandono". A cada oportunidad le agregamos un campo impact (1 a 5, el mismo campo de RICE que ya calculaste en la guía anterior — no lo recalculamos, solo lo reutilizamos). countBranches() cuenta cuántas oportunidades, soluciones y experimentos tiene el árbol completo. pruneTree() se queda solo con las oportunidades de mayor impact.
// countBranches: cuenta cuantas oportunidades, soluciones y experimentos
// tiene el arbol completo -- una forma simple de ver que tan ancho se puso.
function countBranches(tree) {
let solutions = 0;
let experiments = 0;
tree.opportunities.forEach((opp) => {
solutions += opp.solutions.length;
opp.solutions.forEach((sol) => {
experiments += sol.experiments.length;
});
});
return { opportunities: tree.opportunities.length, solutions, experiments };
}
// pruneTree: se queda solo con las N oportunidades de mayor impact (el mismo
// campo impact de RICE, de la guia anterior -- no lo recalculamos, solo lo
// usamos para ordenar). Podar no es descartar para siempre: es elegir por
// donde empezar.
function pruneTree(tree, keep) {
const sorted = [...tree.opportunities].sort((a, b) => b.impact - a.impact);
return { outcome: tree.outcome, opportunities: sorted.slice(0, keep) };
}
const wideTree = {
outcome: '+GMV via conversion del checkout',
opportunities: [
{
problem: 'no descubro productos que me gustarian sin buscarlos por nombre exacto',
impact: 5,
solutions: [
{ idea: 'recomendaciones personalizadas en home y checkout', experiments: ["fake door: boton 'ver mis recomendaciones' en el checkout", 'prototipo clickable con 20 compradores'] },
{ idea: 'categorias curadas a mano por tendencia', experiments: ['prototipo de landing por categoria con 10 compradores'] },
],
},
{
problem: 'no confio en vendedores nuevos sin reseñas',
impact: 3,
solutions: [
{ idea: 'insignia de vendedor verificado en la ficha de producto', experiments: ['prototipo clickable de la ficha con insignia'] },
],
},
{
problem: 'se me olvida el carrito y no vuelvo a completarlo',
impact: 4,
solutions: [
{ idea: 'recordatorio por email del carrito abandonado', experiments: ['wizard-of-oz: enviar el recordatorio a mano a 30 usuarios'] },
],
},
{
problem: 'agregar un boton de compra en un clic',
impact: 2,
solutions: [
{ idea: 'boton de compra en un clic en la ficha de producto', experiments: [] },
],
},
{
problem: 'comparar precios entre productos similares me toma mucho tiempo',
impact: 3,
solutions: [
{ idea: 'tabla comparativa entre productos similares', experiments: ['prototipo clickable de tabla comparativa', 'fake door: boton comparar en la ficha de producto'] },
],
},
{
problem: 'no puedo pagar en cuotas sin tarjeta de credito',
impact: 2,
solutions: [
{ idea: 'pago en cuotas sin tarjeta de credito', experiments: ['encuesta a 30 compradores sobre metodos de pago'] },
],
},
{
problem: 'el checkout tiene demasiados pasos y lo abandono',
impact: 4,
solutions: [
{ idea: 'checkout de un solo paso', experiments: ['prototipo clickable de checkout de un paso'] },
],
},
],
};
console.log('=== ¿que tan ancho esta el arbol de Mercado? ===\n');
const counts = countBranches(wideTree);
console.log('opportunities: ' + counts.opportunities);
console.log('solutions: ' + counts.solutions);
console.log('experiments: ' + counts.experiments);
console.log('\n=== podado a las 3 oportunidades de mayor impact ===\n');
const pruned = pruneTree(wideTree, 3);
pruned.opportunities.forEach((opp) => {
console.log('impact ' + opp.impact + ' -- "' + opp.problem + '"');
});
Qué esperar. Al correr el archivo con Node, la salida es exactamente esta:
=== ¿que tan ancho esta el arbol de Mercado? ===
opportunities: 7
solutions: 8
experiments: 9
=== podado a las 3 oportunidades de mayor impact ===
impact 5 -- "no descubro productos que me gustarian sin buscarlos por nombre exacto"
impact 4 -- "se me olvida el carrito y no vuelvo a completarlo"
impact 4 -- "el checkout tiene demasiados pasos y lo abandono"
Siete oportunidades, ocho soluciones, nueve experimentos candidatos — ese es el tamaño real del árbol después de cinco lecciones agregando ramas. Ningún equipo chico de Mercado puede correr nueve experimentos a la vez con la atención que cada uno necesita; intentarlo produce exactamente el limonero sin podar de la analogía — nueve aprendizajes débiles, en vez de dos o tres sólidos. pruneTree() recorta el árbol a las tres oportunidades de mayor impact: la de descubrimiento de productos (impact 5, la más alta, y la que sostiene directamente la apuesta recommendations), y un empate entre carritos olvidados y el checkout de demasiados pasos (impact 4 ambas).
Por qué podar por impact no es lo mismo que podar por validateTree()
Vale la pena mirar con cuidado qué pasó con la oportunidad "agregar un botón de compra en un clic" — la que las lecciones 4 y 5 marcaron [SOSPECHOSA]. En el árbol de hoy tiene impact: 2, uno de los más bajos, así que de todas formas queda fuera del top 3 podado. Podría ser tentador concluir que pruneTree() "ya resuelve" el problema de las oportunidades disfrazadas, simplemente asignándoles poco impacto. Pero eso sería un error: el impact es un número que alguien del equipo asigna a mano, con su propio criterio —y nada impide que alguien, convencido de su idea, le hubiera puesto impact: 5 a esa misma oportunidad sospechosa. Que haya quedado con impacto bajo en este ejemplo es una coincidencia útil para la lección, no una garantía. Podar por impact y validar con validateTree() son dos chequeos independientes, con dos preguntas distintas: uno pregunta "¿cuánto nos importa esto, si fuera real?"; el otro pregunta "¿esto es real, para empezar?". Los dos hacen falta, y ninguno reemplaza al otro.
Errores comunes
Enamorarse de una rama y dejar de explorar las demás. Qué pasa: el equipo encuentra una oportunidad que le entusiasma particularmente —a menudo porque ya tiene una idea de solución que le gusta mucho, como recomendaciones— y le dedica toda su atención, mientras las otras seis oportunidades del árbol quedan completamente abandonadas, sin ni siquiera un experimento barato para saber si merecen más atención. Por qué pasa: es más cómodo profundizar en una sola dirección conocida que mantener varias ramas vivas a la vez —sobre todo si esa dirección ya genera entusiasmo genuino en el equipo. Cómo detectarlo: si le preguntas al equipo por el estado de las otras oportunidades del árbol, la respuesta es "no hemos vuelto a mirar eso" para casi todas, mientras una sola acapara todas las conversaciones recientes. Cómo corregirlo: podar no significa elegir una sola rama para siempre —significa elegir dos o tres para esta semana, con la intención explícita de revisar el resto más adelante. Vuelve al árbol completo periódicamente, no solo a la rama favorita.
Dejar el árbol tan ancho que no se prueba nada de verdad. Qué pasa: en el sentido opuesto, el equipo se resiste a podar —"todas las oportunidades son importantes, no queremos descartar ninguna"— y termina intentando avanzar un poquito en las siete a la vez, sin dedicarle a ninguna el tiempo suficiente para conseguir una señal confiable. Por qué pasa: podar se siente como renunciar a algo, y nadie quiere ser quien decida qué oportunidad se queda sin atención esta semana. Cómo detectarlo: usa countBranches() — si el número de oportunidades activas supera lo que el equipo puede atender con calidad (para un equipo chico, rara vez más de dos o tres a la vez), el árbol está demasiado ancho para producir aprendizaje sólido en ninguna rama. Cómo corregirlo: recuerda que podar no es descartar para siempre —es elegir un orden. pruneTree() no borra las oportunidades fuera del top N; solo las deja fuera de la lista de "esta semana". Van a seguir ahí para cuando el equipo tenga espacio.
Confundir "impacto alto" con "oportunidad válida". Qué pasa: al ver el resultado de pruneTree(), alguien asume que las oportunidades que sobrevivieron la poda ya están garantizadas como reales y bien formadas, sin volver a pasarlas por validateTree(). Por qué pasa: haber sobrevivido un filtro (impacto alto) se siente como haber sobrevivido todos los filtros necesarios. Cómo detectarlo: como viste en el ejemplo de hoy, una oportunidad disfrazada podría, en otro escenario, tener impacto alto asignado por error y sobrevivir la poda sin que nadie note que en realidad es una solución con otro nombre. Cómo corregirlo: siempre corre ambos chequeos sobre las oportunidades que sobreviven la poda — validateTree() para confirmar que son problemas reales, y solo entonces pruneTree() (o el orden inverso) para decidir cuáles atacar primero. Ningún número de impacto reemplaza el chequeo de contenido de las lecciones 4 y 5.
Ejercicios
Ejercicio 1 — Recalcula la poda con un top 2. Sin ejecutar Node, usando los mismos siete impact del ejemplo de hoy, ¿qué oportunidades quedarían si pruneTree(wideTree, 2) en vez de 3? ¿Cambia el resultado respecto al top 3 que viste ejecutado?
Ver solución
El top 2 por impact sería: impact 5 ("no descubro productos...") e impact 4 ("se me olvida el carrito..." — la primera de las dos oportunidades con impact 4 en el orden original del arreglo, ya que Array.prototype.sort en JavaScript es estable y mantiene el orden relativo entre elementos con el mismo valor). Queda fuera "el checkout tiene demasiados pasos", que sí estaba en el top 3. Este ejercicio muestra algo importante sobre pruneTree(): cuando hay empates de impact (como los dos 4 de este árbol), el resultado exacto depende del orden en que las oportunidades aparecen originalmente en el arreglo — un detalle técnico que vale la pena conocer antes de confiar ciegamente en el resultado de una poda con empates.
Ejercicio 2 — Diagnostica un árbol real. Para un equipo que conozcas (o imagines), estima cuántas oportunidades activas tiene su árbol de discovery ahora mismo (aunque no lo tengan escrito formalmente), y compáralo con lo que el equipo podría atender con calidad en una semana. ¿Está más cerca del limonero sin podar, o de un árbol bien recortado?
Ver solución
No hay una respuesta única —depende del equipo que elijas—, pero el ejercicio busca que apliques el criterio de countBranches() con honestidad, no una impresión vaga de "tenemos muchas cosas en el radar". Muchos equipos, al hacer este ejercicio con cuidado, descubren que tienen media docena de "iniciativas" simultáneas sin ningún experimento activo detrás de la mayoría — el patrón exacto del limonero sin podar, aunque nadie lo haya decidido explícitamente así.
Ejercicio 3 — Defiende una poda impopular. El equipo de Mercado quiere seguir trabajando en las siete oportunidades a la vez, "para no dejar a nadie sin su idea favorita". Usando los números exactos del ejemplo de hoy (opportunities: 7, solutions: 8, experiments: 9), escribe un mensaje de 3-4 frases defendiendo podar a solo tres.
Ver solución
Un mensaje razonable: "Tenemos siete oportunidades activas en el árbol, con ocho soluciones y nueve experimentos candidatos entre todas — si intentamos avanzar en las siete a la vez, cada una se va a llevar apenas una fracción de nuestra atención esta semana, y vamos a terminar con nueve señales débiles en vez de dos o tres confiables. Propongo que nos enfoquemos en las tres de mayor impacto —descubrimiento de productos, carritos olvidados, y el checkout de muchos pasos— y dejemos las otras cuatro en el árbol, sin borrarlas, para retomarlas en cuanto tengamos evidencia sobre estas tres. No estamos descartando ninguna idea para siempre — estamos eligiendo un orden." El argumento funciona porque no minimiza las otras cuatro oportunidades — solo insiste en que atacarlas todas a la vez, sin foco, no produce mejor aprendizaje que atacar pocas con calidad.
Resumen y siguiente paso
En esta lección le pusiste nombre a las dos operaciones que mantienen un árbol útil: ramificar (agregar oportunidades, soluciones y experimentos — lo que hiciste en las lecciones 5 y 6) y podar (elegir, con criterio explícito, en qué ramas concentrar el esfuerzo de esta semana). Viste countBranches() confirmar que el árbol de Mercado creció a siete oportunidades, ocho soluciones y nueve experimentos — demasiado ancho para atacar todo a la vez—, y pruneTree() recortarlo a las tres de mayor impact. Y viste, en el error final, por qué el impacto alto y la validez estructural son dos chequeos independientes, ninguno sustituto del otro.
Antes de avanzar deberías poder: explicar la diferencia entre podar y descartar para siempre; usar countBranches() para diagnosticar si un árbol está demasiado ancho para el tamaño de un equipo; y explicar por qué correr pruneTree() no reemplaza correr validateTree() sobre las oportunidades que sobreviven.
Con esto cierras el cuerpo del módulo 3. Tienes ahora las cuatro piezas completas: la forma del árbol (lección 2), un outcome verificado en la raíz (lección 3), oportunidades reales distinguidas de soluciones disfrazadas (lección 4), soluciones bien colgadas y sin huérfanas (lección 5), experimentos como menú de candidatos (lección 6), y un criterio para ramificar y podar (esta lección). La lección 8, el mini-proyecto, arma el árbol completo de Mercado desde cero, en un solo archivo, y toma la decisión final: qué rama atacar primero, y con qué experimento.
Recursos
- Product Talk, "The Power of Opportunity Solution Trees: 7 Key Benefits Revealed" — producttalk.org/benefits-of-opportunity-solution-trees. Sobre por qué mantener el árbol como un artefacto vivo —que se poda y se actualiza— es lo que le da valor, en vez de dejarlo como un diagrama fijo de una sola reunión. En inglés.
- Marty Cagan (SVPG), "Product Discovery" — svpg.com/product-discovery. Ya lo viste en la lección 2; vale la pena releerlo aquí, con el árbol completo en la cabeza, para ver cómo un equipo real decide, semana a semana, qué oportunidad atacar primero. En inglés.
- Teresa Torres, Continuous Discovery Habits — producttalk.org/continuous-discovery-habits. El libro dedica un capítulo completo a cómo priorizar oportunidades dentro del árbol — el mismo problema que resolviste hoy con
pruneTree(), con mucho más matiz del que cabe en esta lección. En inglés.