<?xml version="1.0" encoding="UTF-8"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="es"><title>Chemaclass - software-design</title><subtitle>Tech Lead compartiendo ideas prácticas sobre artesanía del software, TDD, liderazgo, Bitcoin e IA. Artículos, resúmenes de libros y charlas.</subtitle><link rel="self" type="application/atom+xml" href="https://chemaclass.com/es/tags/software-design/atom.xml"/><link rel="alternate" type="text/html" href="https://chemaclass.com"/><generator uri="https://www.getzola.org/">Zola</generator><updated>2025-01-18T00:00:00+00:00</updated><id>https://chemaclass.com/es/tags/software-design/atom.xml</id><entry xml:lang="es"><title>Bitcoin con Rigor</title><subtitle>Un estudio técnico sobre cómo funciona Bitcoin</subtitle><category term="bitcoin" scheme="https://chemaclass.com/tags/bitcoin/" label="Bitcoin"/><category term="privacy" scheme="https://chemaclass.com/tags/privacy/" label="Privacy"/><category term="software-design" scheme="https://chemaclass.com/tags/software-design/" label="Software Design"/><published>2025-01-18T00:00:00+00:00</published><updated>2025-01-18T00:00:00+00:00</updated><author><name>
Jose Sanchis</name></author><link rel="alternate" type="text/html" href="https://chemaclass.com/es/readings/bitcoin-with-rigor/"/><id>https://chemaclass.com/es/readings/bitcoin-with-rigor/</id><summary type="html">Un análisis detallado de cómo funciona Bitcoin, desglosando sus componentes de forma clara. Explora su potencial y riesgos como experimento monetario que, aunque no ha superado la prueba del tiempo como el oro, tiene un diseño prometedor para el presente y futuro.</summary><content type="html">&lt;p>Un análisis detallado de cómo funciona Bitcoin, desglosando sus componentes de forma clara para entender tanto las partes como el sistema completo. Explora su potencial y riesgos como experimento monetario que, aunque no ha superado la prueba del tiempo como el oro, tiene un diseño prometedor.&lt;/p>
&lt;span id="continue-reading">&lt;/span>
&lt;p>Bitcoin es difícil de entender del todo. Requiere conocimientos de computación, economía y finanzas, y además es un activo digital sin precedente histórico que sirva de guía. Pero igual que Internet (también joven pero innegablemente transformador), Bitcoin tiene el potencial de redefinir sistemas y dejar un impacto duradero.&lt;/p>
&lt;p>Este libro busca darte las herramientas para entender cómo funciona Bitcoin. Así podrás formar tu propia opinión informada sobre su papel en la sociedad o, si lo decides, empezar una carrera profesional en este sector. Está escrito con rigor pero sin tecnicismos excesivos: conciso, accesible y pensado para que comprendas Bitcoin de verdad.&lt;/p>
&lt;hr />
&lt;h2 id="contenido">Contenido
&lt;a class="heading-anchor" href="#contenido" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h2>
&lt;h3 id="1-conceptos-basicos-de-computacion">1. Conceptos Básicos de Computación
&lt;a class="heading-anchor" href="#1-conceptos-basicos-de-computacion" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;ul>
&lt;li>Información y Comunicación&lt;/li>
&lt;li>Cómo Funcionan las Computadoras&lt;/li>
&lt;li>Lenguajes y Protocolos&lt;/li>
&lt;li>El Modelo OSI: La Cebolla de la Computación&lt;/li>
&lt;li>Puertas Lógicas: Funciones Fundamentales de Computación&lt;/li>
&lt;li>Redes Cliente-Servidor y P2P&lt;/li>
&lt;/ul>
&lt;h3 id="2-conceptos-basicos-de-criptografia">2. Conceptos Básicos de Criptografía
&lt;a class="heading-anchor" href="#2-conceptos-basicos-de-criptografia" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;ul>
&lt;li>Complejidad Asimétrica&lt;/li>
&lt;li>Cifrados, Claves y Criptografía Simétrica&lt;/li>
&lt;li>Criptografía Asimétrica&lt;/li>
&lt;li>El Movimiento Cypherpunk&lt;/li>
&lt;li>Funciones Hash Criptográficas&lt;/li>
&lt;/ul>
&lt;h3 id="3-los-fundamentos-de-bitcoin-y-las-criptomonedas">3. Los Fundamentos de Bitcoin y las Criptomonedas
&lt;a class="heading-anchor" href="#3-los-fundamentos-de-bitcoin-y-las-criptomonedas" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;ul>
&lt;li>Generadores de Claves y Aleatoriedad&lt;/li>
&lt;li>Firmas Criptográficas&lt;/li>
&lt;li>El Problema del Logaritmo Discreto&lt;/li>
&lt;li>Criptografía de Curva Elíptica&lt;/li>
&lt;li>Árbol de Merkle&lt;/li>
&lt;li>Dinero Digital Tradicional&lt;/li>
&lt;li>Algoritmos de Consenso Distribuido&lt;/li>
&lt;li>Prueba de Trabajo (PoW)&lt;/li>
&lt;/ul>
&lt;h3 id="4-bitcoin-pieza-por-pieza">4. Bitcoin Pieza por Pieza
&lt;a class="heading-anchor" href="#4-bitcoin-pieza-por-pieza" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;ul>
&lt;li>¿Blockchain o Hashchain?&lt;/li>
&lt;li>Sincronización de Bloques&lt;/li>
&lt;li>La Headerchain&lt;/li>
&lt;li>Claves y Firmas en Bitcoin&lt;/li>
&lt;li>Transacciones y el Modelo UTXO&lt;/li>
&lt;li>Bitcoin Script y Opcodes&lt;/li>
&lt;li>P2PKH (Pay to Public Key Hash) y P2PK&lt;/li>
&lt;li>Multifirmas y P2SH (Pay to Script Hash)&lt;/li>
&lt;/ul>
&lt;h3 id="5-nodos-y-blockchain-en-detalle">5. Nodos y Blockchain en Detalle
&lt;a class="heading-anchor" href="#5-nodos-y-blockchain-en-detalle" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;ul>
&lt;li>Tamaño y Frecuencia de Transacciones&lt;/li>
&lt;li>Inicialización de un Nodo de Red Completo&lt;/li>
&lt;li>Bases de Datos y Pruning&lt;/li>
&lt;li>Cómo Funciona una Wallet&lt;/li>
&lt;li>Wallets, Nodos SPV y Otros&lt;/li>
&lt;li>Del Mempool a la Blockchain&lt;/li>
&lt;li>Forks y Criticidad del Consenso&lt;/li>
&lt;li>Hard Fork vs. Soft Fork&lt;/li>
&lt;/ul>
&lt;h3 id="6-actualizaciones-y-aplicaciones-de-bitcoin">6. Actualizaciones y Aplicaciones de Bitcoin
&lt;a class="heading-anchor" href="#6-actualizaciones-y-aplicaciones-de-bitcoin" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;ul>
&lt;li>Mucho Trabajo por Delante&lt;/li>
&lt;li>Maleabilidad de Transacciones&lt;/li>
&lt;li>Segregated Witness (SegWit)&lt;/li>
&lt;li>P2WPKH y P2WSH&lt;/li>
&lt;li>Canales de Pago Unilaterales&lt;/li>
&lt;li>Canales Lightning&lt;/li>
&lt;li>Pagos Multicanal y HTLCs&lt;/li>
&lt;li>Lightning Network&lt;/li>
&lt;li>Discreet Log Contracts (DLCs)&lt;/li>
&lt;li>MAST, P2SMR y P2CH&lt;/li>
&lt;li>Taproot y Grafroot&lt;/li>
&lt;/ul>
&lt;hr />
&lt;h2 id="presentacion-del-libro">Presentación del libro
&lt;a class="heading-anchor" href="#presentacion-del-libro" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h2>
&lt;div style="position:relative;aspect-ratio:16/9;width:100%;">
&lt;iframe
src="https://www.youtube-nocookie.com/embed/55ZRM7j1Jzc"
title="YouTube video"
width="560"
height="315"
loading="lazy"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
referrerpolicy="strict-origin-when-cross-origin"
style="position:absolute;inset:0;width:100%;height:100%;border:0;"
allowfullscreen>
&lt;/iframe>
&lt;/div>
&lt;hr />
&lt;p>&lt;strong>Enlaces relacionados&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>Sitio web del libro: &lt;a rel="external" href="https://www.bitcoinconrigor.com">www.bitcoinconrigor.com&lt;/a>&lt;/li>
&lt;/ul></content></entry><entry xml:lang="es"><title>Bitcoin: A Work in Progress</title><subtitle>Innovaciones técnicas desde las trincheras</subtitle><category term="bitcoin" scheme="https://chemaclass.com/tags/bitcoin/" label="Bitcoin"/><category term="privacy" scheme="https://chemaclass.com/tags/privacy/" label="Privacy"/><category term="software-design" scheme="https://chemaclass.com/tags/software-design/" label="Software Design"/><published>2024-08-02T00:00:00+00:00</published><updated>2024-08-02T00:00:00+00:00</updated><author><name>
Sjors Provoost</name></author><link rel="alternate" type="text/html" href="https://chemaclass.com/es/readings/bitcoin-wip/"/><id>https://chemaclass.com/es/readings/bitcoin-wip/</id><summary type="html">Con miles de proyectos cripto por ahí, dicen que Bitcoin es viejo y aburrido. Nada más lejos de la realidad. Este libro te guía por los últimos desarrollos de Bitcoin desde la perspectiva de uno de sus desarrolladores.</summary><content type="html">&lt;p>Con miles de proyectos cripto por ahí, dicen que Bitcoin es viejo y aburrido. Nada más lejos de la realidad. Este libro te guía por los últimos desarrollos de Bitcoin desde la perspectiva de uno de sus desarrolladores.&lt;/p>
&lt;span id="continue-reading">&lt;/span>
&lt;p>Aprenderás sobre Taproot (el último soft fork), los retos de mantener software open source libre de bugs y malware, nuevas formas de proteger nodos contra atacantes, cómo gestionar una blockchain que no para de crecer, y mucho más.&lt;/p>
&lt;p>El libro enlaza a más de doscientos artículos, videos, podcasts e incluso código fuente. Y gracias a los códigos QR junto a cada enlace, nunca tendrás que escribir URLs largas.&lt;/p>
&lt;hr />
&lt;h2 id="contenidos">Contenidos
&lt;a class="heading-anchor" href="#contenidos" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h2>
&lt;h3 id="lo-basico">Lo básico
&lt;a class="heading-anchor" href="#lo-basico" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;pre class="giallo" style="color-scheme: light dark; color: light-dark(#24292E, #E1E4E8); background-color: light-dark(#FFFFFF, #24292E);">&lt;code data-lang="plain">&lt;span class="giallo-l">&lt;span>1. Direcciones Bitcoin&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span>2. DNS Bootstrap y Tor V3&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span>3. SegWit&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span>4. libsecp256k1&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;h3 id="uso-de-recursos">Uso de recursos
&lt;a class="heading-anchor" href="#uso-de-recursos" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;pre class="giallo" style="color-scheme: light dark; color: light-dark(#24292E, #E1E4E8); background-color: light-dark(#FFFFFF, #24292E);">&lt;code data-lang="plain">&lt;span class="giallo-l">&lt;span>5. Tiempo de Sincronización y AssumeUTXO&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span>6. Utreexo&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;h3 id="atacando-bitcoin">Atacando Bitcoin
&lt;a class="heading-anchor" href="#atacando-bitcoin" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;pre class="giallo" style="color-scheme: light dark; color: light-dark(#24292E, #E1E4E8); background-color: light-dark(#FFFFFF, #24292E);">&lt;code data-lang="plain">&lt;span class="giallo-l">&lt;span>7. Ataques Eclipse&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span>8. Nodos Falsos&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span>9. Guix&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;h3 id="mejores-wallets">Mejores Wallets
&lt;a class="heading-anchor" href="#mejores-wallets" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;pre class="giallo" style="color-scheme: light dark; color: light-dark(#24292E, #E1E4E8); background-color: light-dark(#FFFFFF, #24292E);">&lt;code data-lang="plain">&lt;span class="giallo-l">&lt;span>10. Script, P2SH, y Miniscript&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;h3 id="taproot">Taproot
&lt;a class="heading-anchor" href="#taproot" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;pre class="giallo" style="color-scheme: light dark; color: light-dark(#24292E, #E1E4E8); background-color: light-dark(#FFFFFF, #24292E);">&lt;code data-lang="plain">&lt;span class="giallo-l">&lt;span>11. Taproot y Schnorr&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span>12. Opciones de Activación&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;h3 id="apendice">Apéndice
&lt;a class="heading-anchor" href="#apendice" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;pre class="giallo" style="color-scheme: light dark; color: light-dark(#24292E, #E1E4E8); background-color: light-dark(#FFFFFF, #24292E);">&lt;code data-lang="plain">&lt;span class="giallo-l">&lt;span>A. Más Episodios&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span>B. Un crimen en Testnet&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span>C. White Paper de Bitcoin&lt;/span>&lt;/span>&lt;/code>&lt;/pre>
&lt;p>&lt;img src="/images/readings/2024-08-02/sjors-and-chema.webp" alt="cover" />&lt;/p>
&lt;hr />
&lt;div style="position:relative;aspect-ratio:16/9;width:100%;">
&lt;iframe
src="https://www.youtube-nocookie.com/embed/pQb24UWWSl8"
title="YouTube video"
width="560"
height="315"
loading="lazy"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
referrerpolicy="strict-origin-when-cross-origin"
style="position:absolute;inset:0;width:100%;height:100%;border:0;"
allowfullscreen>
&lt;/iframe>
&lt;/div>
&lt;hr />
&lt;p>&lt;strong>Enlaces relacionados&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>Código fuente del libro: &lt;a rel="external" href="https://github.com/Sjors/nado-book/">GitHub/Sjors&lt;/a>&lt;/li>
&lt;li>Sitio web del libro: &lt;a rel="external" href="https://www.btcwip.com/">www.btcwip.com&lt;/a>&lt;/li>
&lt;/ul></content></entry><entry xml:lang="es"><title>¿Qué Es Waterfall?</title><subtitle>¿Qué hace que Waterfall sea inadecuado para el desarrollo de software moderno?</subtitle><category term="agile" scheme="https://chemaclass.com/tags/agile/" label="Agile"/><category term="software-design" scheme="https://chemaclass.com/tags/software-design/" label="Software Design"/><category term="team-management" scheme="https://chemaclass.com/tags/team-management/" label="Team Management"/><category term="productivity" scheme="https://chemaclass.com/tags/productivity/" label="Productivity"/><published>2024-08-01T00:00:00+00:00</published><updated>2024-08-01T00:00:00+00:00</updated><author><name>
Chemaclass</name></author><link rel="alternate" type="text/html" href="https://chemaclass.com/es/blog/what-is-waterfall/"/><id>https://chemaclass.com/es/blog/what-is-waterfall/</id><summary type="html">Waterfall es como seguir un camino recto donde te mueves de un paso al siguiente en un orden definido, como el agua fluyendo por una cascada a través de diferentes etapas. El problema es que cada paso puede llevar mucho tiempo y recursos para completarse. Además, no recibes retroalimentación hasta que toda la etapa está terminada, lo que puede llevar a mucho tiempo desperdiciado. Esto es especialmente complicado en el desarrollo de software, donde las cosas siempre están cambiando y evolucionando.</summary><content type="html">&lt;p>Waterfall es como seguir un camino recto donde te mueves de un paso al siguiente en un orden definido, como el agua fluyendo por una cascada a través de diferentes etapas.&lt;/p>
&lt;span id="continue-reading">&lt;/span>
&lt;p>El problema es que cada paso puede llevar mucho tiempo y recursos para completarse. Además, no recibes retroalimentación hasta que toda la etapa está terminada, lo que puede llevar a mucho tiempo desperdiciado. Esto es especialmente complicado en el desarrollo de software, donde las cosas siempre están cambiando y evolucionando.&lt;/p>
&lt;p>Usualmente sigue una secuencia directa como esta:&lt;/p>
&lt;p>&lt;img src="/images/blog/2024-08-01/waterfall.jpg" alt="Waterfall img from Comic Agile" />&lt;/p>
&lt;h2 id="la-realidad-de-waterfall">La realidad de Waterfall
&lt;a class="heading-anchor" href="#la-realidad-de-waterfall" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h2>
&lt;p>Waterfall puede ser como el comunismo en teoría, parece perfecto en papel pero no funciona en el mundo real.&lt;/p>
&lt;ul>
&lt;li>Los clientes a menudo no saben exactamente lo que quieren.&lt;/li>
&lt;li>Los requisitos están constantemente cambiando.&lt;/li>
&lt;li>Los negocios necesitan adaptarse rápidamente a los cambios del mercado y las necesidades de los clientes.&lt;/li>
&lt;li>El software necesita ser flexible para mantenerse al día con estos cambios.&lt;/li>
&lt;/ul>
&lt;p>Entonces, en un mundo en constante cambio, Waterfall puede realmente perjudicar a un negocio. Tiende a frustrar a los desarrolladores y equipos, y también puede molestar a los clientes y a los negocios que pagan por el software. Esto usualmente lleva a retrasos y costos adicionales.&lt;/p>
&lt;h2 id="por-que-las-empresas-aun-usan-waterfall">Por qué las empresas aún usan Waterfall
&lt;a class="heading-anchor" href="#por-que-las-empresas-aun-usan-waterfall" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h2>
&lt;p>Incluso con sus problemas, muchas empresas aún usan Waterfall porque parece directo y lógico. Esto les hace reacios a tomarse el tiempo de aprender Agile. Además, conseguir que la dirección acepte cambiar a Agile puede ser difícil de vender, especialmente ya que requiere una inversión en tiempo y aprendizaje.&lt;/p>
&lt;p>El gran problema es cuando los superiores dictan exactamente cómo deben trabajar los equipos, llevando a la microgestión. Esto arruina la flexibilidad que Agile aporta. Por lo que he visto, esto es un problema común.&lt;/p>
&lt;blockquote>
&lt;p>Mirando hacia atrás, cambiar a Agile podría haber solucionado muchos problemas.&lt;/p>
&lt;/blockquote>
&lt;hr />
&lt;p>&lt;img src="/images/blog/2024-08-01/footer.webp" alt="agile vs waterfall" />&lt;/p>
&lt;h2 id="por-que-se-creo-agile">Por qué se creó Agile
&lt;a class="heading-anchor" href="#por-que-se-creo-agile" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h2>
&lt;p>Agile fue creado para superar las limitaciones del método Waterfall. Se enfoca en la interacción constante con clientes y equipos.&lt;/p>
&lt;p>Agile construye equipos autónomos y responsables que manejan tareas de principio a fin, reduciendo tiempo y recursos desperdiciados. Enfatiza la flexibilidad, la colaboración y la retroalimentación del cliente.&lt;/p>
&lt;p>A diferencia de Waterfall, Agile usa desarrollo iterativo, dividiendo proyectos en pequeños sprints o iteraciones manejables que duran de 1 a 4 semanas. Cada ciclo incluye planificación, desarrollo, pruebas y revisión, con el objetivo de entregar valor rápidamente y recopilar retroalimentación para mejorar.&lt;/p>
&lt;h3 id="aspectos-clave-de-agile">Aspectos clave de Agile
&lt;a class="heading-anchor" href="#aspectos-clave-de-agile" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;ul>
&lt;li>&lt;strong>Desarrollo iterativo&lt;/strong>: Trabaja en pequeños fragmentos y ajusta sobre la marcha.&lt;/li>
&lt;li>&lt;strong>Colaboración con el cliente&lt;/strong>: Mantén la comunicación con los clientes para asegurar que están satisfechos.&lt;/li>
&lt;li>&lt;strong>Equipos multifuncionales&lt;/strong>: Equipos con diferentes habilidades trabajando juntos.&lt;/li>
&lt;li>&lt;strong>Planificación adaptativa&lt;/strong>: Mantente flexible y ajusta los planes basándote en la retroalimentación.&lt;/li>
&lt;li>&lt;strong>Mejora continua&lt;/strong>: Siempre busca formas de mejorar.&lt;/li>
&lt;/ul>
&lt;blockquote>
&lt;p>Lee el &lt;a rel="external" href="https://agilemanifesto.org/">Manifiesto Agile&lt;/a> original.&lt;/p>
&lt;/blockquote>
&lt;h3 id="por-donde-puedes-empezar">¿Por dónde puedes empezar?
&lt;a class="heading-anchor" href="#por-donde-puedes-empezar" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;p>Como desarrollador, puedes impulsar tu agilidad sumergiéndote en &lt;a href="/es/blog/effective-pair-programming/">pair programming&lt;/a> y &lt;a href="/es/blog/test-driven-development/">TDD&lt;/a>.&lt;/p>
&lt;ul>
&lt;li>Con pair programming, dos desarrolladores trabajan lado a lado, lo que significa que obtienes retroalimentación instantánea y resolución de problemas compartida, llevando a mejor código.&lt;/li>
&lt;li>TDD, por otro lado, implica escribir tests antes del código, lo que ayuda a especificar lo que quieres hacer, enfocándote en pequeños pasos.&lt;/li>
&lt;/ul>
&lt;p>Juntas, estas prácticas hacen tu proceso de desarrollo más flexible, colaborativo y de alta calidad, encajando perfectamente con el enfoque de Agile en ajustes rápidos y mejora continua. Ve más prácticas &lt;a href="/es/readings/extreme-programming-explained/#practices">aquí&lt;/a>.&lt;/p>
&lt;blockquote>
&lt;p>La clave es colaboración, pequeños pasos y retroalimentación rápida en todo lo que trabajas.&lt;/p>
&lt;/blockquote>
&lt;h2 id="mi-experiencia-con-agile">Mi experiencia con Agile
&lt;a class="heading-anchor" href="#mi-experiencia-con-agile" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h2>
&lt;p>He &lt;a href="/es/talks/">hablado&lt;/a> sobre Agile en varios eventos tecnológicos y lo he explorado en profundidad porque me apasiona cómo puede potenciar a los equipos de software. Cuando se hace bien, Agile puede cambiar completamente cómo trabajan los equipos, haciéndolos más rápidos, más eficientes y mejores en entregar lo que los clientes y negocios realmente necesitan.&lt;/p>
&lt;ul>
&lt;li>2022-06-26 | &lt;a rel="external" href="https://phpconference.com/mixed/update-your-team-to-be-more-extreme/">International PHP Conference&lt;/a> [Berlín, Alemania] (EN)&lt;/li>
&lt;li>2022-09-16 | &lt;a rel="external" href="https://codetalks.de/speakers#speaker-985?event=7">Code Talks&lt;/a> [Hamburgo, Alemania] (EN)&lt;/li>
&lt;li>2022-10-26 | &lt;a rel="external" href="https://phpconference.com/mixed/update-your-team-to-be-more-extreme/">International PHP Conference&lt;/a> [Múnich, Alemania] (EN)&lt;/li>
&lt;li>2022-12-21 | IES Ginés Pérez Chirinos [Murcia, España] (ES)&lt;/li>
&lt;li>2023-01-19 | &lt;a rel="external" href="https://devm.io/update-your-team-to-be-more-extreme/">devm.io&lt;/a> [Remoto] (EN)&lt;/li>
&lt;li>2023-07-28 | &lt;a rel="external" href="https://www.wearedevelopers.com/world-congress">WeAreDeveloper World Congress&lt;/a> [Berlín, Alemania] (EN)&lt;/li>
&lt;/ul>
&lt;h3 id="wearedevelopers-world-congress-en-berlin">WeAreDevelopers World Congress en Berlín
&lt;a class="heading-anchor" href="#wearedevelopers-world-congress-en-berlin" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;div style="position:relative;aspect-ratio:16/9;width:100%;">
&lt;iframe
src="https://www.youtube-nocookie.com/embed/dqtAyl-SvaY"
title="YouTube video"
width="560"
height="315"
loading="lazy"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
referrerpolicy="strict-origin-when-cross-origin"
style="position:absolute;inset:0;width:100%;height:100%;border:0;"
allowfullscreen>
&lt;/iframe>
&lt;/div></content></entry><entry xml:lang="es"><title>Dominando Bitcoin</title><subtitle>Programando la Blockchain Abierta</subtitle><category term="bitcoin" scheme="https://chemaclass.com/tags/bitcoin/" label="Bitcoin"/><category term="software-design" scheme="https://chemaclass.com/tags/software-design/" label="Software Design"/><category term="privacy" scheme="https://chemaclass.com/tags/privacy/" label="Privacy"/><published>2024-07-05T00:00:00+00:00</published><updated>2024-07-05T00:00:00+00:00</updated><author><name>
Andreas M. Antonopoulos</name></author><author><name>
David A. Harding</name></author><link rel="alternate" type="text/html" href="https://chemaclass.com/es/readings/mastering-bitcoin/"/><id>https://chemaclass.com/es/readings/mastering-bitcoin/</id><summary type="html">Este libro cubre desde los conceptos básicos hasta los aspectos técnicos más profundos de Bitcoin. Una guía excelente para entender este mundo y participar en el Internet del Dinero.</summary><content type="html">&lt;p>Este libro cubre desde los conceptos básicos hasta los aspectos técnicos más profundos de Bitcoin. Una guía excelente para entender este mundo y participar en el Internet del dinero.&lt;/p>
&lt;span id="continue-reading">&lt;/span>
&lt;p>La primera edición se publicó en diciembre de 2014. Diez años después, ya tenemos una tercera edición actualizada. Muy recomendable para cualquier persona interesada en este tema y la tecnología que hay detrás.&lt;/p>
&lt;ul>
&lt;li>Introducción amplia a Bitcoin y su blockchain, ideal para usuarios no técnicos, inversores y ejecutivos.&lt;/li>
&lt;li>Explicación técnica para desarrolladores, ingenieros y arquitectos de software.&lt;/li>
&lt;li>Detalles sobre la red descentralizada, arquitectura P2P, ciclo de vida de transacciones y seguridad.&lt;/li>
&lt;li>Novedades como Taproot, Tapscript, firmas Schnorr y Lightning Network.&lt;/li>
&lt;li>Inmersión profunda en aplicaciones de Bitcoin: cómo combinar sus bloques de construcción en herramientas nuevas.&lt;/li>
&lt;li>Historias, analogías, ejemplos y fragmentos de código que explican los conceptos clave.&lt;/li>
&lt;/ul>
&lt;hr />
&lt;h2 id="contenidos">Contenidos
&lt;a class="heading-anchor" href="#contenidos" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h2>
&lt;ol>
&lt;li>Introducción&lt;/li>
&lt;li>Cómo Funciona Bitcoin&lt;/li>
&lt;li>Bitcoin Core: La Implementación de Referencia&lt;/li>
&lt;li>Claves y Direcciones&lt;/li>
&lt;li>Recuperación de Wallet&lt;/li>
&lt;li>Transacciones&lt;/li>
&lt;li>Autorización y Autenticación&lt;/li>
&lt;li>Firmas Digitales&lt;/li>
&lt;li>Comisiones de Transacción&lt;/li>
&lt;li>La Red Bitcoin&lt;/li>
&lt;li>La Blockchain&lt;/li>
&lt;li>Minería y Consenso&lt;/li>
&lt;li>Seguridad de Bitcoin&lt;/li>
&lt;li>Aplicaciones de Segunda Capa&lt;/li>
&lt;/ol>
&lt;p>&lt;img src="/images/readings/2024-07-05/footer.webp" alt="blog-footer" />&lt;/p>
&lt;blockquote>
&lt;p>Libro completo también en &lt;a rel="external" href="https://github.com/bitcoinbook/bitcoinbook">GitHub&lt;/a>.&lt;/p>
&lt;/blockquote>
&lt;h3 id="puntos-clave">Puntos clave
&lt;a class="heading-anchor" href="#puntos-clave" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;ol>
&lt;li>Tu wallet no almacena bitcoins, solo las claves para acceder a ellos. Las monedas están en la blockchain.&lt;/li>
&lt;li>Entender los &lt;strong>UTXOs&lt;/strong> es clave para entender las transacciones.
&lt;ul>
&lt;li>Son outputs de transacciones anteriores que aún no se han gastado.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>Una transacción necesita:
&lt;ul>
&lt;li>&lt;strong>inputs&lt;/strong>: UTXOs y un script de desbloqueo (scriptSig) que prueba la propiedad.&lt;/li>
&lt;li>&lt;strong>outputs&lt;/strong>: dirección del destinatario y cantidad a enviar.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>El script de desbloqueo usa un lenguaje llamado &lt;a rel="external" href="https://en.bitcoin.it/wiki/Script">&lt;strong>Script&lt;/strong>&lt;/a>.
&lt;ul>
&lt;li>La validación se hace ejecutando el script.&lt;/li>
&lt;li>Permite expresar una variedad casi infinita de condiciones.&lt;/li>
&lt;li>Script es un lenguaje basado en pila, procesado de izquierda a derecha.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>Bitcoin se conoce como “&lt;strong>dinero programable&lt;/strong>” porque permite multifirma, bloqueo temporal y gasto condicional.
&lt;ul>
&lt;li>Va más allá de simples transferencias de valor.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;a href="/es/blog/programmable-money#common-bitcoin-address-types">&lt;strong>Tipos de direcciones&lt;/strong>&lt;/a> comunes:
&lt;ul>
&lt;li>P2PKH: Empieza con &lt;code>1&lt;/code>. Transacciones estándar con hashes de clave pública.&lt;/li>
&lt;li>P2SH: Empieza con &lt;code>3&lt;/code>. Encapsula scripts complejos como multisig.&lt;/li>
&lt;li>P2WPKH: Empieza con &lt;code>bc1&lt;/code>. SegWit nativo, más eficiente.&lt;/li>
&lt;li>P2WSH: Empieza con &lt;code>bc1&lt;/code>. SegWit para scripts complejos.&lt;/li>
&lt;li>P2TR: Empieza con &lt;code>bc1p&lt;/code>. Taproot, mejor privacidad y eficiencia.&lt;/li>
&lt;li>Bech32: Empieza con &lt;code>bc1&lt;/code>. Legible por humanos, para SegWit y Taproot.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>Las firmas digitales cumplen tres funciones en Bitcoin:
&lt;ul>
&lt;li>Prueban que quien controla la clave privada ha &lt;strong>autorizado&lt;/strong> el gasto.&lt;/li>
&lt;li>La prueba de autorización es &lt;strong>innegable&lt;/strong>.&lt;/li>
&lt;li>La transacción autorizada &lt;strong>no puede cambiarse&lt;/strong> por terceros no autenticados.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>Las &lt;a rel="external" href="https://en.wikipedia.org/wiki/Schnorr_signature">firmas de Schnorr&lt;/a> no son exclusivas de la &lt;a rel="external" href="https://en.wikipedia.org/wiki/Elliptic-curve_cryptography">criptografía de curva elíptica&lt;/a> (ECC) de Bitcoin, aunque hoy se asocian mucho con ella. Tienen propiedades interesantes:
&lt;ul>
&lt;li>&lt;strong>Seguridad demostrable&lt;/strong>: garantías fuertes basadas en el problema del logaritmo discreto, con pruebas formales de robustez.&lt;/li>
&lt;li>&lt;strong>Linealidad&lt;/strong>: permite agregar múltiples firmas en una sola firma compacta, simplificando la verificación.&lt;/li>
&lt;li>&lt;strong>Verificación por lotes&lt;/strong>: verificar múltiples firmas a la vez de forma más eficiente.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>El algoritmo más conocido para compartir secretos de forma segura es &lt;a rel="external" href="https://en.wikipedia.org/wiki/Shamir&amp;#x27;s_secret_sharing">Shamir’s Secret Sharing&lt;/a>.&lt;/li>
&lt;li>Ejecutar un &lt;strong>nodo completo&lt;/strong> te da la experiencia pura de Bitcoin: verificas todas las transacciones de forma independiente, sin confiar en nadie.&lt;/li>
&lt;li>Los &lt;strong>árboles Merkle&lt;/strong> resumen todas las transacciones de un bloque, creando un compromiso con el conjunto completo y permitiendo verificar de forma muy eficiente si una transacción está incluida.&lt;/li>
&lt;li>La minería es una de las invenciones que hacen especial a Bitcoin: un mecanismo de &lt;strong>consenso descentralizado&lt;/strong> que es la base del efectivo digital P2P.
&lt;ul>
&lt;li>Asegura el sistema y permite que emerja consenso a nivel de red sin autoridad central.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>Un &lt;strong>soft-fork&lt;/strong> es un cambio compatible hacia adelante en las reglas de consenso. Los clientes no actualizados pueden seguir operando con las nuevas reglas.&lt;/li>
&lt;/ol></content></entry><entry xml:lang="es"><title>Aprendiendo Concurrencia en Golang</title><subtitle>Un emulador de carreras de caballos explicado paso a paso</subtitle><category term="golang" scheme="https://chemaclass.com/tags/golang/" label="Golang"/><category term="software-design" scheme="https://chemaclass.com/tags/software-design/" label="Software Design"/><category term="clean-code" scheme="https://chemaclass.com/tags/clean-code/" label="Clean Code"/><published>2024-04-02T00:00:00+00:00</published><updated>2024-04-02T00:00:00+00:00</updated><author><name>
Chemaclass</name></author><link rel="alternate" type="text/html" href="https://chemaclass.com/es/blog/learning-concurrency-in-golang/"/><id>https://chemaclass.com/es/blog/learning-concurrency-in-golang/</id><summary type="html">Quería aprender un nuevo lenguaje de programación, así que después de probar algunos, terminé con Golang como uno de mis favoritos por su simplicidad y capacidades. Tiene características que no había usado en años, como multithreading y concurrencia.</summary><content type="html">&lt;p>Quería aprender un nuevo lenguaje, así que después de probar algunos, terminé con Golang como uno de mis favoritos por su simplicidad y capacidades. Tiene características que no había usado en años, como multithreading y concurrencia.&lt;/p>
&lt;span id="continue-reading">&lt;/span>
&lt;p>&lt;a rel="external" href="https://go.dev/">Golang&lt;/a> (o &lt;code>Go&lt;/code>) soporta concurrencia mediante hilos ligeros llamados goroutines. Son diferentes del multithreading tradicional de Java, donde hay que manejar sincronización y coordinación para gestionar recursos compartidos de forma segura. Las goroutines son ligeras, las gestiona el runtime de Go, y son más baratas de crear y manejar.&lt;/p>
&lt;p>El paralelismo es &lt;strong>hacer&lt;/strong> varias cosas simultáneamente. La concurrencia es &lt;strong>lidiar&lt;/strong> con varias cosas a la vez. En ambos casos, no conocemos el orden de ejecución: no sabemos qué pasará primero ni qué terminará antes.&lt;/p>
&lt;blockquote>
&lt;p>Imagina que cocinas: preparas una sopa, una ensalada y una tortilla. Eres una sola persona, pero preparas varios platos. Podrías terminar primero la ensalada, la sopa o la tortilla… no hay garantía. Esto es concurrencia: lidias con varias cosas a la vez. Cuando tu pareja viene a ayudarte, eso ya es paralelismo.&lt;/p>
&lt;/blockquote>
&lt;p>&lt;img src="/images/blog/2024-04-02/concurrency-vs-multithreading.jpg" alt="concurrencia vs multithreading" />&lt;/p>
&lt;p>Recuerdo haber construido un juego similar en &lt;code>Java&lt;/code> cuando aprendía multithreading hace diez años. Aprovecho esta oportunidad para hacerlo de nuevo con &lt;code>Go&lt;/code> moderno.&lt;/p>
&lt;p>Construi un juego de terminal que simula una carrera de caballos. Cada caballo es una goroutine que corre en una matriz bidimensional compartida. Cuando un caballo llega al final, notifica al canal compartido con los demas caballos (que corren en diferentes procesos) y todos se detienen, mostrando al ganador.&lt;/p>
&lt;p>Separé el código en cuatro áreas para ayudar a visualizarlo:&lt;/p>
&lt;ul>
&lt;li>Punto de entrada&lt;/li>
&lt;li>Generando el tablero&lt;/li>
&lt;li>Renderizando el juego&lt;/li>
&lt;li>Moviendo los caballos&lt;/li>
&lt;/ul>
&lt;p>&lt;img src="/images/blog/2024-04-02/race-horses-demo.gif" alt="demo de carrera de caballos en terminal" />&lt;/p>
&lt;h3 id="punto-de-entrada">Punto de entrada
&lt;a class="heading-anchor" href="#punto-de-entrada" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;p>La estructura &lt;code>Horse&lt;/code> representa cada Caballo en la carrera.
El juego consiste en una lista de líneas, en las cuales cada Caballo está corriendo.&lt;/p>
&lt;pre class="giallo" style="color-scheme: light dark; color: light-dark(#24292E, #E1E4E8); background-color: light-dark(#FFFFFF, #24292E);">&lt;code data-lang="go">&lt;span class="giallo-l">&lt;span style="color: light-dark(#D73A49, #F97583);">type&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);"> Horse&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> struct&lt;/span>&lt;span> {&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span> Name&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> string&lt;/span>&lt;span style="color: light-dark(#6A737D, #6A737D);"> //&lt;/span>&lt;span style="color: light-dark(#6A737D, #6A737D);"> El nombre del caballo&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span> Line&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> int&lt;/span>&lt;span style="color: light-dark(#6A737D, #6A737D);"> //&lt;/span>&lt;span style="color: light-dark(#6A737D, #6A737D);"> La línea de competición&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span>}&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#D73A49, #F97583);">func&lt;/span>&lt;span> (&lt;/span>&lt;span style="color: light-dark(#E36209, #FFAB70);">h &lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);">Horse&lt;/span>&lt;span>)&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);"> Letter&lt;/span>&lt;span>(&lt;/span>&lt;span>)&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> string&lt;/span>&lt;span> {&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#D73A49, #F97583);"> return&lt;/span>&lt;span> fmt&lt;/span>&lt;span>.&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);">Sprintf&lt;/span>&lt;span>(&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">&amp;quot;&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);">%c&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">&amp;quot;&lt;/span>&lt;span>,&lt;/span>&lt;span> h&lt;/span>&lt;span>.&lt;/span>&lt;span>Name&lt;/span>&lt;span>[&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);">0&lt;/span>&lt;span>]&lt;/span>&lt;span>)&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span>}&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#D73A49, #F97583);">func&lt;/span>&lt;span> (&lt;/span>&lt;span style="color: light-dark(#E36209, #FFAB70);">h &lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);">Horse&lt;/span>&lt;span>)&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);"> Equals&lt;/span>&lt;span>(&lt;/span>&lt;span style="color: light-dark(#E36209, #FFAB70);">other&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> *&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);">Horse&lt;/span>&lt;span>)&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> bool&lt;/span>&lt;span> {&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#D73A49, #F97583);"> return&lt;/span>&lt;span> other&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> !=&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);"> nil&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> &amp;amp;&amp;amp;&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span> h&lt;/span>&lt;span>.&lt;/span>&lt;span>Line&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> ==&lt;/span>&lt;span> other&lt;/span>&lt;span>.&lt;/span>&lt;span>Line&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> &amp;amp;&amp;amp;&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span> h&lt;/span>&lt;span>.&lt;/span>&lt;span>Name&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> ==&lt;/span>&lt;span> other&lt;/span>&lt;span>.&lt;/span>&lt;span>Name&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span>}&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#D73A49, #F97583);">func&lt;/span>&lt;span> (&lt;/span>&lt;span style="color: light-dark(#E36209, #FFAB70);">h &lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);">Horse&lt;/span>&lt;span>)&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);"> String&lt;/span>&lt;span>(&lt;/span>&lt;span>)&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> string&lt;/span>&lt;span> {&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#D73A49, #F97583);"> return&lt;/span>&lt;span> fmt&lt;/span>&lt;span>.&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);">Sprintf&lt;/span>&lt;span>(&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">&amp;quot;&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);">%s&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);"> (line:&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);">%d&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">)&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">&amp;quot;&lt;/span>&lt;span>,&lt;/span>&lt;span> h&lt;/span>&lt;span>.&lt;/span>&lt;span>Name&lt;/span>&lt;span>,&lt;/span>&lt;span> h&lt;/span>&lt;span>.&lt;/span>&lt;span>Line&lt;/span>&lt;span>)&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span>}&lt;/span>&lt;/span>&lt;/code>&lt;/pre>
&lt;p>Puedes generar un nuevo proceso usando la palabra clave &lt;code>go&lt;/code> al invocar cualquier función.
En este juego, esto se usa 1) para renderizar el juego &lt;code>RenderGame()&lt;/code> y 2) para el movimiento de cada caballo &lt;code>startRuningHorseInLine()&lt;/code>. El objetivo es mantener la “renderización” y la “lógica de movimiento” trabajando en paralelo.&lt;/p>
&lt;pre class="giallo" style="color-scheme: light dark; color: light-dark(#24292E, #E1E4E8); background-color: light-dark(#FFFFFF, #24292E);">&lt;code data-lang="go">&lt;span class="giallo-l">&lt;span style="color: light-dark(#D73A49, #F97583);">func&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);"> main&lt;/span>&lt;span>(&lt;/span>&lt;span>)&lt;/span>&lt;span> {&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#D73A49, #F97583);"> const&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);"> lines&lt;/span>&lt;span>,&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);"> lineLength&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> =&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);"> 12&lt;/span>&lt;span>,&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);"> 30&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;/span>
&lt;span class="giallo-l">&lt;span> board&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> :=&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);"> NewRaceBoard&lt;/span>&lt;span>(&lt;/span>&lt;span>lines&lt;/span>&lt;span>,&lt;/span>&lt;span> lineLength&lt;/span>&lt;span>)&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#D73A49, #F97583);"> go&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);"> RenderGame&lt;/span>&lt;span>(&lt;/span>&lt;span>board&lt;/span>&lt;span>)&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;/span>
&lt;span class="giallo-l">&lt;span> winnerChan&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> :=&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);"> make&lt;/span>&lt;span>(&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);">chan&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);"> Horse&lt;/span>&lt;span>)&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#D73A49, #F97583);"> for&lt;/span>&lt;span> line&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> :=&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> range&lt;/span>&lt;span> board&lt;/span>&lt;span> {&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#6A737D, #6A737D);"> //&lt;/span>&lt;span style="color: light-dark(#6A737D, #6A737D);"> cada caballo será movido en diferentes procesos&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#D73A49, #F97583);"> go&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);"> startRunningHorseInLine&lt;/span>&lt;span>(&lt;/span>&lt;span>board&lt;/span>&lt;span>,&lt;/span>&lt;span> line&lt;/span>&lt;span>,&lt;/span>&lt;span> winnerChan&lt;/span>&lt;span>)&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span> }&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#6A737D, #6A737D);"> //&lt;/span>&lt;span style="color: light-dark(#6A737D, #6A737D);"> esperar hasta que un caballo llegue al final&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span> winner&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> :=&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> &amp;lt;-&lt;/span>&lt;span>winnerChan&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#6A737D, #6A737D);"> //&lt;/span>&lt;span style="color: light-dark(#6A737D, #6A737D);"> renderizar una última vez para asegurar el último estado del tablero&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#6F42C1, #B392F0);"> RenderRaceBoard&lt;/span>&lt;span>(&lt;/span>&lt;span>board&lt;/span>&lt;span>,&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> &amp;amp;&lt;/span>&lt;span>winner&lt;/span>&lt;span>)&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;/span>
&lt;span class="giallo-l">&lt;span> fmt&lt;/span>&lt;span>.&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);">Println&lt;/span>&lt;span>(&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">&amp;quot;&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">Race finished!&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">&amp;quot;&lt;/span>&lt;span>)&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span> fmt&lt;/span>&lt;span>.&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);">Printf&lt;/span>&lt;span>(&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">&amp;quot;&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);"># Winner: &lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);">%s&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);">\n&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">&amp;quot;&lt;/span>&lt;span>,&lt;/span>&lt;span> winner&lt;/span>&lt;span>)&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span>}&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;h3 id="generando-el-tablero">Generando el tablero
&lt;a class="heading-anchor" href="#generando-el-tablero" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;p>El tablero de carreras es una matriz bidimensional de punteros a Horses. Cada línea “contiene” un solo Caballo: solo un puntero apunta a un Caballo real, el resto son &lt;code>nil&lt;/code>. Al generar el Tablero, creamos un Caballo en la primera posición de cada línea.&lt;/p>
&lt;pre class="giallo" style="color-scheme: light dark; color: light-dark(#24292E, #E1E4E8); background-color: light-dark(#FFFFFF, #24292E);">&lt;code data-lang="go">&lt;span class="giallo-l">&lt;span style="color: light-dark(#D73A49, #F97583);">func&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);"> NewRaceBoard&lt;/span>&lt;span>(&lt;/span>&lt;span style="color: light-dark(#E36209, #FFAB70);">lines&lt;/span>&lt;span>,&lt;/span>&lt;span style="color: light-dark(#E36209, #FFAB70);"> lineLength&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> int&lt;/span>&lt;span>)&lt;/span>&lt;span> [&lt;/span>&lt;span>]&lt;/span>&lt;span>[&lt;/span>&lt;span>]&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);">*&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);">Horse&lt;/span>&lt;span> {&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span> board&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> :=&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);"> make&lt;/span>&lt;span>(&lt;/span>&lt;span>[&lt;/span>&lt;span>]&lt;/span>&lt;span>[&lt;/span>&lt;span>]&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);">*&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);">Horse&lt;/span>&lt;span>,&lt;/span>&lt;span> lines&lt;/span>&lt;span>)&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#D73A49, #F97583);"> for&lt;/span>&lt;span> line&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> :=&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> range&lt;/span>&lt;span> board&lt;/span>&lt;span> {&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span> board&lt;/span>&lt;span>[&lt;/span>&lt;span>line&lt;/span>&lt;span>]&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> =&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);"> make&lt;/span>&lt;span>(&lt;/span>&lt;span>[&lt;/span>&lt;span>]&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);">*&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);">Horse&lt;/span>&lt;span>,&lt;/span>&lt;span> lineLength&lt;/span>&lt;span>)&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span> board&lt;/span>&lt;span>[&lt;/span>&lt;span>line&lt;/span>&lt;span>]&lt;/span>&lt;span>[&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);">0&lt;/span>&lt;span>]&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> =&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> &amp;amp;&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);">Horse&lt;/span>&lt;span>{&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span> Name&lt;/span>&lt;span>:&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);"> generateHorseName&lt;/span>&lt;span>(&lt;/span>&lt;span>)&lt;/span>&lt;span>,&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span> Line&lt;/span>&lt;span>:&lt;/span>&lt;span> line&lt;/span>&lt;span>,&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span> }&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span> }&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#D73A49, #F97583);"> return&lt;/span>&lt;span> board&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span>}&lt;/span>&lt;/span>&lt;/code>&lt;/pre>
&lt;p>Los nombres se generan aleatoriamente usando &lt;code>HorseNames&lt;/code>.&lt;/p>
&lt;pre class="giallo" style="color-scheme: light dark; color: light-dark(#24292E, #E1E4E8); background-color: light-dark(#FFFFFF, #24292E);">&lt;code data-lang="go">&lt;span class="giallo-l">&lt;span style="color: light-dark(#D73A49, #F97583);">var&lt;/span>&lt;span> HorseNames&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> =&lt;/span>&lt;span> [&lt;/span>&lt;span>]&lt;/span>&lt;span>[&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);">2&lt;/span>&lt;span>]&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);">string&lt;/span>&lt;span>{&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span> {&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">&amp;quot;&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">Alloping&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">&amp;quot;&lt;/span>&lt;span>,&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);"> &amp;quot;&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">Giggles&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">&amp;quot;&lt;/span>&lt;span>}&lt;/span>&lt;span>,&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span> {&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">&amp;quot;&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">A-lot&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">&amp;quot;&lt;/span>&lt;span>,&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);"> &amp;quot;&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">Gallop&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">&amp;quot;&lt;/span>&lt;span>}&lt;/span>&lt;span>,&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span> {&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">&amp;quot;&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">BoJack&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">&amp;quot;&lt;/span>&lt;span>,&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);"> &amp;quot;&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">Jack&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">&amp;quot;&lt;/span>&lt;span>}&lt;/span>&lt;span>,&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span> {&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">&amp;quot;&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">Baroness&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">&amp;quot;&lt;/span>&lt;span>,&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);"> &amp;quot;&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">Belle&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">&amp;quot;&lt;/span>&lt;span>}&lt;/span>&lt;span>,&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#6A737D, #6A737D);"> //&lt;/span>&lt;span style="color: light-dark(#6A737D, #6A737D);"> ...&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span>}&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#D73A49, #F97583);">func&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);"> generateHorseName&lt;/span>&lt;span>(&lt;/span>&lt;span>)&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> string&lt;/span>&lt;span> {&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span> name&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> :=&lt;/span>&lt;span> HorseNames&lt;/span>&lt;span>[&lt;/span>&lt;span>rand&lt;/span>&lt;span>.&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);">Intn&lt;/span>&lt;span>(&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);">len&lt;/span>&lt;span>(&lt;/span>&lt;span>HorseNames&lt;/span>&lt;span>)&lt;/span>&lt;span>)&lt;/span>&lt;span>]&lt;/span>&lt;span>[&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);">0&lt;/span>&lt;span>]&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span> surname&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> :=&lt;/span>&lt;span> HorseNames&lt;/span>&lt;span>[&lt;/span>&lt;span>rand&lt;/span>&lt;span>.&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);">Intn&lt;/span>&lt;span>(&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);">len&lt;/span>&lt;span>(&lt;/span>&lt;span>HorseNames&lt;/span>&lt;span>)&lt;/span>&lt;span>)&lt;/span>&lt;span>]&lt;/span>&lt;span>[&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);">1&lt;/span>&lt;span>]&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#D73A49, #F97583);"> return&lt;/span>&lt;span> name&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> +&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);"> &amp;quot;&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);"> &amp;quot;&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> +&lt;/span>&lt;span> surname&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span>}&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;h3 id="renderizando-el-juego">Renderizando el juego
&lt;a class="heading-anchor" href="#renderizando-el-juego" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;p>Los métodos &lt;code>RenderGame()&lt;/code>, &lt;code>renderRaceBoard()&lt;/code>, &lt;code>renderRaceLine()&lt;/code> y &lt;code>renderRacePosition()&lt;/code> están separados para que cada uno tenga una responsabilidad clara: renderizar su sujeto correspondiente.&lt;/p>
&lt;blockquote>
&lt;p>&lt;code>RenderGame()&lt;/code> se está ejecutando en otro proceso usando &lt;code>go&lt;/code>.&lt;/p>
&lt;/blockquote>
&lt;pre class="giallo" style="color-scheme: light dark; color: light-dark(#24292E, #E1E4E8); background-color: light-dark(#FFFFFF, #24292E);">&lt;code data-lang="go">&lt;span class="giallo-l">&lt;span style="color: light-dark(#D73A49, #F97583);">func&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);"> RenderGame&lt;/span>&lt;span>(&lt;/span>&lt;span style="color: light-dark(#E36209, #FFAB70);">board&lt;/span>&lt;span> [&lt;/span>&lt;span>]&lt;/span>&lt;span>[&lt;/span>&lt;span>]&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);">*&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);">Horse&lt;/span>&lt;span>)&lt;/span>&lt;span> {&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#D73A49, #F97583);"> for&lt;/span>&lt;span> {&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span> time&lt;/span>&lt;span>.&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);">Sleep&lt;/span>&lt;span>(&lt;/span>&lt;span>renderDelay&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> *&lt;/span>&lt;span> time&lt;/span>&lt;span>.&lt;/span>&lt;span>Millisecond&lt;/span>&lt;span>)&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#6F42C1, #B392F0);"> RenderRaceBoard&lt;/span>&lt;span>(&lt;/span>&lt;span>board&lt;/span>&lt;span>,&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);"> nil&lt;/span>&lt;span>)&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span> }&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span>}&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#D73A49, #F97583);">func&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);"> RenderRaceBoard&lt;/span>&lt;span>(&lt;/span>&lt;span style="color: light-dark(#E36209, #FFAB70);">board&lt;/span>&lt;span> [&lt;/span>&lt;span>]&lt;/span>&lt;span>[&lt;/span>&lt;span>]&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);">*&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);">Horse&lt;/span>&lt;span>,&lt;/span>&lt;span style="color: light-dark(#E36209, #FFAB70);"> winner&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> *&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);">Horse&lt;/span>&lt;span>)&lt;/span>&lt;span> {&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#6A737D, #6A737D);"> //&lt;/span>&lt;span style="color: light-dark(#6A737D, #6A737D);"> usar un &amp;quot;buffer de string&amp;quot; para guardar todo el estado del tablero&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#6A737D, #6A737D);"> //&lt;/span>&lt;span style="color: light-dark(#6A737D, #6A737D);"> para que luego podamos usar una sola llamada IO para renderizarlo&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#D73A49, #F97583);"> var&lt;/span>&lt;span> buffer&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);"> bytes&lt;/span>&lt;span>.&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);">Buffer&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span> buffer&lt;/span>&lt;span>.&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);">WriteString&lt;/span>&lt;span>(&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">&amp;quot;&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);">\n&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">&amp;quot;&lt;/span>&lt;span>)&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#D73A49, #F97583);"> for&lt;/span>&lt;span> line&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> :=&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> range&lt;/span>&lt;span> board&lt;/span>&lt;span> {&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#6F42C1, #B392F0);"> renderRaceLine&lt;/span>&lt;span>(&lt;/span>&lt;span>board&lt;/span>&lt;span>,&lt;/span>&lt;span> line&lt;/span>&lt;span>,&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> &amp;amp;&lt;/span>&lt;span>buffer&lt;/span>&lt;span>,&lt;/span>&lt;span> winner&lt;/span>&lt;span>)&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span> }&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#6F42C1, #B392F0);"> clearScreen&lt;/span>&lt;span>(&lt;/span>&lt;span>)&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span> fmt&lt;/span>&lt;span>.&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);">Println&lt;/span>&lt;span>(&lt;/span>&lt;span>buffer&lt;/span>&lt;span>.&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);">String&lt;/span>&lt;span>(&lt;/span>&lt;span>)&lt;/span>&lt;span>)&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span>}&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#D73A49, #F97583);">func&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);"> clearScreen&lt;/span>&lt;span>(&lt;/span>&lt;span>)&lt;/span>&lt;span> {&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span> cmd&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> :=&lt;/span>&lt;span> exec&lt;/span>&lt;span>.&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);">Command&lt;/span>&lt;span>(&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">&amp;quot;&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">clear&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">&amp;quot;&lt;/span>&lt;span>)&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span> cmd&lt;/span>&lt;span>.&lt;/span>&lt;span>Stdout&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> =&lt;/span>&lt;span> os&lt;/span>&lt;span>.&lt;/span>&lt;span>Stdout&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span> cmd&lt;/span>&lt;span>.&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);">Run&lt;/span>&lt;span>(&lt;/span>&lt;span>)&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span>}&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#D73A49, #F97583);">func&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);"> renderRaceLine&lt;/span>&lt;span>(&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#E36209, #FFAB70);"> board&lt;/span>&lt;span> [&lt;/span>&lt;span>]&lt;/span>&lt;span>[&lt;/span>&lt;span>]&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);">*&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);">Horse&lt;/span>&lt;span>,&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#E36209, #FFAB70);"> line&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> int&lt;/span>&lt;span>,&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#E36209, #FFAB70);"> buffer&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> *&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);">bytes&lt;/span>&lt;span>.&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);">Buffer&lt;/span>&lt;span>,&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#E36209, #FFAB70);"> winner&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> *&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);">Horse&lt;/span>&lt;span>,&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span>)&lt;/span>&lt;span> {&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span> buffer&lt;/span>&lt;span>.&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);">WriteString&lt;/span>&lt;span>(&lt;/span>&lt;span>fmt&lt;/span>&lt;span>.&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);">Sprintf&lt;/span>&lt;span>(&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">&amp;quot;&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);"> %.2d&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);"> | &lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">&amp;quot;&lt;/span>&lt;span>,&lt;/span>&lt;span> line&lt;/span>&lt;span>)&lt;/span>&lt;span>)&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#D73A49, #F97583);"> var&lt;/span>&lt;span> current&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);"> Horse&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#D73A49, #F97583);"> for&lt;/span>&lt;span> col&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> :=&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> range&lt;/span>&lt;span> board&lt;/span>&lt;span>[&lt;/span>&lt;span>line&lt;/span>&lt;span>]&lt;/span>&lt;span> {&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span> h&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> :=&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);"> renderRacePosition&lt;/span>&lt;span>(&lt;/span>&lt;span>board&lt;/span>&lt;span>,&lt;/span>&lt;span> line&lt;/span>&lt;span>,&lt;/span>&lt;span> col&lt;/span>&lt;span>,&lt;/span>&lt;span> buffer&lt;/span>&lt;span>,&lt;/span>&lt;span> winner&lt;/span>&lt;span>)&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#D73A49, #F97583);"> if&lt;/span>&lt;span> h&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> !=&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);"> nil&lt;/span>&lt;span> {&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span> current&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> =&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> *&lt;/span>&lt;span>h&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span> }&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span> }&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span> buffer&lt;/span>&lt;span>.&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);">WriteString&lt;/span>&lt;span>(&lt;/span>&lt;span>fmt&lt;/span>&lt;span>.&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);">Sprintf&lt;/span>&lt;span>(&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">&amp;quot;&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">| &lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);">%s&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">&amp;quot;&lt;/span>&lt;span>,&lt;/span>&lt;span> current&lt;/span>&lt;span>.&lt;/span>&lt;span>Name&lt;/span>&lt;span>)&lt;/span>&lt;span>)&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#D73A49, #F97583);"> if&lt;/span>&lt;span> current&lt;/span>&lt;span>.&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);">Equals&lt;/span>&lt;span>(&lt;/span>&lt;span>winner&lt;/span>&lt;span>)&lt;/span>&lt;span> {&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span> buffer&lt;/span>&lt;span>.&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);">WriteString&lt;/span>&lt;span>(&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">&amp;quot;&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);"> [Won!]&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">&amp;quot;&lt;/span>&lt;span>)&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span> }&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span> buffer&lt;/span>&lt;span>.&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);">WriteString&lt;/span>&lt;span>(&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">&amp;quot;&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);">\n&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">&amp;quot;&lt;/span>&lt;span>)&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span>}&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#D73A49, #F97583);">func&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);"> renderRacePosition&lt;/span>&lt;span>(&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#E36209, #FFAB70);"> board&lt;/span>&lt;span> [&lt;/span>&lt;span>]&lt;/span>&lt;span>[&lt;/span>&lt;span>]&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);">*&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);">Horse&lt;/span>&lt;span>,&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#E36209, #FFAB70);"> line&lt;/span>&lt;span>,&lt;/span>&lt;span style="color: light-dark(#E36209, #FFAB70);"> col&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> int&lt;/span>&lt;span>,&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#E36209, #FFAB70);"> buffer&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> *&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);">bytes&lt;/span>&lt;span>.&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);">Buffer&lt;/span>&lt;span>,&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#E36209, #FFAB70);"> winner&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> *&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);">Horse&lt;/span>&lt;span>,&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span>)&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> *&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);">Horse&lt;/span>&lt;span> {&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#D73A49, #F97583);"> if&lt;/span>&lt;span> board&lt;/span>&lt;span>[&lt;/span>&lt;span>line&lt;/span>&lt;span>]&lt;/span>&lt;span>[&lt;/span>&lt;span>col&lt;/span>&lt;span>]&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> ==&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);"> nil&lt;/span>&lt;span> {&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span> buffer&lt;/span>&lt;span>.&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);">WriteString&lt;/span>&lt;span>(&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">&amp;quot;&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);"> &amp;quot;&lt;/span>&lt;span>)&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#D73A49, #F97583);"> return&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);"> nil&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span> }&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;/span>
&lt;span class="giallo-l">&lt;span> current&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> :=&lt;/span>&lt;span> board&lt;/span>&lt;span>[&lt;/span>&lt;span>line&lt;/span>&lt;span>]&lt;/span>&lt;span>[&lt;/span>&lt;span>col&lt;/span>&lt;span>]&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#D73A49, #F97583);"> if&lt;/span>&lt;span> current&lt;/span>&lt;span>.&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);">Equals&lt;/span>&lt;span>(&lt;/span>&lt;span>winner&lt;/span>&lt;span>)&lt;/span>&lt;span> {&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#6F42C1, #B392F0);"> removeChars&lt;/span>&lt;span>(&lt;/span>&lt;span>buffer&lt;/span>&lt;span>,&lt;/span>&lt;span> col&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);">+&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);">1&lt;/span>&lt;span>)&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#D73A49, #F97583);"> for&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> range&lt;/span>&lt;span> board&lt;/span>&lt;span>[&lt;/span>&lt;span>line&lt;/span>&lt;span>]&lt;/span>&lt;span> {&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span> buffer&lt;/span>&lt;span>.&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);">WriteString&lt;/span>&lt;span>(&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">&amp;quot;&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">-&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">&amp;quot;&lt;/span>&lt;span>)&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span> }&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span> }&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;/span>
&lt;span class="giallo-l">&lt;span> buffer&lt;/span>&lt;span>.&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);">WriteString&lt;/span>&lt;span>(&lt;/span>&lt;span>current&lt;/span>&lt;span>.&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);">Letter&lt;/span>&lt;span>(&lt;/span>&lt;span>)&lt;/span>&lt;span>)&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#D73A49, #F97583);"> return&lt;/span>&lt;span> current&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span>}&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;h3 id="moviendo-los-caballos">Moviendo los caballos
&lt;a class="heading-anchor" href="#moviendo-los-caballos" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;p>En &lt;code>main(...)&lt;/code>, el &lt;code>winnerChan&lt;/code> es un canal compartido que usará el primer Caballo que llegue a la última posición de su línea.&lt;/p>
&lt;p>Cada Caballo ejecuta un bucle hasta llegar al final de la línea o recibir (vía &lt;code>winnerChan&lt;/code>) el mensaje de que otro Caballo ya ganó. Hasta entonces, cada caballo se mueve de forma independiente, durmiendo milisegundos aleatorios antes de avanzar a la siguiente posición.&lt;/p>
&lt;blockquote>
&lt;p>&lt;code>startRuningHorseInLine()&lt;/code> se ejecuta en otro proceso usando &lt;code>go&lt;/code>.&lt;/p>
&lt;/blockquote>
&lt;pre class="giallo" style="color-scheme: light dark; color: light-dark(#24292E, #E1E4E8); background-color: light-dark(#FFFFFF, #24292E);">&lt;code data-lang="go">&lt;span class="giallo-l">&lt;span style="color: light-dark(#D73A49, #F97583);">func&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);"> main&lt;/span>&lt;span>(&lt;/span>&lt;span>)&lt;/span>&lt;span> {&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#6A737D, #6A737D);"> //&lt;/span>&lt;span style="color: light-dark(#6A737D, #6A737D);">...&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span> winnerChan&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> :=&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);"> make&lt;/span>&lt;span>(&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);">chan&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);"> Horse&lt;/span>&lt;span>)&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#D73A49, #F97583);"> for&lt;/span>&lt;span> line&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> :=&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> range&lt;/span>&lt;span> board&lt;/span>&lt;span> {&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#6A737D, #6A737D);"> //&lt;/span>&lt;span style="color: light-dark(#6A737D, #6A737D);"> cada caballo será movido en diferentes procesos&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#D73A49, #F97583);"> go&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);"> startHorseRunning&lt;/span>&lt;span>(&lt;/span>&lt;span>board&lt;/span>&lt;span>,&lt;/span>&lt;span> line&lt;/span>&lt;span>,&lt;/span>&lt;span> winnerChan&lt;/span>&lt;span>)&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span> }&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#6A737D, #6A737D);"> //&lt;/span>&lt;span style="color: light-dark(#6A737D, #6A737D);"> esperar hasta que un caballo llegue al final&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span> winner&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> :=&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> &amp;lt;-&lt;/span>&lt;span>winnerChan&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#6A737D, #6A737D);"> //&lt;/span>&lt;span style="color: light-dark(#6A737D, #6A737D);">...&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span>}&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#D73A49, #F97583);">func&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);"> startRunningHorseInLine&lt;/span>&lt;span>(&lt;/span>&lt;span style="color: light-dark(#E36209, #FFAB70);">board&lt;/span>&lt;span> [&lt;/span>&lt;span>]&lt;/span>&lt;span>[&lt;/span>&lt;span>]&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);">*&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);">Horse&lt;/span>&lt;span>,&lt;/span>&lt;span style="color: light-dark(#E36209, #FFAB70);"> line&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> int&lt;/span>&lt;span>,&lt;/span>&lt;span style="color: light-dark(#E36209, #FFAB70);"> winnerChan&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> chan&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);"> Horse&lt;/span>&lt;span>)&lt;/span>&lt;span> {&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#D73A49, #F97583);"> for&lt;/span>&lt;span> {&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#D73A49, #F97583);"> select&lt;/span>&lt;span> {&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#D73A49, #F97583);"> case&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> &amp;lt;-&lt;/span>&lt;span>winnerChan&lt;/span>&lt;span>:&lt;/span>&lt;span style="color: light-dark(#6A737D, #6A737D);"> //&lt;/span>&lt;span style="color: light-dark(#6A737D, #6A737D);"> verificar si otro caballo terminó&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#D73A49, #F97583);"> return&lt;/span>&lt;span style="color: light-dark(#6A737D, #6A737D);"> //&lt;/span>&lt;span style="color: light-dark(#6A737D, #6A737D);"> en tal caso, entonces detener el bucle for&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#D73A49, #F97583);"> default&lt;/span>&lt;span>:&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span> time&lt;/span>&lt;span>.&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);">Sleep&lt;/span>&lt;span>(&lt;/span>&lt;span>time&lt;/span>&lt;span>.&lt;/span>&lt;span>Millisecond&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> *&lt;/span>&lt;span> time&lt;/span>&lt;span>.&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);">Duration&lt;/span>&lt;span>(&lt;/span>&lt;span>rand&lt;/span>&lt;span>.&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);">Intn&lt;/span>&lt;span>(&lt;/span>&lt;span>maxSleepDelay&lt;/span>&lt;span>)&lt;/span>&lt;span>)&lt;/span>&lt;span>)&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#6F42C1, #B392F0);"> moveHorseOnePos&lt;/span>&lt;span>(&lt;/span>&lt;span>board&lt;/span>&lt;span>,&lt;/span>&lt;span> line&lt;/span>&lt;span>,&lt;/span>&lt;span> winnerChan&lt;/span>&lt;span>)&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span> }&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span> }&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span>}&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#D73A49, #F97583);">func&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);"> moveHorseOnePos&lt;/span>&lt;span>(&lt;/span>&lt;span style="color: light-dark(#E36209, #FFAB70);">board&lt;/span>&lt;span> [&lt;/span>&lt;span>]&lt;/span>&lt;span>[&lt;/span>&lt;span>]&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);">*&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);">Horse&lt;/span>&lt;span>,&lt;/span>&lt;span style="color: light-dark(#E36209, #FFAB70);"> line&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> int&lt;/span>&lt;span>,&lt;/span>&lt;span style="color: light-dark(#E36209, #FFAB70);"> winnerChan&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> chan&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);"> Horse&lt;/span>&lt;span>)&lt;/span>&lt;span> {&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span> cols&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> :=&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);"> len&lt;/span>&lt;span>(&lt;/span>&lt;span>board&lt;/span>&lt;span>[&lt;/span>&lt;span>line&lt;/span>&lt;span>]&lt;/span>&lt;span>)&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#D73A49, #F97583);"> for&lt;/span>&lt;span> col&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> :=&lt;/span>&lt;span> cols&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> -&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);"> 1&lt;/span>&lt;span>;&lt;/span>&lt;span> col&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> &amp;gt;&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);"> 0&lt;/span>&lt;span>;&lt;/span>&lt;span> col&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);">--&lt;/span>&lt;span> {&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#D73A49, #F97583);"> if&lt;/span>&lt;span> board&lt;/span>&lt;span>[&lt;/span>&lt;span>line&lt;/span>&lt;span>]&lt;/span>&lt;span>[&lt;/span>&lt;span>col&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);">-&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);">1&lt;/span>&lt;span>]&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> ==&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);"> nil&lt;/span>&lt;span> {&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#D73A49, #F97583);"> continue&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span> }&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#6A737D, #6A737D);"> //&lt;/span>&lt;span style="color: light-dark(#6A737D, #6A737D);"> aquí identificamos que hay un caballo en&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#6A737D, #6A737D);"> //&lt;/span>&lt;span style="color: light-dark(#6A737D, #6A737D);"> la siguiente columna, así que lo movemos a la&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#6A737D, #6A737D);"> //&lt;/span>&lt;span style="color: light-dark(#6A737D, #6A737D);"> columna actual, y ponemos `nil` en la otra&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span> board&lt;/span>&lt;span>[&lt;/span>&lt;span>line&lt;/span>&lt;span>]&lt;/span>&lt;span>[&lt;/span>&lt;span>col&lt;/span>&lt;span>]&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> =&lt;/span>&lt;span> board&lt;/span>&lt;span>[&lt;/span>&lt;span>line&lt;/span>&lt;span>]&lt;/span>&lt;span>[&lt;/span>&lt;span>col&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);">-&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);">1&lt;/span>&lt;span>]&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span> board&lt;/span>&lt;span>[&lt;/span>&lt;span>line&lt;/span>&lt;span>]&lt;/span>&lt;span>[&lt;/span>&lt;span>col&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);">-&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);">1&lt;/span>&lt;span>]&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> =&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);"> nil&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#D73A49, #F97583);"> if&lt;/span>&lt;span> col&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);">+&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);">1&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> ==&lt;/span>&lt;span> cols&lt;/span>&lt;span> {&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span> winnerChan&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> &amp;lt;-&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> *&lt;/span>&lt;span>board&lt;/span>&lt;span>[&lt;/span>&lt;span>line&lt;/span>&lt;span>]&lt;/span>&lt;span>[&lt;/span>&lt;span>col&lt;/span>&lt;span>]&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span> }&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#D73A49, #F97583);"> break&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span> }&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span>}&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;h3 id="codigo-fuente">Código fuente
&lt;a class="heading-anchor" href="#codigo-fuente" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;p>El código de este post es una versión simplificada. Si quieres ver el código completo funcionando, está aquí: &lt;a rel="external" href="https://github.com/Chemaclass/go-horse-racing">Chemaclass/go-horse-racing&lt;/a>.&lt;/p>
&lt;aside class="kudos">
&lt;span class="kudos__icon" aria-hidden="true">🧠&lt;/span>
&lt;div class="kudos__content">
&lt;p>Gracias a mi antiguo Team Lead, Andrei Boar, que me ayudó a revisar mi solución original y proporcionó una &lt;a rel="external" href="https://gist.github.com/zuzuleinen/79413aa7933d7d6c6d84ec6ba8c3910a">solución alternativa&lt;/a> (más simple y mejor) que apliqué a mi código. Lo principal que aprendí fue usar un &lt;code>chan Horse&lt;/code> para pasar el Caballo ganador desde &lt;code>main()&lt;/code>, en vez de usar un &lt;code>chan bool&lt;/code> y un &lt;code>sync.WaitGroup&lt;/code> entre todos los hilos.&lt;/p>
&lt;/div>
&lt;/aside></content></entry><entry xml:lang="es"><title>Gran Ingeniería</title><subtitle>Un gran ingeniero no es solo un gran programador</subtitle><category term="software-design" scheme="https://chemaclass.com/tags/software-design/" label="Software Design"/><category term="career" scheme="https://chemaclass.com/tags/career/" label="Career"/><category term="communication" scheme="https://chemaclass.com/tags/communication/" label="Communication"/><category term="clean-code" scheme="https://chemaclass.com/tags/clean-code/" label="Clean Code"/><published>2023-12-30T00:00:00+00:00</published><updated>2023-12-30T00:00:00+00:00</updated><author><name>
Chemaclass</name></author><link rel="alternate" type="text/html" href="https://chemaclass.com/es/blog/great-engineering/"/><id>https://chemaclass.com/es/blog/great-engineering/</id><summary type="html">Programar no es solo otro trabajo. En el entorno adecuado, escribir software puede ser realmente divertido y, aún más, ¡puede ser tu hobby personal también! Así que... podrías estar enfocado en programar, programar y más programar para subir de nivel tus propias habilidades profesionales.</summary><content type="html">&lt;p>Programar no es solo otro trabajo. Escribir software puede ser realmente divertido y, aún más, ¡puede ser tu hobby personal también! Podrías estar enfocado en programar, programar y más programar para subir de nivel tus propias habilidades profesionales.&lt;/p>
&lt;span id="continue-reading">&lt;/span>
&lt;p>Eso no tiene nada de malo. La práctica hace al maestro, y programar mucho te ayudará a mejorar tus habilidades de codificación. Pero hay &lt;a href="/es/blog/the-path-to-seniority-in-software/">otros aspectos&lt;/a> que debes tener en cuenta para crecer como gran ingeniero.&lt;/p>
&lt;p>Como ingeniero de software, tu trabajo no es “solo escribir código”, sino &lt;strong>usar el software para resolver problemas reales de negocio&lt;/strong>. Para lograrlo, existen muchas metodologías. Pero en algo hay que estar de acuerdo: necesitas identificar y entender las necesidades de tu cliente para saber qué construir.&lt;/p>
&lt;p>Necesitas conocer tu producto, al menos hasta cierto nivel, para diseñar tu software usando un lenguaje cercano al negocio. Esto ayuda a su evolución y calidad, y facilita el mantenimiento presente y futuro.&lt;/p>
&lt;p>IT, Software, Producto y Personas están muy conectados. Entender la relación entre estos campos ayuda a cada persona a cumplir mejor sus objetivos.&lt;/p>
&lt;p>Un gran trabajo en equipo no es solo la suma de las partes: multiplica el valor creado entre los compañeros. Para eso, saber comunicar bien es clave para generar claridad a cualquier nivel.&lt;/p>
&lt;p>Por eso un gran ingeniero conoce de negocio, cliente, producto y programación. Entender estos puntos marca la diferencia entre un ingeniero promedio y uno excelente.&lt;/p>
&lt;hr />
&lt;p>Imagen original de &lt;a rel="external" href="https://hybridhacker.email">Nicola Ballotta&lt;/a>.&lt;/p></content></entry><entry xml:lang="es"><title>¿Cómo Testear Métodos Privados?</title><subtitle>Testeando métodos privados. ¿Cuándo y cómo?</subtitle><category term="testing" scheme="https://chemaclass.com/tags/testing/" label="Testing"/><category term="tdd" scheme="https://chemaclass.com/tags/tdd/" label="Tdd"/><category term="software-design" scheme="https://chemaclass.com/tags/software-design/" label="Software Design"/><category term="clean-code" scheme="https://chemaclass.com/tags/clean-code/" label="Clean Code"/><published>2023-10-20T00:00:00+00:00</published><updated>2023-10-20T00:00:00+00:00</updated><author><name>
Chemaclass</name></author><link rel="alternate" type="text/html" href="https://chemaclass.com/es/blog/how-to-test-private-methods/"/><id>https://chemaclass.com/es/blog/how-to-test-private-methods/</id><summary type="html">De vez en cuando he tenido que enfrentar esta pregunta: ¿cómo testear métodos privados? He recopilado en un artículo las técnicas que suelo usar.</summary><content type="html">&lt;p>Esta pregunta me la han hecho muchas veces a lo largo de los años. Aquí recopilo mis ideas al respecto.&lt;/p>
&lt;span id="continue-reading">&lt;/span>&lt;h2 id="respuesta-corta">Respuesta corta
&lt;a class="heading-anchor" href="#respuesta-corta" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h2>
&lt;p>Nunca.&lt;/p>
&lt;h2 id="respuesta-larga">Respuesta larga
&lt;a class="heading-anchor" href="#respuesta-larga" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h2>
&lt;p>Nunca jamás.&lt;/p>
&lt;hr />
&lt;h2 id="y-si">¿Y si…?
&lt;a class="heading-anchor" href="#y-si" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h2>
&lt;p>Si realmente quieres testear un método privado, considera extraer esa lógica del método privado en una clase separada, y escribe un test unitario para el comportamiento de esa clase.&lt;/p>
&lt;blockquote>
&lt;p>Para este, me inspiré en el &lt;a rel="external" href="https://franiglesias.github.io/test-private-methods/">post original&lt;/a> de Fran Iglesias.&lt;/p>
&lt;/blockquote></content></entry><entry xml:lang="es"><title>Introduciendo un Nuevo Stack Tecnológico</title><subtitle>Cómo introducir nuevas tecnologías en tu equipo</subtitle><category term="software-design" scheme="https://chemaclass.com/tags/software-design/" label="Software Design"/><category term="architecture" scheme="https://chemaclass.com/tags/architecture/" label="Architecture"/><category term="team-management" scheme="https://chemaclass.com/tags/team-management/" label="Team Management"/><category term="communication" scheme="https://chemaclass.com/tags/communication/" label="Communication"/><published>2023-04-14T00:00:00+00:00</published><updated>2023-04-14T00:00:00+00:00</updated><author><name>
Chemaclass</name></author><link rel="alternate" type="text/html" href="https://chemaclass.com/es/blog/introducing-a-new-tech-stack/"/><id>https://chemaclass.com/es/blog/introducing-a-new-tech-stack/</id><summary type="html">Cuando introduces una nueva tecnología en tu equipo, necesitas explicar el porqué y tener una estrategia clara. Va a afectar a todos.</summary><content type="html">&lt;p>Cuando introduces una nueva tecnología en tu equipo, necesitas explicar el porqué y tener una estrategia clara. Va a afectar a todos.&lt;/p>
&lt;span id="continue-reading">&lt;/span>&lt;h2 id="por-que-ese-nuevo-stack-tecnologico">¿Por qué ese nuevo stack tecnológico?
&lt;a class="heading-anchor" href="#por-que-ese-nuevo-stack-tecnologico" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h2>
&lt;p>Antes de decidir, recuerda que es una decisión de equipo. Piensa en la estandarización y mantenibilidad del proyecto. Pero lo más importante: ¿qué problema quieres resolver? ¿Es porque mola? ¿O hay una necesidad real que esta tecnología resuelve?&lt;/p>
&lt;h3 id="la-direccion-de-la-tecnologia">La dirección de la tecnología
&lt;a class="heading-anchor" href="#la-direccion-de-la-tecnologia" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;p>Cuando propones adoptar una nueva biblioteca, framework o tecnología, hay que conocer su trasfondo y hacia dónde se dirige.&lt;/p>
&lt;p>¿Cuál es la motivación detrás de esa tecnología? ¿Por qué quieres añadirla a tu stack actual?&lt;/p>
&lt;h3 id="acoplamiento-y-dependencias">Acoplamiento y dependencias
&lt;a class="heading-anchor" href="#acoplamiento-y-dependencias" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;p>Al adoptar nuevas tecnologías en el día a día, es fácil acoplarse a ellas. Eso hace más difícil dar marcha atrás si después nos arrepentimos.&lt;/p>
&lt;p>No me malinterpretes: aprender y experimentar con nuevas tecnologías está genial. Pero introducirlas en tu trabajo diario es otra historia. Afecta a todo el equipo, así que hay que ser cuidadosos.&lt;/p>
&lt;p>&lt;img src="/images/blog/2023-04-14/middle.webp" alt="blog-middle" />&lt;/p>
&lt;h2 id="el-enfoque-de-la-conversacion">El enfoque de la conversación
&lt;a class="heading-anchor" href="#el-enfoque-de-la-conversacion" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h2>
&lt;ul>
&lt;li>¿Qué aporta esta nueva tecnología al proyecto?&lt;/li>
&lt;li>¿Qué problema queremos resolver?&lt;/li>
&lt;li>¿Podemos resolverlo con nuestra tecnología actual?&lt;/li>
&lt;li>Si ya tenemos algo similar, ¿queremos mezclar ambas?&lt;/li>
&lt;li>¿Cuáles son los trade-offs de usarla vs. no usarla?&lt;/li>
&lt;li>¿Vale la pena la complejidad extra a largo plazo?&lt;/li>
&lt;li>¿Cuál es la estrategia para que todos se suban al carro?&lt;/li>
&lt;/ul>
&lt;h3 id="architectural-decision-records-adrs">Architectural Decision Records (ADRs)
&lt;a class="heading-anchor" href="#architectural-decision-records-adrs" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;p>Sea cual sea el resultado, escríbelo como un &lt;a rel="external" href="https://adr.github.io/">ADR&lt;/a> para poder revisarlo con el tiempo. Un ADR documenta las decisiones del equipo: pros, contras y los argumentos que encontrasteis juntos para decidir qué hacer y por qué.&lt;/p>
&lt;p>Los ADRs ayudan a entender decisiones antiguas. Guárdalos en el control de versiones, en el mismo proyecto si es posible. Son útiles para el equipo actual y para los nuevos que lleguen.&lt;/p>
&lt;p>&lt;img src="/images/blog/2023-04-14/footer.webp" alt="blog-footer" />&lt;/p>
&lt;aside class="kudos">
&lt;span class="kudos__icon" aria-hidden="true">🧠&lt;/span>
&lt;div class="kudos__content">
&lt;p>Gracias a mis amigos &lt;a rel="external" href="https://x.com/evrtrabajo">Manu&lt;/a>, &lt;a rel="external" href="https://x.com/Tito_Kati">Antonio&lt;/a> y &lt;a rel="external" href="https://x.com/JesusValera96">Jesus&lt;/a>, que me ayudaron a crear este resumen de ideas haciendo brainstorming juntos.&lt;/p>
&lt;/div>
&lt;/aside></content></entry><entry xml:lang="es"><title>Accelerate</title><subtitle>Construyendo y Escalando Organizaciones Tecnológicas de Alto Rendimiento</subtitle><category term="devops" scheme="https://chemaclass.com/tags/devops/" label="Devops"/><category term="software-design" scheme="https://chemaclass.com/tags/software-design/" label="Software Design"/><category term="agile" scheme="https://chemaclass.com/tags/agile/" label="Agile"/><category term="productivity" scheme="https://chemaclass.com/tags/productivity/" label="Productivity"/><published>2023-03-19T00:00:00+00:00</published><updated>2023-03-19T00:00:00+00:00</updated><author><name>
Nicole Forsgren</name></author><author><name>
Jez Humble</name></author><author><name>
Gene Kim</name></author><link rel="alternate" type="text/html" href="https://chemaclass.com/es/readings/accelerate/"/><id>https://chemaclass.com/es/readings/accelerate/</id><summary type="html">Cómo medir el rendimiento de equipos de software y cómo ese rendimiento impacta a toda la organización. La ciencia detrás de Lean Software y DevOps.</summary><content type="html">&lt;span id="continue-reading">&lt;/span>
&lt;p>Accelerate explora cómo los equipos que usan &lt;strong>Lean Software&lt;/strong> y &lt;strong>DevOps&lt;/strong> pueden medir su rendimiento. También muestra cómo el rendimiento de ingeniería impacta a toda la organización.&lt;/p>
&lt;blockquote>
&lt;p>Nota: DevOps integra y automatiza el desarrollo de software (Dev) con las operaciones de TI (Ops). El foco: mejorar y acortar el ciclo de vida de desarrollo.&lt;/p>
&lt;/blockquote>
&lt;h2 id="capacidades-clave">Capacidades Clave
&lt;a class="heading-anchor" href="#capacidades-clave" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h2>
&lt;h3 id="entrega-continua">Entrega Continua
&lt;a class="heading-anchor" href="#entrega-continua" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;ul>
&lt;li>Usar Control de Versiones para todos los Artefactos de Producción&lt;/li>
&lt;li>Automatizar tu Proceso de Despliegue&lt;/li>
&lt;li>Implementar Integración Continua&lt;/li>
&lt;li>Usar Métodos de Desarrollo Basado en Trunk&lt;/li>
&lt;li>Implementar Automatización de Tests&lt;/li>
&lt;li>Entrega Continua (CD)&lt;/li>
&lt;/ul>
&lt;h3 id="arquitectura">Arquitectura
&lt;a class="heading-anchor" href="#arquitectura" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;ul>
&lt;li>Usar una Arquitectura Débilmente Acoplada&lt;/li>
&lt;/ul>
&lt;h3 id="producto-y-proceso">Producto y Proceso
&lt;a class="heading-anchor" href="#producto-y-proceso" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;ul>
&lt;li>Recopilar e Implementar Feedback del Cliente&lt;/li>
&lt;li>Hacer Visible el Flujo de Trabajo a través del Value Stream&lt;/li>
&lt;li>Trabajar en Lotes Pequeños&lt;/li>
&lt;li>Fomentar y Habilitar la Experimentación del Equipo&lt;/li>
&lt;/ul>
&lt;h3 id="gestion-lean-y-monitoreo">Gestión Lean y Monitoreo
&lt;a class="heading-anchor" href="#gestion-lean-y-monitoreo" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;ul>
&lt;li>Tener Procesos Ligeros de Aprobación de Cambios&lt;/li>
&lt;li>Monitorear la Aplicación e Infraestructura para Informar Decisiones de Negocio&lt;/li>
&lt;li>Verificar la Salud del Sistema Proactivamente&lt;/li>
&lt;li>Mejorar Procesos y Gestionar el Trabajo con Límites WIP (Work-In-Process)&lt;/li>
&lt;li>Visualizar el Trabajo para Monitorear la Calidad y Comunicar a través del Equipo&lt;/li>
&lt;/ul>
&lt;h3 id="cultural">Cultural
&lt;a class="heading-anchor" href="#cultural" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;ul>
&lt;li>Apoyar una Cultura Generativa&lt;/li>
&lt;li>Fomentar y Apoyar el Aprendizaje&lt;/li>
&lt;li>Apoyar y Facilitar la Colaboración entre Equipos&lt;/li>
&lt;li>Proporcionar Recursos y Herramientas que Hacen el Trabajo Significativo&lt;/li>
&lt;li>Apoyar o Encarnar el Liderazgo Transformacional&lt;/li>
&lt;/ul>
&lt;h2 id="cuatro-metricas-clave">Cuatro Métricas Clave
&lt;a class="heading-anchor" href="#cuatro-metricas-clave" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h2>
&lt;ul>
&lt;li>&lt;strong>Lead Time de Cambio&lt;/strong>
&lt;ul>
&lt;li>Tiempo para implementar, probar y entregar código para una funcionalidad&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;strong>Frecuencia de Despliegue&lt;/strong>
&lt;ul>
&lt;li>Número de despliegues en un período de tiempo dado&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;strong>Tasa de Fallo de Cambios&lt;/strong>
&lt;ul>
&lt;li>Porcentaje de cambios fallidos sobre todos los cambios (independientemente del éxito)&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;strong>Tiempo Medio de Recuperación&lt;/strong>
&lt;ul>
&lt;li>Tiempo que toma restaurar el servicio después de un fallo en producción&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;div style="position:relative;aspect-ratio:16/9;width:100%;">
&lt;iframe
src="https://www.youtube-nocookie.com/embed/_d9cws_T9qk"
title="YouTube video"
width="560"
height="315"
loading="lazy"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
referrerpolicy="strict-origin-when-cross-origin"
style="position:absolute;inset:0;width:100%;height:100%;border:0;"
allowfullscreen>
&lt;/iframe>
&lt;/div></content></entry><entry xml:lang="es"><title>Recipes for Decoupling</title><category term="php" scheme="https://chemaclass.com/tags/php/" label="Php"/><category term="software-design" scheme="https://chemaclass.com/tags/software-design/" label="Software Design"/><category term="architecture" scheme="https://chemaclass.com/tags/architecture/" label="Architecture"/><category term="clean-code" scheme="https://chemaclass.com/tags/clean-code/" label="Clean Code"/><published>2022-11-28T00:00:00+00:00</published><updated>2022-11-28T00:00:00+00:00</updated><author><name>
Matthias Noback</name></author><link rel="alternate" type="text/html" href="https://chemaclass.com/es/readings/recipes-for-decoupling/"/><id>https://chemaclass.com/es/readings/recipes-for-decoupling/</id><summary type="html">¿Qué es el acoplamiento y por qué nos perjudica? Este libro recopila estrategias prácticas para separar tu código de dominio de la infraestructura y mantener un sistema sano a largo plazo.</summary><content type="html">&lt;span id="continue-reading">&lt;/span>
&lt;p>¿Qué es el acoplamiento y por qué nos perjudica? ¿Cómo desacoplar de forma eficiente? Este libro recopila estrategias para separar tu código de dominio de los detalles de infraestructura. El resultado: un sistema más sano a largo plazo.&lt;/p>
&lt;p>Aprenderás a crear reglas de &lt;a rel="external" href="https://phpstan.org/">&lt;strong>PHPStan&lt;/strong>&lt;/a> desde cero. Además, el libro te guía por múltiples oportunidades de desacoplamiento:&lt;/p>
&lt;ul>
&lt;li>framework web&lt;/li>
&lt;li>frameworks cli&lt;/li>
&lt;li>validación de formularios&lt;/li>
&lt;li>orm y base de datos&lt;/li>
&lt;li>framework de testing&lt;/li>
&lt;/ul>
&lt;p>Lee más sobre el libro: &lt;a rel="external" href="https://matthiasnoback.nl/book/recipes-for-decoupling/">matthiasnoback.nl/book/recipes-for-decoupling/&lt;/a>&lt;/p>
&lt;blockquote>
&lt;p>Cómpralo aquí: &lt;a rel="external" href="https://leanpub.com/recipes-for-decoupling">leanpub.com/recipes-for-decoupling&lt;/a>&lt;/p>
&lt;/blockquote></content></entry><entry xml:lang="es"><title>Ingeniería de Software Moderna</title><subtitle>Haciendo lo que funciona para construir mejor software más rápido</subtitle><category term="software-design" scheme="https://chemaclass.com/tags/software-design/" label="Software Design"/><category term="testing" scheme="https://chemaclass.com/tags/testing/" label="Testing"/><category term="architecture" scheme="https://chemaclass.com/tags/architecture/" label="Architecture"/><category term="agile" scheme="https://chemaclass.com/tags/agile/" label="Agile"/><published>2022-06-29T00:00:00+00:00</published><updated>2022-06-29T00:00:00+00:00</updated><author><name>
David Farley</name></author><link rel="alternate" type="text/html" href="https://chemaclass.com/es/readings/modern-software-engineering/"/><id>https://chemaclass.com/es/readings/modern-software-engineering/</id><summary type="html">El desarrollo de software como práctica de ingeniería real. Para dominarlo hay que ser experto en aprender y gestionar la complejidad.</summary><content type="html">&lt;span id="continue-reading">&lt;/span>
&lt;p>El libro presenta el desarrollo de software como una práctica de ingeniería real. Para dominarlo hay que ser experto en aprender y gestionar la complejidad.&lt;/p>
&lt;h3 id="optimizar-para-aprender">Optimizar para aprender
&lt;a class="heading-anchor" href="#optimizar-para-aprender" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;p>El libro presenta cinco comportamientos clave para aprender mejor:&lt;/p>
&lt;ul>
&lt;li>Trabajar de forma iterativa&lt;/li>
&lt;li>Buscar feedback&lt;/li>
&lt;li>Incrementalismo&lt;/li>
&lt;li>Empirismo&lt;/li>
&lt;li>Ser experimental&lt;/li>
&lt;/ul>
&lt;p>La idea central: trabajar en pasos pequeños, recoger feedback y ajustar.&lt;/p>
&lt;h3 id="optimizar-para-gestionar-la-complejidad">Optimizar para gestionar la complejidad
&lt;a class="heading-anchor" href="#optimizar-para-gestionar-la-complejidad" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;p>Cinco ideas para manejar la complejidad:&lt;/p>
&lt;ul>
&lt;li>Modularidad&lt;/li>
&lt;li>Cohesión&lt;/li>
&lt;li>Separación de responsabilidades&lt;/li>
&lt;li>Ocultación de información y abstracción&lt;/li>
&lt;li>Gestión del acoplamiento&lt;/li>
&lt;/ul>
&lt;p>Gestionar la complejidad de nuestros sistemas es fundamental.&lt;/p>
&lt;h3 id="herramientas-para-apoyar-la-ingenieria">Herramientas para apoyar la ingeniería
&lt;a class="heading-anchor" href="#herramientas-para-apoyar-la-ingenieria" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;p>El libro profundiza en ideas como:&lt;/p>
&lt;ul>
&lt;li>Testeabilidad&lt;/li>
&lt;li>Desplegabilidad&lt;/li>
&lt;li>Control de variables&lt;/li>
&lt;li>Entrega continua&lt;/li>
&lt;/ul>
&lt;hr />
&lt;p>Un vídeo donde el autor explica las ideas principales del libro:&lt;/p>
&lt;div style="position:relative;aspect-ratio:16/9;width:100%;">
&lt;iframe
src="https://www.youtube-nocookie.com/embed/TRqYQnCfgH8"
title="YouTube video"
width="560"
height="315"
loading="lazy"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
referrerpolicy="strict-origin-when-cross-origin"
style="position:absolute;inset:0;width:100%;height:100%;border:0;"
allowfullscreen>
&lt;/iframe>
&lt;/div></content></entry><entry xml:lang="es"><title>Modern CTO</title><category term="leadership" scheme="https://chemaclass.com/tags/leadership/" label="Leadership"/><category term="team-management" scheme="https://chemaclass.com/tags/team-management/" label="Team Management"/><category term="software-design" scheme="https://chemaclass.com/tags/software-design/" label="Software Design"/><category term="communication" scheme="https://chemaclass.com/tags/communication/" label="Communication"/><published>2022-01-23T00:00:00+00:00</published><updated>2022-01-23T00:00:00+00:00</updated><author><name>
Joel Beasley</name></author><link rel="alternate" type="text/html" href="https://chemaclass.com/es/readings/modern-cto/"/><id>https://chemaclass.com/es/readings/modern-cto/</id><summary type="html">Joel Beasley ofrece una guía práctica para pasar de desarrollador a CTO. Comparte desde su experiencia los retos, las lecciones aprendidas y los errores típicos en este camino.</summary><content type="html">&lt;span id="continue-reading">&lt;/span>
&lt;p>Los desarrolladores no son CTOs, pero pueden aprender a serlo.&lt;/p>
&lt;p>Joel Beasley ofrece una guía práctica para pasar de desarrollador a CTO. Comparte desde su experiencia los retos, las lecciones aprendidas y los errores típicos en este camino.&lt;/p>
&lt;p>Estos son los temas que encontrarás en el libro:&lt;/p>
&lt;h4 id="un-cto-moderno-sabe">Un CTO moderno sabe…
&lt;a class="heading-anchor" href="#un-cto-moderno-sabe" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h4>
&lt;ul>
&lt;li>Los desarrolladores no son CTOs&lt;/li>
&lt;li>La epidemia del código espagueti MVP&lt;/li>
&lt;li>La sobre-ingeniería es un problema&lt;/li>
&lt;li>Si contratar, comprar o superar a la competencia&lt;/li>
&lt;li>Cómo no escalar prematuramente&lt;/li>
&lt;li>Cómo resolver cualquier problema&lt;/li>
&lt;li>Cómo trabajar con programadores cuando no eres uno&lt;/li>
&lt;li>Errores de UX a tener en cuenta&lt;/li>
&lt;li>Cuándo hablar&lt;/li>
&lt;li>Cuándo contratar y despedir consultores&lt;/li>
&lt;li>Cómo analizar el fracaso&lt;/li>
&lt;li>Cómo recuperarse de restricciones imprevistas&lt;/li>
&lt;li>Responder la pregunta: “¿Qué tan difícil es codificar…?”&lt;/li>
&lt;li>Cómo evitar al “tipo del noveno inning”&lt;/li>
&lt;li>Cuándo responder a la retroalimentación&lt;/li>
&lt;li>Cómo validar a un experto en cualquier campo&lt;/li>
&lt;li>Cómo comunicar efectivamente ideas complejas&lt;/li>
&lt;/ul>
&lt;h3 id="citas-favoritas">Citas favoritas
&lt;a class="heading-anchor" href="#citas-favoritas" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;blockquote>
&lt;p>Si me apoyo en logros pasados, nunca creceré.&lt;/p>
&lt;/blockquote>
&lt;blockquote>
&lt;p>APROVECHA LA EXPERIENCIA DE OTROS. Los libros condensan toda una vida de experiencia en unas pocas horas de lectura.&lt;/p>
&lt;/blockquote>
&lt;blockquote>
&lt;p>Solo hay dos razones por las que escribes mal código:&lt;/p>
&lt;ol>
&lt;li>Sabes cómo escribir buen código, pero eliges escribir mal código.&lt;/li>
&lt;li>No sabes cómo escribir buen código. Y ambas apestan.&lt;/li>
&lt;/ol>
&lt;/blockquote>
&lt;blockquote>
&lt;p>Como CTO, debes tener un enfoque de negocio.&lt;/p>
&lt;/blockquote>
&lt;blockquote>
&lt;p>Siempre vuelve a tus metas principales. […] Me aseguro de que cada meta tenga un “por qué” claro detrás. Así, cuando me pierdo, vuelvo a mi “por qué”.&lt;/p>
&lt;/blockquote>
&lt;ul>
&lt;li>Referencia a “&lt;a href="/es/readings/start-with-why">Empieza con el Por Qué&lt;/a>” de Simon Sinek.&lt;/li>
&lt;/ul>
&lt;blockquote>
&lt;p>Cuando eres el jefe, recuerda esta regla de oro: Pregunta a la gente qué piensa en lugar de decirles qué hacer.&lt;/p>
&lt;/blockquote>
&lt;blockquote>
&lt;p>Si no puedo evaluar el componente humano, no puedo liderar un equipo. […] La composición del equipo pesa tanto o más que la experiencia técnica.&lt;/p>
&lt;/blockquote>
&lt;blockquote>
&lt;p>Como CTO, si no puedes explicar el valor de forma simple, significa que no entiendes el valor de negocio detrás de tu tecnología.&lt;/p>
&lt;/blockquote></content></entry><entry xml:lang="es"><title>London vs Chicago</title><subtitle>Es una integración, no una elección</subtitle><category term="tdd" scheme="https://chemaclass.com/tags/tdd/" label="Tdd"/><category term="testing" scheme="https://chemaclass.com/tags/testing/" label="Testing"/><category term="software-design" scheme="https://chemaclass.com/tags/software-design/" label="Software Design"/><category term="refactoring" scheme="https://chemaclass.com/tags/refactoring/" label="Refactoring"/><published>2021-11-20T00:00:00+00:00</published><updated>2021-11-20T00:00:00+00:00</updated><author><name>
Chemaclass</name></author><link rel="alternate" type="text/html" href="https://chemaclass.com/es/blog/london-vs-chicago/"/><id>https://chemaclass.com/es/blog/london-vs-chicago/</id><summary type="html">Hay dos escuelas conocidas en TDD: la escuela mockista (también conocida como Outside-in) y la escuela clasicista (también conocida como Inside-out).</summary><content type="html">&lt;p>Hay dos escuelas conocidas en TDD: la escuela mockista (también conocida como Outside-in) y la escuela clasicista (también conocida como Inside-out).&lt;/p>
&lt;span id="continue-reading">&lt;/span>&lt;h3 id="por-que-london-y-chicago">¿Por qué London y Chicago?
&lt;a class="heading-anchor" href="#por-que-london-y-chicago" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;p>Dos empresas, una de Londres y otra de Chicago, afirmaban hacer TDD pero con enfoques diferentes. La de Londres construía software de afuera hacia adentro; la de Chicago, de adentro hacia afuera. Veamos cada una.&lt;/p>
&lt;h2 id="outside-in-escuela-de-londres">Outside-in: Escuela de Londres
&lt;a class="heading-anchor" href="#outside-in-escuela-de-londres" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h2>
&lt;p>Un enfoque guiado por comportamiento para TDD. Empiezas desde el exterior de la aplicación y vas hacia adentro, bajando a capas inferiores. Por ejemplo, desde la API/Controladores hacia las capas de aplicación o dominio.&lt;/p>
&lt;h3 id="pros">PROS
&lt;a class="heading-anchor" href="#pros" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;ul>
&lt;li>&lt;strong>Enfocado en Comportamiento&lt;/strong>: requiere muchos dobles de test porque testeas abstracciones que aún no existen (creas lógica de alto nivel primero). No escribirás código muerto, pero es fácil crear tests muy acoplados a la lógica, lo que dificulta el refactoring.&lt;/li>
&lt;li>&lt;strong>Separación Comando-Consulta&lt;/strong>: es una disciplina para gestionar efectos secundarios. O realizas una acción (comando) o pides un valor (consulta).&lt;/li>
&lt;/ul>
&lt;h3 id="contras">CONTRAS
&lt;a class="heading-anchor" href="#contras" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;ul>
&lt;li>&lt;strong>Tests Frágiles&lt;/strong>: tiende a crear tests que se rompen fácilmente porque suelen estar muy acoplados al código de producción.&lt;/li>
&lt;li>&lt;strong>Refactoring Difícil&lt;/strong>: por la misma razón, tener tests acoplados hace que el refactoring continuo sea lento y complicado.&lt;/li>
&lt;/ul>
&lt;h2 id="inside-out-escuela-de-chicago">Inside-out: Escuela de Chicago
&lt;a class="heading-anchor" href="#inside-out-escuela-de-chicago" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h2>
&lt;p>Un enfoque informal, exploratorio, basado en estado. Empiezas desde el interior de la aplicación (normalmente el dominio) y vas hacia afuera, hacia las APIs.&lt;/p>
&lt;h3 id="pros-1">PROS
&lt;a class="heading-anchor" href="#pros-1" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;ul>
&lt;li>&lt;strong>Red de Seguridad Fuerte&lt;/strong>: produce tests desacoplados de la implementación. Puedes cambiar el software sin miedo a romperlo, ideal para el refactoring continuo.&lt;/li>
&lt;li>&lt;strong>Alta Cohesión&lt;/strong>: a medida que los tests se vuelven más generales, el código de producción se vuelve más específico. Alta cohesión lleva a bajo acoplamiento, lo que mejora extensibilidad, mantenibilidad y testeabilidad.&lt;/li>
&lt;li>&lt;strong>Minimiza Dobles de Test&lt;/strong>: construir de adentro hacia afuera requiere menos dobles porque construyes sobre tests previamente escritos. Esto ayuda a tener tests menos frágiles.&lt;/li>
&lt;/ul>
&lt;h3 id="contras-1">CONTRAS
&lt;a class="heading-anchor" href="#contras-1" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;ul>
&lt;li>&lt;strong>YAGNI&lt;/strong>: a menudo sobre-diseña soluciones, con código que realmente no se necesita (¡o ni siquiera se usa!) al final.&lt;/li>
&lt;/ul>
&lt;h2 id="londres-y-chicago-funcionan-mejor-juntas">Londres y Chicago funcionan mejor juntas
&lt;a class="heading-anchor" href="#londres-y-chicago-funcionan-mejor-juntas" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h2>
&lt;p>No se trata de elegir uno u otro. Se trata de entender tu contexto y optimizar las cualidades que lo necesitan. London y Chicago tienen sus pros y contras. El mejor enfoque para TDD es integrar ambas escuelas.&lt;/p>
&lt;div style="position:relative;aspect-ratio:16/9;width:100%;">
&lt;iframe
src="https://www.youtube-nocookie.com/embed/rbSDGr-_UwY"
title="YouTube video"
width="560"
height="315"
loading="lazy"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
referrerpolicy="strict-origin-when-cross-origin"
style="position:absolute;inset:0;width:100%;height:100%;border:0;"
allowfullscreen>
&lt;/iframe>
&lt;/div>
&lt;hr />
&lt;h3 id="referencias">Referencias
&lt;a class="heading-anchor" href="#referencias" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;ul>
&lt;li>&lt;a href="/es/blog/test-driven-development/">Test-Driven (Development)&lt;/a>&lt;/li>
&lt;li>&lt;a href="/es/blog/tdd-vs-bdd/">TDD vs BDD&lt;/a>&lt;/li>
&lt;li>&lt;a rel="external" href="https://gist.github.com/xpepper/2e3519d2cb8568a0b13739d9ae497f21">Notes about “London vs Chicago TDD styles”&lt;/a>&lt;/li>
&lt;/ul></content></entry><entry xml:lang="es"><title>TDD vs BDD</title><subtitle>¿Diseño o Flujo de trabajo?</subtitle><category term="tdd" scheme="https://chemaclass.com/tags/tdd/" label="Tdd"/><category term="testing" scheme="https://chemaclass.com/tags/testing/" label="Testing"/><category term="software-design" scheme="https://chemaclass.com/tags/software-design/" label="Software Design"/><published>2021-09-25T00:00:00+00:00</published><updated>2021-09-25T00:00:00+00:00</updated><author><name>
Chemaclass</name></author><link rel="alternate" type="text/html" href="https://chemaclass.com/es/blog/tdd-vs-bdd/"/><id>https://chemaclass.com/es/blog/tdd-vs-bdd/</id><summary type="html">Estas son dos técnicas diferentes. La clave de cada una está en la mentalidad y el contexto de lo que quieres lograr.</summary><content type="html">&lt;p>Estas son dos técnicas diferentes. La clave de cada una está en la mentalidad y el contexto de lo que quieres lograr.&lt;/p>
&lt;span id="continue-reading">&lt;/span>&lt;h2 id="bdd-es-una-funcionalidad-guiada-por-tests">BDD es una “funcionalidad guiada por tests”
&lt;a class="heading-anchor" href="#bdd-es-una-funcionalidad-guiada-por-tests" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h2>
&lt;p>Básicamente, es un desarrollo test-first, donde el enfoque principal es asegurar el comportamiento final esperado, y por lo tanto el resultado de la lógica de software que quieres tener al final.&lt;/p>
&lt;p>En BDD el enfoque principal es el comportamiento de tu lógica de dominio que aún no existe. Es, desde un punto de vista abstracto, sobre toda la funcionalidad y los requisitos del dominio.&lt;/p>
&lt;h2 id="tdd-es-sobre-el-ritmo">TDD es sobre el ritmo
&lt;a class="heading-anchor" href="#tdd-es-sobre-el-ritmo" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h2>
&lt;ol>
&lt;li>Especifica lo que quieres.&lt;/li>
&lt;li>Hazlo funcionar.&lt;/li>
&lt;li>Hazlo mejor.&lt;/li>
&lt;/ol>
&lt;p>TDD no es solo la ya conocida mentalidad “red-green-refactor”, sino principalmente sobre el flujo de trabajo que te ayuda a entender las constantes decisiones de diseño que haces cada vez para cada lógica que estás diseñando.&lt;/p>
&lt;blockquote>
&lt;p>TDD es sobre retroalimentación constante de tus decisiones.&lt;/p>
&lt;/blockquote>
&lt;p>En el contexto de OOP (para hacer los ejemplos más claros), siempre hay toneladas de formas diferentes de diseñar tu clase:&lt;/p>
&lt;ul>
&lt;li>¿Cuál es el nombre de la clase de este método?&lt;/li>
&lt;li>¿Cuáles son las dependencias o colaboradores de esta clase?&lt;/li>
&lt;li>¿Cómo se comportará esta clase cuando use esta otra clase dentro de ella?&lt;/li>
&lt;li>¿Cuál es el resultado esperado de este método cuando le doy estos argumentos?&lt;/li>
&lt;li>etc, etc…&lt;/li>
&lt;/ul>
&lt;p>Hacemos estas preguntas (y muchas más) cada vez, y también les damos una respuesta, pero normalmente sin ningún pensamiento racional o reflexión sobre ello. Simplemente hacemos lo que creemos que es “lo mejor” en ese momento particular enfocándonos en hacer que algo funcione, pero ¿es suficiente hacerlo funcionar?&lt;/p>
&lt;h2 id="el-bucle-de-retroalimentacion-constante">El bucle de retroalimentación constante
&lt;a class="heading-anchor" href="#el-bucle-de-retroalimentacion-constante" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h2>
&lt;p>El testing no es solo una gran herramienta porque te da una red de seguridad para refactorizar con confianza, sino también porque ayuda a diseñar mejor el sistema. &lt;strong>¿Cómo es eso?&lt;/strong> Porque antes de implementar cualquier solución, te obliga a pensar en las decisiones que necesitas tomar. Te desafías a ti mismo para entender los argumentos de tus decisiones, y por qué A y no B es mejor solución en un contexto particular.&lt;/p>
&lt;p>BDD y TDD no son mutuamente excluyentes, de hecho, pueden y deben coexistir. Depende principalmente del contexto de lo que quieres construir y testear.&lt;/p>
&lt;p>&lt;img src="/images/blog/2021-09-25/bdd-and-tdd.webp" alt="blog-bdd-and-tdd" />&lt;/p>
&lt;p>BDD es sobre desarrollo de funcionalidades Test-First. El objetivo no es el cómo sino el qué. El bucle de retroalimentación es largo porque obtendrás el “verde” una vez que la funcionalidad esté implementada y funcionando como se esperaba.&lt;/p>
&lt;p>TDD también es otro desarrollo guiado por Test-First pero, a diferencia de BDD, se trata de un bucle de retroalimentación más corto y rápido.&lt;/p>
&lt;ol>
&lt;li>Primero, &lt;strong>especificas lo que quieres&lt;/strong>. Piensas sobre el diseño de tu clase o método. Su nombre o firma. Sus dependencias. Pero todo esto con pequeños pasos, uno a la vez.&lt;/li>
&lt;li>Segundo, &lt;strong>haces que esa pequeña cosa funcione&lt;/strong> de la manera más simple posible.&lt;/li>
&lt;li>Finalmente, &lt;strong>lo haces mejor&lt;/strong>. Porque el software es lo suficientemente difícil y complicado como para hacerlo bien al primer intento, así que el refactoring es imprescindible para mantener un sistema saludable. En este punto, con un “test verde ejecutándose”, puedes refactorizar y mejorar tu lógica de forma segura.&lt;/li>
&lt;/ol>
&lt;p>Lo anterior es básicamente TDD, cierto, pero… ¿qué tiene de especial? El &lt;strong>bucle de retroalimentación&lt;/strong> constante y las &lt;strong>decisiones de diseño&lt;/strong> que necesitas tomar antes de escribir realmente la solución. Este es el poder de TDD.&lt;/p>
&lt;h3 id="por-que-pasos-tan-pequenos-en-tdd">¿Por qué pasos tan pequeños en TDD?
&lt;a class="heading-anchor" href="#por-que-pasos-tan-pequenos-en-tdd" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;p>Teóricamente “debes” escribir pequeños pasos para cada iteración, pero ¿por qué? &lt;strong>Se trata del bucle de retroalimentación&lt;/strong>. Esto depende de ti, tus expectativas y tu experiencia con testing.&lt;/p>
&lt;p>&lt;img src="/images/blog/2021-09-25/footer.jpg" alt="pequeños pasos en el bucle de retroalimentación de tdd" />&lt;/p>
&lt;hr />
&lt;h3 id="recursos">Recursos
&lt;a class="heading-anchor" href="#recursos" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;ul>
&lt;li>&lt;a rel="external" href="https://chemaclass.com/es/blog/test-driven-development/">https://chemaclass.com/es/blog/test-driven-development/&lt;/a>&lt;/li>
&lt;li>&lt;a rel="external" href="https://blog.testlodge.com/tdd-vs-bdd/">https://blog.testlodge.com/tdd-vs-bdd/&lt;/a>&lt;/li>
&lt;/ul></content></entry><entry xml:lang="es"><title>Test-Driven (Development)</title><subtitle>¿Qué tiene de desafiante?</subtitle><category term="tdd" scheme="https://chemaclass.com/tags/tdd/" label="Tdd"/><category term="testing" scheme="https://chemaclass.com/tags/testing/" label="Testing"/><category term="software-design" scheme="https://chemaclass.com/tags/software-design/" label="Software Design"/><category term="refactoring" scheme="https://chemaclass.com/tags/refactoring/" label="Refactoring"/><published>2021-08-01T00:00:00+00:00</published><updated>2021-08-01T00:00:00+00:00</updated><author><name>
Chemaclass</name></author><link rel="alternate" type="text/html" href="https://chemaclass.com/es/blog/test-driven-development/"/><id>https://chemaclass.com/es/blog/test-driven-development/</id><summary type="html">TDD es una práctica de diseño, no solo una técnica de testing. Escribir tests primero cambia cómo piensas sobre el código y su estructura.</summary><content type="html">&lt;p>La complejidad aquí no está en escribir tests en sí, sino en los hábitos que tenemos que cambiar para crear software que sea fácil de testear.&lt;/p>
&lt;span id="continue-reading">&lt;/span>&lt;h2 id="la-raiz-del-problema">La raíz del problema
&lt;a class="heading-anchor" href="#la-raiz-del-problema" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h2>
&lt;p>Sin experiencia sólida en testing, los desarrolladores lo pasan mal al intentar aplicar tests en su trabajo diario. No es solo por la complejidad del tema, sino &lt;strong>porque están acostumbrados a escribir código difícil de testear.&lt;/strong>&lt;/p>
&lt;p>Escribir tests para software que ya funciona (sobre todo cuando se hizo sin pensar en testing) se siente aburrido y casi inútil. Viene acompañado de falta de motivación, culpando al sujeto equivocado: “los tests me hacen ir más lento”.&lt;/p>
&lt;blockquote>
&lt;p>En un contexto de dominio, si una pieza de lógica de software es difícil de testear, el problema no es el test, sino el código que no estaba bien escrito.&lt;/p>
&lt;/blockquote>
&lt;p>Ya hay cientos de tutoriales, libros y documentación sobre testing. Aquí comparto mi experiencia y cómo aplico esta filosofía en mi trabajo diario.&lt;/p>
&lt;h3 id="test-driven-se-basa-en-esta-simple-regla">Test-Driven se basa en esta simple regla
&lt;a class="heading-anchor" href="#test-driven-se-basa-en-esta-simple-regla" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;ul>
&lt;li>En lugar de: diseñar código -&amp;gt; desarrollar código -&amp;gt; escribir tests.&lt;/li>
&lt;/ul>
&lt;p>&lt;img src="/images/blog/2021-08-01/non-tdd-style.png" alt="non-tdd-style" />&lt;/p>
&lt;ul>
&lt;li>Se trata de: escribir test automatizado que falla -&amp;gt; ejecutar test que falla -&amp;gt; desarrollar código para hacer pasar el test -&amp;gt; ejecutar test -&amp;gt; repetir.&lt;/li>
&lt;/ul>
&lt;p>&lt;img src="/images/blog/2021-08-01/tdd-style.png" alt="tdd-style" />&lt;/p>
&lt;p>La idea de guiar tu código con tests depende del nivel de abstracción de lo que estés escribiendo. No quieres acoplar mal los tests con el código testeado. Quieres testear el comportamiento de tu lógica.&lt;/p>
&lt;p>TDD se basa en un bucle de pequeños pasos que te ayuda a encontrar &lt;strong>patrones&lt;/strong> y guiar tu diseño de software con &lt;strong>refactorizaciones constantes&lt;/strong>. Es la mejor opción si quieres asegurar el comportamiento esperado de todos los caminos posibles de tu lógica.&lt;/p>
&lt;p>Lo bonito es que no necesitas conocer el algoritmo completo desde el principio. Vas &lt;strong>descubriendo&lt;/strong> cómo debería ser tu lógica expresando la implementación deseada, paso a paso, en tests automatizados.&lt;/p>
&lt;p>Escribir tests al mismo tiempo que escribes el código te &lt;strong>obliga a escribir mejor software&lt;/strong>. Porque quieres que sea fácil de testear, y eso lleva a mayor calidad.&lt;/p>
&lt;blockquote>
&lt;p>Ya escribí otro post sobre la relación entre &lt;strong>calidad y testing&lt;/strong> del software: &lt;a href="/es/blog/the-art-of-testing/">El Arte del Testing: donde el diseño se encuentra con la calidad&lt;/a>.&lt;/p>
&lt;/blockquote>
&lt;h2 id="mejora-tus-habilidades-de-test-driven">Mejora tus habilidades de Test-Driven
&lt;a class="heading-anchor" href="#mejora-tus-habilidades-de-test-driven" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h2>
&lt;p>&lt;img src="/images/blog/2021-08-01/tdd-style-with-git.png" alt="tdd-style" />&lt;/p>
&lt;p>La mejor manera de aprender Test-Driven es haciendo katas de software. Pruébalas solo y con otros. Ambas son igualmente importantes.&lt;/p>
&lt;ul>
&lt;li>Solo: para desafiar tu yo interior sin ninguna distracción excepto tú mismo.&lt;/li>
&lt;li>Con otros: el pair-programming es esencial en nuestro trabajo. Las katas son las mejores herramientas para entrenar nuestras habilidades de comunicación y aprender juntos unos de otros.&lt;/li>
&lt;/ul>
&lt;h3 id="que-es-una-code-kata">¿Qué es una Code Kata?
&lt;a class="heading-anchor" href="#que-es-una-code-kata" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;p>Los desarrolladores no practicamos lo suficiente. La mayor parte de nuestro aprendizaje ocurre en el trabajo, y ahí es donde cometemos la mayoría de nuestros errores.&lt;/p>
&lt;p>Otras profesiones creativas sí practican: los músicos tocan piezas técnicas, los poetas reescriben obras constantemente. En karate, un estudiante dedica la mayor parte del tiempo a aprender y perfeccionar movimientos básicos. Esas son las katas.&lt;/p>
&lt;h3 id="cual-es-el-objetivo-de-una-kata-que-deberiamos-tener-al-final">¿Cuál es el objetivo de una kata? ¿Qué deberíamos tener al final?
&lt;a class="heading-anchor" href="#cual-es-el-objetivo-de-una-kata-que-deberiamos-tener-al-final" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;p>Las katas existen para que los desarrolladores obtengamos los mismos beneficios que practicar en otras profesiones. Son ejercicios simples y artificiales que permiten experimentar y aprender sin la presión de producción.&lt;/p>
&lt;blockquote>
&lt;p>No hay respuestas correctas o incorrectas en ninguna kata de software: el beneficio viene del proceso, no del resultado.&lt;/p>
&lt;/blockquote>
&lt;h3 id="consejos">Consejos
&lt;a class="heading-anchor" href="#consejos" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;ul>
&lt;li>Cuando resuelvas una kata, vuelve a intentarla en unas semanas o meses.&lt;/li>
&lt;li>Explora nuevas soluciones. Sé creativo y no te apresures.&lt;/li>
&lt;li>En grupo, no es una competición para ver quién logra más.&lt;/li>
&lt;li>El foco debe estar en el proceso, nunca en el resultado.&lt;/li>
&lt;li>El verdadero valor de cualquier kata son los aprendizajes que obtendréis después de hablar y compartir experiencias.&lt;/li>
&lt;/ul>
&lt;p>Puedes encontrar muchas katas en Internet. Por ejemplo:&lt;/p>
&lt;ul>
&lt;li>&lt;a rel="external" href="http://codekata.com">http://codekata.com&lt;/a>&lt;/li>
&lt;li>&lt;a rel="external" href="https://codingdojo.org/kata">https://codingdojo.org/kata&lt;/a>&lt;/li>
&lt;li>&lt;a rel="external" href="https://github.com/gamontal/awesome-katas">https://github.com/gamontal/awesome-katas&lt;/a>&lt;/li>
&lt;/ul>
&lt;hr />
&lt;h3 id="tdd-es-mas-un-flujo-de-trabajo-que-un-diseno">TDD es más un flujo de trabajo que un diseño
&lt;a class="heading-anchor" href="#tdd-es-mas-un-flujo-de-trabajo-que-un-diseno" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;blockquote>
&lt;p>“TDD es una herramienta de diseño.” Eso es lo que Sandro dijo durante años. Pero ya no. Tras trabajar con diferentes equipos y organizaciones, y observar cómo trabaja él mismo, Sandro cambió de opinión sobre el rol de TDD en el diseño de software.&lt;/p>
&lt;/blockquote>
&lt;div style="position:relative;aspect-ratio:16/9;width:100%;">
&lt;iframe
src="https://www.youtube-nocookie.com/embed/KyFVA4Spcgg"
title="YouTube video"
width="560"
height="315"
loading="lazy"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
referrerpolicy="strict-origin-when-cross-origin"
style="position:absolute;inset:0;width:100%;height:100%;border:0;"
allowfullscreen>
&lt;/iframe>
&lt;/div>
&lt;p>TDD en pocas palabras; se trata del ritmo.&lt;/p>
&lt;ol>
&lt;li>Especifica lo que quieres.&lt;/li>
&lt;li>Hazlo funcionar.&lt;/li>
&lt;li>Hazlo mejor.&lt;/li>
&lt;/ol>
&lt;hr />
&lt;h2 id="kent-beck">Kent Beck
&lt;a class="heading-anchor" href="#kent-beck" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h2>
&lt;blockquote class="twitter-tweet">&lt;p lang="en" dir="ltr">1. Change the code as usual&lt;br>2. Write a test that only passes after the change&lt;br>3. Revert to before 1&lt;br>4. Type the test again (copy/paste is cheating &amp;amp; invalidates the warranty of the exercise)&lt;br>5. Make it compile by changing the code&lt;br>6. See it fail&lt;br>7. Change the code to make it pass&lt;/p>&amp;mdash; Kent Beck 🌻 (@KentBeck) &lt;a href="https://twitter.com/KentBeck/status/1421257650113634304?ref_src=twsrc%5Etfw">July 30, 2021&lt;/a>&lt;/blockquote> &lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8">&lt;/script>
&lt;hr />
&lt;p>Imágenes originales de &lt;a rel="external" href="https://x.com/evrtrabajo">Emmanuel Valverde Ramos&lt;/a>.&lt;/p></content></entry><entry xml:lang="es"><title>Phel: el Lisp que Compila a PHP</title><subtitle>Un nuevo lenguaje funcional con interoperabilidad total con PHP</subtitle><category term="phel" scheme="https://chemaclass.com/tags/phel/" label="Phel"/><category term="php" scheme="https://chemaclass.com/tags/php/" label="Php"/><category term="open-source" scheme="https://chemaclass.com/tags/open-source/" label="Open Source"/><category term="software-design" scheme="https://chemaclass.com/tags/software-design/" label="Software Design"/><published>2021-02-01T00:00:00+00:00</published><updated>2021-02-01T00:00:00+00:00</updated><author><name>
Chemaclass</name></author><link rel="alternate" type="text/html" href="https://chemaclass.com/es/blog/phel-first-release/"/><id>https://chemaclass.com/es/blog/phel-first-release/</id><summary type="html">El nuevo lenguaje de Programación Funcional construido para PHP.</summary><content type="html">&lt;p>Un nuevo lenguaje de Programación Funcional construido sobre el ecosistema de PHP.&lt;/p>
&lt;span id="continue-reading">&lt;/span>&lt;h2 id="el-lenguaje-phel">El Lenguaje Phel
&lt;a class="heading-anchor" href="#el-lenguaje-phel" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h2>
&lt;p>Phel es un lenguaje de Programación Funcional (&lt;a rel="external" href="https://en.wikipedia.org/wiki/Functional_programming">FP&lt;/a>) que compila a PHP. Es un dialecto de &lt;a rel="external" href="https://en.wikipedia.org/wiki/Lisp_(programming_language)">Lisp&lt;/a> inspirado en Clojure y Janet.&lt;/p>
&lt;h2 id="caracteristicas">Características
&lt;a class="heading-anchor" href="#caracteristicas" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h2>
&lt;ul>
&lt;li>Construido sobre el ecosistema de PHP&lt;/li>
&lt;li>Buenos reportes de errores&lt;/li>
&lt;li>Diferentes estructuras de datos (Arrays, Tables y Tuples)&lt;/li>
&lt;li>Macros&lt;/li>
&lt;li>Funciones recursivas&lt;/li>
&lt;li>Sintaxis potente pero simple&lt;/li>
&lt;li>REPL&lt;/li>
&lt;/ul>
&lt;h2 id="por-que-phel">¿Por qué Phel?
&lt;a class="heading-anchor" href="#por-que-phel" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h2>
&lt;p>Phel lo creó Jens Haase. Como menciona en el sitio web, “es el resultado de muchos &lt;a rel="external" href="https://phel-lang.org/blog/functional-programming-in-php">intentos fallidos de hacer programación funcional en PHP&lt;/a>”. Buscaba algo con estas características:&lt;/p>
&lt;ul>
&lt;li>Inspirado en LISP&lt;/li>
&lt;li>Lenguaje de Programación Funcional&lt;/li>
&lt;li>Que funcione en proveedores de hosting baratos&lt;/li>
&lt;li>Sea fácil de escribir y depurar&lt;/li>
&lt;/ul>
&lt;p>A finales de mayo de 2020 terminé el libro &lt;a href="/es/readings/7-languages-in-7-weeks/">Seven Languages in Seven Weeks&lt;/a>, donde aprendí los fundamentos de Prolog, Erlang, Clojure, Haskell… Incluso creé un &lt;a rel="external" href="https://github.com/Chemaclass/7LangIn7Weeks">repositorio en GitHub&lt;/a> para guardar mi progreso.&lt;/p>
&lt;p>A principios de junio de 2020, vi un post en el canal de PHP de Reddit mencionando este proyecto “&lt;strong>Phel&lt;/strong>”: un &lt;strong>lenguaje de programación funcional escrito en PHP&lt;/strong>.&lt;/p>
&lt;p>Llevo unos 8 años trabajando con PHP, y siempre intento combinar OOP con FP (creo que ambos paradigmas funcionan mejor juntos; no son excluyentes). Un nuevo dialecto de Lisp escrito en &lt;strong>PHP 7.4&lt;/strong> nativo sonaba emocionante. Decidí echarle un vistazo al código.&lt;/p>
&lt;p>Las lecturas recientes de &lt;a rel="external" href="https://x.com/matthiasnoback">Mathias NoBack&lt;/a>, como &lt;a href="/es/readings/object-design-style-guide">Object Design Style Guide&lt;/a> y &lt;a href="/es/readings/advance-web-application-architecture/">Advanced Web Application Architecture&lt;/a>, me dieron el empuje para aplicar lo aprendido en un proyecto real. Este fue (y sigue siendo) un desafío que me ayuda a crecer profesionalmente.&lt;/p>
&lt;p>Mi primer commit fue el 6 de junio de 2020. Desde entonces dedico un poco de tiempo cada día en mis horas libres.
Me ayuda a aprender sobre FP, diseño interno de lenguajes, testing y arquitectura de software en general.&lt;/p>
&lt;p>Empecé con cambios menores hasta que acabé refactorizando toda la estructura del compilador para hacer los módulos más legibles. Psalm, tipos estrictos, buena cobertura de tests, estilo de código unificado… Estos fueron algunos de mis temas favoritos.&lt;/p>
&lt;h2 id="ejemplo-de-codigo-phel">Ejemplo de código Phel
&lt;a class="heading-anchor" href="#ejemplo-de-codigo-phel" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h2>
&lt;p>El siguiente ejemplo da una breve impresión de cómo se ve Phel:&lt;/p>
&lt;pre class="giallo" style="color-scheme: light dark; color: light-dark(#24292E, #E1E4E8); background-color: light-dark(#FFFFFF, #24292E);">&lt;code data-lang="plain">&lt;span class="giallo-l">&lt;span># Define un namespace&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span>(ns my\example)&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span># Define una variable con nombre &amp;quot;my-name&amp;quot; y valor &amp;quot;world&amp;quot;&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span>(def my-name &amp;quot;world&amp;quot;)&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span># Define una función con nombre &amp;quot;print-name&amp;quot; y un argumento&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span>(defn print-name [your-name]&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span> (print &amp;quot;hello&amp;quot; your-name))&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span># Llama a la función&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span>(print-name my-name)&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;h2 id="estado-actual-de-phel">Estado actual de Phel
&lt;a class="heading-anchor" href="#estado-actual-de-phel" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h2>
&lt;ul>
&lt;li>Preparamos una fácil &lt;a rel="external" href="https://phel-lang.org/documentation/getting-started/">Guía de Inicio&lt;/a>&lt;/li>
&lt;li>Preparamos un Repositorio GitHub fácil con una &lt;a rel="external" href="https://github.com/phel-lang/phel-scaffolding">Plantilla de Scaffolding de Phel&lt;/a>&lt;/li>
&lt;li>Acabamos de lanzar la primera versión oficial: &lt;a rel="external" href="https://github.com/phel-lang/phel-lang/tags">0.1.0&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>Consulta el sitio web oficial con toda la documentación: &lt;a rel="external" href="https://phel-lang.org/">https://phel-lang.org/&lt;/a>&lt;/p>
&lt;hr />
&lt;h3 id="tambien-recomendado">También recomendado
&lt;a class="heading-anchor" href="#tambien-recomendado" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;ul>
&lt;li>&lt;a rel="external" href="https://jesusvalera.dev/functional-programming-with-phel/">Functional Programming with Phel - JesusValera&lt;/a>&lt;/li>
&lt;/ul></content></entry><entry xml:lang="es"><title>Mockear o No Mockear</title><subtitle>Cómo escapar del infierno del mocking</subtitle><category term="testing" scheme="https://chemaclass.com/tags/testing/" label="Testing"/><category term="tdd" scheme="https://chemaclass.com/tags/tdd/" label="Tdd"/><category term="software-design" scheme="https://chemaclass.com/tags/software-design/" label="Software Design"/><category term="clean-code" scheme="https://chemaclass.com/tags/clean-code/" label="Clean Code"/><category term="php" scheme="https://chemaclass.com/tags/php/" label="Php"/><published>2021-01-11T00:00:00+00:00</published><updated>2021-01-11T00:00:00+00:00</updated><author><name>
Chemaclass</name></author><link rel="alternate" type="text/html" href="https://chemaclass.com/es/blog/to-mock-or-not-to-mock/"/><id>https://chemaclass.com/es/blog/to-mock-or-not-to-mock/</id><summary type="html">Mockear es útil, pero 'qué mockear' suele resultar más complicado de lo esperado si no tratas esto con cuidado.</summary><content type="html">&lt;p>Mockear es útil, pero “qué mockear” suele resultar más complicado de lo esperado si no tratas esto con cuidado.&lt;/p>
&lt;span id="continue-reading">&lt;/span>&lt;h4 id="como-escapar-del-infierno-del-mocking">Cómo escapar del infierno del mocking
&lt;a class="heading-anchor" href="#como-escapar-del-infierno-del-mocking" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h4>
&lt;p>¿Qué pasa realmente cuando creamos un mock? ¿Qué tipos hay? ¿Es bueno o malo mockear? Como siempre, depende del contexto. Aquí veremos las situaciones principales: cuándo mockear, cuándo no hacerlo, y sobre todo por qué.&lt;/p>
&lt;h2 id="que-pasa-cuando-mockeas-algo">¿Qué pasa cuando mockeas algo?
&lt;a class="heading-anchor" href="#que-pasa-cuando-mockeas-algo" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h2>
&lt;p>Primero, deberíamos definir qué es un mock:&lt;/p>
&lt;blockquote>
&lt;p>En un test unitario, los objetos mock pueden simular el comportamiento de objetos reales complejos y por lo tanto son útiles cuando es impracticable o imposible incorporar un objeto real en un test unitario.&lt;/p>
&lt;/blockquote>
&lt;p>Mockear tiene sentido en &lt;em>testing unitario&lt;/em>. Un test de integración pasa por la implementación real, verificando cómo interactúan varias unidades. Estos tests sí pueden hablar con la BD o el sistema de archivos.
Partimos de esta base: &lt;em>un test unitario es rápido, determinista, no depende de recursos externos y no requiere contexto especial para ejecutarse&lt;/em>.&lt;/p>
&lt;p>Los mocks cumplen el contrato de la &lt;em>interfaz&lt;/em>. Nos permiten testear funcionalidad sin invocar clases colaboradoras complejas.&lt;/p>
&lt;p>Un mock es un doble de test que sustituye la implementación real. Además, puede verificar cómo el código bajo test lo utilizó durante la ejecución.&lt;/p>
&lt;blockquote>
&lt;p>Recomiendo encarecidamente que leas este post si quieres entrar en los detalles de por qué &lt;a rel="external" href="https://medium.com/javascript-scene/mocking-is-a-code-smell-944a70c90a6a">Mockear es un code smell&lt;/a> (Temas como estos: ¿Qué es un mock? ¿Qué es un test unitario? ¿Qué es la cobertura de tests? ¿Qué es el acoplamiento fuerte? ¿Qué causa el acoplamiento fuerte? ¿Qué tiene que ver la composición con el mocking? ¿Cómo eliminamos el acoplamiento? ¡y más!)&lt;/p>
&lt;/blockquote>
&lt;h2 id="el-problema-con-mockear">El problema con mockear
&lt;a class="heading-anchor" href="#el-problema-con-mockear" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h2>
&lt;p>Cuando mockeas, anulas la lógica de la clase mockeada. La lógica real queda oculta, y ahí es donde los bugs se esconden. Ten en cuenta que:&lt;/p>
&lt;ul>
&lt;li>
&lt;p>El mock puede tener atributos, métodos o argumentos que el objeto real no tiene.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Los &lt;em>valores de retorno del mock pueden diferir de los reales&lt;/em>. Por ejemplo, puede devolver un tipo distinto con atributos diferentes.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Los &lt;em>efectos secundarios y comportamiento del mock pueden diferir del objeto real&lt;/em>. Quizás el mock no lanza una excepción que el objeto real sí lanzaría.&lt;/p>
&lt;/li>
&lt;/ul>
&lt;h2 id="alternativas-a-mockear">Alternativas a mockear
&lt;a class="heading-anchor" href="#alternativas-a-mockear" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h2>
&lt;p>“¿Estás diciendo que mockear es malo y no deberíamos mockear?” No.&lt;/p>
&lt;p>Depende de lo que estés “anulando”.&lt;/p>
&lt;ul>
&lt;li>¿Es tu lógica de dominio de negocio lo que estás mockeando? Entonces está mal.&lt;/li>
&lt;li>¿Es la conexión a la BD lo que estás mockeando? Entonces está bien.&lt;/li>
&lt;/ul>
&lt;blockquote>
&lt;p>Depende del contexto de la lógica y dónde pertenece esa lógica.&lt;/p>
&lt;/blockquote>
&lt;p>¿Es parte de tu lógica de dominio de negocio? Entonces no deberías mockearla sino instanciarla.&lt;/p>
&lt;p>¿Es una dependencia de infraestructura como conexión a BD, sistema de archivos, red, o cualquier servicio externo que no tiene que ver con tu dominio de negocio? Entonces &lt;em>mockéala usando abstracciones/interfaces&lt;/em>.&lt;/p>
&lt;p>La interfaz es el &lt;em>contrato entre tu lógica de dominio y sus dependencias de infraestructura&lt;/em>.
Imagina lo fácil que es testear tu dominio instanciándolo y llamando a sus métodos con diferentes argumentos, todo bajo tu control total.&lt;/p>
&lt;h2 id="algunos-trucos">Algunos trucos
&lt;a class="heading-anchor" href="#algunos-trucos" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h2>
&lt;p>Cuando estés escribiendo un test unitario:&lt;/p>
&lt;ul>
&lt;li>Intenta instanciar tus clases primero.&lt;/li>
&lt;li>Evita mockear clases concretas. Escribí un artículo exclusivamente sobre esto:
fomentando &lt;a rel="external" href="https://medium.com/swlh/final-classes-in-php-9174e3e2747e">clases finales&lt;/a> e interfaces.&lt;/li>
&lt;/ul>
&lt;blockquote>
&lt;p>Mockea interfaces. Instancia clases concretas.&lt;/p>
&lt;/blockquote>
&lt;div style="position:relative;aspect-ratio:16/9;width:100%;">
&lt;iframe
src="https://www.youtube-nocookie.com/embed/RbSqXFUfRMU"
title="YouTube video"
width="560"
height="315"
loading="lazy"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
referrerpolicy="strict-origin-when-cross-origin"
style="position:absolute;inset:0;width:100%;height:100%;border:0;"
allowfullscreen>
&lt;/iframe>
&lt;/div>
&lt;p>“El uso excesivo de mocks lleva a código legacy.” - Philippe Boargau&lt;/p>
&lt;h3 id="como-podemos-evitar-el-mocking-excesivo">¿Cómo podemos evitar el mocking excesivo?
&lt;a class="heading-anchor" href="#como-podemos-evitar-el-mocking-excesivo" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;ul>
&lt;li>Favorece el estado inmutable sobre el estado mutable.&lt;/li>
&lt;li>Haz las dependencias explícitas.&lt;/li>
&lt;li>Programa hacia una interfaz, no hacia una implementación.&lt;/li>
&lt;/ul>
&lt;p>&lt;img src="/images/blog/2021-01-11/footer.webp" alt="mockea interfaces, instancia clases concretas" />&lt;/p>
&lt;hr />
&lt;h4 id="referencias">Referencias
&lt;a class="heading-anchor" href="#referencias" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h4>
&lt;ul>
&lt;li>&lt;a rel="external" href="https://medium.com/javascript-scene/mocking-is-a-code-smell-944a70c90a6a">Mocking is a code smell&lt;/a> - Eric Elliott&lt;/li>
&lt;li>&lt;a rel="external" href="https://blog.cleancoder.com/uncle-bob/2014/05/10/WhenToMock.html">When to mock&lt;/a> &amp;amp; &lt;a rel="external" href="https://blog.cleancoder.com/uncle-bob/2017/05/05/TestDefinitions.html">Test Definitions&lt;/a> - Uncle Bob&lt;/li>
&lt;li>&lt;a rel="external" href="https://matthiasnoback.nl/2018/09/final-classes-by-default-why/">Final classes by default&lt;/a> - Matthias Noback&lt;/li>
&lt;li>&lt;a rel="external" href="https://www.seanh.cc/2017/03/17/the-problem-with-mocks/">The problem with mocks&lt;/a> - Sean Hammond&lt;/li>
&lt;li>&lt;a rel="external" href="https://www.artima.com/weblogs/viewpost.jsp?thread=126923">A Set of Unit Testing Rules&lt;/a> - Michael Feathers&lt;/li>
&lt;/ul></content></entry><entry xml:lang="es"><title>Principios de diseño de paquetes</title><subtitle>Cómo crear componentes de software reutilizables</subtitle><category term="software-design" scheme="https://chemaclass.com/tags/software-design/" label="Software Design"/><category term="architecture" scheme="https://chemaclass.com/tags/architecture/" label="Architecture"/><category term="clean-code" scheme="https://chemaclass.com/tags/clean-code/" label="Clean Code"/><published>2020-11-12T00:00:00+00:00</published><updated>2020-11-12T00:00:00+00:00</updated><author><name>
Matthias Noback</name></author><link rel="alternate" type="text/html" href="https://chemaclass.com/es/readings/packaging-design/"/><id>https://chemaclass.com/es/readings/packaging-design/</id><summary type="html">Cómo crear paquetes con la cohesión y el acoplamiento justos, útiles tanto para usuarios como mantenedores</summary><content type="html">&lt;span id="continue-reading">&lt;/span>
&lt;p>Aprende a aplicar principios de diseño a tus clases para que sean reutilizables. El libro te enseña a crear paquetes con la cohesión y acoplamiento adecuados, pensados para usuarios y mantenedores.&lt;/p>
&lt;p>La primera parte cubre los cinco principios SOLID para mejorar el diseño de clases. La segunda parte entra en las mejores prácticas de diseño de paquetes: principios de cohesión y de acoplamiento.&lt;/p>
&lt;p>Los principios de cohesión te dicen qué clases van juntas, cuándo dividir un paquete, y cuándo un grupo de clases puede llamarse “paquete”. Los de acoplamiento te ayudan a elegir bien las dependencias y evitar ciclos en el grafo de dependencias.&lt;/p>
&lt;h3 id="lo-que-aprenderas">Lo que aprenderás
&lt;a class="heading-anchor" href="#lo-que-aprenderas" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;ul>
&lt;li>Aplicar los principios SOLID&lt;/li>
&lt;li>Decidir si las clases pertenecen al mismo paquete&lt;/li>
&lt;li>Saber cuándo un paquete puede depender de otro&lt;/li>
&lt;/ul></content></entry><entry xml:lang="es"><title>Arrays Tipados en PHP</title><subtitle>Una alternativa a la característica que falta en PHP: Generics</subtitle><category term="php" scheme="https://chemaclass.com/tags/php/" label="Php"/><category term="software-design" scheme="https://chemaclass.com/tags/software-design/" label="Software Design"/><category term="clean-code" scheme="https://chemaclass.com/tags/clean-code/" label="Clean Code"/><published>2020-10-13T00:00:00+00:00</published><updated>2020-10-13T00:00:00+00:00</updated><author><name>
Chemaclass</name></author><link rel="alternate" type="text/html" href="https://chemaclass.com/es/blog/typed-arrays-php/"/><id>https://chemaclass.com/es/blog/typed-arrays-php/</id><summary type="html">Desempaquetado de argumentos, lista de argumentos variables de función, y funciones variádicas.</summary><content type="html">&lt;p>Desempaquetado de argumentos, lista de argumentos variables de función, y funciones variádicas.&lt;/p>
&lt;span id="continue-reading">&lt;/span>&lt;h3 id="la-combinacion-perfecta">La combinación perfecta
&lt;a class="heading-anchor" href="#la-combinacion-perfecta" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;ul>
&lt;li>&lt;strong>Desempaquetado de argumentos&lt;/strong>: pasa los elementos de un array como argumentos individuales a una función.&lt;/li>
&lt;li>&lt;strong>Lista de argumentos variables&lt;/strong>: la función recibe los argumentos como un array.&lt;/li>
&lt;li>&lt;strong>Función variádica&lt;/strong>: permite verificar los tipos con un type-hint.&lt;/li>
&lt;/ul>
&lt;p>Usaremos este snippet para nuestros ejemplos.
Tenemos una clase &lt;code>Customer&lt;/code>:&lt;/p>
&lt;pre class="giallo" style="color-scheme: light dark; color: light-dark(#24292E, #E1E4E8); background-color: light-dark(#FFFFFF, #24292E);">&lt;code data-lang="php">&lt;span class="giallo-l">&lt;span style="color: light-dark(#D73A49, #F97583);">&amp;lt;&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);">?&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);">php&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#6A737D, #6A737D);">/**&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#6A737D, #6A737D);"> * @psalm-immutable&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#6A737D, #6A737D);"> */&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#D73A49, #F97583);">final&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> class&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);"> Customer&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span>{&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#6A737D, #6A737D);"> //&lt;/span>&lt;span style="color: light-dark(#6A737D, #6A737D);"> Usando la promoción de propiedades en constructor de PHP 8&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#6A737D, #6A737D);"> //&lt;/span>&lt;span style="color: light-dark(#6A737D, #6A737D);"> https://wiki.php.net/rfc/constructor_promotion&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#D73A49, #F97583);"> public&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> function&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);"> __construct&lt;/span>&lt;span>(&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#D73A49, #F97583);"> public&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> string&lt;/span>&lt;span> $&lt;/span>&lt;span>name&lt;/span>&lt;span>,&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span> )&lt;/span>&lt;span> {&lt;/span>&lt;span>}&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span>}&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#6A737D, #6A737D);">//&lt;/span>&lt;span style="color: light-dark(#6A737D, #6A737D);"> Creamos una lista de 6 clientes&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span>$&lt;/span>&lt;span>customers&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> =&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);"> array_map&lt;/span>&lt;span>(&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#D73A49, #F97583);"> fn&lt;/span>&lt;span>(&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);">int&lt;/span>&lt;span> $&lt;/span>&lt;span>i&lt;/span>&lt;span>)&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);">:&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);"> Customer&lt;/span>&lt;span> =&amp;gt;&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> new&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);"> Customer&lt;/span>&lt;span>(&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">&amp;quot;&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">name-&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">{&lt;/span>&lt;span>$&lt;/span>&lt;span>i&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">}&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">&amp;quot;&lt;/span>&lt;span>)&lt;/span>&lt;span>,&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#005CC5, #79B8FF);"> range&lt;/span>&lt;span>(&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);">1&lt;/span>&lt;span>,&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);"> 6&lt;/span>&lt;span>)&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span>)&lt;/span>&lt;span>;&lt;/span>&lt;/span>&lt;/code>&lt;/pre>
&lt;p>Siempre que queramos manipular una lista de Customers, podemos pasar como argumento: &lt;code>…$customers&lt;/code>.&lt;/p>
&lt;h2 id="como-soliamos-hacerlo">Cómo solíamos hacerlo
&lt;a class="heading-anchor" href="#como-soliamos-hacerlo" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h2>
&lt;p>Definimos el tipo del array con PHPDoc, pero no podemos forzar el tipo real de cada elemento. El código se ejecuta sin problemas aunque pases cualquier tipo en &lt;code>array $customers&lt;/code>:&lt;/p>
&lt;pre class="giallo" style="color-scheme: light dark; color: light-dark(#24292E, #E1E4E8); background-color: light-dark(#FFFFFF, #24292E);">&lt;code data-lang="php">&lt;span class="giallo-l">&lt;span style="color: light-dark(#D73A49, #F97583);">&amp;lt;&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);">?&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);">php&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#6A737D, #6A737D);">/**&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#6A737D, #6A737D);"> * &lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);">@param&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);"> Customer&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);">[]&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#6A737D, #6A737D);"> */&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#D73A49, #F97583);">function&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);"> createInvoiceForCustomers&lt;/span>&lt;span>(&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);">array&lt;/span>&lt;span> $&lt;/span>&lt;span>customers&lt;/span>&lt;span>)&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);">:&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> void&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span>{&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#D73A49, #F97583);"> foreach&lt;/span>&lt;span> (&lt;/span>&lt;span>$&lt;/span>&lt;span>customers&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> as&lt;/span>&lt;span> $&lt;/span>&lt;span>customer&lt;/span>&lt;span>)&lt;/span>&lt;span> {&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#6A737D, #6A737D);"> //&lt;/span>&lt;span style="color: light-dark(#6A737D, #6A737D);"> ... alguna lógica irrelevante para este ejemplo&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span> }&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span>}&lt;/span>&lt;/span>&lt;/code>&lt;/pre>
&lt;p>El código de abajo funcionaría en “tiempo de compilación”. Pero podría fallar en “tiempo de ejecución”.&lt;/p>
&lt;pre class="giallo" style="color-scheme: light dark; color: light-dark(#24292E, #E1E4E8); background-color: light-dark(#FFFFFF, #24292E);">&lt;code data-lang="php">&lt;span class="giallo-l">&lt;span style="color: light-dark(#D73A49, #F97583);">&amp;lt;&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);">?&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);">php&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#6F42C1, #B392F0);">createInvoiceForCustomers&lt;/span>&lt;span>(&lt;/span>&lt;span>$&lt;/span>&lt;span>customers&lt;/span>&lt;span>)&lt;/span>&lt;span>;&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#6F42C1, #B392F0);">createInvoiceForCustomers&lt;/span>&lt;span>(&lt;/span>&lt;span>[&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);">new&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);"> Customer&lt;/span>&lt;span>(&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">&amp;#39;&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">any name&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">&amp;#39;&lt;/span>&lt;span>)&lt;/span>&lt;span>]&lt;/span>&lt;span>)&lt;/span>&lt;span>;&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#6F42C1, #B392F0);">createInvoiceForCustomers&lt;/span>&lt;span>(&lt;/span>&lt;span>[&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);">new&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);"> AnyOtherType&lt;/span>&lt;span>(&lt;/span>&lt;span>)&lt;/span>&lt;span>]&lt;/span>&lt;span>)&lt;/span>&lt;span>;&lt;/span>&lt;/span>&lt;/code>&lt;/pre>
&lt;p>Una alternativa recomendada: extraer la lógica y pedir el tipo concreto para verificarlo en tiempo de ejecución. Fallará si alguno de los elementos no es un Customer:&lt;/p>
&lt;pre class="giallo" style="color-scheme: light dark; color: light-dark(#24292E, #E1E4E8); background-color: light-dark(#FFFFFF, #24292E);">&lt;code data-lang="php">&lt;span class="giallo-l">&lt;span style="color: light-dark(#D73A49, #F97583);">&amp;lt;&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);">?&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);">php&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#6A737D, #6A737D);">/**&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#6A737D, #6A737D);"> * &lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);">@param&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);"> Customer&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);">[]&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#6A737D, #6A737D);"> */&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#D73A49, #F97583);">function&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);"> createInvoiceForCustomers&lt;/span>&lt;span>(&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);">array&lt;/span>&lt;span> $&lt;/span>&lt;span>customers&lt;/span>&lt;span>)&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);">:&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> void&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span>{&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#D73A49, #F97583);"> foreach&lt;/span>&lt;span> (&lt;/span>&lt;span>$&lt;/span>&lt;span>customers&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> as&lt;/span>&lt;span> $&lt;/span>&lt;span>customer&lt;/span>&lt;span>)&lt;/span>&lt;span> {&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#6F42C1, #B392F0);"> createInvoice&lt;/span>&lt;span>(&lt;/span>&lt;span>$&lt;/span>&lt;span>customer&lt;/span>&lt;span>)&lt;/span>&lt;span>;&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span> }&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span>}&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#D73A49, #F97583);">function&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);"> createInvoice&lt;/span>&lt;span>(&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);">Customer&lt;/span>&lt;span> $&lt;/span>&lt;span>customer&lt;/span>&lt;span>)&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);">:&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> void&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span>{&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#6A737D, #6A737D);"> //&lt;/span>&lt;span style="color: light-dark(#6A737D, #6A737D);"> ... alguna lógica irrelevante para este ejemplo&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span>}&lt;/span>&lt;/span>&lt;/code>&lt;/pre>
&lt;p>Todo lo de aquí abajo funcionaría en “tiempo de compilación”. Seguro que fallará durante “tiempo de ejecución” si &lt;code>createInvoice(Customer $customer)&lt;/code> recibe algo diferente a un Customer.&lt;/p>
&lt;pre class="giallo" style="color-scheme: light dark; color: light-dark(#24292E, #E1E4E8); background-color: light-dark(#FFFFFF, #24292E);">&lt;code data-lang="php">&lt;span class="giallo-l">&lt;span style="color: light-dark(#D73A49, #F97583);">&amp;lt;&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);">?&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);">php&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#6F42C1, #B392F0);">createInvoiceForCustomers&lt;/span>&lt;span>(&lt;/span>&lt;span>$&lt;/span>&lt;span>customers&lt;/span>&lt;span>)&lt;/span>&lt;span>;&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#6F42C1, #B392F0);">createInvoiceForCustomers&lt;/span>&lt;span>(&lt;/span>&lt;span>[&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);">new&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);"> Customer&lt;/span>&lt;span>(&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">&amp;#39;&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">any name&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">&amp;#39;&lt;/span>&lt;span>)&lt;/span>&lt;span>]&lt;/span>&lt;span>)&lt;/span>&lt;span>;&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#6F42C1, #B392F0);">createInvoiceForCustomers&lt;/span>&lt;span>(&lt;/span>&lt;span>[&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);">new&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);"> AnyOtherType&lt;/span>&lt;span>(&lt;/span>&lt;span>)&lt;/span>&lt;span>]&lt;/span>&lt;span>)&lt;/span>&lt;span>;&lt;/span>&lt;span style="color: light-dark(#6A737D, #6A737D);"> //&lt;/span>&lt;span style="color: light-dark(#6A737D, #6A737D);"> no funcionará&lt;/span>&lt;/span>&lt;/code>&lt;/pre>
&lt;p>Con &lt;code>createInvoice(Customer $customer)&lt;/code> aseguramos el tipo del argumento. Pero, ¿podemos ir un paso más allá? ¿Podríamos verificar los tipos al llamar a &lt;code>createInvoiceForCustomers(array $customers)&lt;/code>, y que el IDE se queje si los tipos no son correctos?&lt;/p>
&lt;p>Eso es precisamente para lo que sirven los Generics, pero aún no existen en PHP. Ni siquiera en PHP 8. Quizás lleguen pronto, pero por ahora hay una alternativa menos conocida con sus pros y contras. Veamos un ejemplo:&lt;/p>
&lt;pre class="giallo" style="color-scheme: light dark; color: light-dark(#24292E, #E1E4E8); background-color: light-dark(#FFFFFF, #24292E);">&lt;code data-lang="php">&lt;span class="giallo-l">&lt;span style="color: light-dark(#D73A49, #F97583);">&amp;lt;&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);">?&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);">php&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#D73A49, #F97583);">function&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);"> createInvoiceForCustomers&lt;/span>&lt;span>(&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);">Customer&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> ...&lt;/span>&lt;span>$&lt;/span>&lt;span>customers&lt;/span>&lt;span>)&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);">:&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> void&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span>{&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#D73A49, #F97583);"> foreach&lt;/span>&lt;span> (&lt;/span>&lt;span>$&lt;/span>&lt;span>customers&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> as&lt;/span>&lt;span> $&lt;/span>&lt;span>customer&lt;/span>&lt;span>)&lt;/span>&lt;span> {&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#6F42C1, #B392F0);"> createInvoice&lt;/span>&lt;span>(&lt;/span>&lt;span>$&lt;/span>&lt;span>customer&lt;/span>&lt;span>)&lt;/span>&lt;span>;&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span> }&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span>}&lt;/span>&lt;/span>&lt;/code>&lt;/pre>
&lt;p>Todo lo de aquí abajo funcionaría en “tiempo de compilación”. Seguro que fallará durante “tiempo de ejecución” si &lt;code>createInvoice()&lt;/code> recibe algo diferente a un Customer.&lt;/p>
&lt;pre class="giallo" style="color-scheme: light dark; color: light-dark(#24292E, #E1E4E8); background-color: light-dark(#FFFFFF, #24292E);">&lt;code data-lang="php">&lt;span class="giallo-l">&lt;span style="color: light-dark(#D73A49, #F97583);">&amp;lt;&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);">?&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);">php&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#6F42C1, #B392F0);">createInvoiceForCustomers&lt;/span>&lt;span>(&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);">...&lt;/span>&lt;span>$&lt;/span>&lt;span>customers&lt;/span>&lt;span>)&lt;/span>&lt;span>;&lt;/span>&lt;span style="color: light-dark(#6A737D, #6A737D);"> //&lt;/span>&lt;span style="color: light-dark(#6A737D, #6A737D);"> OK&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#6F42C1, #B392F0);">createInvoiceForCustomers&lt;/span>&lt;span>(&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#D73A49, #F97583);"> new&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);"> Customer&lt;/span>&lt;span>(&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">&amp;#39;&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">any name&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">&amp;#39;&lt;/span>&lt;span>)&lt;/span>&lt;span>,&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#D73A49, #F97583);"> new&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);"> Customer&lt;/span>&lt;span>(&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">&amp;#39;&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">any name&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">&amp;#39;&lt;/span>&lt;span>)&lt;/span>&lt;span>,&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span>)&lt;/span>&lt;span>;&lt;/span>&lt;span style="color: light-dark(#6A737D, #6A737D);"> //&lt;/span>&lt;span style="color: light-dark(#6A737D, #6A737D);"> OK&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#6A737D, #6A737D);">//&lt;/span>&lt;span style="color: light-dark(#6A737D, #6A737D);"> Esto ni siquiera es posible de escribir. El IDE te gritará.&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#6A737D, #6A737D);">//&lt;/span>&lt;span style="color: light-dark(#6A737D, #6A737D);"> Está esperando un `Customer`, pero `AnyOtherType` es dado:&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#6F42C1, #B392F0);">createInvoiceForCustomers&lt;/span>&lt;span>(&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);">new&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);"> AnyOtherType&lt;/span>&lt;span>(&lt;/span>&lt;span>)&lt;/span>&lt;span>)&lt;/span>&lt;span>;&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;h3 id="pros">PROS
&lt;a class="heading-anchor" href="#pros" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;ul>
&lt;li>Podemos tipar una lista de cualquier tipo concreto de forma sencilla.&lt;/li>
&lt;/ul>
&lt;h3 id="contras">CONTRAS
&lt;a class="heading-anchor" href="#contras" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;ul>
&lt;li>Mejor limitar las funciones a uno o dos argumentos. De lo contrario, se complica la lectura.&lt;/li>
&lt;/ul>
&lt;h3 id="observaciones-importantes">Observaciones importantes
&lt;a class="heading-anchor" href="#observaciones-importantes" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;ul>
&lt;li>Debe ser el último argumento de la función.&lt;/li>
&lt;li>Ayuda a minimizar el número de argumentos.&lt;/li>
&lt;/ul>
&lt;h2 id="los-variadics-simulan-arrays-tipados-usalos-con-cabeza">Los variadics simulan arrays tipados, úsalos con cabeza
&lt;a class="heading-anchor" href="#los-variadics-simulan-arrays-tipados-usalos-con-cabeza" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h2>
&lt;p>El desempaquetado de argumentos, combinado con funciones variádicas, nos permite simular arrays tipados. Un gran poder conlleva una gran responsabilidad.
Hay que conocer bien nuestras herramientas para usarlas con criterio.&lt;/p>
&lt;p>&lt;img src="/images/blog/2020-10-13/footer.webp" alt="arrays tipados con variádicas en php" />&lt;/p>
&lt;hr />
&lt;h3 id="referencias">Referencias
&lt;a class="heading-anchor" href="#referencias" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;ul>
&lt;li>&lt;a rel="external" href="https://wiki.php.net/rfc/argument_unpacking">Desempaquetado de argumentos&lt;/a>&lt;/li>
&lt;li>&lt;a rel="external" href="https://www.php.net/manual/en/functions.arguments.php#functions.variable-arg-list">Lista de argumentos variables de función&lt;/a>&lt;/li>
&lt;li>&lt;a rel="external" href="https://wiki.php.net/rfc/variadics">Función variádica&lt;/a>&lt;/li>
&lt;/ul></content></entry><entry xml:lang="es"><title>Guía de estilo para diseño de objetos</title><category term="software-design" scheme="https://chemaclass.com/tags/software-design/" label="Software Design"/><category term="clean-code" scheme="https://chemaclass.com/tags/clean-code/" label="Clean Code"/><category term="php" scheme="https://chemaclass.com/tags/php/" label="Php"/><published>2020-10-10T00:00:00+00:00</published><updated>2020-10-10T00:00:00+00:00</updated><author><name>
Matthias Noback</name></author><link rel="alternate" type="text/html" href="https://chemaclass.com/es/readings/object-design-style-guide/"/><id>https://chemaclass.com/es/readings/object-design-style-guide/</id><summary type="html">&lt;p>Los objetos son el corazón de lenguajes como Java, Python y C#. Si aplicas buenas prácticas de diseño, tu código será más fácil de leer, escribir y mantener.&lt;/p>
&lt;p>Este libro reúne docenas de técnicas para crear código OO profesional que aguanta el paso del tiempo.&lt;/p></summary><content type="html">&lt;p>Los objetos son el corazón de lenguajes como Java, Python y C#. Si aplicas buenas prácticas de diseño, tu código será más fácil de leer, escribir y mantener.&lt;/p>
&lt;p>Este libro reúne docenas de técnicas para crear código OO profesional que aguanta el paso del tiempo.&lt;/p>
&lt;span id="continue-reading">&lt;/span>
&lt;p>Los ejemplos usan pseudocódigo fácil de entender. Las técnicas aplican a cualquier lenguaje OO, desde C++ hasta PHP.&lt;/p></content></entry><entry xml:lang="es"><title>Domain-Driven Design Distilled</title><subtitle>DDD explicado de forma clara y práctica</subtitle><category term="ddd" scheme="https://chemaclass.com/tags/ddd/" label="Ddd"/><category term="architecture" scheme="https://chemaclass.com/tags/architecture/" label="Architecture"/><category term="software-design" scheme="https://chemaclass.com/tags/software-design/" label="Software Design"/><published>2020-09-10T00:00:00+00:00</published><updated>2020-09-10T00:00:00+00:00</updated><author><name>
Vaughn Vernon</name></author><link rel="alternate" type="text/html" href="https://chemaclass.com/es/readings/domain-driven-design-distilled/"/><id>https://chemaclass.com/es/readings/domain-driven-design-distilled/</id><summary type="html">Una introducción accesible a DDD para desarrolladores, consultores y cualquiera que quiera entender el diseño guiado por dominio</summary><content type="html">&lt;p>Este libro hace que DDD cobre vida. Da igual si eres desarrollador, consultor o cliente: te ayuda a entenderlo y sacarle provecho.&lt;/p>
&lt;span id="continue-reading">&lt;/span>
&lt;hr />
&lt;p>Desarrolladores de todo el mundo lo están adoptando porque da resultados reales. Es una guía accesible que responde:&lt;/p>
&lt;ul>
&lt;li>¿Qué es DDD?&lt;/li>
&lt;li>¿Qué problemas resuelve?&lt;/li>
&lt;li>¿Cómo funciona?&lt;/li>
&lt;li>¿Cómo sacarle valor rápido?&lt;/li>
&lt;/ul>
&lt;p>Aprenderás a separar modelos de dominio con &lt;strong>Contextos Acotados&lt;/strong> (Bounded Contexts), a desarrollar un &lt;strong>Lenguaje Ubicuo&lt;/strong> dentro de cada contexto, y a lograr que &lt;strong>expertos de dominio&lt;/strong> y &lt;strong>desarrolladores&lt;/strong> colaboren para crear ese lenguaje.&lt;/p>
&lt;p>También cubre cómo usar Subdominios para manejar sistemas legacy e integrar varios Contextos Acotados definiendo relaciones entre equipos.&lt;/p>
&lt;blockquote>
&lt;p>Domain-Driven Design Distilled da vida a &lt;strong>DDD&lt;/strong>.&lt;/p>
&lt;/blockquote></content></entry><entry xml:lang="es"><title>Advanced Web Application Architecture</title><subtitle>La guía que lleva tus habilidades de código al siguiente nivel</subtitle><category term="architecture" scheme="https://chemaclass.com/tags/architecture/" label="Architecture"/><category term="php" scheme="https://chemaclass.com/tags/php/" label="Php"/><category term="software-design" scheme="https://chemaclass.com/tags/software-design/" label="Software Design"/><category term="refactoring" scheme="https://chemaclass.com/tags/refactoring/" label="Refactoring"/><published>2020-08-16T00:00:00+00:00</published><updated>2020-08-16T00:00:00+00:00</updated><author><name>
Matthias Noback</name></author><link rel="alternate" type="text/html" href="https://chemaclass.com/es/readings/advance-web-application-architecture/"/><id>https://chemaclass.com/es/readings/advance-web-application-architecture/</id><summary type="html">Cómo desacoplar tu aplicación del framework y la base de datos con PHP moderno y diseño modular</summary><content type="html">&lt;p>Este libro te ayuda a poner en forma tus aplicaciones web. Trae muchas técnicas para desacoplar tu código de la infraestructura (el framework, la base de datos, etc.).&lt;/p>
&lt;span id="continue-reading">&lt;/span>
&lt;p>La Parte 1 presenta patrones de diseño para separar código de negocio e infraestructura. La Parte 2 muestra cómo estos patrones encajan con conceptos arquitectónicos como capas, puertos y adaptadores (arquitectura Hexagonal). El libro cierra con estrategias de testing y decisiones de diseño.&lt;/p>
&lt;h3 id="lo-que-aprenderas">Lo que aprenderás
&lt;a class="heading-anchor" href="#lo-que-aprenderas" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;ul>
&lt;li>Separar código mezclado en código de negocio e infraestructura usando patrones.&lt;/li>
&lt;li>Dividir tu código en capas con una distinción clara entre puertos y adaptadores.&lt;/li>
&lt;li>Testear aplicaciones desacopladas.&lt;/li>
&lt;/ul>
&lt;blockquote>
&lt;p>Compra el libro: &lt;a rel="external" href="https://leanpub.com/web-application-architecture">https://leanpub.com/web-application-architecture&lt;/a>&lt;/p>
&lt;/blockquote>
&lt;hr />
&lt;h3 id="patrones-de-diseno-para-modernizar-codigo-legacy">Patrones de diseño para modernizar código legacy
&lt;a class="heading-anchor" href="#patrones-de-diseno-para-modernizar-codigo-legacy" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;div style="position:relative;aspect-ratio:16/9;width:100%;">
&lt;iframe
src="https://www.youtube-nocookie.com/embed/WI1QY6OMglE"
title="YouTube video"
width="560"
height="315"
loading="lazy"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
referrerpolicy="strict-origin-when-cross-origin"
style="position:absolute;inset:0;width:100%;height:100%;border:0;"
allowfullscreen>
&lt;/iframe>
&lt;/div></content></entry><entry xml:lang="es"><title>Strict Types en PHP</title><subtitle>declare(strict_types=1);</subtitle><category term="php" scheme="https://chemaclass.com/tags/php/" label="Php"/><category term="clean-code" scheme="https://chemaclass.com/tags/clean-code/" label="Clean Code"/><category term="software-design" scheme="https://chemaclass.com/tags/software-design/" label="Software Design"/><published>2020-08-09T00:00:00+00:00</published><updated>2020-08-09T00:00:00+00:00</updated><author><name>
Chemaclass</name></author><link rel="alternate" type="text/html" href="https://chemaclass.com/es/blog/strict-types/"/><id>https://chemaclass.com/es/blog/strict-types/</id><summary type="html">Por qué declarar strict_types en PHP mejora la legibilidad del código y previene errores silenciosos de coerción de tipos.</summary><content type="html">&lt;p>En diciembre de 2015, PHP 7 introdujo las declaraciones de tipos escalares y la bandera strict types. ¿Qué es esto?&lt;/p>
&lt;span id="continue-reading">&lt;/span>
&lt;p>Lo bueno de declarar un archivo PHP como estricto es que se aplica &lt;strong>solo al archivo actual&lt;/strong>. Asegura tipos estrictos en ese archivo, pero no afecta al resto del proyecto. Puedes migrar de código no estricto a estricto paso a paso, especialmente en archivos o proyectos nuevos.&lt;/p>
&lt;blockquote>
&lt;p>Para habilitar el modo estricto, coloca una directiva declare al principio del archivo. La estrictez de tipado para escalares se configura por archivo. Esta directiva afecta tanto a los parámetros como al tipo de retorno de las funciones.&lt;/p>
&lt;/blockquote>
&lt;h2 id="strict-types-afecta-la-coercion-de-tipos">Strict types afecta la coerción de tipos
&lt;a class="heading-anchor" href="#strict-types-afecta-la-coercion-de-tipos" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h2>
&lt;p>Usar type hints sin &lt;code>strict_types&lt;/code> puede causar bugs sutiles.&lt;/p>
&lt;p>Sin strict types, &lt;code>int $x&lt;/code> significa “$x debe ser coercionable a int”. Cualquier valor coercionable a int pasaría:&lt;/p>
&lt;ul>
&lt;li>un &lt;code>int&lt;/code> (42 -&amp;gt; 42)&lt;/li>
&lt;li>un &lt;code>float&lt;/code> (13.1459 -&amp;gt; 13)&lt;/li>
&lt;li>un &lt;code>bool&lt;/code> (true -&amp;gt; 1)&lt;/li>
&lt;li>un &lt;code>null&lt;/code> (null -&amp;gt; 0)&lt;/li>
&lt;li>un &lt;code>string&lt;/code> con dígitos al inicio (“15 Trees” -&amp;gt; 15)&lt;/li>
&lt;/ul>
&lt;p>Con &lt;code>strict_types=1&lt;/code>, le dices al motor que &lt;code>int $x&lt;/code> significa que $x debe ser un int real, sin coerción. Tienes la seguridad de que recibes exactamente lo que se pasó, sin conversiones ni pérdida de datos.&lt;/p>
&lt;h2 id="a-quien-le-importa-esta-linea">¿A quién le importa esta línea?
&lt;a class="heading-anchor" href="#a-quien-le-importa-esta-linea" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h2>
&lt;p>&lt;code>declare(strict_types=1);&lt;/code> es más para el lector que para el escritor. Le dice explícitamente:&lt;/p>
&lt;ul>
&lt;li>Los tipos en este archivo se tratan de forma estricta.&lt;/li>
&lt;/ul>
&lt;blockquote>
&lt;p>‘strict_types=1’ es más para el lector que para el escritor&lt;/p>
&lt;/blockquote>
&lt;p>El escritor solo necesita mantener esa estrictez mientras escribe. Pero como escritor, deberías preocuparte por tus lectores. Eso incluye a tu yo futuro.&lt;/p>
&lt;p>&lt;img src="/images/blog/2020-08-09/footer.webp" alt="declaración strict_types en php" />&lt;/p>
&lt;hr />
&lt;h2 id="referencias">Referencias
&lt;a class="heading-anchor" href="#referencias" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h2>
&lt;ul>
&lt;li>&lt;a rel="external" href="https://www.php.net/manual/en/migration70.new-features.php#migration70.new-features.scalar-type-declarations">Declaraciones de tipos escalares&lt;/a>&lt;/li>
&lt;li>&lt;a rel="external" href="https://stackoverflow.com/questions/48723637/what-do-strict-types-do-in-php/48723830#48723830">Qué hacen los strict types en PHP&lt;/a>&lt;/li>
&lt;/ul></content></entry><entry xml:lang="es"><title>El Arte del Refactoring</title><subtitle>Cuándo, cómo y por qué</subtitle><category term="refactoring" scheme="https://chemaclass.com/tags/refactoring/" label="Refactoring"/><category term="clean-code" scheme="https://chemaclass.com/tags/clean-code/" label="Clean Code"/><category term="testing" scheme="https://chemaclass.com/tags/testing/" label="Testing"/><category term="software-design" scheme="https://chemaclass.com/tags/software-design/" label="Software Design"/><published>2020-06-28T00:00:00+00:00</published><updated>2020-06-28T00:00:00+00:00</updated><author><name>
Chemaclass</name></author><link rel="alternate" type="text/html" href="https://chemaclass.com/es/blog/the-art-of-refactoring/"/><id>https://chemaclass.com/es/blog/the-art-of-refactoring/</id><summary type="html">Si ves algo, en el ámbito de tu tarea actual, que puede mejorarse fácilmente, mejóralo. Y si tienes alguna pregunta al respecto, pregunta.</summary><content type="html">&lt;p>Si ves algo, en el ámbito de tu tarea actual, que puede mejorarse fácilmente, mejóralo. Y si tienes alguna pregunta al respecto, pregunta.&lt;/p>
&lt;span id="continue-reading">&lt;/span>&lt;h2 id="que-es-el-refactoring">¿Qué es el refactoring?
&lt;a class="heading-anchor" href="#que-es-el-refactoring" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h2>
&lt;p>Refactoring significa mejorar tu código. Puede ser renombrar una variable, extraer líneas en un método privado, o separar responsabilidades de una clase en varias.&lt;/p>
&lt;p>El refactoring demuestra que te importa lo que haces como profesional. Es un tema controvertido desde hace tiempo. Pero eso no debería frenarnos de mejorar la calidad del sistema.&lt;/p>
&lt;h2 id="cuando-y-como-refactorizar">¿Cuándo y cómo refactorizar?
&lt;a class="heading-anchor" href="#cuando-y-como-refactorizar" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h2>
&lt;p>Siempre. Dentro del ámbito de tu tarea actual, a menos que sea una tarea planificada específicamente para refactoring de arquitectura.&lt;/p>
&lt;blockquote>
&lt;p>El refactoring debería ser parte del trabajo diario, no una tarea separada.&lt;/p>
&lt;/blockquote>
&lt;p>No necesitamos pedir permiso para refactorizar. ¿Acaso pedimos permiso para hacer nuestro mejor trabajo?&lt;/p>
&lt;p>Para refactorizar bien, la intención debe estar clara. ¿Qué queremos lograr y cómo? El pair programming (o incluso el “pair thinking”) ayuda porque sincroniza dos cerebros y fomenta mejor comprensión mutua.&lt;/p>
&lt;p>Refactorizar de forma colaborativa es fundamental en equipo. No debería ser tabú. Al contrario: ayuda a unificar objetivos y dirección de calidad del código.&lt;/p>
&lt;h3 id="algunos-consejos-sobre-el-como">Algunos consejos sobre el “cómo”
&lt;a class="heading-anchor" href="#algunos-consejos-sobre-el-como" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;p>Buscamos mejora continua, pero…&lt;/p>
&lt;ul>
&lt;li>
&lt;p>Si tus cambios generan más ruido que ayuda, para. Piensa si valen la pena en el estado actual del sistema. Quizás no es el momento. Quizás estás contaminando el diff con cambios fuera del ámbito. O quizás es demasiado grande para tu tarea actual. En ese caso, mejor crear una tarea de seguimiento.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Si el refactoring es necesario antes de empezar tu tarea, hazlo primero.&lt;/p>
&lt;/li>
&lt;/ul>
&lt;p>Refactorizamos para aumentar productividad: código más legible es código más fácil de entender.&lt;/p>
&lt;h3 id="testing">Testing
&lt;a class="heading-anchor" href="#testing" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;p>Necesitas un buen conjunto de tests cubriendo la lógica que vas a cambiar. Sin tests, refactorizar es arriesgado. Por lo general, cuanto más fácil es testear algo, más fácil es reemplazarlo o eliminarlo.&lt;/p>
&lt;p>Puedes leer más sobre cómo el testing está relacionado con la calidad aquí.&lt;/p>
&lt;h2 id="por-que-hacerlo">¿Por qué hacerlo?
&lt;a class="heading-anchor" href="#por-que-hacerlo" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h2>
&lt;p>¿No querrías un sistema mejor con el tiempo?&lt;/p>
&lt;p>El software no es como el vino: no mejora solo. Si quieres un sistema mejor, tienes que trabajar para conseguirlo.&lt;/p>
&lt;p>&lt;img src="/images/blog/2020-06-28/footer.webp" alt="el refactoring como mejora continua" />&lt;/p></content></entry><entry xml:lang="es"><title>Clases Final en PHP | Java | Cualquiera</title><subtitle>Final, o no final, esa es la cuestión</subtitle><category term="php" scheme="https://chemaclass.com/tags/php/" label="Php"/><category term="software-design" scheme="https://chemaclass.com/tags/software-design/" label="Software Design"/><category term="clean-code" scheme="https://chemaclass.com/tags/clean-code/" label="Clean Code"/><category term="testing" scheme="https://chemaclass.com/tags/testing/" label="Testing"/><published>2020-06-06T00:00:00+00:00</published><updated>2020-06-06T00:00:00+00:00</updated><author><name>
Chemaclass</name></author><link rel="alternate" type="text/html" href="https://chemaclass.com/es/blog/final-classes/"/><id>https://chemaclass.com/es/blog/final-classes/</id><summary type="html">Contratos claros, efectos secundarios aislados, testeabilidad, baja complejidad y carga cognitiva, fluidez del código y confianza en ti mismo.</summary><content type="html">&lt;p>Contratos claros, efectos secundarios aislados, testeabilidad, baja complejidad y carga cognitiva, fluidez del código y confianza en ti mismo.&lt;/p>
&lt;span id="continue-reading">&lt;/span>&lt;h2 id="motivacion">Motivación
&lt;a class="heading-anchor" href="#motivacion" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h2>
&lt;h3 id="reduce-la-visibilidad-al-minimo">Reduce la visibilidad al mínimo
&lt;a class="heading-anchor" href="#reduce-la-visibilidad-al-minimo" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;p>Cuando una clase es &lt;code>final&lt;/code>, no puede ser extendida. Esto la hace más legible y te asegura que la lógica está limitada a esa clase.&lt;/p>
&lt;h3 id="fomenta-composicion-sobre-herencia">Fomenta “composición sobre herencia”
&lt;a class="heading-anchor" href="#fomenta-composicion-sobre-herencia" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;p>El Principio Abierto-Cerrado dice: abierto para extensión, cerrado para modificación.&lt;/p>
&lt;p>Si decides crear una herencia (por una buena razón, de la que deberías ser consciente), simplemente quita &lt;code>final&lt;/code> y listo.&lt;/p>
&lt;p>Cuando por defecto no puedes extender una clase, te fuerzas a pensar en composición en lugar de herencia.&lt;/p>
&lt;h2 id="por-que-esta-clase-no-es-final">¿Por qué esta clase no es final?
&lt;a class="heading-anchor" href="#por-que-esta-clase-no-es-final" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h2>
&lt;p>Si preferimos composición sobre herencia, deberíamos evitar la herencia tanto como sea posible. La herencia se usa mal a menudo en POO.&lt;/p>
&lt;h3 id="un-concepto-mal-entendido">Un concepto mal entendido
&lt;a class="heading-anchor" href="#un-concepto-mal-entendido" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;p>Cuando nos enseñaron POO, normalmente empezamos con el ejemplo clásico de herencia.&lt;/p>
&lt;p>Pero cuando Alan Kay creó Smalltalk, la herencia no era el concepto principal. Lo principal era el paso de mensajes: enviar mensajes a objetos que encapsulan datos y lógica, cambiando comportamiento mediante diferentes objetos. Eso es composición. La herencia se hizo tan popular que terminó eclipsando a la composición.&lt;/p>
&lt;h3 id="beneficios">Beneficios
&lt;a class="heading-anchor" href="#beneficios" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;ul>
&lt;li>&lt;strong>Contratos claros.&lt;/strong> Usar interfaces te obliga a pensar en comunicación entre objetos.&lt;/li>
&lt;li>&lt;strong>Código aislado, sin efectos secundarios.&lt;/strong> Inyectar solo interfaces elimina efectos secundarios molestos.&lt;/li>
&lt;li>&lt;strong>Testeabilidad.&lt;/strong> Mockear interfaces es muy fácil.&lt;/li>
&lt;li>&lt;strong>Complejidad manejable.&lt;/strong> Todo aislado significa menos cambios en cascada.&lt;/li>
&lt;li>&lt;strong>Baja carga cognitiva.&lt;/strong> Menos complejidad, más foco en lo importante.&lt;/li>
&lt;li>&lt;strong>Flexibilidad.&lt;/strong> Sin acoplamiento innecesario, mover código es más fácil.&lt;/li>
&lt;li>&lt;strong>Confianza.&lt;/strong> Testear código aislado te da seguridad para cambiarlo.&lt;/li>
&lt;/ul>
&lt;h2 id="composicion-sobre-herencia">Composición sobre herencia
&lt;a class="heading-anchor" href="#composicion-sobre-herencia" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h2>
&lt;p>Si necesitas reconfigurar un objeto, cambiar partes de un algoritmo o reescribir parte de la implementación, considera crear una nueva clase en lugar de sobreescribir una existente.&lt;/p>
&lt;p>¿Necesitas representar una jerarquía donde las subclases sustituyen a las clases padre? Esta sería la situación clásica donde podrías usar herencia. Aun así, el resultado suele ser mejor si heredas de interfaces abstractas, no de clases concretas.&lt;/p>
&lt;h3 id="que-hacer-en-su-lugar">Qué hacer en su lugar
&lt;a class="heading-anchor" href="#que-hacer-en-su-lugar" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;ul>
&lt;li>Usa interfaces para definir contratos entre clases.&lt;/li>
&lt;li>Usa clases finales para implementar esas interfaces.&lt;/li>
&lt;li>Usa composición (inyección de dependencias por constructor) para unir las piezas.&lt;/li>
&lt;/ul>
&lt;blockquote>
&lt;p>Interfaces -&amp;gt; Clases finales -&amp;gt; Composición&lt;/p>
&lt;/blockquote>
&lt;p>&lt;img src="/images/blog/2020-06-06/footer.webp" alt="interfaces, clases finales y composición" />&lt;/p></content></entry><entry xml:lang="es"><title>Siete lenguajes en siete semanas</title><subtitle>Una guía práctica para aprender lenguajes de programación</subtitle><category term="software-design" scheme="https://chemaclass.com/tags/software-design/" label="Software Design"/><category term="software" scheme="https://chemaclass.com/tags/software/" label="Software"/><category term="career" scheme="https://chemaclass.com/tags/career/" label="Career"/><published>2020-05-21T00:00:00+00:00</published><updated>2020-05-21T00:00:00+00:00</updated><author><name>
Bruce Tate</name></author><link rel="alternate" type="text/html" href="https://chemaclass.com/es/readings/7-languages-in-7-weeks/"/><id>https://chemaclass.com/es/readings/7-languages-in-7-weeks/</id><summary type="html">Una guía práctica para expandir tu mente como programador explorando paradigmas diferentes</summary><content type="html">&lt;span id="continue-reading">&lt;/span>
&lt;p>El Programador Pragmático recomienda aprender un lenguaje nuevo cada año. Pero si uno por año está bien, ¿por qué no siete en siete semanas?&lt;/p>
&lt;p>Este libro te lleva de paseo por Clojure, Haskell, Io, Prolog, Scala, Erlang y Ruby. Aunque tu lenguaje favorito no esté en la lista, vas a ampliar tu forma de pensar al ver estos lenguajes lado a lado. Aprenderás algo valioso de cada uno. Y lo mejor: aprenderás a aprender lenguajes rápido.&lt;/p>
&lt;hr />
&lt;p>Creé este repositorio con todo lo que fui aprendiendo mientras leía y experimentaba con los lenguajes del libro: &lt;a rel="external" href="https://github.com/Chemaclass/7LangIn7Weeks">https://github.com/Chemaclass/7LangIn7Weeks&lt;/a>&lt;/p></content></entry><entry xml:lang="es"><title>El Arte del Testing: Donde el Diseño se Encuentra con la Calidad</title><subtitle>Desde el punto de vista de un desarrollador de software</subtitle><category term="testing" scheme="https://chemaclass.com/tags/testing/" label="Testing"/><category term="software-design" scheme="https://chemaclass.com/tags/software-design/" label="Software Design"/><category term="clean-code" scheme="https://chemaclass.com/tags/clean-code/" label="Clean Code"/><category term="tdd" scheme="https://chemaclass.com/tags/tdd/" label="Tdd"/><published>2020-04-07T00:00:00+00:00</published><updated>2020-04-07T00:00:00+00:00</updated><author><name>
Chemaclass</name></author><link rel="alternate" type="text/html" href="https://chemaclass.com/es/blog/the-art-of-testing/"/><id>https://chemaclass.com/es/blog/the-art-of-testing/</id><summary type="html">Por qué deberías considerar el testing como parte de tu hábito diario de desarrollo y cómo está directamente vinculado a la calidad del software.</summary><content type="html">&lt;p>¿Por qué considerar el testing parte de tu desarrollo diario? Porque está directamente vinculado a la calidad del software.&lt;/p>
&lt;span id="continue-reading">&lt;/span>
&lt;p>No voy a explicar las diferentes técnicas de testing ni las diferencias entre tests unitarios, de integración, funcionales o end-to-end.&lt;/p>
&lt;p>Me sigue sorprendiendo la falta de experiencia con testing en el mundo del software. Hay una ignorancia generalizada sobre buenas prácticas. Si has trabajado en varios proyectos y equipos, seguro que lo has visto.&lt;/p>
&lt;h3 id="testing-de-software">Testing de software
&lt;a class="heading-anchor" href="#testing-de-software" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;p>Algunos patrones horribles que he visto (y hecho):&lt;/p>
&lt;ul>
&lt;li>Testear por testear: testear cada archivo individual, confundiéndolo con una “unidad”.&lt;/li>
&lt;li>Mockear cada clase, anulando la implementación real y creando comportamiento falso. Esto da una falsa sensación de cobertura.&lt;/li>
&lt;li>Acoplar código de producción con tests por todas partes. Imposible cambiar nada sin romper tests, aunque la funcionalidad siga funcionando.&lt;/li>
&lt;li>No testear nada porque “ya funciona, ¿para qué perder más tiempo?”&lt;/li>
&lt;/ul>
&lt;p>Una razón principal del testing es verificar el comportamiento esperado del software. Pero el testing puede (y debería) ser mucho más que eso.&lt;/p>
&lt;h3 id="diseno-de-software">Diseño de software
&lt;a class="heading-anchor" href="#diseno-de-software" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;p>El diseño de software abarca desde algoritmos hasta arquitectura. Aunque estos dos niveles tienen necesidades distintas, comparten patrones comunes. Por ejemplo, el testing:&lt;/p>
&lt;blockquote>
&lt;p>Si es fácil de testear, probablemente será debido a un buen diseño.&lt;/p>
&lt;/blockquote>
&lt;h3 id="calidad-del-software">Calidad del software
&lt;a class="heading-anchor" href="#calidad-del-software" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;p>Medir la calidad es difícil. Hay muchas métricas a considerar. Aun así, seguro que podemos estar de acuerdo en esto:&lt;/p>
&lt;blockquote>
&lt;p>Si aspiras a la calidad en tu software, mejor busca un buen diseño.&lt;/p>
&lt;/blockquote>
&lt;p>Testear significa “probar”. ¿Cuántas veces hemos abandonado tests por la complejidad de probar cierta lógica?&lt;/p>
&lt;p>El arte del testing consiste en usar los tests para contribuir al resultado final. Si usamos el testing a nuestro favor, según el contexto, mejoraremos la calidad del producto.&lt;/p>
&lt;p>Por tanto, el testing no solo verifica comportamiento. También guía el software hacia un mejor diseño.&lt;/p>
&lt;p>¿Deberíamos testear todo? Depende del contexto. Habrá situaciones donde los tests no aporten beneficio. Aun así, escribe código como si fuera a ser testeado.&lt;/p>
&lt;p>&lt;img src="/images/blog/2020-04-07/footer.webp" alt="código testeable y buen diseño" />&lt;/p>
&lt;blockquote>
&lt;p>El código testeable tiende a un mejor diseño y, por lo tanto, a mejor calidad.&lt;/p>
&lt;/blockquote></content></entry><entry xml:lang="es"><title>Agile Limpio</title><subtitle>De Vuelta a lo Básico</subtitle><category term="agile" scheme="https://chemaclass.com/tags/agile/" label="Agile"/><category term="tdd" scheme="https://chemaclass.com/tags/tdd/" label="Tdd"/><category term="software-design" scheme="https://chemaclass.com/tags/software-design/" label="Software Design"/><published>2020-03-12T00:00:00+00:00</published><updated>2020-03-12T00:00:00+00:00</updated><author><name>
Robert C. Martin</name></author><link rel="alternate" type="text/html" href="https://chemaclass.com/es/readings/clean-agile/"/><id>https://chemaclass.com/es/readings/clean-agile/</id><summary type="html">Uncle Bob, uno de los padres fundadores de Agile, vuelve a lo básico: qué fue Agile, qué es y qué será.</summary><content type="html">&lt;span id="continue-reading">&lt;/span>
&lt;p>Clean Agile viene de Uncle Bob, uno de los padres fundadores de Agile. Fue una de las diecisiete personas que escribieron el &lt;a rel="external" href="https://agilemanifesto.org/">Manifiesto Ágil&lt;/a> en 2001.&lt;/p>
&lt;hr />
&lt;p>El libro trata sobre Agile: lo que fue, lo que es y lo que será. Es un regreso a lo básico que cubre la historia de Agile, qué lo motivó y qué ha pasado desde entonces. Cubre las prácticas básicas y las compara con la variedad actual de procesos ágiles.&lt;/p>
&lt;div style="position:relative;aspect-ratio:16/9;width:100%;">
&lt;iframe
src="https://www.youtube-nocookie.com/embed/FedQ2NlgxMI"
title="YouTube video"
width="560"
height="315"
loading="lazy"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
referrerpolicy="strict-origin-when-cross-origin"
style="position:absolute;inset:0;width:100%;height:100%;border:0;"
allowfullscreen>
&lt;/iframe>
&lt;/div></content></entry><entry xml:lang="es"><title>Trabajando con código legado</title><subtitle>Estrategias para trabajar con código heredado</subtitle><category term="refactoring" scheme="https://chemaclass.com/tags/refactoring/" label="Refactoring"/><category term="testing" scheme="https://chemaclass.com/tags/testing/" label="Testing"/><category term="tdd" scheme="https://chemaclass.com/tags/tdd/" label="Tdd"/><category term="software-design" scheme="https://chemaclass.com/tags/software-design/" label="Software Design"/><published>2019-07-01T00:00:00+00:00</published><updated>2019-07-01T00:00:00+00:00</updated><author><name>
Michael Feathers</name></author><link rel="alternate" type="text/html" href="https://chemaclass.com/es/readings/working-effectively-with-legacy-code/"/><id>https://chemaclass.com/es/readings/working-effectively-with-legacy-code/</id><summary type="html">Estrategias prácticas para lidiar con grandes bases de código sin tests. Cómo añadir tests, romper dependencias y refactorizar con seguridad.</summary><content type="html">&lt;span id="continue-reading">&lt;/span>&lt;h2 id="que-es-codigo-legacy">¿Qué es código legacy?
&lt;a class="heading-anchor" href="#que-es-codigo-legacy" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h2>
&lt;blockquote>
&lt;p>El código legacy es simplemente código sin tests.&lt;/p>
&lt;/blockquote>
&lt;h3 id="beneficios-de-los-tests">Beneficios de los tests
&lt;a class="heading-anchor" href="#beneficios-de-los-tests" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;p>El comportamiento es clave para entender los beneficios del testing:&lt;/p>
&lt;blockquote>
&lt;p>El comportamiento es lo más importante del software. Los usuarios dependen de él. Les gusta que añadamos funcionalidad (si es lo que querían), pero si cambiamos o rompemos comportamiento del que dependen, pierden la confianza.&lt;/p>
&lt;/blockquote>
&lt;h3 id="como-implementar-tests-en-bases-de-codigo-legacy">Cómo implementar tests en bases de código legacy
&lt;a class="heading-anchor" href="#como-implementar-tests-en-bases-de-codigo-legacy" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;p>Para cambiar código necesitas tests. Pero para añadir tests muchas veces tienes que cambiar código.&lt;/p>
&lt;p>El enfoque sugerido:&lt;/p>
&lt;ol>
&lt;li>Identificar puntos de cambio.&lt;/li>
&lt;li>Encontrar puntos de test.&lt;/li>
&lt;li>Romper dependencias.&lt;/li>
&lt;li>Escribir tests.&lt;/li>
&lt;li>Hacer cambios y refactorizar.&lt;/li>
&lt;/ol>
&lt;p>Un término útil es “&lt;strong>costura&lt;/strong>” (seam): &lt;strong>un lugar donde puedes cambiar el comportamiento sin editar ese código directamente&lt;/strong>. Como la costura en la ropa, donde dos partes se unen.
En software, &lt;strong>estos lugares suelen tener interfaces bien definidas&lt;/strong>. Puedes aprovecharlos para cambiar implementaciones con inyección de dependencias o mocking en tests.&lt;/p>
&lt;hr />
&lt;div style="position:relative;aspect-ratio:16/9;width:100%;">
&lt;iframe
src="https://www.youtube-nocookie.com/embed/wRtJRkRIa2s"
title="YouTube video"
width="560"
height="315"
loading="lazy"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
referrerpolicy="strict-origin-when-cross-origin"
style="position:absolute;inset:0;width:100%;height:100%;border:0;"
allowfullscreen>
&lt;/iframe>
&lt;/div></content></entry><entry xml:lang="es"><title>Arquitectura Limpia</title><subtitle>Guía del artesano para la estructura y diseño de software</subtitle><category term="architecture" scheme="https://chemaclass.com/tags/architecture/" label="Architecture"/><category term="software-design" scheme="https://chemaclass.com/tags/software-design/" label="Software Design"/><category term="clean-code" scheme="https://chemaclass.com/tags/clean-code/" label="Clean Code"/><category term="ddd" scheme="https://chemaclass.com/tags/ddd/" label="Ddd"/><published>2018-06-04T00:00:00+00:00</published><updated>2018-06-04T00:00:00+00:00</updated><author><name>
Robert C. Martin</name></author><link rel="alternate" type="text/html" href="https://chemaclass.com/es/readings/clean-architecture/"/><id>https://chemaclass.com/es/readings/clean-architecture/</id><summary type="html">Cómo estructurar y diseñar software de forma profesional. Principios SOLID, componentes y capas explicados con claridad.</summary><content type="html">&lt;span id="continue-reading">&lt;/span>&lt;h3 id="principios-de-diseno-de-codigo-solid">Principios de diseño de código (SOLID)
&lt;a class="heading-anchor" href="#principios-de-diseno-de-codigo-solid" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;ul>
&lt;li>&lt;strong>Responsabilidad Única&lt;/strong>: una clase debe tener una sola razón para cambiar. O en su versión nueva: un módulo responde ante un solo actor.&lt;/li>
&lt;li>&lt;strong>Abierto-cerrado&lt;/strong>: abierta para extensión, cerrada para modificación.&lt;/li>
&lt;li>&lt;strong>Sustitución de Liskov&lt;/strong>: puedes reemplazar objetos por instancias de sus subtipos sin romper el programa.&lt;/li>
&lt;li>&lt;strong>Segregación de Interfaces&lt;/strong>: mejor muchas interfaces específicas que una general.&lt;/li>
&lt;li>&lt;strong>Inversión de Dependencias&lt;/strong>: depende de abstracciones, no de implementaciones concretas.&lt;/li>
&lt;/ul>
&lt;h3 id="principios-de-componentes">Principios de componentes
&lt;a class="heading-anchor" href="#principios-de-componentes" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;h4 id="cohesion-de-componentes">Cohesión de componentes
&lt;a class="heading-anchor" href="#cohesion-de-componentes" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h4>
&lt;ul>
&lt;li>&lt;strong>Equivalencia Reutilización/Liberación&lt;/strong>: las clases reutilizadas juntas deben liberarse juntas. Mismo número de versión y changelog adecuado.&lt;/li>
&lt;li>&lt;strong>Cierre Común&lt;/strong>: las clases que cambian juntas van juntas. Es el principio de responsabilidad única a nivel de componente.&lt;/li>
&lt;li>&lt;strong>Reutilización Común&lt;/strong>: no obligues a los usuarios a depender de lo que no necesitan. Segregación de interfaces a nivel de componente.&lt;/li>
&lt;/ul>
&lt;h4 id="acoplamiento-de-componentes">Acoplamiento de componentes
&lt;a class="heading-anchor" href="#acoplamiento-de-componentes" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h4>
&lt;ul>
&lt;li>&lt;strong>Dependencias Acíclicas&lt;/strong>: sin ciclos en el grafo de dependencias. Los ciclos fuerzan a liberar componentes juntos. Usa inversión de dependencias para romperlos.&lt;/li>
&lt;li>&lt;strong>Dependencia Estable&lt;/strong>: los componentes menos estables dependen de los más estables. Depende en dirección de la estabilidad.&lt;/li>
&lt;li>&lt;strong>Abstracciones Estables&lt;/strong>: los componentes estables deben ser abstractos. Ejemplo: una política de alto nivel que se extiende siguiendo abierto-cerrado.&lt;/li>
&lt;/ul>
&lt;h3 id="principios-de-arquitectura">Principios de arquitectura
&lt;a class="heading-anchor" href="#principios-de-arquitectura" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;h4 id="estableciendo-limites">Estableciendo límites
&lt;a class="heading-anchor" href="#estableciendo-limites" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h4>
&lt;p>Los límites separan elementos de software: lo que importa de lo que no, lo de alto nivel de lo de bajo nivel. Si el código de alto nivel depende del de bajo nivel, los cambios se propagan hacia arriba. Ponemos un límite usando polimorfismo para invertir el flujo. Esto es el Principio de Inversión de Dependencias de SOLID.&lt;/p>
&lt;h4 id="separando-capas">Separando capas
&lt;a class="heading-anchor" href="#separando-capas" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h4>
&lt;p>Cuatro capas principales (aunque puede variar):&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Entidades&lt;/strong>: objetos con lógica de negocio crítica. Ejemplo: un banco que no da préstamos a clientes sin cierta puntuación crediticia. Se comparten entre aplicaciones de la empresa.&lt;/li>
&lt;li>&lt;strong>Casos de uso&lt;/strong>: reglas de negocio específicas de la aplicación. Ejemplo: la secuencia de pantallas para hacer una transferencia.&lt;/li>
&lt;li>&lt;strong>Adaptadores de interfaz&lt;/strong>: gateways, presenters, controllers. Aquí va la arquitectura MVC de la GUI y la transformación de datos entre base de datos y casos de uso.&lt;/li>
&lt;li>&lt;strong>Frameworks y drivers&lt;/strong>: frameworks web, base de datos, la vista de MVC.&lt;/li>
&lt;/ul></content></entry><entry xml:lang="es"><title>El Programador Pragmático</title><subtitle>El camino hacia la maestría</subtitle><category term="software-design" scheme="https://chemaclass.com/tags/software-design/" label="Software Design"/><category term="clean-code" scheme="https://chemaclass.com/tags/clean-code/" label="Clean Code"/><category term="refactoring" scheme="https://chemaclass.com/tags/refactoring/" label="Refactoring"/><category term="career" scheme="https://chemaclass.com/tags/career/" label="Career"/><published>2016-10-01T00:00:00+00:00</published><updated>2016-10-01T00:00:00+00:00</updated><author><name>
Andrew Hunt</name></author><author><name>
David Thomas</name></author><link rel="alternate" type="text/html" href="https://chemaclass.com/es/readings/the-pragmatic-programmer/"/><id>https://chemaclass.com/es/readings/the-pragmatic-programmer/</id><summary type="html">Un clásico sobre cómo convertirse en mejor desarrollador. Mentalidad, herramientas y buenas prácticas para dominar el oficio.</summary><content type="html">&lt;span id="continue-reading">&lt;/span>&lt;h3 id="aprendizajes">Aprendizajes
&lt;a class="heading-anchor" href="#aprendizajes" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;ul>
&lt;li>No te repitas.&lt;/li>
&lt;li>La mentalidad importa tanto como el conocimiento.&lt;/li>
&lt;li>El buen código es más fácil de cambiar que el mal diseño.&lt;/li>
&lt;li>Elige buenas herramientas y domínalas.&lt;/li>
&lt;/ul>
&lt;hr />
&lt;h4 id="no-te-repitas-dry">No Te Repitas (DRY)
&lt;a class="heading-anchor" href="#no-te-repitas-dry" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h4>
&lt;ul>
&lt;li>Cada pieza de conocimiento debe tener una única representación clara dentro del sistema.&lt;/li>
&lt;li>DRY trata sobre la duplicación de conocimiento, de intención. Es expresar lo mismo en dos lugares, quizás de formas diferentes.&lt;/li>
&lt;/ul>
&lt;h4 id="la-mentalidad-importa-tanto-como-el-conocimiento">La mentalidad importa tanto como el conocimiento
&lt;a class="heading-anchor" href="#la-mentalidad-importa-tanto-como-el-conocimiento" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h4>
&lt;p>Aspectos clave:&lt;/p>
&lt;ul>
&lt;li>Asume la responsabilidad de tu trabajo. Sin excusas ni culpas cuando algo sale mal.&lt;/li>
&lt;li>Escribe software “suficientemente bueno”. No pierdas tiempo perfeccionando lo que ya funciona para el producto.&lt;/li>
&lt;li>No ignores la deuda técnica. Los autores usan la analogía de las ventanas rotas:&lt;/li>
&lt;/ul>
&lt;blockquote>
&lt;p>No dejes “ventanas rotas” (malos diseños, decisiones incorrectas o código pobre) sin reparar.
Arregla cada una cuando la descubras. Si no hay tiempo, al menos tápalas.
Comenta el código problemático, muestra un mensaje de “No Implementado” o usa datos ficticios temporalmente.&lt;/p>
&lt;/blockquote></content></entry><entry xml:lang="es"><title>97 cosas que todo programador debería saber</title><subtitle>Sabiduría colectiva de los expertos</subtitle><category term="software-design" scheme="https://chemaclass.com/tags/software-design/" label="Software Design"/><category term="clean-code" scheme="https://chemaclass.com/tags/clean-code/" label="Clean Code"/><category term="career" scheme="https://chemaclass.com/tags/career/" label="Career"/><category term="productivity" scheme="https://chemaclass.com/tags/productivity/" label="Productivity"/><published>2016-07-15T00:00:00+00:00</published><updated>2016-07-15T00:00:00+00:00</updated><author><name>
Kevlin Henney</name></author><link rel="alternate" type="text/html" href="https://chemaclass.com/es/readings/97-things-every-programmer-should-know/"/><id>https://chemaclass.com/es/readings/97-things-every-programmer-should-know/</id><summary type="html">97 consejos cortos y prácticos para mejorar como programador. Da igual qué lenguaje uses: aquí encontrarás nuevos enfoques, buenas prácticas y consejos sólidos de expertos.</summary><content type="html">&lt;p>97 consejos cortos y útiles para programadores. Da igual qué lenguaje uses: aquí encontrarás nuevos enfoques para viejos problemas, buenas prácticas y consejos de expertos para mejorar tu oficio.&lt;/p>
&lt;span id="continue-reading">&lt;/span>&lt;h3 id="mis-principales-aprendizajes">Mis principales aprendizajes
&lt;a class="heading-anchor" href="#mis-principales-aprendizajes" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;p>01.- Paga la deuda técnica lo antes posible.&lt;/p>
&lt;p>02.- Aprende y domina la &lt;strong>programación funcional&lt;/strong>.&lt;/p>
&lt;ul>
&lt;li>Hace tu código menos propenso a errores y más fácil de depurar.&lt;/li>
&lt;/ul>
&lt;p>03.- No adivines lo que haría un usuario; haz que los usuarios hagan cosas y obsérvalos.&lt;/p>
&lt;p>04.- &lt;strong>Automatiza&lt;/strong> los estándares de código.&lt;/p>
&lt;p>05.- Escribe código &lt;strong>simple&lt;/strong>, nombres descriptivos simples, relaciones simples.&lt;/p>
&lt;p>06.- Antes de refactorizar: considera los tests existentes y el código.&lt;/p>
&lt;ul>
&lt;li>Trabaja en incrementos, asegúrate de que los tests sigan pasando después de cada cambio.&lt;/li>
&lt;/ul>
&lt;p>08.- Siempre deja el código &lt;strong>más limpio&lt;/strong> de lo que lo encontraste, incluso si no lo escribiste.&lt;/p>
&lt;p>10.- Elige tus librerías/frameworks cuidadosamente para evitar complejidad innecesaria.&lt;/p>
&lt;p>11.- Haz tu código fácil de entender usando términos del &lt;strong>dominio&lt;/strong>.&lt;/p>
&lt;p>13.- El &lt;strong>formato&lt;/strong> del código también es importante.&lt;/p>
&lt;p>14.- Usa &lt;strong>revisiones&lt;/strong> de código enfocándote en compartir conocimiento entre miembros del equipo.&lt;/p>
&lt;p>15.- Objetos &lt;strong>inmutables&lt;/strong> siempre que sea relevante. Cada variable debería tener el menor alcance posible. Nunca incluyas más de cuatro argumentos de función.&lt;/p>
&lt;p>18.- Toma &lt;strong>responsabilidad&lt;/strong> de tu propia educación. Nunca dejes de aprender.&lt;/p>
&lt;ul>
&lt;li>Basta con dedicar un poco de tiempo cada semana: podcasts, cursos, libros…&lt;/li>
&lt;/ul>
&lt;p>19.- Al diseñar una API, apunta a hacerla &lt;strong>fácil de usar&lt;/strong>, no conveniente de codificar.&lt;/p>
&lt;p>20.- Despliega temprano y &lt;strong>frecuentemente&lt;/strong>. No lo dejes hasta el final del proyecto.&lt;/p>
&lt;p>22.- Mejorar tus habilidades debería ser algo diario.&lt;/p>
&lt;p>23.- Adapta el nivel técnico de tu lenguaje específico del dominio a tu audiencia.&lt;/p>
&lt;p>24.- &lt;strong>No tengas miedo&lt;/strong> de romper cosas si eso es lo necesario para arreglar cosas.&lt;/p>
&lt;p>25.- Ten cuidado con tus datos de prueba porque podrían hacerse públicos accidentalmente.&lt;/p>
&lt;p>26.- Maneja tus errores cuando aparecen, no lo dejes para después.&lt;/p>
&lt;p>27.- Aprende &lt;strong>diferentes&lt;/strong> lenguajes de programación.&lt;/p>
&lt;ul>
&lt;li>Aprende su propia “cultura” o forma de hacer las cosas.&lt;/li>
&lt;li>Definitivamente te hará un mejor programador.&lt;/li>
&lt;/ul>
&lt;p>28.- No solo captures tus errores, realmente manéjalos.&lt;/p>
&lt;p>29.- Entiende al menos algunas complejidades de tu negocio, no solo programación.&lt;/p>
&lt;p>30.- &lt;strong>DRY&lt;/strong>: No Te Repitas.&lt;/p>
&lt;p>32.- Encapsula comportamiento, no solo estado.&lt;/p>
&lt;p>33.- Los números de punto flotante inevitablemente pueden crear errores en los cálculos.&lt;/p>
&lt;p>34.- El &lt;strong>código abierto&lt;/strong> es una gran oportunidad para hacer trabajo interesante y desarrollar habilidades de programación.&lt;/p>
&lt;p>36.- Da el &lt;strong>contexto&lt;/strong> adecuado cuando pidas ayuda, porque la gente no puede adivinar lo que está pasando.&lt;/p>
&lt;p>37.- No se trata de echar muchas horas. Aprende a &lt;strong>trabajar con eficacia&lt;/strong>.&lt;/p>
&lt;ul>
&lt;li>Dedica tiempo a aprender y a pensar en lo que haces.&lt;/li>
&lt;/ul>
&lt;p>38.- Escribe &lt;strong>reportes de bugs&lt;/strong> apropiados:&lt;/p>
&lt;ul>
&lt;li>Precisamente cómo reproducir el bug,&lt;/li>
&lt;li>con qué frecuencia aparece,&lt;/li>
&lt;li>qué debería haber pasado,&lt;/li>
&lt;li>qué realmente pasó.&lt;/li>
&lt;/ul>
&lt;p>39.- No escribas código innecesario.&lt;/p>
&lt;ul>
&lt;li>Solo escribe código que añada valor y se necesite ahora mismo.&lt;/li>
&lt;li>&lt;strong>Elimina código muerto&lt;/strong>.&lt;/li>
&lt;/ul>
&lt;p>41.- La causa principal de lentitud en aplicaciones suele ser el exceso de llamadas remotas &lt;strong>entre procesos&lt;/strong>, no el algoritmo.&lt;/p>
&lt;ul>
&lt;li>Por ejemplo, conexiones a base de datos.&lt;/li>
&lt;/ul>
&lt;p>42.- Si aparece una advertencia del compilador, arréglala.&lt;/p>
&lt;ul>
&lt;li>No lo dejes para después, aunque no vaya a ser problema en producción.&lt;/li>
&lt;li>“Compilador” incluye cualquier análisis estático en lenguajes no compilados.&lt;/li>
&lt;/ul>
&lt;p>43.- Aprender a usar herramientas de &lt;strong>línea de comandos&lt;/strong> es una experiencia educativa valiosa, y podrías terminar prefiriéndolas.&lt;/p>
&lt;p>44.- Aprende (al menos) dos lenguajes y paradigmas diferentes bien.&lt;/p>
&lt;p>45.- Invierte algo de tiempo para &lt;strong>dominar&lt;/strong> el IDE que usas.&lt;/p>
&lt;ul>
&lt;li>Te hará la vida más fácil y te ahorrará tiempo a largo plazo.&lt;/li>
&lt;/ul>
&lt;p>46.- Conoce y trabaja con tus limitaciones: presupuesto, recursos, tiempo, etc.&lt;/p>
&lt;p>47.- Trabaja en &lt;strong>tareas pequeñas&lt;/strong>. No tengas miedo de descartar cambios.&lt;/p>
&lt;ul>
&lt;li>El conocimiento adquirido no se pierde.&lt;/li>
&lt;li>Ten claro qué quieres lograr antes de empezar.&lt;/li>
&lt;/ul>
&lt;p>48.- Usa una BD relacional si tu aplicación va a manejar un conjunto grande, persistente e interconectado de datos.&lt;/p>
&lt;p>49.- Aprende a &lt;strong>comunicar&lt;/strong> bien: no solo con tu máquina, también con negocio. Y quizás otro idioma.&lt;/p>
&lt;ul>
&lt;li>Es bueno para las conexiones y para la vida.&lt;/li>
&lt;/ul>
&lt;p>54.- Piensa dos veces antes de implementar “soluciones temporales”.&lt;/p>
&lt;p>55.- Haz la &lt;strong>GUI&lt;/strong> fácil de usar bien y difícil de usar mal.&lt;/p>
&lt;ul>
&lt;li>Anticipa errores y busca cómo prevenirlos.&lt;/li>
&lt;li>Se trata de la experiencia del usuario, no de la tuya.&lt;/li>
&lt;/ul>
&lt;p>56.- En proyectos, encuentra formas de hacer &lt;strong>lo invisible visible&lt;/strong>.&lt;/p>
&lt;p>57.- El paso de mensajes lleva a mejor &lt;strong>escalabilidad&lt;/strong> en sistemas paralelos.&lt;/p>
&lt;p>58.- Escribe código que otras personas puedan &lt;strong>entender&lt;/strong> fácilmente.&lt;/p>
&lt;p>59.- El &lt;strong>polimorfismo&lt;/strong> reduce la necesidad de if/else, lo que produce código más corto y seguro.&lt;/p>
&lt;p>60.- QA es tu amigo, no tu enemigo.&lt;/p>
&lt;p>61.- Versiona tus releases.&lt;/p>
&lt;p>62.- Asegúrate de que tu código fuente indique claramente lo que el programa está haciendo.&lt;/p>
&lt;p>63.- Aprende sobre el proceso de build. Es una parte importante del desarrollo.&lt;/p>
&lt;p>64.- Practica &lt;strong>pair programming&lt;/strong>.&lt;/p>
&lt;p>65.- Prefiere &lt;strong>tipos específicos del dominio&lt;/strong> sobre tipos primitivos.&lt;/p>
&lt;ul>
&lt;li>Hacen el código más legible y menos propenso a errores en el desarrollo.&lt;/li>
&lt;/ul>
&lt;p>67.- Un profesional toma &lt;strong>responsabilidad personal&lt;/strong> por su carrera y su código.&lt;/p>
&lt;p>68.- Usa control de versiones.&lt;/p>
&lt;p>69.- A veces la mejor forma de resolver un problema es alejarte del ordenador y dejar que la solución aparezca mágicamente en tu mente.&lt;/p>
&lt;p>70.- Leer código es una buena forma de &lt;strong>aprender&lt;/strong>. El código de otras personas o tu código antiguo.&lt;/p>
&lt;p>72.- Reinventar la rueda es una gran forma de desarrollar tus habilidades.&lt;/p>
&lt;p>75.- Si el código que escribiste es verdaderamente horrible, no intentes arreglarlo. &lt;strong>Bórralo&lt;/strong> y empieza de nuevo.&lt;/p>
&lt;p>76.- Aplica el Principio de Responsabilidad Única (&lt;strong>SRP&lt;/strong>).&lt;/p>
&lt;p>77.- Si alguien pide un cambio de producto, no lo descartes aunque no estés de acuerdo. Pregunta por qué.&lt;/p>
&lt;ul>
&lt;li>Llegarás a conversaciones más productivas y mejores resultados.&lt;/li>
&lt;/ul>
&lt;p>78.- Si estás haciendo lo mismo una y otra vez, intenta encontrar una forma de &lt;strong>automatizarlo&lt;/strong>.&lt;/p>
&lt;p>79.- Aprovecha las herramientas de análisis de código.&lt;/p>
&lt;p>80.- Escribe tests basados en la &lt;strong>funcionalidad deseada&lt;/strong> de tu programa, no en comportamiento incidental.&lt;/p>
&lt;p>83.- El testing toma tiempo, pero asegura la &lt;strong>calidad&lt;/strong> del producto final. Hazlo.&lt;/p>
&lt;p>85.- Hay muchos beneficios en el trabajo colaborativo y pair programming.&lt;/p>
&lt;p>86.- A veces arreglar un error en el código lleva a descubrir un error oculto.&lt;/p>
&lt;p>87.- Escribe código &lt;strong>pensando en otros programadores&lt;/strong>.&lt;/p>
&lt;p>88.- Aprende a usar herramientas Unix. Aprende a usar el &lt;strong>terminal&lt;/strong>.&lt;/p>
&lt;p>89.- Usa el algoritmo y estructura de datos correctos para el trabajo.&lt;/p>
&lt;ul>
&lt;li>Para hacer eso, necesitas entenderlos bien.&lt;/li>
&lt;/ul>
&lt;p>90.- Ten una buena política de logging.&lt;/p>
&lt;p>91.- Usar el principio DRY te ayuda a identificar y reparar cuellos de botella de rendimiento.&lt;/p>
&lt;p>92.- Testers y programadores deberían &lt;strong>colaborar&lt;/strong>.&lt;/p>
&lt;p>93.- Escribe código como si tuvieras que mantenerlo &lt;strong>el resto de tu vida&lt;/strong>.&lt;/p>
&lt;p>94.- Intenta escribir &lt;strong>funciones “pequeñas”&lt;/strong>.&lt;/p>
&lt;ol start="95">
&lt;li>Los buenos tests actúan como &lt;strong>documentación&lt;/strong> para el código que prueban.&lt;/li>
&lt;/ol>
&lt;ul>
&lt;li>Describen cómo funciona el código.&lt;/li>
&lt;/ul>
&lt;ol start="96">
&lt;li>Para ser un buen programador, tienes que preocuparte por la &lt;strong>calidad&lt;/strong> del código.&lt;/li>
&lt;/ol>
&lt;p>97.- &lt;strong>Habla con tus clientes&lt;/strong> antes de asumir que entiendes lo que quieren. De verdad.&lt;/p></content></entry><entry xml:lang="es"><title>Código Limpio</title><subtitle>Manual de artesanía ágil de software</subtitle><category term="clean-code" scheme="https://chemaclass.com/tags/clean-code/" label="Clean Code"/><category term="software-design" scheme="https://chemaclass.com/tags/software-design/" label="Software Design"/><category term="testing" scheme="https://chemaclass.com/tags/testing/" label="Testing"/><category term="tdd" scheme="https://chemaclass.com/tags/tdd/" label="Tdd"/><category term="refactoring" scheme="https://chemaclass.com/tags/refactoring/" label="Refactoring"/><published>2016-05-01T00:00:00+00:00</published><updated>2016-05-01T00:00:00+00:00</updated><author><name>
Robert C. Martin</name></author><link rel="alternate" type="text/html" href="https://chemaclass.com/es/readings/clean-code/"/><id>https://chemaclass.com/es/readings/clean-code/</id><summary type="html">El código malo funciona, pero puede hundir a una empresa. Cada año se pierden horas y recursos por código mal escrito. Este libro te enseña a evitarlo.</summary><content type="html">&lt;p>El código malo puede funcionar, pero si no está limpio, puede hundir a una empresa. Cada año se pierden horas y recursos por culpa de código mal escrito. No tiene por qué ser así.&lt;/p>
&lt;span id="continue-reading">&lt;/span>
&lt;hr />
&lt;h2 id="resumen">Resumen
&lt;a class="heading-anchor" href="#resumen" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h2>
&lt;h3 id="capitulo-1-que-es-el-codigo-limpio">Capítulo 1: ¿Qué es el código limpio?
&lt;a class="heading-anchor" href="#capitulo-1-que-es-el-codigo-limpio" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;ul>
&lt;li>El código se puede medir como “bueno” o “malo” en una revisión, o por cuánto tiempo tardas en explicarlo.&lt;/li>
&lt;li>El código limpio es elegante, eficiente, legible, simple, sin duplicaciones y bien escrito.&lt;/li>
&lt;li>Tu código debe añadir valor al negocio.&lt;/li>
&lt;li>Al abrir un archivo fuente, el código limpio transmite calidad y se entiende fácilmente.&lt;/li>
&lt;li>Haz tu código limpio y legible para que cualquiera pueda entenderlo rápido. No hagas perder tiempo a otros.&lt;/li>
&lt;/ul>
&lt;h3 id="capitulo-2-nombres-significativos">Capítulo 2: Nombres significativos
&lt;a class="heading-anchor" href="#capitulo-2-nombres-significativos" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;ul>
&lt;li>Los nombres de las clases, variables y métodos deben ser significativos e indicar claramente lo que hace un método o lo que es un atributo.&lt;/li>
&lt;li>Crea nombres pronunciables para facilitar la comunicación.&lt;/li>
&lt;li>Evita acrónimos y nombres confusos, que pueden llevar a conclusiones erróneas a cualquiera que lea el código.&lt;/li>
&lt;li>Usa nombres que reflejen el dominio del sistema, el contexto y los problemas que deben resolverse.&lt;/li>
&lt;/ul>
&lt;h3 id="capitulo-3-funciones">Capítulo 3: Funciones
&lt;a class="heading-anchor" href="#capitulo-3-funciones" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;ul>
&lt;li>Los métodos deben ser fáciles de leer y entender.&lt;/li>
&lt;li>Deben transmitir su intención.&lt;/li>
&lt;li>Deben ser pequeños: hasta 20 líneas.&lt;/li>
&lt;li>Deben hacer solo una cosa.&lt;/li>
&lt;li>Usa nombres que digan claramente qué hace el método.&lt;/li>
&lt;li>El número ideal de parámetros es cero, luego uno, luego dos.&lt;/li>
&lt;li>Evita tres parámetros; si los usas, justifícalo.&lt;/li>
&lt;li>Un &lt;code>Boolean&lt;/code> como parámetro indica que el método hace más de una cosa.&lt;/li>
&lt;li>Evita la duplicación.&lt;/li>
&lt;/ul>
&lt;h3 id="capitulo-4-comentarios">Capítulo 4: Comentarios
&lt;a class="heading-anchor" href="#capitulo-4-comentarios" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;ul>
&lt;li>Cuando necesitas comentarios suele ser porque el código es malo.&lt;/li>
&lt;li>Si piensas escribir un comentario, mejor refactoriza el código.&lt;/li>
&lt;li>Los comentarios no salvan el código malo.&lt;/li>
&lt;li>El código debe explicarse por sí mismo.&lt;/li>
&lt;li>A veces los comentarios son útiles en ciertos lugares específicos.&lt;/li>
&lt;li>No expliques el código con comentarios. Usa nombres descriptivos de variables y métodos.&lt;/li>
&lt;li>Los comentarios pueden destacar la importancia de ciertos puntos.&lt;/li>
&lt;li>No escribas comentarios redundantes, inútiles o falsos.&lt;/li>
&lt;li>Para saber quién cambió qué y por qué, usa control de versiones.&lt;/li>
&lt;li>No comentes código sin usar. Elimínalo.&lt;/li>
&lt;/ul>
&lt;h3 id="capitulo-5-formato">Capítulo 5: Formato
&lt;a class="heading-anchor" href="#capitulo-5-formato" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;ul>
&lt;li>El formato es una forma de comunicación entre desarrolladores.&lt;/li>
&lt;li>El código desordenado es difícil de leer.&lt;/li>
&lt;li>La legibilidad afecta a todos los cambios futuros.&lt;/li>
&lt;li>Las clases pequeñas son más fáciles de entender.&lt;/li>
&lt;li>Pon un límite de caracteres por línea (por ejemplo, 120).&lt;/li>
&lt;li>Mantén los conceptos relacionados cerca verticalmente para crear un flujo natural.&lt;/li>
&lt;li>Usa espacios entre operadores, parámetros y comas.&lt;/li>
&lt;/ul>
&lt;h3 id="capitulo-6-objetos-y-estructuras-de-datos">Capítulo 6: Objetos y estructuras de datos
&lt;a class="heading-anchor" href="#capitulo-6-objetos-y-estructuras-de-datos" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;ul>
&lt;li>Sigue la &lt;a rel="external" href="https://en.wikipedia.org/wiki/Law_of_Demeter">Ley de Demeter&lt;/a>:
&lt;ul>
&lt;li>Cada unidad debe tener solo conocimiento limitado sobre otras unidades: solo unidades “estrechamente” relacionadas con la unidad actual.&lt;/li>
&lt;li>Cada unidad solo debe hablar con sus amigos; no hables con extraños.&lt;/li>
&lt;li>Solo habla con tus amigos inmediatos.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>No hagas objetos tontos.&lt;/li>
&lt;li>Los objetos ocultan la abstracción de datos y exponen métodos que operan los datos.&lt;/li>
&lt;li>Las estructuras de datos exponen sus datos y no tienen métodos significativos.&lt;/li>
&lt;/ul>
&lt;h3 id="capitulo-7-manejo-de-errores">Capítulo 7: Manejo de errores
&lt;a class="heading-anchor" href="#capitulo-7-manejo-de-errores" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;ul>
&lt;li>Planifica el manejo de errores con cuidado.&lt;/li>
&lt;li>Cuando algo falla, hay que hacer que el sistema responda correctamente.&lt;/li>
&lt;li>Lanza excepciones en lugar de ocultarlas.&lt;/li>
&lt;li>Crea mensajes de error informativos: qué falló, dónde y, si es posible, por qué.&lt;/li>
&lt;li>Separa las reglas de negocio del manejo de errores.&lt;/li>
&lt;li>Evita devolver &lt;code>NULL&lt;/code>; devuelve un objeto vacío.&lt;/li>
&lt;li>Evita pasar &lt;code>NULL&lt;/code> a los métodos; puede causar &lt;code>NullPointerExceptions&lt;/code>.&lt;/li>
&lt;/ul>
&lt;h3 id="capitulo-8-limites">Capítulo 8: Límites
&lt;a class="heading-anchor" href="#capitulo-8-limites" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;ul>
&lt;li>Al usar código de terceros, encapsula las APIs para no exponer objetos externos.&lt;/li>
&lt;li>Haz tests de las APIs de terceros.&lt;/li>
&lt;li>Estudia la documentación y prueba la API antes de usarla.&lt;/li>
&lt;li>Conoce bien las características que vas a usar.&lt;/li>
&lt;/ul>
&lt;h3 id="capitulo-9-tests-unitarios">Capítulo 9: Tests unitarios
&lt;a class="heading-anchor" href="#capitulo-9-tests-unitarios" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;ul>
&lt;li>Asegúrate de que cada pieza de código hace lo que esperas.&lt;/li>
&lt;li>Sigue las &lt;a rel="external" href="https://en.wikipedia.org/wiki/Test-driven_development">leyes de TDD&lt;/a>:
&lt;ul>
&lt;li>No escribas código sin tener primero un test que falle.&lt;/li>
&lt;li>No escribas más tests de los necesarios para fallar.&lt;/li>
&lt;li>No escribas más código del necesario para pasar el test.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>Mantén tus tests limpios.&lt;/li>
&lt;li>Los tests evolucionan junto con el código.&lt;/li>
&lt;li>Código sucio = tests difíciles de mantener.&lt;/li>
&lt;li>Usa la regla F.I.R.S.T:
&lt;ul>
&lt;li>&lt;strong>F&lt;/strong>ast: ejecución rápida.&lt;/li>
&lt;li>&lt;strong>I&lt;/strong>ndependent: independientes entre sí.&lt;/li>
&lt;li>&lt;strong>R&lt;/strong>epeatable: repetibles en cualquier entorno.&lt;/li>
&lt;li>&lt;strong>S&lt;/strong>elf-validating: auto-validantes.&lt;/li>
&lt;li>&lt;strong>T&lt;/strong>imely: escritos a tiempo.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>Los tests son tan importantes como el código de producción.&lt;/li>
&lt;/ul>
&lt;h3 id="capitulo-10-clases">Capítulo 10: Clases
&lt;a class="heading-anchor" href="#capitulo-10-clases" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;ul>
&lt;li>Organiza las clases así:
&lt;ul>
&lt;li>Constantes públicas estáticas.&lt;/li>
&lt;li>Variables privadas estáticas.&lt;/li>
&lt;li>Variables de instancia privadas.&lt;/li>
&lt;li>Luego los métodos.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>El nombre de la clase debe reflejar su responsabilidad.&lt;/li>
&lt;li>Cada clase debe tener &lt;a rel="external" href="https://en.wikipedia.org/wiki/Single-responsibility_principle">una sola responsabilidad&lt;/a>: una razón para cambiar.&lt;/li>
&lt;li>Intenta describir la clase en una frase breve.&lt;/li>
&lt;li>Los métodos deben ser pequeños y con una sola responsabilidad.&lt;/li>
&lt;/ul>
&lt;hr />
&lt;p>Esta entrevista se basa en el libro de Uncle Bob “Código Limpio”. Repasan algunas guías que te ayudarán a ser mejor programador y exploran cómo los libros y tendencias actuales están moldeando el mundo del software.&lt;/p>
&lt;div style="position:relative;aspect-ratio:16/9;width:100%;">
&lt;iframe
src="https://www.youtube-nocookie.com/embed/QnmRpHFoYLk"
title="YouTube video"
width="560"
height="315"
loading="lazy"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
referrerpolicy="strict-origin-when-cross-origin"
style="position:absolute;inset:0;width:100%;height:100%;border:0;"
allowfullscreen>
&lt;/iframe>
&lt;/div></content></entry></feed>