<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="4.3.2">Jekyll</generator><link href="https://edwinabot.github.io/es/feed.xml" rel="self" type="application/atom+xml" /><link href="https://edwinabot.github.io/es/" rel="alternate" type="text/html" /><updated>2026-05-22T19:11:17+00:00</updated><id>https://edwinabot.github.io/feed.xml</id><title type="html">Edwin Alexis Abot</title><subtitle>This website is my space for leaving annotations and stuff that helped me or  had to elaborate and might prove helpful for somebody else. It might be of  interest to folks considering me for a project.</subtitle><entry xml:lang="es"><title type="html">La spec es el código</title><link href="https://edwinabot.github.io/es/2026/05/22/erebor-post-3.html" rel="alternate" type="text/html" title="La spec es el código" /><published>2026-05-22T00:00:00+00:00</published><updated>2026-05-22T00:00:00+00:00</updated><id>https://edwinabot.github.io/2026/05/22/erebor-post-3.es</id><content type="html" xml:base="https://edwinabot.github.io/2026/05/22/erebor-post-3.html"><![CDATA[<h2 id="nombrando-la-metodología">Nombrando la metodología</h2>

<p>Estuve dando vueltas alrededor de algo en estos posts sin nombrarlo directamente. El flujo de trabajo — arquitectar, delegar, revisar, aceptar — es una instancia de <strong>spec-driven development</strong>, o SDD. La afirmación central del SDD es simple: la spec es el artefacto principal. No el código. El código es una consecuencia de la spec, producido por un agente que implementa exactamente lo que la spec describe — incluyendo lo que describe mal.</p>

<p>Esa afirmación tiene consecuencias. Cambia qué es realmente la habilidad de ingeniería en este flujo de trabajo, y cambia qué prácticas existentes terminan importando.</p>

<hr />

<h2 id="la-spec-del-producto-es-lo-que-importa">La spec del producto es lo que importa</h2>

<p>En SDD la spec del producto ocupa el lugar que antes ocupaba el código. Es aquello de lo que sos dueño. Es de lo que sos responsable. Es donde viven las decisiones de diseño. Cuando algo está mal en la implementación, la primera pregunta no es “¿por qué el agente hizo eso?” — es “¿qué dejó ambiguo la spec?”</p>

<p>Esto es un trabajo más difícil de lo que suena. Escribir una spec lo suficientemente precisa como para que un agente la implemente sin adivinar es una habilidad que tardé varias semanas en empezar a desarrollar, y todavía la estoy desarrollando. La dificultad es que la ambigüedad en una spec es a menudo invisible hasta que la implementación la revela. Creías que habías sido claro. El agente entendió algo diferente. El código es la evidencia.</p>

<p>Todo lo que viene después de la spec — la calidad del código, la cobertura de tests, la limpieza arquitectónica — es función de qué tan bien fue escrita la spec.</p>

<hr />

<h2 id="clean-code-como-mecanismo-de-verificación">Clean Code como mecanismo de verificación</h2>

<p><em>Clean Code</em> solía ser sobre cómo escribir buen código. Bajo el SDD es sobre cómo verificar que la implementación realmente expresa la spec.</p>

<p>Cuando Claude Code produce una implementación, mi primera pasada de revisión es una pasada de Clean Code. ¿Los nombres son honestos? ¿La función hace una sola cosa? ¿Hay comentarios compensando lógica oscura? Estas no son preferencias estéticas — son señales diagnósticas. Una función larga con un comentario explicativo me dice que o el modelo no encontró una abstracción limpia, o la spec no restringió la interfaz con suficiente precisión como para producir una. El smell no está en el código. Es evidencia de algo que salió mal en la spec.</p>

<p>El código limpio es el mecanismo por el cual puedo decir, con confianza, que la implementación expresa fielmente lo que la spec pretendía. Cuando el código es oscuro, no puedo hacer esa afirmación. Puedo verificar que los tests pasen. No puedo verificar que lo que se está testeando es lo que fue especificado. Esa es la brecha.</p>

<p>Robert Martin escribía para equipos donde las personas que escribían el código y las que lo revisaban eran personas distintas. Resulta que esa es exactamente la situación en el SDD — excepto que el autor es un agente al que no se le pueden hacer preguntas de seguimiento. La legibilidad no es una preferencia; es el único canal a través del cual la spec y la implementación pueden compararse.</p>

<hr />

<h2 id="clean-architecture-y-el-loop-spec-arquitectura">Clean Architecture y el loop spec-arquitectura</h2>

<p>La arquitectura y la spec no tienen una secuencia limpia. No podés arquitectar completamente un producto que no fue especificado — no sabés qué necesita hacer el sistema, así que no sabés cuáles deberían ser sus límites. Pero tampoco podés especificar completamente una feature sin conocer las restricciones arquitectónicas — no sabés qué es posible, qué está prohibido, o contra qué capa estás especificando.</p>

<p>Algunas decisiones pueden venir primero. Las elecciones tecnológicas — Go para el motor principal, TypeScript para la UI, TimescaleDB para la persistencia de series temporales — son más como axiomas que como arquitectura. No requieren una spec completa del producto; requieren una comprensión del dominio del problema y un conjunto de preferencias sobre herramientas. Podés fijarlas temprano y construir desde ahí.</p>

<p>Pero las decisiones más profundas — cómo se dividen las capas, dónde se ubican los límites, cuáles son las reglas de dependencia — esas emergen del producto. Necesitás saber que estás ingiriendo diffs del libro de órdenes a alta frecuencia antes de poder decidir que la capa WebSocket no debe llegar a la capa de persistencia. Necesitás saber que múltiples símbolos corren concurrentemente antes de poder diseñar la arquitectura de dispatch interno. La spec revela lo que la arquitectura debe acomodar. La arquitectura revela lo que la spec puede demandar con precisión.</p>

<p>Lo que Clean Architecture aporta al SDD es disciplina sobre este feedback loop. A medida que la spec y la arquitectura co-evolucionan, las reglas de Clean Architecture — abstracciones estables, dependencias acíclicas, definiciones claras de límites — mantienen ambos lados coherentes. Sin esa disciplina, el loop produce capas enredadas imposibles de especificar limpiamente. Con ella, el loop eventualmente se estabiliza: el producto está lo suficientemente comprendido, los límites están lo suficientemente claros, y llegás al momento de delegación con algo preciso contra lo que escribir una spec.</p>

