wandres.dev
NIVEL DIOS: SÍNTESIS · MVI en la práctica

Seguir aprendiendo: fuentes primarias y plan de dominio

El track termina donde empieza la autonomía: saber leer las fuentes primarias sin intermediarios y construir un plan de estudio que no dependa de que alguien lo escriba por ti. Esta lección enseña a leer la documentación de Orbit y su código como fuente de verdad, a leer las guías de arquitectura de Android críticamente distinguiendo la recomendación del razonamiento que la sostiene, propone un plan de dominio en cuatro fases con entregables comprobables en vez de lecturas acumuladas, y cierra con el método para detectar que un conocimiento se ha quedado obsoleto antes de que lo haga un incidente en producción.

⏱ 20 min

Todo material didáctico tiene una fecha de caducidad y una función que sobrevive a esa fecha: el contenido envejece, el método de aprender no. Este track te ha dado un mapa, pero un mapa es una simplificación deliberada de un territorio que cambia, y las versiones de las librerías, las recomendaciones oficiales y hasta los consensos del ecosistema se moverán mientras tú sigues escribiendo código. Lo que decide si dentro de tres años sigues siendo competente no es cuánto recuerdes de estas lecciones, sino si has adquirido el hábito de ir a las fuentes primarias, leerlas con criterio y verificar en tu propio proyecto en vez de acumular artículos de terceros que repiten mal lo que otro entendió a medias. Esta última lección trata de eso: de cómo se sigue solo.

🎯 Al terminar esta lección sabrás
  • Leer la documentación y el código de Orbit como fuente de verdad, no como recetario.
  • Leer las guías de arquitectura de Android separando la recomendación de su razonamiento.
  • Construir un plan de dominio por fases con entregables verificables y no con lecturas.
  • Detectar que un conocimiento se ha oxidado antes de que lo detecte un incidente.

Leer Orbit como fuente primaria

La documentación de Orbit vive en orbit-mvi.org y el código en github.com/orbit-mvi/orbit-mvi. Esa distinción importa más de lo que parece, porque una documentación te dice cómo se usa una librería y el código te dice qué garantiza de verdad, y solo lo segundo resuelve las preguntas difíciles.

Hay cuatro lecturas que conviene hacer al menos una vez y que cambian la relación con la librería. La primera es la implementación del container: te enseñará cómo se serializan las reducciones y por qué el bloque reduce no puede suspender. La segunda es la del canal de efectos: verás qué tipo de búfer usa y qué ocurre exactamente cuando nadie colecciona. La tercera es el módulo de pruebas: descubrirás que la afirmación por traza es más expresiva de lo que la documentación deja ver. Y la cuarta son las notas de versión, que son el mejor resumen que existe de qué problemas reales ha tenido la gente.

🔱

Documentación para el cómo

Resuelve el uso corriente: cómo se declara un container, cómo se guarda estado, cómo se prueba. Léela entera una vez, no a trozos vía buscador.

🔱

Código para el qué garantiza

Cuando la duda es si algo está garantizado o solo suele ocurrir, la única respuesta fiable está en la implementación. Es más corta y más legible de lo que temes.

🔱

Issues para los límites

Los problemas abiertos y cerrados son un catálogo de casos límite que nadie escribiría en la documentación. Busca ahí antes de concluir que has encontrado un fallo.

🔱

Notas de versión para la dirección

Qué se añade, qué se marca como obsoleto y con qué justificación. Es la señal más honesta de hacia dónde va el proyecto y de si sigue vivo.

Hay un tipo de pregunta que solo el código responde, y conviene reconocerla para no perder el tiempo buscándola en la documentación: son las preguntas sobre qué ocurre en el caso raro. Qué pasa si se emiten dos efectos y nadie colecciona; qué pasa si se llama a un intent desde otro intent; qué pasa si el proceso muere entre dos reducciones; en qué orden se aplican dos reducciones lanzadas desde corrutinas distintas. Ninguna documentación razonable cubre esas combinaciones, y todas ellas aparecen en producción.

// La forma correcta de responder a una duda sobre garantias:
// escribir el test que la falsaria, no buscar el articulo que la confirma.
@Test
fun `dos intents concurrentes no pisan sus reducciones`() = runTest {
    val vm = ContadorViewModel().test(this)
    repeat(100) { vm.invokeIntent { incrementar() } }
    vm.assert(ContadorState(valor = 100)) { }
}