<p>El ADR es donde ese loop se cierra. Es el registro de las decisiones que estabilizaron el feedback — no las primeras decisiones tomadas, sino las que se sostuvieron.</p>

<hr />

<h2 id="lean-y-la-paradoja-del-recién-llegado">Lean y la paradoja del recién llegado</h2>

<p>El Lean Software Development tiene un principio al que sigo volviendo: decidir lo más tarde posible. No comprometerse con una decisión irreversible hasta que sea necesario. Diferir hasta el último momento responsable, cuando la información necesaria para decidir bien ha tenido tiempo de acumularse.</p>

<p>Todavía estoy trabajando cómo aplicar esto al SDD. Hay una situación específica que vengo llamando la Paradoja del Recién Llegado desde el post anterior — la tentación de seguir definiendo specs e inmediatamente dárselas a Claude para implementar. La velocidad es real. El volumen de lo que podés construir en una sesión está más allá de lo que experimenté antes. Y a veces tengo que resistir activamente la tentación de simplemente generar lo siguiente.</p>

<p>El principio Lean es el contrapeso. No toda decisión necesita una spec hoy. No toda spec necesita una implementación en esta sesión. Algo de lo que estoy tentado de generar ahora se beneficiaría de dejarlo reposar un día — de preguntarme qué todavía no sé antes de escribir lo que creo que sí sé.</p>

<p>El principio de eliminar el desperdicio corta en la otra dirección. El exceso de especificación también es desperdicio. Un prompt de delegación que especifica lo que el agente habría hecho bien de todas formas es ruido que aumenta la probabilidad de malinterpretación. La spec debe ser exactamente tan larga como para ser inequívoca, y no más.</p>

<hr />

<h2 id="qué-pasa-cuando-corrés-agentes-en-paralelo">Qué pasa cuando corrés agentes en paralelo</h2>

<p>La pregunta de la velocidad tiene una segunda dimensión que todavía no describí: el paralelismo.</p>

<p>Durante las primeras semanas de Erebor, estaba corriendo Claude Code en forma secuencial — una spec, una sesión de implementación, una revisión. Eso ya es rápido. Pero Claude Code soporta worktrees aislados, lo que significa que podés correr múltiples agentes simultáneamente, cada uno en una rama separada, cada uno implementando una spec diferente, sin que interfieran entre sí. Las ramas se mantienen limpias. Las revisiones se mantienen independientes.</p>

<p>Estuve coordinando estas sesiones en Warp. Múltiples paneles, cada uno corriendo una sesión de Claude Code en su propio worktree. Escribís dos o tres specs a la mañana, levantás los worktrees, lanzás agentes en los paneles, y los dejás correr. Después revisás cada uno por turno. La fase de implementación — que antes serializaba todo — se vuelve paralela. El cuello de botella se desplaza completamente hacia la revisión y la calidad de la spec, que es donde debería estar.</p>

<p>Lo que esto produce es una experiencia diferente del tiempo en un proyecto. La pregunta deja de ser “¿cuándo va a estar lista esta feature?” y pasa a ser “¿cuántas specs puedo sostener con suficiente claridad en mi cabeza para correr en paralelo y revisar con precisión?” Esa es una pregunta cognitiva, no de planificación. Todavía no encontré el techo. Tres sesiones en paralelo se siente sostenible. Cuatro es posible si las specs son relativamente independientes. Más que eso y la calidad de la revisión empieza a degradarse, lo cual derrota el propósito.</p>

<p>Vale la pena nombrar Warp específicamente acá porque su gestión de sesiones y su layout de paneles hacen que esta coordinación sea práctica en lugar de solo teóricamente posible. Cada panel tiene contexto. Podés scrollear hacia atrás, correr comandos junto a la salida del agente, y cambiar entre sesiones sin perder estado. No es una feature revolucionaria, pero el flujo de trabajo se rompe sin ella.</p>

<hr />

<h2 id="lo-que-no-puedo-creer">Lo que no puedo creer</h2>

<p>Describir lo que se siente combinar herramientas a este nivel es difícil sin sonar hiperbólico, pero lo intento.</p>

<p>Kiro agrega otra dimensión — orquestación agéntica a nivel de IDE que va más allá de lo que Claude Code maneja solo. Las capacidades de IA de Figma están por delante de mí en la capa del dashboard que todavía no construí. Lo que sé por los experimentos tempranos es que hay un umbral donde las herramientas dejan de sentirse como aceleración y empiezan a sentirse como algo cualitativamente diferente. La comparación no es “trabajar más rápido.” Se parece más a “operar a una escala diferente.” Más cosas en vuelo, más decisiones ejecutándose en paralelo, más superficie bajo desarrollo en cualquier momento dado.</p>

<p>La restricción que queda es la que siempre permanece: la spec. Todo lo demás está aguas abajo de si la spec fue escrita bien.</p>

<hr />

<h2 id="los-fundamentos-y-la-nueva-pregunta">Los fundamentos y la nueva pregunta</h2>

<p>Los fundamentos no importan menos bajo el SDD. Los principios de Clean Code son los criterios para revisar el output generado por IA. Clean Architecture es el prerequisito para escribir software especificable. Los principios Lean son la guía para cuándo especificar y cuándo esperar.</p>

<p>El cambio está en para qué son estas prácticas. Fueron diseñadas para un mundo donde los ingenieros escribían el código. Resultan ser exactamente lo que necesitás en un mundo donde lo revisás, lo especificás, y decidís cuándo está listo — y un agente lo produce.</p>

<p>La nueva pregunta que están respondiendo no es “¿cómo escribo mejor código?” Es “¿cómo escribo mejores specs?”</p>

<hr />

<p><em>Edwin Alexis Abot — Mayo de 2026</em></p>]]></content><author><name></name></author><category term="agentic-ai" /><category term="software-engineering" /><category term="spec-driven-development" /><category term="side-projects" /><summary type="html"><![CDATA[Nombrando la metodología]]></summary></entry><entry xml:lang="es"><title type="html">Cuando conocés la spec pero no el código</title><link href="https://edwinabot.github.io/es/2026/05/11/erebor-post-2.html" rel="alternate" type="text/html" title="Cuando conocés la spec pero no el código" /><published>2026-05-11T00:00:00+00:00</published><updated>2026-05-11T00:00:00+00:00</updated><id>https://edwinabot.github.io/2026/05/11/erebor-post-2.es</id><content type="html" xml:base="https://edwinabot.github.io/2026/05/11/erebor-post-2.html"><![CDATA[<p>En el <a href="/es/2026/04/27/erebor-post-1.html">primer post</a> describí el flujo de trabajo al que me estoy comprometiendo para Erebor: arquitectar, delegar, revisar, aceptar. Dije que el siguiente post iba a ser sobre el servicio de ingestión del libro de órdenes — cómo era la spec, qué produjo Claude Code, y qué tuve que cuestionarle.</p>