Ese test no comprueba tu código: comprueba tu modelo mental del código ajeno. Si pasa, tu suposición sobre la serialización era correcta y ahora está documentada de forma ejecutable en tu propio repositorio. Si falla, acabas de ahorrarte un incidente y una discusión.

💡
El ejercicio que más rendimiento da por hora invertida

Escribe tu propia versión mínima de un container —estado, canal, mutex— y después lee la de Orbit comparando decisión por decisión. Cada diferencia entre tu versión y la suya es una pregunta concreta que puedes investigar, y las respuestas a esas preguntas son exactamente el conocimiento que distingue a quien usa una librería de quien la entiende. Es la forma más rápida que existe de convertir una dependencia opaca en una herramienta transparente.

Leer las guías de Android críticamente

La guía oficial de arquitectura de Android, en developer.android.com/topic/architecture, es la referencia que más cambia y la que más gente cita sin leer. Merece una lectura completa y una relectura anual, pero merece sobre todo un modo de lectura que poca gente practica: separar la recomendación de su razonamiento.

Casi todas las recomendaciones de esa guía vienen acompañadas de un porqué, y el porqué es lo único que se puede transferir a una situación distinta de la ejemplificada. Cuando recomienda exponer un único flujo de estado de interfaz, el razonamiento es que varios flujos independientes permiten combinaciones inválidas; ese razonamiento es tuyo aunque la sintaxis cambie. Cuando recomienda modelar los eventos de una sola vez como estado con consumo explícito, el razonamiento es la fuente única de verdad frente a la muerte del proceso; ese razonamiento es el que te permite decidir si tu caso concreto encaja o si el canal de efectos es mejor arbitraje.

Hay un segundo hábito de lectura crítica que ahorra muchos disgustos: distinguir lo descriptivo de lo prescriptivo. La documentación describe cómo funcionan las herramientas y prescribe cómo cree que deberías usarlas. Lo descriptivo es verdad sobre el sistema y debes aceptarlo. Lo prescriptivo es una opinión informada, formulada para un caso medio que puede no ser el tuyo, y debe evaluarse. Confundir ambas cosas produce equipos que aplican recomendaciones fuera de su dominio de validez y luego culpan a la arquitectura.

Un tercer hábito, más incómodo, es rastrear cuándo cambió una recomendación y por qué. Las guías de Android han modificado su postura varias veces sobre asuntos importantes —dónde vive el estado de la interfaz, cómo se modelan los eventos de una sola vez, cuánta ceremonia merece una capa intermedia— y cada cambio vino acompañado de un razonamiento. Leer esa historia es más formativo que leer la versión actual, porque enseña qué clase de evidencia hace que una recomendación se revise, que es justamente lo que necesitarás para revisar las tuyas.

Junto a la guía, la aplicación de referencia oficial —el proyecto de ejemplo que acompaña a la documentación de arquitectura— es una fuente infravalorada, porque muestra las decisiones aplicadas a escala real y con sus incoherencias visibles. Leerla buscando dónde el código se aparta de lo que la guía recomienda, y preguntándose por qué, enseña más que leerla como modelo a imitar.

ℹ️
Las cuatro fuentes primarias que conviene seguir de verdad

Además de las dos anteriores: la documentación de corrutinas de Kotlin, que es donde se explican con precisión la concurrencia estructurada y la cancelación cooperativa; y la documentación de Compose sobre fases, estabilidad y recomposición, que es la única referencia fiable para diagnosticar rendimiento. Cuatro fuentes bien leídas rinden más que cien artículos de terceros, porque los artículos son interpretaciones fechadas de estas fuentes y heredan sus errores sin heredar sus correcciones.

Un plan de dominio por fases

Un plan de estudio basado en lecturas es un plan que no se puede evaluar, porque haber leído no es una capacidad. El plan que funciona se define por entregables comprobables: cosas que o funcionan o no funcionan, y que por tanto revelan sin ambigüedad si el conocimiento está.

Fase uno, consolidar. Construye una aplicación pequeña y completa —dos o tres pantallas, red real, base de datos, navegación— aplicando el bucle entero sin atajos. El entregable es que el reductor viva en un módulo sin Android y que la suite de pruebas del reductor corra en menos de un segundo.

Fase dos, profundizar. Escribe tu propio container mínimo, sustituye Orbit por él en una pantalla y documenta cada diferencia de comportamiento que encuentres. El entregable es un documento con al menos cinco diferencias explicadas por su causa.

Fase tres, ampliar. Elige una de las tres direcciones —composición de reductores para una pantalla grande, comprobación basada en propiedades sobre invariantes del estado, o compartir el dominio entre plataformas— y llévala hasta un resultado funcionando. El entregable es un caso real en tu proyecto, no un prototipo.

Fase cuatro, transferir. Enseña lo aprendido: una sesión interna, un artículo, una revisión de código sistemática. El entregable es que otra persona pueda aplicar lo que explicaste sin volver a preguntarte.

flowchart LR
F1[Consolidar: app completa sin atajos] --> F2[Profundizar: container propio y comparacion]
F2 --> F3[Ampliar: composicion, propiedades o multiplataforma]
F3 --> F4[Transferir: enseniar y revisar]
F4 -->|el hueco detectado vuelve al inicio| F1
style F1 fill:#89b4fa,color:#11111b
style F4 fill:#a6e3a1,color:#11111b

La cuarta fase es la que más gente se salta y la que más rendimiento tiene, por una razón que la experiencia confirma siempre: explicar obliga a construir el modelo causal completo, y las preguntas de quien escucha localizan con precisión quirúrgica los huecos que uno había disimulado consigo mismo. Un conocimiento que solo funciona mientras nadie pregunta por qué no es conocimiento, es familiaridad.

Merece la pena escribir el plan de forma que se pueda evaluar sin discusión, y la manera más simple es redactar cada fase como una condición que se cumple o no se cumple.

// El plan como asercion, no como lista de lecturas
// Fase 1 completa cuando: el reducer compila en un modulo sin Android
//   y su suite entera corre en menos de un segundo.
// Fase 2 completa cuando: existe un documento con cinco diferencias
//   entre mi container y el de Orbit, cada una explicada por su causa.
// Fase 3 completa cuando: la tecnica elegida esta en produccion,
//   no en una rama de pruebas.
// Fase 4 completa cuando: otra persona aplico lo que explique
//   sin volver a preguntarme.

Dos advertencias sobre el plan, porque casi todo el mundo tropieza en las mismas piedras. La primera es la tentación de saltar a la fase tres sin haber hecho la dos: ampliar antes de profundizar produce a alguien capaz de configurar cosas que no entiende, y esa persona no puede diagnosticar nada cuando falla. La segunda es medir el progreso en horas dedicadas en vez de en entregables cerrados; las horas miden esfuerzo y el esfuerzo no es capacidad. Un plan honesto puede completarse en menos tiempo del previsto o quedarse atascado meses, y ambas cosas son información útil que la contabilidad por horas oculta.

Detectar el conocimiento oxidado

El conocimiento técnico no caduca de golpe: se degrada en silencio mientras tú sigues aplicándolo con confianza intacta, y esa desconexión entre confianza y validez es lo peligroso. Hay cuatro señales fiables de oxidación y conviene revisarlas de forma deliberada un par de veces al año.

La primera es la explicación que se detiene. Si al justificar una decisión llegas a “así es como se hace” en menos de dos niveles de porqué, ese conocimiento es una costumbre heredada, no un criterio.

La segunda es la sorpresa recurrente. Si el comportamiento del sistema te sorprende con regularidad en la misma área, tu modelo de esa área es incorrecto, no incompleto, y arreglarlo exige releer la fuente y no acumular más experiencia.

La tercera es la receta sin condiciones. Si aplicas un patrón sin poder enunciar en qué caso sería erróneo, no tienes un criterio, tienes un reflejo; y los reflejos fallan exactamente cuando el contexto cambia.

La cuarta es la fuente indirecta. Si tu conocimiento de algo procede íntegramente de artículos y de respuestas ajenas y nunca has abierto la documentación ni el código, estás heredando la interpretación de otro con todos sus errores y sin sus actualizaciones.

Frente a esas cuatro señales, la corrección eficaz tiene una forma concreta y bastante ingrata: volver a la fuente primaria del punto exacto donde el modelo falla, y no releer un resumen. Releer resúmenes produce la sensación de estar corrigiendo sin corregir nada, porque el resumen fue escrito por alguien que tenía tu mismo hueco o uno distinto, y en ningún caso el tuyo.