<p>Este es ese post. Fueron entre 8 y 10 horas de trabajo real distribuidas en varios días. <a href="https://github.com/edwinabot/erebor/pull/1">El PR</a> terminó con 4.893 líneas agregadas en 36 archivos — un servicio Go completo, esquema de base de datos, configuración Docker, pipeline de CI y suite de tests. Acá va lo que pasó en realidad.</p>

<hr />

<h2 id="empezar-desde-una-spec-no-desde-una-tarea">Empezar desde una spec, no desde una tarea</h2>

<p>Antes de abrir Claude Code, tuve dos conversaciones con Claude para preparar el trabajo de implementación. La primera produjo el <a href="https://github.com/edwinabot/erebor/blob/main/adrs/ADR-001-order-book-ingestion/ADR-001-order-book-ingestion.md">ADR-001</a>. Las decisiones de arquitectura son mías — yo hice la investigación, evalué las opciones y tomé las decisiones. Lo que aportó Claude fue organizar y componer el manuscrito: convertir mis decisiones y notas en un documento estructurado y legible. El ADR cubre cinco decisiones: persistencia híbrida (diffs crudos más checkpoints periódicos), TimescaleDB como capa de almacenamiento, un stream WebSocket combinado con dispatch interno, <code class="language-plaintext highlighter-rouge">shopspring/decimal</code> para toda la aritmética financiera, y un límite de profundidad configurable por símbolo.</p>

<p>La segunda conversación produjo el <a href="https://github.com/edwinabot/erebor/blob/main/adrs/ADR-001-order-book-ingestion/CODE-REVIEW-CHECKLIST-001.md">checklist de code review</a>. Ocho secciones: corrección, integridad de interfaces, seguridad, comportamiento operacional, esquema de persistencia, cobertura de tests y calidad de código. El checklist existe porque revisar código generado por IA sin un contrato previo es un ejercicio de adivinación. El contrato tiene que venir primero.</p>

<p>Después escribí el prompt de delegación — un documento que desde entonces guardé como <a href="https://github.com/edwinabot/erebor/blob/main/adrs/ADR-001-order-book-ingestion/DELEGATION-PROMPTS-001.md">DELEGATION-PROMPTS-001.md</a>. Tiene varios cientos de palabras, incluye firmas exactas de interfaces, tipos de dominio exactos, condiciones exactas de alineación del bootstrap, y una lista de cosas que explícitamente no hay que construir. Esta es la spec que recibió Claude Code.</p>

<hr />

<h2 id="el-código-funcionó-el-sistema-no">El código funcionó. El sistema, no.</h2>

<p>Después del prompt inicial, Claude Code produjo una implementación sustancial. Todos los tests pasaban. El código Go compilaba limpiamente. Y entonces intenté ejecutarlo de verdad.</p>

<p>No se podía ejecutar. La configuración de los contenedores estaba mal, las migraciones no se estaban aplicando, la integración entre el CLI y la base de datos en ejecución no estaba cableada correctamente. Los tests estaban en verde porque probaban las unidades en aislamiento — lo que estaba roto era todo lo que las rodeaba. Esto requirió varias rondas adicionales de prompts para resolver, incluyendo uno focalizado para agregar Docker Compose para una instancia local de TimescaleDB y un comando CLI para pruebas de integración contra ella.</p>

<p>Esta fue una lección útil sobre la brecha entre la corrección a nivel de unidad y la ejecutabilidad a nivel de sistema. Que los tests pasen no es lo mismo que que el software funcione. La spec había cubierto el protocolo de bootstrap con un detalle exhaustivo y no decía casi nada sobre la ejecución local. Esa omisión fue mía, y el agente entregó exactamente lo que estaba descripto.</p>

<hr />

<h2 id="la-paradoja-del-recién-llegado">La paradoja del recién llegado</h2>

<p>Una vez que tuve algo funcionando, me topé con algo que no esperaba.</p>

<p>Me sentí como un recién llegado al proyecto.</p>

<p>No de manera confusa — había escrito la spec del producto, y había tomado cada decisión de arquitectura en el ADR. Son cosas distintas: la spec define qué construir; el ADR define los guardrails y las restricciones de implementación que determinan cómo la spec puede ejecutarse. Ambas eran mías, y ambas me tenían todo el sentido. Pero en los primeros diez o quince minutos después de que Claude terminó de generar el código, no podía conectar inmediatamente lo que estaba leyendo con ninguna de las dos. El código era correcto, los nombres eran razonables, la estructura seguía el diseño. Y aun así sentí la fricción específica de llegar a una codebase en curso sin haber estado presente durante la implementación.</p>

<p>Esta es la paradoja: tenía dos capas de documentación — la spec del producto y las restricciones de arquitectura — y aun así me sentí como un recién llegado al código que las implementaba. El código no es la spec, aunque el código implemente fielmente la spec.</p>

<p>Los Engineering Managers que no son tan hands-on van a reconocer esta sensación. Son dueños del roadmap, aprobaron la arquitectura, saben exactamente por qué se tomó cada decisión — y después se sientan con la codebase y se pierden. No es ignorancia del dominio. Es la brecha entre el mapa y el territorio. Yo fui ese EM. Esto fue un recordatorio de lo que esa brecha se siente de verdad desde adentro.</p>

<p>Pensé en el capítulo de Robert Martin sobre comentarios en <em>Clean Code</em>. Todavía tiene razón. Le pedí a Claude que agregara docstrings a todos los símbolos exportados — métodos, structs, interfaces. Eso hizo una diferencia inmediata. No porque los nombres estuvieran mal, sino porque la intención detrás de cada componente se volvió explícita en el lugar donde la necesitaba, en vez de obligarme a rastrear de vuelta hacia el ADR.</p>

<hr />

<h2 id="aprendiendo-goroutines-siendo-un-desarrollador-de-python">Aprendiendo goroutines siendo un desarrollador de Python</h2>

<p>Un efecto secundario inesperado de trabajar con cuidado este código fue aprender más sobre goroutines de lo que había aprendido antes.</p>

<p>Mi background es Python. Entiendo los procesos y los threads de la vieja escuela, y en los últimos años trabajé bastante con asyncio. Las goroutines son un modelo diferente — conceptualmente entre los threads y las corrutinas, pero con un scheduler en el runtime que las hace sentir más livianas y componibles que cualquiera de los dos. Trabajar a través del procedimiento de bootstrap del <code class="language-plaintext highlighter-rouge">SymbolHandler</code>, donde el fetch del snapshot corre concurrentemente con el buffer de diffs y los dos tienen que unirse de manera segura, ayudó a que las goroutines se sintieran concretas en lugar de abstractas. Son genuinamente elegantes para este tipo de problema.</p>

<hr />

<h2 id="qlty-y-el-costo-de-la-complejidad-cognitiva">Qlty y el costo de la complejidad cognitiva</h2>

<p>Le pedí a Claude que agregara configuración de Qlty CLI al proyecto. Qlty ejecutó <code class="language-plaintext highlighter-rouge">golangci-lint</code> y su propio análisis y devolvió una lista de hallazgos. Después le pedí a Claude que los abordara.</p>

<p>Las reducciones de complejidad cognitiva fueron significativas. Varias funciones en el <code class="language-plaintext highlighter-rouge">SymbolHandler</code> tenían puntajes de complejidad que eran Go técnicamente válido pero difícil de leer — condicionales profundamente anidadas dentro de las transiciones de la máquina de estados. El refactoring que Qlty empujó produjo código más limpio sin cambiar el comportamiento. No los hubiera detectado todos en la revisión.</p>

<hr />

<h2 id="los-tests-como-documentación-y-sus-límites">Los tests como documentación, y sus límites</h2>

<p>Tenía poca cobertura de tests después de la implementación inicial. Ejecuté Codecov y lo confirmó. Reprompeé en etapas: primero para tests del happy path en todos los paquetes, después para los caminos de ejecución faltantes, y después específicamente para comentar cada test sin comentar explicando la funcionalidad siendo testeada.</p>

<p>El último prompt fue el que más valor aportó. Llevo años diciendo que los tests son gran documentación. Y lo son — pero solo cuando tengo tiempo de leerlos con cuidado. Lo que en realidad necesitaba era que los tests se explicaran a sí mismos sin requerir ese tiempo de estudio. El prompt “comentá todos los tests sin comentar explicando la funcionalidad siendo testeada” entregó exactamente eso.</p>

<p>Me tomé el tiempo de verificar que los comentarios fueran precisos — que la explicación coincidiera con las aserciones del test. Coincidían. Después de hacer eso, pude explicar cómo funciona el servicio de ingestión, de punta a punta, con confianza. Esa confianza vino de los tests comentados, no del código en sí.</p>

<hr />

<h2 id="dónde-están-las-cosas">Dónde están las cosas</h2>

<p>El <a href="https://github.com/edwinabot/erebor/pull/1">PR</a> está mergeado. El servicio ingesta datos del libro de órdenes desde Binance, persiste diffs crudos y checkpoints periódicos en TimescaleDB, implementa el protocolo de sincronización de bootstrap especificado en el ADR-001, y hace un shutdown gracioso ante SIGTERM y SIGINT.</p>

<p>El próximo paso es ejecutar esto en hardware dedicado. Compré una máquina que voy a usar como servidor — es más barato que la nube en esta etapa y me da más runway para experimentar con infraestructura de contenedores antes de compreterme con una topología. El próximo post va a cubrir eso: hardware local, deployment basado en Docker, y la primera corrida de recolección de datos continua.</p>

<p>Entre 8 y 10 horas de trabajo. Diecinueve commits. Una cosa más que sé cómo construir.</p>

<hr />

<p><em>Edwin Alexis Abot — Mayo de 2026</em></p>]]></content><author><name></name></author><category term="agentic-ai" /><category term="software-engineering" /><category term="go" /><category term="side-projects" /><summary type="html"><![CDATA[En el primer post describí el flujo de trabajo al que me estoy comprometiendo para Erebor: arquitectar, delegar, revisar, aceptar. Dije que el siguiente post iba a ser sobre el servicio de ingestión del libro de órdenes — cómo era la spec, qué produjo Claude Code, y qué tuve que cuestionarle.]]></summary></entry><entry xml:lang="es"><title type="html">Por qué estoy construyendo un sistema de trading sin escribir la mayor parte del código</title><link href="https://edwinabot.github.io/es/2026/04/27/erebor-post-1.html" rel="alternate" type="text/html" title="Por qué estoy construyendo un sistema de trading sin escribir la mayor parte del código" /><published>2026-04-27T00:00:00+00:00</published><updated>2026-04-27T00:00:00+00:00</updated><id>https://edwinabot.github.io/2026/04/27/erebor-post-1.es</id><content type="html" xml:base="https://edwinabot.github.io/2026/04/27/erebor-post-1.html"><![CDATA[<p>Tengo más de trece años en desarrollo de software, principalmente backend. Escribí mucho código. Y hace un tiempo que vengo dándole vueltas a una idea incómoda: creo que los días del código artesanal, como medida principal del valor de un ingeniero, están terminando.</p>

<p>Este post es sobre un side project que recién empecé — Erebor, una solución de trading de microestructura de alta frecuencia para Binance, enfocada exclusivamente en datos de Level 2 del libro de órdenes. Pero en realidad va de otra cosa: un intento deliberado de pasar de ser alguien que escribe software a alguien que dirige agentes que escriben software. Un arquitecto. Un líder técnico. Un guardián de la calidad.</p>

<p>Quiero ser transparente sobre todo el proceso, incluyendo cómo arrancó este proyecto.</p>

<hr />

<h2 id="una-preocupación-que-viene-gestándose-hace-rato">Una preocupación que viene gestándose hace rato</h2>

<p>Esto no apareció de la nada. La primera vez que vi a un modelo producir código realmente de calidad de producción —no un fragmento, no un ejemplo de juguete, sino algo que efectivamente publicarías— algo cambió. Empecé a tener la misma conversación una y otra vez: con colegas de la empresa donde trabajo hoy, con gente de afuera, tomando un café, por Slack, a veces simplemente conmigo mismo en el viaje al trabajo.</p>