Conviene además distinguir dos tipos de oxidación, porque se tratan de forma opuesta. La oxidación del contexto ocurre cuando lo que sabías sigue siendo cierto pero ya no es lo recomendable: la API que usabas funciona, simplemente hay otra mejor. Se corrige leyendo notas de versión y guías de migración, y su coste es bajo. La oxidación del modelo ocurre cuando lo que creías sobre el funcionamiento interno era falso o dejó de serlo, y se manifiesta como sorpresas repetidas y diagnósticos erróneos. Esta segunda es la cara, se corrige leyendo el código o escribiendo pruebas que falsen la suposición, y es la que produce incidentes, porque quien la sufre sigue razonando con seguridad sobre un mecanismo que ya no existe.

Por último, una nota sobre el ritmo. La tentación al terminar un track es buscar inmediatamente el siguiente, y suele ser un error: el conocimiento recién adquirido necesita atravesar el ciclo completo de uso real, fallo y corrección para consolidarse, y ese ciclo tarda meses, no días. La secuencia que funciona es aplicar, fallar, corregir y solo entonces ampliar. Quien encadena materiales sin ese intervalo acumula familiaridad con muchos temas y competencia con ninguno.

📝
Un ritual barato que funciona

Una vez por trimestre, elige un componente de tu aplicación y explícalo por escrito a un lector imaginario que sabe programar pero no conoce tu proyecto: qué hace, por qué está así, qué alternativa se descartó y qué lo haría cambiar. El texto no importa y probablemente nadie lo leerá; lo que importa es dónde se te atasca la escritura, porque ahí está exactamente el hueco. Escribir es el detector de huecos más barato que existe y el único que no depende de que alguien te examine.

La competencia no es un estado alcanzado: es una tasa de corrección

Hay una idea final que conviene llevarse por encima de todo lo demás, y es incómoda porque desmonta la imagen implícita que casi todo el mundo tiene del aprendizaje técnico. Ser competente no consiste en haber acumulado un conjunto suficiente de conocimientos correctos; consiste en mantener una tasa de corrección de errores superior a la tasa a la que el mundo invalida lo que sabes. Es una propiedad dinámica, no un inventario, y por eso el experto que deja de corregirse deja de ser experto sin notarlo, mientras sigue sintiendo exactamente la misma confianza que tenía cuando su modelo era válido. La sensación subjetiva de dominio no distingue entre saber y haber sabido, y esa es la razón por la que las trayectorias de mucha gente competente se estancan justo después de alcanzar la fluidez: la fluidez elimina la fricción que producía las correcciones, y sin fricción el modelo se congela. De ahí salen tres consecuencias prácticas que valen para MVI y para cualquier otra cosa que aprendas después. La primera es que hay que buscar deliberadamente las situaciones que corrigen —leer el código de lo que usas, escribir lo que crees saber, exponerse a quien piensa distinto, construir algo que pueda fallar de forma visible— porque la comodidad no corrige nada. La segunda es que conviene sostener las opiniones técnicas por su razonamiento y no por su conclusión, ya que un razonamiento se puede actualizar cuando llega evidencia nueva mientras que una conclusión sin razonamiento solo se puede defender o abandonar, y ambas cosas son formas de no aprender. Y la tercera, la más útil de todas: cuando descubras que estabas equivocado en algo que defendiste, esa es la señal de que el mecanismo funciona, no de que fallaste. El objetivo de un track como este nunca fue que memorizaras un patrón. Fue que salieras de él con un aparato de razonamiento capaz de evaluar el siguiente patrón por su cuenta, incluido el que dentro de unos años deje obsoleto todo lo que aquí se ha dado por bueno. Si has llegado hasta aquí entendiendo por qué cada pieza está donde está, y no solo dónde está, ya tienes ese aparato. El resto es usarlo.

⚔️ Construye tu propio plan
  1. Lee entera la documentación de Orbit y anota tres cosas que creías saber y estaban mal; verifica cada una en el código antes de darla por cierta.
  2. Relee la guía de arquitectura de Android separando en dos columnas lo descriptivo de lo prescriptivo, y evalúa cada prescripción contra tu contexto real.
  3. Define tus cuatro fases con entregables verificables y una fecha para cada una, y escribe qué evidencia demostrará que la fase está completa.
  4. Aplica las cuatro señales de oxidación a un área de tu conocimiento y elige la que peor puntúe; planifica su corrección con una fuente primaria.
  5. Prepara una explicación de treinta minutos sobre MVI para alguien que no lo conoce, dala de verdad y anota qué preguntas te dejaron sin respuesta.