<p>La conversación siempre va por el mismo camino. Alguien menciona un post que leyó —ya hay muchos— argumentando que el código artesanal como modo por defecto de la ingeniería está terminado. Algunos van más lejos y predicen que dentro de diez años el ingeniero senior típico no escribirá demasiado código. Va a supervisar agentes que lo escriben. Las respuestas en estas conversaciones van desde el rechazo hasta la ansiedad y el acuerdo cauteloso. Yo aterricé en el acuerdo cauteloso, con un agregado: si para allá vamos, prefiero practicar el rol nuevo deliberadamente y no llegar a él de casualidad.</p>

<p>Erebor es esa práctica.</p>

<hr />

<h2 id="cómo-empezó-erebor--en-una-conversación-de-planificación-con-claude">Cómo empezó Erebor — en una conversación de planificación con Claude</h2>

<p>No abrí un editor de código para arrancar este proyecto. Abrí una conversación con Claude.</p>

<p>Le describí lo que quería construir y lo que quería sacar de eso. Lo que volvió no fue solo una lista de tareas. Fue una hoja de ruta estructurada de 6 meses, con fases, hitos, un ritmo semanal sugerido y —cuando seguí presionando— un replanteo que yo no había articulado del todo.</p>

<p>En algún momento de esa conversación dije algo como: <em>este proyecto también es mi entrenamiento para hacer la transición de programar a supervisar agentes</em>. Y la respuesta me ayudó a ver que esto no era un objetivo secundario. Era el primario. El sistema de trading es el vehículo. El verdadero destino es aprender a operar como arquitecto en un mundo donde los agentes hacen la implementación.</p>

<p>Estoy documentando esa conversación como parte del registro del proyecto. No porque usar una herramienta de planificación con IA sea remarcable —no lo es, en 2026— sino porque creo que la <em>honestidad</em> de esa conversación importa. No estaba actuando una visión. La estaba elaborando.</p>

<hr />

<h2 id="qué-es-erebor-en-realidad">Qué es Erebor en realidad</h2>

<p>Erebor es una solución de trading de alta frecuencia con un foco angosto: datos de Level 2 del libro de órdenes de Binance. Sin análisis de sentimiento, sin predicción de precios con ML, sin ruido. Solo microestructura — desbalance del libro de órdenes, dinámica de spreads, detección de órdenes grandes, las señales que viven en la forma del mercado antes de que ocurra una operación.</p>

<p>El stack es Go para el motor principal, TypeScript y Next.js para el dashboard y la UI de estrategias, con prácticas de DevSecOps integradas desde el día uno —no atornilladas al final—. Tengo la certificación CSSLP y parte de lo que quiero demostrar es que la ingeniería segura es una postura, no una fase. El proyecto dura seis meses y termina con un harness de backtesting funcionando y un loop de paper trading contra el Testnet de Binance.</p>

<hr />

<h2 id="lo-que-en-realidad-estoy-entrenando">Lo que en realidad estoy entrenando</h2>

<p>Acá viene la parte incómoda de decirla en limpio: no estoy construyendo Erebor para mostrar que puedo escribir Go o TypeScript. Lo estoy construyendo para mostrar que no necesito hacerlo.</p>

<p>Lo que quiero decir es esto. El flujo de trabajo al que me estoy comprometiendo para cada feature se ve así:</p>

<ol>
  <li><strong>Arquitectar</strong> — definir la interfaz, el contrato, los criterios de aceptación, los casos límite. Todavía no hay código. Esto es la spec.</li>
  <li><strong>Delegar</strong> — entregarle la spec a Claude Code. Dejar que implemente el módulo con tests.</li>
  <li><strong>Revisar</strong> — leer el output como un revisor senior. Cuestionar las decisiones de diseño. Rechazar y reprompar si la abstracción está mal, el patrón es inseguro, o la suposición de performance es ingenua.</li>
  <li><strong>Aceptar y documentar</strong> — mergear. Escribir un Architecture Decision Record para las decisiones no triviales.</li>
</ol>

<p>La spec es mi artefacto. El ADR es mi artefacto. La revisión es mi artefacto. El agente escribió el archivo Go.</p>

<p>Esto es lo que un líder técnico hace de verdad — solo que tradicionalmente hay un equipo de ingenieros donde está el agente. La transición que estoy haciendo es aprender a hacer ese trabajo con un colaborador muy rápido, muy capaz y muy literal. Y “muy literal” es la palabra clave. Los agentes implementan exactamente lo que les describiste — incluyendo las partes que describiste mal. La habilidad más difícil en este flujo no es promptear. Es escribir una spec lo suficientemente precisa como para que no haya espacio para una interpretación incorrecta.</p>

<p>Estas son habilidades de arquitecto. Las quiero practicar con cada commit.</p>

<hr />

<h2 id="por-qué-escribo-sobre-esto">Por qué escribo sobre esto</h2>

<p>Mi sitio en GitHub Pages es, como yo mismo lo describí, un lugar para anotaciones — cosas que tuve que resolver y que podrían serle útiles a alguien más. Este proyecto encaja exactamente en esa descripción.</p>

<p>Escribo sobre Erebor porque creo que esta transición —de implementador a arquitecto, de escribir código a dirigir agentes— es una que muchos ingenieros con experiencia están enfrentando y de la que no se está hablando con claridad. Hay mucho contenido sobre cómo las herramientas de IA hacen a los desarrolladores más productivos. Hay bastante menos sobre lo que realmente significa <em>cambiar tu rol</em> en respuesta a lo que estas herramientas pueden hacer.</p>

<p>Voy a estar posteando a lo largo del proyecto. No solo las victorias. Los rechazos, los re-prompts, los momentos en los que el agente produjo algo que parecía bien y no lo estaba. Las specs que estaban demasiado vagas. Las revisiones que detectaron algo sutil.</p>

<p>Si sos un ingeniero senior preguntándote si el camino de arquitecto / TL tiene sentido para vos en este contexto, espero que esto te resulte útil. Si me estás considerando para un proyecto — así es como pienso y como trabajo.</p>

<p>El proyecto es <a href="https://github.com/users/edwinabot/projects/3">Erebor en GitHub</a> y acá está el <a href="https://github.com/edwinabot/erebor">repo de erebor</a>. El próximo post va a ser sobre la construcción del servicio de ingestión del libro de órdenes en Go — específicamente cómo era la spec, qué produjo Claude Code, y qué tuve que cuestionarle.</p>

<p>Todavía no sé cuánto de la transición de rol va a sentirse natural y cuánto va a sentirse como pérdida. Probablemente las dos cosas. Eso también vale la pena escribirlo.</p>

<hr />

<p><em>Edwin Alexis Abot — Abril de 2026</em></p>]]></content><author><name></name></author><category term="agentic-ai" /><category term="software-engineering" /><category term="career" /><category term="side-projects" /><summary type="html"><![CDATA[Tengo más de trece años en desarrollo de software, principalmente backend. Escribí mucho código. Y hace un tiempo que vengo dándole vueltas a una idea incómoda: creo que los días del código artesanal, como medida principal del valor de un ingeniero, están terminando.]]></summary></entry><entry xml:lang="es"><title type="html">Revisiones de código efectivas y eficientes</title><link href="https://edwinabot.github.io/es/good-practices/2023/05/15/pull-requests-code-reviews.html" rel="alternate" type="text/html" title="Revisiones de código efectivas y eficientes" /><published>2023-05-15T11:03:00+00:00</published><updated>2023-05-15T11:03:00+00:00</updated><id>https://edwinabot.github.io/good-practices/2023/05/15/pull-requests-code-reviews.es</id><content type="html" xml:base="https://edwinabot.github.io/good-practices/2023/05/15/pull-requests-code-reviews.html"><![CDATA[<p>En todos los proyectos en los que participé, observé variaciones de los mismos desperdiciadores de tiempo y de sus efectos sobre el equipo durante el proceso de revisión de código. En este post voy a recopilarlos, explicarlos brevemente junto con sus efectos secundarios, y describir prácticas que fomenté e implementé cuando fue posible.</p>

<p>Empiezo resumiendo un proceso de code review:</p>

<blockquote>
  <p>Después de trabajar en una nueva feature o de arreglar un bug, le pedimos a nuestros pares que revisen nuestro trabajo abriendo un pull request.
La mayor parte del tiempo, nuestra colaboración cumple los criterios de calidad del equipo, pero a veces no. Entramos en debates, recibimos feedback y hacemos ajustes. <strong>Eventualmente</strong>, nuestro código pasa la revisión y se libera a producción.</p>
</blockquote>

<p>Vi que las revisiones de código son valiosas para mejorar la calidad del código e identificar problemas potenciales. Sin embargo, hay <strong>desperdiciadores de tiempo</strong> específicos que pueden afectar la efectividad y eficiencia de las revisiones, impactando directamente en los tiempos de entrega y en la moral del equipo. Tuve la oportunidad de levantar estos desperdiciadores como issues en muchas reuniones de retrospectiva y de colaborar en su mitigación.</p>

<h2 id="desperdiciadores-de-tiempo">Desperdiciadores de tiempo</h2>

<p>Sin un orden particular, estos son los principales desperdiciadores de tiempo durante las revisiones de código:</p>

<p><strong>Falta de claridad en el envío del código:</strong> Cuando el envío no es claro o le falta contexto suficiente, los revisores pueden gastar una cantidad de tiempo poco razonable tratando de entender el propósito del código o cómo encaja en el sistema del que forma parte. Explicaciones claras y concisas que acompañen al código ayudan a reducir esa pérdida de tiempo.</p>

<p><strong>Changesets grandes o demasiado complejos:</strong> Revisar changesets grandes o código complejo puede consumir mucho tiempo. Dividir los cambios en piezas más chicas y manejables ayuda a los revisores a enfocarse en áreas específicas y a dar feedback más certero.</p>

<p><strong>Documentación incompleta o ausente:</strong> Documentación insuficiente dentro de la base de código puede llevar a los revisores a dedicar tiempo extra descifrando la funcionalidad o intención del código. Código bien documentado y comentarios breves ayudan a los revisores a entender el código más rápido y a dar feedback más relevante.</p>

<p><strong>Falta de adherencia a los estándares de código:</strong> Código que se aparta de los estándares establecidos o de las buenas prácticas puede llevar a discusiones y debates largos durante las revisiones. Adherir consistentemente a las pautas acordadas minimiza este desperdicio.</p>

<p><strong>Discusiones excesivas de ida y vuelta:</strong> Si las revisiones se vuelven debates largos sin resoluciones claras, consumen tiempo valioso. Promover discusiones concisas y enfocadas, fijar un límite de tiempo, o involucrar a un mediador ayuda a evitar idas y vueltas excesivos.</p>

<p><strong>Comentarios no accionables o subjetivos:</strong> Comentarios vagos o subjetivos pueden generar confusión y pedidos adicionales de aclaración, ralentizando el proceso de revisión. Los revisores deben dar feedback específico y accionable, sugiriendo mejoras concretas o señalando problemas potenciales.</p>

<p><strong>Sobrecarga de revisores:</strong> Si un grupo chico de revisores ya saturado con otras tareas también es asignado a code review, se generan demoras y backlogs. Distribuir la carga entre varios revisores o adoptar un sistema de rotación previene el burnout y acelera el proceso.</p>

<p><strong>Falta de herramientas y chequeos automatizados:</strong> La inspección manual de cada línea de código consume tiempo y es propensa a errores. Herramientas automáticas, como análisis estático o linters, ayudan a detectar problemas comunes y reducen el esfuerzo manual durante la revisión.</p>

<p>Más adelante voy a describir un conjunto de prácticas que evitaron, si no por completo, en gran medida los efectos de estos desperdiciadores. La mayoría fueron listadas como action items en retrospectivas y adoptadas después.</p>

<h2 id="impacto-de-los-desperdiciadores-en-la-moral-del-equipo">Impacto de los desperdiciadores en la moral del equipo</h2>

<p>Como decía antes, discutí estos desperdiciadores en retrospectivas, lo que me permitió hablar de los sentimientos a su alrededor y de cómo nos sentíamos mis compañeros y yo. Nos permitió analizar el impacto en el equipo y en nuestra capacidad de entrega.</p>

<p><strong>Frustración y desmotivación:</strong> Algunos miembros del equipo se frustran con el proceso cuando las revisiones se vuelven costosas en tiempo por distintas ineficiencias. La sensación de estar perdiendo tiempo en una actividad improductiva los desmotivó y les bajó el entusiasmo por participar en code reviews.</p>

<p><strong>Productividad disminuida:</strong> Tiempo excesivo en revisiones le quita tiempo y energía necesarios para otras tareas esenciales como programar o monitorear. Lleva a demoras en los timelines del proyecto y a una caída en la productividad, impactando la capacidad del equipo de entregar resultados eficientemente.</p>

<p><strong>Falta de compromiso y participación:</strong> Los miembros del equipo se desconectan gradualmente si las revisiones son consistentemente largas e improductivas. Las perciben como una carga más que como una oportunidad valiosa de colaboración. Esa desconexión resulta en menos personas participando activamente, lo que reduce la diversidad de perspectivas y la efectividad general del proceso.</p>

<p><strong>Tensión y conflicto:</strong> Debates prolongados o discusiones sin resolver durante las revisiones generaron tensión en el equipo. Desacuerdos sobre cuestiones subjetivas o nitpicking excesivo llevaron a conflictos interpersonales, dañando la dinámica del equipo y su moral. Crearon un clima hostil durante las revisiones, desalentando la comunicación abierta y la colaboración.</p>

<p><strong>Calidad y orgullo en el trabajo:</strong> las revisiones no identificaron y abordaron problemas con efectividad; pasar por alto esos problemas permitió mergear código de menor calidad. Eso erosionó el sentido de orgullo del equipo en su trabajo, y lo percibieron como que los estándares de calidad de la entrega estaban comprometidos. Una caída en la calidad del código también lleva a más esfuerzo de mantenimiento y a problemas potenciales.</p>

<p><strong>Retención y rotación:</strong> Frustraciones prolongadas y desconexión derivadas de los desperdiciadores en las revisiones contribuyeron a una baja moral y, en última instancia, impactaron la retención. Algunos compañeros empezaron a buscar oportunidades en otro lado tras sentirse consistentemente improductivos y perdiendo el tiempo.</p>

<h2 id="optimizando-la-eficiencia-de-las-revisiones">Optimizando la eficiencia de las revisiones</h2>

<blockquote>
  <p><em>TL;DR: la eficiencia es una cuestión de voluntad.</em></p>
</blockquote>

<p>Lo que quiero decir con esa frase es que, no importa qué nivel de automatización tenga tu proceso de code review, el eslabón más débil de la cadena es la voluntad de las personas para hacer las cosas con consciencia y a fondo. Esa debilidad vive en quienes programan y en quienes revisan.</p>

<p>Podemos reducir el desperdicio al mínimo siendo conscientes de nuestro uso del tiempo y del tiempo de los demás. Pensar: “voy a hacer todo lo que pueda para que Jane me dé feedback accionable en el menor tiempo posible”, o “primero, me voy a asegurar de entender en qué está trabajando John”, son buenos puntos de partida que pueden guiar nuestras acciones como colaboradores.</p>

<p>La idea de fondo es que queremos ahorrarnos tiempo, y ahorrárselo a otros, para disfrutar de otras actividades. Ser eficiente y efectivo en el trabajo nos ahorra tiempo, y ser eficiente se vuelve esencial cuando pasamos el tiempo de nuestras vidas trabajando, literalmente. Así que aprovechemos mejor nuestro tiempo y no desperdiciemos el de los demás.</p>

<p>Te comparto un conjunto de buenas prácticas que recopilé con el tiempo y que te van a ayudar a ser más eficiente como revisor y como autor.</p>

<h3 id="buenas-prácticas-para-el-autor-del-pr">Buenas prácticas para el autor del PR</h3>

<blockquote>
  <p><em>TL;DR: dá contexto y acotá el alcance.</em></p>
</blockquote>

<p>La estrategia es maximizar la salida de los revisores, minimizando el tiempo que necesitan para revisar el código. Se trata de acotar el alcance y de dar contexto. La táctica es usar estas prácticas recomendadas:</p>

<p><strong>Dale al PR un título corto y significativo:</strong> el título suele ser la primera impresión, y las primeras impresiones importan. Acá es donde le entregás al revisor la primera pieza de contexto.</p>

<p><strong>Escribí una descripción corta y bien organizada del PR:</strong> si tu equipo todavía no tiene una plantilla de PR, podés empezar a llenar la descripción respondiendo tres preguntas simples: ¿Qué? ¿Por qué? ¿Cómo? Estás explicando qué estás haciendo, por qué lo estás haciendo y cómo lo hiciste. Proponele al equipo una plantilla de PR para futuras colaboraciones.</p>

<p><strong>Seguí las convenciones:</strong> asegurate de seguirlas. Tu comunidad fomenta convenciones porque demostraron su valor en miles de proyectos. Las podés ver como estándares; los estándares hacen que producir y comunicar sea más fácil. Habrá un momento en que vas a tener que ser creativo porque no te están ayudando, pero la mayor parte del tiempo son suficientes.</p>

<p><strong>Mantené los PR por debajo de 400 líneas de código (LOC):</strong> esto es bueno por dos razones. Primero, porque la atención del revisor es limitada: cuanto más código tenga que leer, más se le debilita la atención con el tiempo, así que mantenelo corto o partilo. Segundo, densidad de errores: encontrar un error en demasiado código es como encontrar una aguja en un pajar, así que si hay mucho código y hay errores, va a ser más difícil detectarlos por el solo volumen de cosas a analizar.</p>

<p><strong>PRs atómicos:</strong> resolvé un problema a la vez; tu PR debería atender uno y solo un asunto. Podés dividir una feature en varias piezas y combinarlas más adelante en la rama de la feature. Un bug suele requerir un solo PR, salvo que se distribuya en varios repositorios.</p>

<p><strong>Anotá tu código:</strong> el código fuente es para humanos, no para máquinas, así que hacé que leerlo sea una buena experiencia. Va a haber piezas difíciles de seguir; lo vi sobre todo cuando se expresan reglas de negocio complejas, así que agregar comentarios para dar contexto es bueno. Pensá también en el vos del futuro o en un colega que llegue a este pedazo de código a refactorizarlo. ¿No es lindo recibir el contexto que llevó a esta implementación?</p>

<p><strong>Escribí tests:</strong> escribir tests es la mejor práctica; no puedo enfatizarlo lo suficiente; es la práctica de codificación que todas las buenas prácticas quieren ser. En el contexto de un code review, los tests le explican al revisor el comportamiento de tu código; también muestran qué tan profundamente pensaste el código que escribiste. Son, además, otra forma de documentación.</p>

<h3 id="buenas-prácticas-para-el-revisor">Buenas prácticas para el revisor</h3>

<blockquote>
  <p><em>TL;DR: conseguí los requisitos, sé minucioso y dá feedback accionable.</em></p>
</blockquote>

<p>Como revisor, es tu responsabilidad asegurar que la calidad de la entrega sea buena. Es enriquecedor para todos si te esforzás por analizar el código con una actitud reflexiva, paciencia y un espíritu de escepticismo sano. Siempre podés buscar aprender y criticar constructivamente la colaboración de otros. Para hacerlo, te recomiendo:</p>

<p><strong>Entendé a fondo la feature o el bug:</strong> aunque parezca obvio, este entendimiento se pasa por alto más seguido de lo que pensás. Es más fácil validar la implementación con un buen conocimiento del bug o de la feature. De lo contrario, no sos un guardián del valor de entrega esperado. Si no entendés la entrega esperada, te enfocás simplemente en la corrección técnica, que es importante, pero no tanto como el valor agregado.</p>

<p><strong>Time box:</strong> tenés muchas tareas que cumplir, y el code review es una de ellas, así que asignale tiempo a propósito. Tomá un PR a la vez y asignale tiempo para hacerlo. Tu atención cede con el tiempo, así que dedicale a lo sumo una hora por sesión de revisión. Tratá de mantenerte enfocado durante ese tiempo. Hacer time boxing te ayuda a organizar tus tareas.</p>

<p><strong>Validá si la colaboración arregla el bug o entrega la feature:</strong> esto es fundamental. De nuevo, sos un guardián del valor de entrega. Si es un bug, tenés que asegurarte de que lo arregle. Si es una feature, tenés que asegurarte de que cumpla todos los requisitos.</p>

<p><strong>Dá feedback significativo y accionable:</strong> vas a encontrar algo que merezca un comentario, sea un code smell, una mala práctica, o un bloque poco claro que te parezca incorrecto; eso te va a obligar a producir un comentario, y ese comentario tiene que ser una pieza de feedback accionable. Es una oportunidad para ayudar a un compañero a aprender algo nuevo sobre la tecnología en juego, el negocio, etc. La mejor manera de aprender es enseñar, así que si tenés ganas de aprender, aprovechá la oportunidad, juntá recursos y referencias, y armá una microclase.</p>

<p><strong>Revisá a tiempo:</strong> es esencial hacerlo a tiempo, o estamos demorando o bloqueando el progreso de algún trabajo. Al revisar a tiempo también evitás un cambio de contexto al compañero que construyó la solución. Algunos colegas van a tomar otra tarea apenas esté disponible; querés que se contengan y que mantengan caliente su conocimiento de la solución que estás revisando, haciéndolo rápido y eficazmente. Revisar a tiempo también evita generar ansiedad en los colaboradores.</p>

<p><strong>No te dejes condicionar por la seniority:</strong> te vas a encontrar revisando código de un compañero más senior. No te frenes en levantar un defecto por su seniority; tarde o temprano va a cometer un error, y vos tenés que estar bien encontrando ese defecto. Y cuando pase, tenés que reconocerlo y comunicarlo con un buen comentario, una pieza de feedback accionable y significativa. A veces los devs senior tienen que prestarle más atención a cosas básicas, como escribir un test.</p>

<p><strong>Sé un promotor de las buenas prácticas y convenciones:</strong> si hay una forma más idiomática o una solución mejor establecida para un problema común, comunicale al colaborador y pedile que siga las convenciones. De nuevo, dá feedback accionable y significativo, y aprovechá la oportunidad para reforzar buen conocimiento enseñando a otros.</p>

<h3 id="ejemplos-de-code-reviews">Ejemplos de code reviews</h3>

<p>Me gusta explorar proyectos Open Source para aprender cómo hacen las cosas. Estas herramientas increíbles las construyen miles de contribuidores, y unos pocos son miembros del core team que cuidan las buenas prácticas; estos proyectos son elementos centrales de productos que llegan a millones de personas en todo el mundo. ¿Y adiviná qué? Estos equipos también hacen code reviews. Te dejo una lista para que los explores:</p>

<ul>
  <li><a href="https://github.com/django/django/pull/16835">Un bug en Django</a></li>
  <li><a href="https://gitlab.com/gitlab-org/gitlab/-/merge_requests/13703#2c3621e9eaa266f4e1db62954ec460a38c45d8b2">Un refactor en GitLab</a></li>
  <li><a href="https://github.com/rails/rails/pull/48220">Un bug en Rails</a></li>
  <li><a href="https://github.com/python/cpython/pull/104547">Un refactor en Python</a></li>
  <li><a href="https://github.com/spring-projects/spring-boot/pull/10944">Una feature en Spring Boot</a></li>
</ul>

<p>En algunos casos escriben una descripción completa en el PR, en otros casos enlazan al issue que contiene toda la discusión. Tratá de seguir los enlaces de estos PRs y MRs y aprendé cómo colaboran estos equipos.</p>

<h2 id="cierre">Cierre</h2>

<p>Siempre hay lugar para mejorar nuestros procesos. Experimentamos distintas formas de implementar el Software Development Lifecycle (SDLC) en cada proyecto del que formamos parte.</p>

<p>En este evento particular del SDLC, el code review, hay lugar para la controversia, las batallas de ego y los síndromes del impostor. Tenemos que ser amables y humildes; eso construye un espacio de colaboración seguro y fructífero.</p>

<p>Quiero cerrar con una lista de pensamientos que guiaron la escritura de este post:</p>

<ul>
  <li>Quiero evitar la frustración del ida y vuelta sin sentido y sin fin en las revisiones de código.</li>
  <li>Quiero dejar de perder el tiempo, recuperarlo para mí, y usarlo en otras actividades gratificantes como estudiar música o pasar tiempo con mi familia.</li>
  <li>Quiero permitirles a otros hacer lo mismo.</li>
</ul>]]></content><author><name></name></author><category term="good-practices" /><category term="pr" /><category term="codereviews" /><category term="teamwork" /><summary type="html"><![CDATA[o cómo ser amable y profesional al programar y revisar con otros]]></summary></entry></feed>