<?xml version="1.0" encoding="UTF-8"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="es"><title>Chemaclass - clean-code</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/clean-code/atom.xml"/><link rel="alternate" type="text/html" href="https://chemaclass.com"/><generator uri="https://www.getzola.org/">Zola</generator><updated>2024-04-02T00:00:00+00:00</updated><id>https://chemaclass.com/es/tags/clean-code/atom.xml</id><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>Pair Programming Efectivo</title><subtitle>Abrazando prácticas de calidad en tu cultura de ingeniería</subtitle><category term="pair-programming" scheme="https://chemaclass.com/tags/pair-programming/" label="Pair Programming"/><category term="xp" scheme="https://chemaclass.com/tags/xp/" label="Xp"/><category term="tdd" scheme="https://chemaclass.com/tags/tdd/" label="Tdd"/><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>2024-03-28T00:00:00+00:00</published><updated>2024-03-28T00:00:00+00:00</updated><author><name>
Chemaclass</name></author><link rel="alternate" type="text/html" href="https://chemaclass.com/es/blog/effective-pair-programming/"/><id>https://chemaclass.com/es/blog/effective-pair-programming/</id><summary type="html">Guía práctica de pair programming que funciona: roles, rotación, cuándo hacerlo, errores comunes y cómo hacer sesiones productivas.</summary><content type="html">&lt;p>¿Qué es el pair programming? Dos personas trabajando juntas en el mismo problema, al mismo tiempo.&lt;/p>
&lt;span id="continue-reading">&lt;/span>
&lt;p>No se trata de que una persona muestre sus habilidades frente a otra, ni de que una persona tenga miedo de cometer errores debido al síndrome del impostor.&lt;/p>
&lt;p>Cada persona tendrá un rol:&lt;/p>
&lt;ul>
&lt;li>Navegador: prestará atención al panorama general; ej: arquitectura, relación entre colaboradores, diseño de objetos, etc.&lt;/li>
&lt;li>Conductor: prestará atención a los pequeños detalles; ej: naming, convenciones de código, sintaxis de escritura, diseño de objetos, etc.&lt;/li>
&lt;/ul>
&lt;blockquote>
&lt;p>La pareja podría, y debería, intercambiar roles ocasionalmente; ej: cada X commits pusheados, cada 10 min,… depende de ellos.&lt;/p>
&lt;/blockquote>
&lt;p>El pair programming no debería considerarse una práctica solo para “seniors” hacia juniors, sino independientemente del nivel de experiencia de los miembros del equipo.&lt;/p>
&lt;p>Se trata del &lt;strong>flujo de colaboración&lt;/strong>, la comunicación de calidad, la ausencia de sentirse juzgado y la idea de dar la bienvenida a la vulnerabilidad con tus compañeros, sabiendo que te apoyarán y ayudarán.&lt;/p>
&lt;p>Se trata de desafiarse constantemente mutuamente, buscando la solución más pragmática mientras se mantiene simple. Siempre buscando &lt;strong>retroalimentación rápida&lt;/strong> al hablar entre ustedes, pero también sobre la solución que acordaron implementar y su dirección.&lt;/p>
&lt;p>Se trata del bucle de retroalimentación corto, rápido e inmediato mientras hablas con tu compañero, quien &lt;strong>revisa tu código sobre la marcha&lt;/strong>. Puedes guiar como navegador o ayudar al conductor a validar sus ideas en un panorama más amplio.&lt;/p>
&lt;p>Se trata de la atmósfera constante de &lt;strong>compartir conocimiento&lt;/strong> por defecto, reduciendo bus-factors y áreas de conocimiento aislado al máximo. Aumentando el enfoque al tener dos mentes trabajando en la misma tarea simultáneamente.&lt;/p>
&lt;p>Se trata de &lt;strong>cohesión de equipo&lt;/strong> y afilar el sentimiento de que pertenecemos. Cuando entendemos las fortalezas y debilidades de cada uno, nos daremos cuenta de cuánto podemos ayudarnos a crecer mutuamente.&lt;/p>
&lt;p>&lt;img src="/images/blog/2024-03-28/footer.webp" alt="blog-img" />&lt;/p>
&lt;h2 id="como-puedes-practicar-pair-programming">¿Cómo puedes practicar pair programming?
&lt;a class="heading-anchor" href="#como-puedes-practicar-pair-programming" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h2>
&lt;p>El pair programming puede hacerse de diferentes maneras:&lt;/p>
&lt;ul>
&lt;li>Puedes empezar y terminar una tarea con pairing. Puedes limitarlo a 30, 60, 90 minutos. De cualquier manera, se recomienda tener pausas en el medio - Pomodoro.&lt;/li>
&lt;li>Puedes empezar la tarea juntos y parar cuando uno de tus compañeros se sienta lo suficientemente confiado para continuar solo.&lt;/li>
&lt;/ul>
&lt;blockquote>
&lt;p>Depende del equipo, y de la tarea en contexto, decidir cuándo y cómo aplicar pairing para sacar lo mejor de ello.&lt;/p>
&lt;/blockquote>
&lt;p>Esto no significa que debas trabajar constantemente “sin importar qué” en pareja. No se trata de crear reglas; por el contrario, se trata de abrazar esta práctica hasta el punto de que te sientas confiado para elegir cuándo y cómo usarla para sacar lo mejor de ella.&lt;/p>
&lt;p>El pair programming podría convertirse en una de las mejores herramientas en la caja de herramientas de tu equipo para las interacciones diarias. No porque lo hayas leído en algún lugar, sino por los beneficios que tú y tu equipo encontrarán.&lt;/p>
&lt;h3 id="patrones-comunes">Patrones Comunes
&lt;a class="heading-anchor" href="#patrones-comunes" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;h4 id="diferentes-estrategias-para-pairing-efectivo">Diferentes estrategias para pairing efectivo
&lt;a class="heading-anchor" href="#diferentes-estrategias-para-pairing-efectivo" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h4>
&lt;ul>
&lt;li>&lt;strong>Driver-Navigator&lt;/strong>: Una persona está conduciendo el código (con el teclado), enfocándose en el aspecto de detalle de la tarea en sí. La otra es navegadora (sin teclado), teniendo una imagen más abstracta de la tarea en mente.&lt;/li>
&lt;li>&lt;strong>Ping-Pong&lt;/strong>: Cambio frecuente de roles driver-navigator en pequeñas interacciones, ej: cada N minutos, cada N commits, etc.&lt;/li>
&lt;li>&lt;strong>Backseat driver&lt;/strong>: El navegador se involucra activamente con el conductor.&lt;/li>
&lt;li>&lt;strong>Tourist guide&lt;/strong>: El navegador aprende pasivamente con el conductor.&lt;/li>
&lt;/ul>
&lt;p>&lt;img src="/images/blog/2024-03-28/good-pair-prog.jpg" alt="patrones de pair programming efectivo" />&lt;/p>
&lt;h4 id="anti-patrones-mientras-haces-pairing">Anti-patrones mientras haces pairing
&lt;a class="heading-anchor" href="#anti-patrones-mientras-haces-pairing" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h4>
&lt;ul>
&lt;li>&lt;strong>The silent partner&lt;/strong>: El navegador no participa, está en silencio.&lt;/li>
&lt;li>&lt;strong>The solo act&lt;/strong>: El conductor ignora todas las aportaciones del navegador.&lt;/li>
&lt;li>&lt;strong>Distracted pair&lt;/strong>: La pareja no se enfoca en el problema a resolver.&lt;/li>
&lt;li>&lt;strong>The Dictator&lt;/strong>: Una persona está diciendo qué hacer, ignorando las aportaciones del otro.&lt;/li>
&lt;li>&lt;strong>Philosophical pair&lt;/strong>: La pareja está haciendo &lt;a href="/es/blog/bikeshedding/">bikeshedding&lt;/a> en temas irrelevantes.&lt;/li>
&lt;li>&lt;strong>The code war&lt;/strong>: La pareja no llega a un acuerdo y comienza una guerra innecesaria, que desperdicia tiempo y esfuerzo.&lt;/li>
&lt;/ul>
&lt;p>&lt;img src="/images/blog/2024-03-28/anti-pair-prog.jpg" alt="anti-patrones de pair programming" />&lt;/p>
&lt;p>&lt;strong>¿Quieres más?&lt;/strong> Mira esto: &lt;a rel="external" href="https://www.figma.com/file/FCmGwRPIO8cLowDRraJhgr/Learning-TDD">Learning Through KATAS&lt;/a>&lt;/p>
&lt;p>&lt;img src="/images/blog/2024-03-28/learning-through-katas.jpg" alt="aprendiendo a través de katas" />&lt;/p>
&lt;h2 id="la-conclusion">La conclusión
&lt;a class="heading-anchor" href="#la-conclusion" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h2>
&lt;p>El pairing no es una regla que imponer, es una herramienta a la que recurrir. Úsalo cuando la tarea es compleja, el
conocimiento está aislado o lo que está en juego es importante. Sáltalo cuando el trabajo es trivial. El objetivo nunca
es “hacer siempre pairing”, es &lt;strong>mejor software y un equipo más fuerte&lt;/strong>. Elige una tarea real esta semana, hazla en
pareja e intercambia roles a menudo. Los beneficios aparecen más rápido de lo que esperas.&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 amigo &lt;a rel="external" href="https://x.com/evrtrabajo">Manu&lt;/a>, quien me ayudó con este post. Incluso compartimos un &lt;a rel="external" href="https://phpconference.com/agile-culture/practical-tdd-workshop/">taller&lt;/a> sobre este tema.&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>¿Equipos de QA Dedicados en Software?</title><subtitle>¿Cómo encaja una persona QA dedicada en tu equipo agile?</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="agile" scheme="https://chemaclass.com/tags/agile/" label="Agile"/><category term="clean-code" scheme="https://chemaclass.com/tags/clean-code/" label="Clean Code"/><published>2023-05-17T00:00:00+00:00</published><updated>2023-05-17T00:00:00+00:00</updated><author><name>
Chemaclass</name></author><link rel="alternate" type="text/html" href="https://chemaclass.com/es/blog/dedicated-qa-teams/"/><id>https://chemaclass.com/es/blog/dedicated-qa-teams/</id><summary type="html">Esto será controvertido, pero hablemos de la posición de QA. La verdad oculta detrás de la falta de calidad del software y por qué esto debería preocuparte si escribes software.</summary><content type="html">&lt;p>Esto será controvertido, pero hablemos de la posición de QA. La verdad oculta detrás de la falta de calidad del software y por qué esto debería preocuparte si escribes software.&lt;/p>
&lt;span id="continue-reading">&lt;/span>&lt;h2 id="qa-es-un-rol-no-una-posicion">QA es un rol, no una posición
&lt;a class="heading-anchor" href="#qa-es-un-rol-no-una-posicion" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h2>
&lt;p>Como desarrollador de software, cuando escribes software, eres responsable de la calidad de lo que sea que estés escribiendo. Una tercera persona actuando como QA podría encontrar que tu solución no funciona como se esperaba, pero ¿cómo es posible? Podrías argumentar que podrían encontrar casos límite, pero ¿cómo podría ser posible si el software ya fue testeado previamente?&lt;/p>
&lt;p>El objetivo final de un equipo de software es hacer la posición de QA inútil porque no deberían encontrar nada más que software bien funcionando. Pero ¿cómo llegas a ese punto? ¿Cómo podemos asegurar que el software que escribimos funciona como se espera y no hay necesidad de una persona QA en nuestro equipo?&lt;/p>
&lt;h2 id="la-verdad-oculta-detras-de-la-falta-de-calidad-del-software">La verdad oculta detrás de la falta de calidad del software
&lt;a class="heading-anchor" href="#la-verdad-oculta-detras-de-la-falta-de-calidad-del-software" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h2>
&lt;p>Desafortunadamente, en nuestra industria del software, la demanda de proyectos “rápidos, rápidos y sucios” terminó en MVPs pobremente desarrollados simplemente aplicando parches y código sobre código con solo testing manual comprobando caminos felices, a veces incluso ignorando casos límite.&lt;/p>
&lt;blockquote>
&lt;p>“La fecha límite es en una semana, ¡así que mejor termínalo a tiempo!”&lt;/p>
&lt;/blockquote>
&lt;p>No aprendemos la importancia de lo que el testing automatizado puede aportar a nuestro trabajo diario, así que no lo tomamos en serio, y por lo tanto, no lo practicamos lo suficiente. Y, por esa misma razón, porque no lo practicamos, no sabemos cómo realizarlo correctamente. ¡Sí, estoy hablando de escribir tests automatizados que prueban el comportamiento de tu software!&lt;/p>
&lt;p>Nuestra incapacidad para escribir código testeable resulta en software que es difícil de testear, y por lo tanto delegamos el testing a terceros trasladando la responsabilidad de la calidad final general del producto o servicio que escribimos.&lt;/p>
&lt;h2 id="la-practica-hace-al-maestro">La práctica hace al maestro
&lt;a class="heading-anchor" href="#la-practica-hace-al-maestro" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h2>
&lt;p>Debes aprender y aplicar técnicas de testing apropiadas cuando tengan sentido. ¿Cómo y cuándo usar efectivamente dobles de test, preparar tests solitarios o sociables, qué compromisos y razones respaldan tu mente al elegir uno u otro camino hacia tus estrategias de testing?&lt;/p>
&lt;p>Eres la última y principal persona responsable de tu conocimiento, así que mejor invierte en ti mismo porque nadie más lo hará por ti.&lt;/p>
&lt;p>Mira todo lo que haces como una oportunidad de aprendizaje. Practica y mejora por defecto en todo lo que haces.&lt;/p>
&lt;p>Si no sabes cómo empezar, aquí está mi consejo favorito: siempre puedes practicar y mejorar tus habilidades de testing usando katas de código. Lee más sobre este tema &lt;a href="/es/blog/test-driven-development/">aquí&lt;/a>.&lt;/p>
&lt;h2 id="buena-teoria-pero-para-que-molestarse">Buena teoría, pero… ¿para qué molestarse?
&lt;a class="heading-anchor" href="#buena-teoria-pero-para-que-molestarse" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h2>
&lt;p>El testing manual es, por supuesto, necesario. Es otra estrategia de testing que no estoy culpando o atacando. Aún podríamos necesitar una persona dedicada a cargo de descubrir qué nuevas funcionalidades queremos construir para satisfacer a nuestros clientes. Pero este post no es sobre esa posición.&lt;/p>
&lt;p>Se trata de acortar el bucle de retroalimentación. Si puedes escribir software para que funcione de maneras específicas, ¿no puedes escribir tests automatizados para probar que el software que escribiste se comporta de la manera que esperas?&lt;/p>
&lt;p>Si has cubierto con tests automatizados el comportamiento de tu software a cualquier nivel que tenga sentido, ¿qué queda para una persona QA dedicada?&lt;/p>
&lt;p>La próxima vez que pienses “Necesitamos una persona QA para testear esto”, intenta el ejercicio de pensar en cambio, “¿Cómo puedo escribir un test automatizado que verifique lo que esperaría si una persona QA estuviera comprobando esto?”&lt;/p>
&lt;p>Y así es como cambias la “posición de QA a tiempo completo” en una “mentalidad de rol para todos los que escriben software.”&lt;/p>
&lt;p>El código nunca miente y nunca olvida; una vez que está escrito y automatizado en tu pipeline, puedes ejecutarlo en cualquier momento sin coste.&lt;/p>
&lt;p>&lt;img src="/images/blog/2023-05-17/footer.webp" alt="blog-footer" />&lt;/p></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>Diferentes Creencias sobre la Calidad del Software</title><subtitle>Algunas reflexiones sobre la calidad del software en tu equipo</subtitle><category term="clean-code" scheme="https://chemaclass.com/tags/clean-code/" label="Clean Code"/><category term="agile" scheme="https://chemaclass.com/tags/agile/" label="Agile"/><category term="xp" scheme="https://chemaclass.com/tags/xp/" label="Xp"/><category term="communication" scheme="https://chemaclass.com/tags/communication/" label="Communication"/><category term="career" scheme="https://chemaclass.com/tags/career/" label="Career"/><published>2022-10-08T00:00:00+00:00</published><updated>2022-10-08T00:00:00+00:00</updated><author><name>
Chemaclass</name></author><link rel="alternate" type="text/html" href="https://chemaclass.com/es/blog/different-beliefs-about-software-quality/"/><id>https://chemaclass.com/es/blog/different-beliefs-about-software-quality/</id><summary type="html">¿Qué hacer cuando trabajas en "software malo" y no puedes mejorarlo porque va en contra de las creencias de tus compañeros? ¿Deberías cambiar de empresa?</summary><content type="html">&lt;p>Hace poco recibí una pregunta en Twitter que me hizo pensar bastante. Decidí compartir mis reflexiones al respecto.&lt;/p>
&lt;span id="continue-reading">&lt;/span>
&lt;hr />
&lt;h2 id="el-tweet-que-empezo-esto">El tweet que empezó esto
&lt;a class="heading-anchor" href="#el-tweet-que-empezo-esto" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h2>
&lt;p>Primero, algo de contexto: me siento muy bien porque el código base donde trabajo mejora cada vez más, así que tuiteé esto:&lt;/p>
&lt;blockquote>
&lt;p>“A medida que el software mejora con el tiempo, puedes sentir que lo estás haciendo bien.”&lt;/p>
&lt;/blockquote>
&lt;p>Y entonces recibí una pregunta pidiendo sugerencias:&lt;/p>
&lt;p>&lt;img src="/images/blog/2022-10-08/tweet.jpg" alt="blog-tweet" />&lt;/p>
&lt;p>Así que aquí vamos…&lt;/p>
&lt;hr />
&lt;h2 id="mi-respuesta">Mi respuesta
&lt;a class="heading-anchor" href="#mi-respuesta" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h2>
&lt;h3 id="crear-acuerdos">Crear acuerdos
&lt;a class="heading-anchor" href="#crear-acuerdos" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;p>Lo primero es crear acuerdos sobre qué significa software de calidad para tu equipo y para ti. Esto aclara qué cultura de software quieres construir. Dejar tu empresa debería ser el &lt;em>último recurso&lt;/em>.&lt;/p>
&lt;p>Antes de pensar en irte, pregúntate:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>¿Por qué crees&lt;/strong> que no puedes mejorar el código base de tu empresa?&lt;/li>
&lt;li>&lt;strong>¿Qué puedes hacer&lt;/strong> para reducir la fricción entre tus diferentes creencias sobre calidad?&lt;/li>
&lt;/ul>
&lt;p>No existe un código base perfecto. El software es una entidad viva que cambia constantemente. Para mí, software de calidad es el que puede adaptarse al cambio con facilidad.&lt;/p>
&lt;p>Una vez que acordéis ese objetivo, hay muchas formas de lograrlo. Mi favorita es mantener una &lt;strong>mentalidad agile&lt;/strong> con dosis de &lt;strong>valores, principios y prácticas de Extreme Programming&lt;/strong>.&lt;/p>
&lt;h3 id="el-software-es-sobre-personas">El software es sobre personas
&lt;a class="heading-anchor" href="#el-software-es-sobre-personas" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;p>El software no es solo escribir &lt;em>código limpio y sólido&lt;/em>. Eso es deseable, claro, pero primero hay que entender por qué lo queremos. El “&lt;em>por qué&lt;/em>” se basa en los &lt;strong>valores&lt;/strong> del equipo.&lt;/p>
&lt;p>Si no compartís el mismo propósito, el mismo “por qué”, no &lt;em>disfrutaréis&lt;/em> trabajando juntos. En ese caso, buscar otra empresa que comparta tus valores es una opción. Pero antes, intenta arreglar el problema de raíz y ayuda a tu equipo a mejorar.&lt;/p>
&lt;h3 id="entendiendo-tu-por-que">Entendiendo tu por qué
&lt;a class="heading-anchor" href="#entendiendo-tu-por-que" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;p>Primero necesitas entender tu “&lt;em>por qué&lt;/em>” a fondo para transmitirlo a tus compañeros. ¿Has hecho todo lo posible para comunicar tu “&lt;em>por qué&lt;/em>”?&lt;/p>
&lt;p>Algunas ideas: fomentar la programación colaborativa (pair/mob), dar charlas técnicas internas, crear una cultura de compartir conocimiento a diario, cuestionar el statu quo y buscar oportunidades de mejora en todas partes.&lt;/p>
&lt;h3 id="tu-trayectoria-profesional">Tu trayectoria profesional
&lt;a class="heading-anchor" href="#tu-trayectoria-profesional" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;p>Si después de varios meses intentando estas ideas de verdad ninguna funciona, busca una empresa que comparta tus creencias. Al fin y al cabo, tú eres el principal responsable de tu carrera profesional.&lt;/p>
&lt;blockquote>
&lt;p>&lt;a rel="external" href="https://x.com/Chemaclass/status/1578425454562021376">Hilo de twitter&lt;/a> original.&lt;/p>
&lt;/blockquote>
&lt;hr />
&lt;p>&lt;img src="/images/blog/2022-10-08/footer.webp" alt="blog-footer" />&lt;/p>
&lt;h2 id="pensamientos-adicionales">Pensamientos adicionales
&lt;a class="heading-anchor" href="#pensamientos-adicionales" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h2>
&lt;p>Si &lt;strong>quieres que algo sea diferente&lt;/strong>, no esperes a que cambie solo. Intenta &lt;strong>cambiarlo&lt;/strong>; si no funciona, déjalo. Quizás no es tu sitio.&lt;/p>
&lt;p>Eso sí, reflexiona si ves este patrón repetirse a menudo (cambiar de empresa demasiado rápido). Si es así, quizás el problema no son las empresas sino tú.&lt;/p>
&lt;p>El desarrollo de software no es solo código, es &lt;strong>negocio&lt;/strong>. Hay que encontrar un equilibrio justo entre velocidad, costes y calidad según la situación. A veces conviene asumir algo de &lt;em>deuda técnica&lt;/em> para llegar antes al mercado.&lt;/p>
&lt;p>Ningún equipo debería tener “baja calidad” como parte de su identidad. Cada equipo tiene expectativas de calidad. La &lt;strong>clave&lt;/strong> está en &lt;strong>acordar qué es buena calidad&lt;/strong>.&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 anterior Engineering Manager, Evgenii Sokolov, quien me inspiró a escribir estas líneas adicionales después de compartir el post original.&lt;/p>
&lt;/div>
&lt;/aside></content></entry><entry xml:lang="es"><title>Artesanía Limpia</title><subtitle>Disciplinas, Estándares y Ética</subtitle><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"/><category term="refactoring" scheme="https://chemaclass.com/tags/refactoring/" label="Refactoring"/><category term="testing" scheme="https://chemaclass.com/tags/testing/" label="Testing"/><category term="xp" scheme="https://chemaclass.com/tags/xp/" label="Xp"/><published>2022-07-11T00:00:00+00:00</published><updated>2022-07-11T00: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-craftsmanship/"/><id>https://chemaclass.com/es/readings/clean-craftsmanship/</id><summary type="html">Disciplinas, estándares y ética del desarrollo de software profesional.</summary><content type="html">&lt;span id="continue-reading">&lt;/span>
&lt;p>El libro tiene tres partes: disciplinas, estándares y ética.&lt;/p>
&lt;p>La primera es la más técnica. Te guía con ejemplos de TDD y muestra cómo el testing te ayuda a diseñar tu código.&lt;/p>
&lt;p>La segunda trata sobre productividad, calidad y coraje.&lt;/p>
&lt;p>La tercera explica cómo hemos llegado hasta aquí como profesionales del software y nuestra responsabilidad ética: no hacer daño, integridad y trabajo en equipo.&lt;/p>
&lt;hr />
&lt;p>Una de mis partes favoritas del libro:&lt;/p>
&lt;blockquote>
&lt;p>Nuestra industria es dinámica y cambia constantemente. Hay que aprender de forma continua y agresiva.&lt;/p>
&lt;p>¿Cómo y cuándo aprendes? Si tu empresa te da tiempo para ello, aprovéchalo al máximo. Si no, tendrás que hacerlo por tu cuenta.&lt;/p>
&lt;p>Prepárate para dedicar varias horas al mes. Reserva ese tiempo.&lt;/p>
&lt;p>Sí, ya sé: familia, facturas, viajes, la vida. Pero también tienes una profesión. Y las profesiones requieren cuidado y mantenimiento. Aprendamos de forma continua y agresiva.&lt;/p>
&lt;p>&lt;code>Capítulo 11. Coraje - Aprendizaje Agresivo Continuo&lt;/code>&lt;/p>
&lt;/blockquote>
&lt;hr />
&lt;h2 id="indice">Índice
&lt;a class="heading-anchor" href="#indice" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h2>
&lt;h3 id="parte-i-las-disciplinas">Parte I: Las Disciplinas
&lt;a class="heading-anchor" href="#parte-i-las-disciplinas" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;h4 id="capitulo-1-artesania">Capítulo 1. Artesanía
&lt;a class="heading-anchor" href="#capitulo-1-artesania" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h4>
&lt;ul>
&lt;li>Extreme Programming&lt;/li>
&lt;li>Test-Driven Development&lt;/li>
&lt;li>Refactoring&lt;/li>
&lt;li>Diseño Simple&lt;/li>
&lt;li>Programación Colaborativa&lt;/li>
&lt;li>Tests de Aceptación&lt;/li>
&lt;/ul>
&lt;h4 id="capitulo-2-test-driven-development">Capítulo 2. Test-Driven Development
&lt;a class="heading-anchor" href="#capitulo-2-test-driven-development" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h4>
&lt;ul>
&lt;li>Visión General&lt;/li>
&lt;li>Lo Básico&lt;/li>
&lt;/ul>
&lt;h4 id="capitulo-3-tdd-avanzado">Capítulo 3. TDD Avanzado
&lt;a class="heading-anchor" href="#capitulo-3-tdd-avanzado" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h4>
&lt;ul>
&lt;li>Quedarse Atascado&lt;/li>
&lt;li>Arrange, Act, Assert&lt;/li>
&lt;li>Test Doubles&lt;/li>
&lt;li>Arquitectura&lt;/li>
&lt;/ul>
&lt;h4 id="capitulo-4-diseno-de-tests">Capítulo 4. Diseño de Tests
&lt;a class="heading-anchor" href="#capitulo-4-diseno-de-tests" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h4>
&lt;ul>
&lt;li>Testeando Bases de Datos&lt;/li>
&lt;li>Testeando GUIs&lt;/li>
&lt;li>Patrones de Test&lt;/li>
&lt;li>Subclase Específica de Test&lt;/li>
&lt;li>Humble Object&lt;/li>
&lt;li>Diseño de Tests&lt;/li>
&lt;li>Rompiendo la Correspondencia&lt;/li>
&lt;/ul>
&lt;h4 id="capitulo-5-refactoring">Capítulo 5. Refactoring
&lt;a class="heading-anchor" href="#capitulo-5-refactoring" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h4>
&lt;ul>
&lt;li>¿Qué es Refactoring?&lt;/li>
&lt;li>El Kit Básico de Herramientas&lt;/li>
&lt;li>Extract Method&lt;/li>
&lt;li>Las Disciplinas&lt;/li>
&lt;/ul>
&lt;h4 id="capitulo-6-diseno-simple">Capítulo 6. Diseño Simple
&lt;a class="heading-anchor" href="#capitulo-6-diseno-simple" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h4>
&lt;ul>
&lt;li>YAGNI&lt;/li>
&lt;li>Cubierto por Tests&lt;/li>
&lt;li>Cobertura&lt;/li>
&lt;li>¿Diseño?&lt;/li>
&lt;li>Maximizar Expresión&lt;/li>
&lt;li>La Abstracción Subyacente&lt;/li>
&lt;li>Minimizar Duplicación&lt;/li>
&lt;li>Minimizar Tamaño&lt;/li>
&lt;/ul>
&lt;h4 id="capitulo-7-programacion-colaborativa">Capítulo 7. Programación Colaborativa
&lt;a class="heading-anchor" href="#capitulo-7-programacion-colaborativa" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h4>
&lt;h4 id="capitulo-8-tests-de-aceptacion">Capítulo 8. Tests de Aceptación
&lt;a class="heading-anchor" href="#capitulo-8-tests-de-aceptacion" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h4>
&lt;ul>
&lt;li>La Disciplina&lt;/li>
&lt;li>El Build Continuo&lt;/li>
&lt;/ul>
&lt;h3 id="parte-ii-los-estandares">Parte II: Los Estándares
&lt;a class="heading-anchor" href="#parte-ii-los-estandares" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;h4 id="capitulo-9-productividad">Capítulo 9. Productividad
&lt;a class="heading-anchor" href="#capitulo-9-productividad" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h4>
&lt;ul>
&lt;li>Nunca Enviaremos M***da&lt;/li>
&lt;li>Adaptabilidad Económica&lt;/li>
&lt;li>Siempre Estaremos Listos&lt;/li>
&lt;li>Productividad Estable&lt;/li>
&lt;/ul>
&lt;h4 id="capitulo-10-calidad">Capítulo 10. Calidad
&lt;a class="heading-anchor" href="#capitulo-10-calidad" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h4>
&lt;ul>
&lt;li>Mejora Continua&lt;/li>
&lt;li>Competencia Sin Miedo&lt;/li>
&lt;li>Calidad Extrema&lt;/li>
&lt;li>No Volcaremos en QA&lt;/li>
&lt;li>QA No Encontrará Nada&lt;/li>
&lt;li>Automatización de Tests&lt;/li>
&lt;li>Testing Automatizado e Interfaces de Usuario&lt;/li>
&lt;li>Testeando la Interfaz de Usuario&lt;/li>
&lt;/ul>
&lt;h4 id="capitulo-11-coraje">Capítulo 11. Coraje
&lt;a class="heading-anchor" href="#capitulo-11-coraje" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h4>
&lt;ul>
&lt;li>Nos Cubrimos Mutuamente&lt;/li>
&lt;li>Estimaciones Honestas&lt;/li>
&lt;li>Debes Decir NO&lt;/li>
&lt;li>Aprendizaje Agresivo Continuo&lt;/li>
&lt;li>Mentoría&lt;/li>
&lt;/ul>
&lt;h3 id="parte-iii-la-etica">Parte III: La Ética
&lt;a class="heading-anchor" href="#parte-iii-la-etica" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;ul>
&lt;li>El Primer Programador&lt;/li>
&lt;li>Setenta y Cinco Años&lt;/li>
&lt;li>Nerds y Salvadores&lt;/li>
&lt;li>Modelos a Seguir y Villanos&lt;/li>
&lt;li>Gobernamos el Mundo&lt;/li>
&lt;li>Catástrofes&lt;/li>
&lt;li>El Juramento&lt;/li>
&lt;/ul>
&lt;h4 id="capitulo-12-dano">Capítulo 12. Daño
&lt;a class="heading-anchor" href="#capitulo-12-dano" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h4>
&lt;ul>
&lt;li>Primero, No Hacer Daño&lt;/li>
&lt;li>Mejor Trabajo&lt;/li>
&lt;li>Prueba Repetible&lt;/li>
&lt;/ul>
&lt;h4 id="capitulo-13-integridad">Capítulo 13. Integridad
&lt;a class="heading-anchor" href="#capitulo-13-integridad" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h4>
&lt;ul>
&lt;li>Ciclos Pequeños&lt;/li>
&lt;li>Mejora Implacable&lt;/li>
&lt;li>Mantener Alta Productividad&lt;/li>
&lt;/ul>
&lt;h4 id="capitulo-14-trabajo-en-equipo">Capítulo 14. Trabajo en Equipo
&lt;a class="heading-anchor" href="#capitulo-14-trabajo-en-equipo" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h4>
&lt;ul>
&lt;li>Trabajar como Equipo&lt;/li>
&lt;li>Estimar Honesta y Justamente&lt;/li>
&lt;li>Respeto&lt;/li>
&lt;li>Nunca Dejes de Aprender&lt;/li>
&lt;/ul>
&lt;hr />
&lt;p>Charla de Uncle Bob donde cubre la mayoría de los temas del libro.&lt;/p>
&lt;div style="position:relative;aspect-ratio:16/9;width:100%;">
&lt;iframe
src="https://www.youtube-nocookie.com/embed/sPXk11hrWTM"
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;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>Escucha sobre:&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span>* Cita e Intro - [00:00:00]&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span>* Trayectoria Profesional - [00:07:29]&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span>* Clean Craftsmanship - [00:10:53]&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span>* Programador como Profesión - [00:15:31]&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span>* Artesanía - [00:18:45]&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span>* Disciplinas - [00:22:45]&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span>* Disciplinas: Test-Driven Development - [00:28:49]&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span>* Disciplinas: Refactoring - [00:34:31]&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span>* Cobertura de Código - [00:39:02]&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span>* Estándar: Nunca Enviar M***da - [00:42:35]&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span>* Estándar: Siempre Estar Listo - [00:47:15]&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span>* Ética: No Hacer Daño - [00:50:00]&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span>* Ética: Estimar Honestamente - [00:53:56]&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span>* 2 Sabiduría de Tech Lead - [00:57:50]&lt;/span>&lt;/span>&lt;/code>&lt;/pre></content></entry><entry xml:lang="es"><title>El Camino a la Seniority en Software</title><subtitle>¿Cómo convertirse en un Desarrollador Senior?</subtitle><category term="career" scheme="https://chemaclass.com/tags/career/" label="Career"/><category term="mentoring" scheme="https://chemaclass.com/tags/mentoring/" label="Mentoring"/><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"/><category term="communication" scheme="https://chemaclass.com/tags/communication/" label="Communication"/><published>2022-06-08T00:00:00+00:00</published><updated>2022-06-08T00:00:00+00:00</updated><author><name>
Chemaclass</name></author><link rel="alternate" type="text/html" href="https://chemaclass.com/es/blog/the-path-to-seniority-in-software/"/><id>https://chemaclass.com/es/blog/the-path-to-seniority-in-software/</id><summary type="html">La verdadera seniority va más allá de los títulos. Se trata de impacto, mentoría, asumir resultados y elevar el nivel de todo tu equipo.</summary><content type="html">&lt;p>Todos hemos sido desarrolladores junior en algún momento. Esto es fácil de saber porque es al principio de tu carrera. Tus responsabilidades fueron delimitadas por otros compañeros que cuidaban de ti.&lt;/p>
&lt;span id="continue-reading">&lt;/span>
&lt;p>En algún momento, después de meses o años, conseguiste tu promoción u otro trabajo, donde ya no eras junior, sino intermedio.&lt;/p>
&lt;p>Un intermedio (también conocido como middle) es algo entre junior y senior. Ahora sabes que ya no eres junior, sabes cómo entregar valor pero aún tienes sentimientos encontrados sobre la seniority. Quieres ser senior, pero no sabes cómo. No hay un camino claro para alcanzar este objetivo.&lt;/p>
&lt;p>Espera un segundo… ¡en realidad hay dos formas fáciles de conseguir el título de senior! Puedes ser promovido como tal en tu empresa, o puedes empezar una nueva posición como “senior” en otra empresa, ¿fácil no?&lt;/p>
&lt;h2 id="marketing-y-politica">Marketing y política
&lt;a class="heading-anchor" href="#marketing-y-politica" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h2>
&lt;p>Desafortunadamente, el nivel de “seniority” está muy contaminado por marketing y política. Primero, ¿qué significa “senior” en este contexto? En todas las empresas donde he trabajado (si no todas) siempre he estado rodeado de personas que afirmaban ser “seniors” cuando en realidad solo a unos pocos los consideraría como tales.&lt;/p>
&lt;p>La etiqueta de senior está inflada por la necesidad de las empresas de tener expertos en papel más que en la realidad, y es un problema con el que debemos lidiar y del que debemos hablar.&lt;/p>
&lt;p>Seniority generalmente significa más experiencia, pero ¿cómo calculas esto? Es fácil desde el punto de vista de una empresa: más años en la industria. Pero, ¿es realmente relevante el número de años que has estado trabajando en una industria que está en constante cambio y evolución? En realidad, esto no sería un gran problema si tienes los fundamentos del software bien interiorizados, pero curiosamente, he visto estos fundamentos solo en ~10% de los seniors que he conocido a lo largo de muchos años y varias empresas.&lt;/p>
&lt;p>El hecho de que hayas estado trabajando durante 10 o más años no significa necesariamente que seas un “senior” con el software. ¿Qué más podemos medir para identificar si realmente mereces este título?&lt;/p>
&lt;h3 id="no-todo-se-trata-del-dinero">No todo se trata del dinero
&lt;a class="heading-anchor" href="#no-todo-se-trata-del-dinero" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;p>Seamos honestos, los títulos senior están mejor pagados que las posiciones junior o middle. Si tienes la oportunidad de conseguir un salario más alto porque tienes “senior” en tu título de trabajo, bueno, no sería inteligente rechazarlo. Pero, independientemente de la política y el marketing, debemos abordar algunos fundamentos de seniority para entender mejor qué significa la palabra “senior” en este contexto.&lt;/p>
&lt;blockquote>
&lt;p>No todo se trata del dinero, sino también de las responsabilidades que vienen con la seniority.&lt;/p>
&lt;/blockquote>
&lt;h2 id="fundamentos-de-la-seniority">Fundamentos de la seniority
&lt;a class="heading-anchor" href="#fundamentos-de-la-seniority" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h2>
&lt;p>Ser senior en nuestra industria del software no se trata del “número de años de experiencia” sino:&lt;/p>
&lt;ul>
&lt;li>¿Qué tan bien &lt;strong>transmites tu conocimiento&lt;/strong> a otros? Compartir lo que sabes es una tarea esencial para una persona senior.&lt;/li>
&lt;li>¿Qué tan bien &lt;strong>colaboras&lt;/strong> con otras personas, incluyendo al PM/PO y a otros equipos? La colaboración es crucial para crear un bucle de retroalimentación constante.&lt;/li>
&lt;li>¿Qué tan bien &lt;strong>trabajas en conjunto&lt;/strong> con tus compañeros? El pair-programming fomenta la cohesión del equipo y ayuda a que todos mejoren.&lt;/li>
&lt;li>¿Qué tan fuertes son tus habilidades de &lt;strong>testing&lt;/strong>? El testing está ligado a la calidad de tu trabajo, y un senior debería apuntar a un diseño incremental.&lt;/li>
&lt;li>¿Qué tan bien entiendes &lt;strong>entregar valor constantemente&lt;/strong> en pequeñas partes? Cuanto antes entregues valor, antes obtendrás retroalimentación sobre ello.&lt;/li>
&lt;li>¿Qué tan profundo es tu &lt;strong>conocimiento técnico&lt;/strong> sobre software de calidad y los trade-offs para llegar allí? Principios SOLID, código limpio, TDD, refactoring como parte de tu trabajo diario, bajo acoplamiento, alta cohesión, estructuras de datos apropiadas y elegir la solución correcta (KISS, YAGNI…).&lt;/li>
&lt;li>¿Qué tan bien te adaptas y &lt;strong>lidias con el cambio&lt;/strong>? El cambio es inevitable, así que debemos aprender a gestionarlo, especialmente lo que no podemos controlar.&lt;/li>
&lt;li>¿Qué tan desarrollado está tu &lt;strong>pensamiento emprendedor&lt;/strong>? Siempre manteniendo los objetivos de la organización en mente.&lt;/li>
&lt;/ul>
&lt;p>Como puedes ver, no hay mención de tecnología concreta o años de experiencia. ¿Por qué? Porque la tecnología es solo un “detalle de implementación”, y la experiencia viene de practicar y la actitud, no de dejar pasar el tiempo.&lt;/p>
&lt;h3 id="la-actitud-es-importante">La actitud es importante
&lt;a class="heading-anchor" href="#la-actitud-es-importante" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;p>Tenemos dos personas:&lt;/p>
&lt;p>A) una persona que trabaja desde hace 15 años, haciendo relativamente lo mismo cada día, y sin preocuparse por sus propias habilidades. Simplemente hace lo que otros le dicen que haga.&lt;/p>
&lt;p>B) una persona que trabaja desde hace 5 años, desafiándose a sí misma cada semana, probando diferentes enfoques al lidiar con problemas, y afilando sus propias habilidades constantemente.&lt;/p>
&lt;p>¿Puedes ver la diferencia principal? No, no son los 10 años de diferencia de “experiencia” entre ellos, sino su &lt;strong>actitud&lt;/strong>.&lt;/p>
&lt;p>Entendemos erróneamente que &lt;em>un año de experiencia debe venir con aprendizaje y conocimiento&lt;/em>, así que tendemos a usar el tiempo como medida de seniority. Pero argumento que el “factor actitud” es igual o incluso más importante. He estado rodeado de muchas personas que se llaman a sí mismas seniors con 3, 6, 10 y más años de “experiencia” pero sin actitud, y podías ver claramente este problema a diario.&lt;/p>
&lt;blockquote>
&lt;p>Necesitas esta combinación para construirte como un desarrollador verdaderamente senior; tiempo, experiencia, y lo más importante: actitud hacia &lt;strong>mejorar tus propias habilidades y las de quienes te rodean&lt;/strong>.&lt;/p>
&lt;/blockquote>
&lt;h2 id="por-donde-empezar">Por dónde empezar
&lt;a class="heading-anchor" href="#por-donde-empezar" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h2>
&lt;p>La seniority no se concede, se practica. No esperas el título, construyes el comportamiento hasta que el título te alcanza. Empieza pequeño, y empieza ahora:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Enseña lo que sabes.&lt;/strong> Elige una cosa que entiendas y explícasela a alguien esta semana. Si no puedes explicarla, aún no la dominas.&lt;/li>
&lt;li>&lt;strong>Busca lo incómodo.&lt;/strong> Ofrécete para la tarea que te queda algo grande. El crecimiento vive en el borde de lo que ya sabes hacer.&lt;/li>
&lt;li>&lt;strong>Reflexiona con intención.&lt;/strong> Después de cada proyecto, pregúntate qué harías diferente. Experiencia sin reflexión es solo repetición.&lt;/li>
&lt;/ul>
&lt;p>El camino no es una promoción. Es la decisión diaria de mejorarte a ti mismo y a quienes te rodean. Hazlo el tiempo suficiente, y el título se vuelve un trámite.&lt;/p></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>Nunca Uses array_merge en un Bucle</title><subtitle>El operador spread al rescate</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="refactoring" scheme="https://chemaclass.com/tags/refactoring/" label="Refactoring"/><published>2020-11-10T00:00:00+00:00</published><updated>2020-11-10T00:00:00+00:00</updated><author><name>
Chemaclass</name></author><link rel="alternate" type="text/html" href="https://chemaclass.com/es/blog/array-merge-in-loop/"/><id>https://chemaclass.com/es/blog/array-merge-in-loop/</id><summary type="html">Usar array_merge dentro de un bucle mata el rendimiento. El operador spread te ayudará a mejorar esto aplanando el array.</summary><content type="html">&lt;p>Usar array_merge dentro de un bucle mata el rendimiento.
El operador spread te ayudará a mejorar esto aplanando el array.&lt;/p>
&lt;span id="continue-reading">&lt;/span>&lt;h2 id="aplanando-un-array-de-un-nivel">Aplanando un array de un nivel
&lt;a class="heading-anchor" href="#aplanando-un-array-de-un-nivel" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h2>
&lt;p>He visto a gente usar array_merge dentro de un bucle así:&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>$&lt;/span>&lt;span>lists&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> [&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);"> 2&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(#005CC5, #79B8FF);">3&lt;/span>&lt;span>,&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);"> 4&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(#005CC5, #79B8FF);">5&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>&lt;/span>
&lt;span class="giallo-l">&lt;span>]&lt;/span>&lt;span>;&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span>$&lt;/span>&lt;span>merged&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>
&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>lists&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> as&lt;/span>&lt;span> $&lt;/span>&lt;span>list&lt;/span>&lt;span>)&lt;/span>&lt;span> {&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span> $&lt;/span>&lt;span>merged&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> =&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);"> array_merge&lt;/span>&lt;span>(&lt;/span>&lt;span>$&lt;/span>&lt;span>merged&lt;/span>&lt;span>,&lt;/span>&lt;span> $&lt;/span>&lt;span>list&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);"> $merged === [1, 2, 3, 4, 5, 6];&lt;/span>&lt;/span>&lt;/code>&lt;/pre>
&lt;p>Esto es mala práctica porque destroza el rendimiento de memoria.
Mejor usa el operador spread (disponible desde PHP 5.6):&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>$&lt;/span>&lt;span>lists&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> [&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);"> 2&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(#005CC5, #79B8FF);">3&lt;/span>&lt;span>,&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);"> 4&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(#005CC5, #79B8FF);">5&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>&lt;/span>
&lt;span class="giallo-l">&lt;span>]&lt;/span>&lt;span>;&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span>$&lt;/span>&lt;span>merged&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> =&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);"> array_merge&lt;/span>&lt;span>(&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);">...&lt;/span>&lt;span>$&lt;/span>&lt;span>lists&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);"> === [1, 2, 3, 4, 5, 6];&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;h2 id="desempaquetando-un-array-asociativo">Desempaquetando un array asociativo
&lt;a class="heading-anchor" href="#desempaquetando-un-array-asociativo" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h2>
&lt;p>¿Y si tuvieras un array asociativo como este?&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>$&lt;/span>&lt;span>lists&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(#032F62, #9ECBFF);"> &amp;#39;&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">key-1&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">&amp;#39;&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> =&amp;gt;&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);"> 2&lt;/span>&lt;span>]&lt;/span>&lt;span>,&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#032F62, #9ECBFF);"> &amp;#39;&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">key-2&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">&amp;#39;&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> =&amp;gt;&lt;/span>&lt;span> [&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);">3&lt;/span>&lt;span>,&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);"> 4&lt;/span>&lt;span>]&lt;/span>&lt;span>,&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#032F62, #9ECBFF);"> &amp;#39;&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">key-3&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">&amp;#39;&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> =&amp;gt;&lt;/span>&lt;span> [&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);">5&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>&lt;/span>
&lt;span class="giallo-l">&lt;span>]&lt;/span>&lt;span>;&lt;/span>&lt;/span>&lt;/code>&lt;/pre>
&lt;p>En ese caso, necesitarás desempaquetar sus valores:&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>$&lt;/span>&lt;span>merged&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> =&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);"> array_merge&lt;/span>&lt;span>(&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);">...&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);">array_values&lt;/span>&lt;span>(&lt;/span>&lt;span>$&lt;/span>&lt;span>lists&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);"> === [1, 2, 3, 4, 5, 6];&lt;/span>&lt;/span>&lt;/code>&lt;/pre>
&lt;p>En programación funcional, esto se conoce como aplanar una lista.
Sin bucles ni problemas de rendimiento.&lt;/p>
&lt;h2 id="aplanando-un-array-multinivel">Aplanando un array multinivel
&lt;a class="heading-anchor" href="#aplanando-un-array-multinivel" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h2>
&lt;p>¿Y si quisieras aplanar un array multinivel como este?&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>$&lt;/span>&lt;span>lists&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> =&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>&lt;span style="color: light-dark(#005CC5, #79B8FF);"> 2&lt;/span>&lt;span>,&lt;/span>&lt;span> [&lt;/span>&lt;span>[&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);">3&lt;/span>&lt;span>,&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);"> 4&lt;/span>&lt;span>]&lt;/span>&lt;span>,&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);"> 5&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;/span>&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;span style="color: light-dark(#005CC5, #79B8FF);">6&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);"> 7&lt;/span>&lt;span>,&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);"> 8&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>¿O como este, incluso con clave-valores?&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>$&lt;/span>&lt;span>lists&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(#032F62, #9ECBFF);"> &amp;#39;&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">key-1&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">&amp;#39;&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> =&amp;gt;&lt;/span>&lt;span> [&lt;/span>&lt;/span>
&lt;span class="giallo-l">&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>&lt;span style="color: light-dark(#005CC5, #79B8FF);">2&lt;/span>&lt;span>]&lt;/span>&lt;span>,&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#032F62, #9ECBFF);"> &amp;#39;&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">key-2&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">&amp;#39;&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> =&amp;gt;&lt;/span>&lt;span> [&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#005CC5, #79B8FF);"> 3&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(#032F62, #9ECBFF);"> &amp;#39;&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">key-3&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">&amp;#39;&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> =&amp;gt;&lt;/span>&lt;span> [&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);">4&lt;/span>&lt;span>,&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);"> 5&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>
&lt;span class="giallo-l">&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>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#005CC5, #79B8FF);"> 6&lt;/span>&lt;span>,&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#032F62, #9ECBFF);"> &amp;#39;&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">key-4&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">&amp;#39;&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> =&amp;gt;&lt;/span>&lt;span> [&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);">7&lt;/span>&lt;span>,&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);"> 8&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>&lt;/code>&lt;/pre>
&lt;p>Para estos casos, puedes usar la librería estándar de PHP:&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>$&lt;/span>&lt;span>merged&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> =&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);"> iterator_to_array&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);"> RecursiveIteratorIterator&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);"> RecursiveArrayIterator&lt;/span>&lt;span>(&lt;/span>&lt;span>$&lt;/span>&lt;span>lists&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> $&lt;/span>&lt;span>use_keys&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> =&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);"> false&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 style="color: light-dark(#6A737D, #6A737D);">//&lt;/span>&lt;span style="color: light-dark(#6A737D, #6A737D);"> $merged === [1, 2, 3, 4, 5, 6, 7, 8];&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;h2 id="que-enfoque-de-aplanado-usar">Qué enfoque de aplanado usar
&lt;a class="heading-anchor" href="#que-enfoque-de-aplanado-usar" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h2>
&lt;p>Normalmente, saber aplanar un array de dos niveles suele ser suficiente:&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>$&lt;/span>&lt;span>flattenList&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> =&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);"> array_merge&lt;/span>&lt;span>(&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);">...&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);">array_values&lt;/span>&lt;span>(&lt;/span>&lt;span>$&lt;/span>&lt;span>lists&lt;/span>&lt;span>)&lt;/span>&lt;span>)&lt;/span>&lt;span>;&lt;/span>&lt;/span>&lt;/code>&lt;/pre>
&lt;p>Para casos más complejos, la librería estándar de PHP te saca del apuro.&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/spread_operator_for_array">Spread_operator_for_array - Wikipedia&lt;/a>&lt;/li>
&lt;li>&lt;a rel="external" href="https://rosettacode.org/wiki/Flatten_a_list">Flatten_a_list - Rosettacode&lt;/a>&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>Testeando Código Legacy de Forma Efectiva</title><subtitle>Cómo escribir tests adecuados para código ya escrito</subtitle><category term="testing" scheme="https://chemaclass.com/tags/testing/" label="Testing"/><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="tdd" scheme="https://chemaclass.com/tags/tdd/" label="Tdd"/><published>2020-08-17T00:00:00+00:00</published><updated>2020-08-17T00:00:00+00:00</updated><author><name>
Chemaclass</name></author><link rel="alternate" type="text/html" href="https://chemaclass.com/es/blog/testing-effectively-legacy-code/"/><id>https://chemaclass.com/es/blog/testing-effectively-legacy-code/</id><summary type="html">Cómo escribir tests de caracterización para código legacy y refactorizar de forma segura sin romper el comportamiento existente.</summary><content type="html">&lt;p>Estos tests también se conocen como tests de caracterización.&lt;/p>
&lt;span id="continue-reading">&lt;/span>
&lt;blockquote>
&lt;p>Un test de caracterización describe el comportamiento real de una pieza de software existente, y por lo tanto protege el
comportamiento existente del código legacy contra cambios no intencionados mediante testing automatizado. Este término fue acuñado por &lt;a href="/es/readings/working-effectively-with-legacy-code/">Michael Feathers&lt;/a>.&lt;/p>
&lt;/blockquote>
&lt;p>Permiten y proporcionan una red de seguridad para extender y refactorizar código que no tiene tests adecuados. Se puede
escribir un test que afirme que la salida del código legacy coincide con el resultado observado para las entradas dadas.&lt;/p>
&lt;h2 id="como-empezar">¿Cómo empezar?
&lt;a class="heading-anchor" href="#como-empezar" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h2>
&lt;p>Estos son mis aprendizajes un año después de
leer &lt;a href="/es/readings/working-effectively-with-legacy-code/">Working Effectively with Legacy Code&lt;/a> y aplicarlo a los
diferentes proyectos en los que he trabajado desde entonces.&lt;/p>
&lt;h3 id="1-que-quieres-testear">1. ¿Qué quieres testear?
&lt;a class="heading-anchor" href="#1-que-quieres-testear" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;p>Averigua las aserciones. Crea un archivo de test para tu clase, y un método de test para la función que quieres testear.
Pista:&lt;/p>
&lt;ul>
&lt;li>Si tienes el siguiente método &lt;code>applySomeLogic(): ReturnType&lt;/code>,&lt;/li>
&lt;li>el test que podrías escribir es &lt;code>test_apply_some_logic(): void&lt;/code>.&lt;/li>
&lt;/ul>
&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);">final&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> class&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);"> MyBusinessLogic&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);"> private&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);"> DependencyInterface&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);"> dependencyInterface&lt;/span>&lt;span>;&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#D73A49, #F97583);"> private&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);"> ConcreteDependency&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);"> concrete&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);"> 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> DependencyInterface dependencyInterface&lt;/span>&lt;span>,&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span> ConcreteDependency concrete&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 style="color: light-dark(#005CC5, #79B8FF);"> this&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);">.&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);">dependencyInterface&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> =&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);"> dependencyInterface&lt;/span>&lt;span>;&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#005CC5, #79B8FF);"> this&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);">.&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);">concrete&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> =&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);"> concrete&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);"> public&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> function&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);"> applySomeLogic&lt;/span>&lt;span>(&lt;/span>&lt;span>Input input&lt;/span>&lt;span>)&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);">:&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);"> ReturnType&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);"> caja negra responsable de crear un ReturnType&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);"> basado en el Input dado&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);"> returnType&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);">final&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> class&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);"> MyBusinessLogicTest&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> extends&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);"> TestCase&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);"> public&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> function&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);"> test_apply_some_logic&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(#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);"> Quiero afirmar que &amp;quot;aplicando alguna lógica&amp;quot;&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);"> de MyBusinessLogic con el Input dado&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);"> recibiré un ReturnType concreto con un&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);"> cierto valor como su propiedad. Algo como:&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#005CC5, #79B8FF);"> returnType&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> =&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);"> myBusinessLogic&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);">.&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);">applySomeLogic&lt;/span>&lt;span>(&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);">input&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);"> assertEquals&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);">expected&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">&amp;#39;&lt;/span>&lt;span>,&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);"> returnType&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);">.&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);">getProperty&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> }&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span>}&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;h3 id="2-instancia-la-clase-concreta-final-que-quieres-testear">2. Instancia la clase concreta/final que quieres testear.
&lt;a class="heading-anchor" href="#2-instancia-la-clase-concreta-final-que-quieres-testear" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;p>No mockees tus clases concretas. Especialmente tu dominio de negocio. Mockea solo interfaces. De lo contrario, puedes estar ocultando
bugs sin querer (¡con tests verdes/pasando!). Trata tus &lt;a href="/es/blog/final-classes">clases de dominio de negocio como finales&lt;/a>.&lt;/p>
&lt;p>O mockea la interfaz o instancia una clase anónima si quieres crear un Stub:&lt;/p>
&lt;blockquote>
&lt;p>Los Stubs proporcionan respuestas a llamadas hechas durante el test, normalmente sin responder a nada fuera de lo programado para el test.&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="php">&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);"> MyBusinessLogicTest&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> extends&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);"> TestCase&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);"> public&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> function&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);"> test_apply_some_logic&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(#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(#005CC5, #79B8FF);"> myBusinessLogic&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> =&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> new&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);"> MyBusinessLogic&lt;/span>&lt;span>(&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#005CC5, #79B8FF);"> this&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);">.&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);">createMock&lt;/span>&lt;span>(&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);">DependencyInterface&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);">.&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);">class&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);"> ConcreteDependency&lt;/span>&lt;span>(&lt;/span>&lt;span style="color: light-dark(#6A737D, #6A737D);">/*&lt;/span>&lt;span style="color: light-dark(#6A737D, #6A737D);"> ... &lt;/span>&lt;span style="color: light-dark(#6A737D, #6A737D);">*/&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 style="color: light-dark(#6A737D, #6A737D);"> //&lt;/span>&lt;span style="color: light-dark(#6A737D, #6A737D);"> O&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#005CC5, #79B8FF);"> myBusinessLogic&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> =&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> new&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);"> MyBusinessLogic&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);"> FakeDependency&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);"> new&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);"> ConcreteDependency&lt;/span>&lt;span>(&lt;/span>&lt;span style="color: light-dark(#6A737D, #6A737D);">/*&lt;/span>&lt;span style="color: light-dark(#6A737D, #6A737D);"> ... &lt;/span>&lt;span style="color: light-dark(#6A737D, #6A737D);">*/&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 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>&lt;/span>&lt;/code>&lt;/pre>
&lt;blockquote>
&lt;p>Donde &lt;code>FakeDependency&lt;/code> es una implementación concreta de &lt;code>DependencyInterface&lt;/code> con “datos/implementación falsos” ya preparados que solo es útil para propósitos de testing.&lt;/p>
&lt;/blockquote>
&lt;h3 id="3-llama-al-metodo-de-esa-clase-proporcionando-la-entrada-deseada">3. Llama al método de esa clase proporcionando la entrada deseada.
&lt;a class="heading-anchor" href="#3-llama-al-metodo-de-esa-clase-proporcionando-la-entrada-deseada" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;p>La salida será determinada por el estado inicial de la clase de lógica de negocio que queremos testear MÁS los argumentos
de entrada que estamos usando.&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(#005CC5, #79B8FF);">input&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> =&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> new&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);"> Input&lt;/span>&lt;span>(&lt;/span>&lt;span style="color: light-dark(#6A737D, #6A737D);">/*&lt;/span>&lt;span style="color: light-dark(#6A737D, #6A737D);"> ... &lt;/span>&lt;span style="color: light-dark(#6A737D, #6A737D);">*/&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);">returnType&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> =&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);"> myBusinessLogic&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);">.&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);">applySomeLogic&lt;/span>&lt;span>(&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);">input&lt;/span>&lt;span>)&lt;/span>&lt;span>;&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;h3 id="4-afirma-la-salida-con-el-valor-esperado">4. Afirma la salida con el valor esperado.
&lt;a class="heading-anchor" href="#4-afirma-la-salida-con-el-valor-esperado" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;p>Del paso 1 necesitas saber qué quieres. Aplica la(s) aserción(es) ahora.&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);">final&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> class&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);"> MyBusinessLogicTest&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> extends&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);"> TestCase&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);"> public&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> function&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);"> test_apply_some_logic&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(#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(#005CC5, #79B8FF);"> myBusinessLogic&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> =&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> new&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);"> MyBusinessLogic&lt;/span>&lt;span>(&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#005CC5, #79B8FF);"> this&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);">.&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);">createMock&lt;/span>&lt;span>(&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);">DependencyInterface&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);">::&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);">class&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);"> ConcreteDependency&lt;/span>&lt;span>(&lt;/span>&lt;span style="color: light-dark(#6A737D, #6A737D);">/*&lt;/span>&lt;span style="color: light-dark(#6A737D, #6A737D);"> ... &lt;/span>&lt;span style="color: light-dark(#6A737D, #6A737D);">*/&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>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#005CC5, #79B8FF);"> input&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> =&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> new&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);"> Input&lt;/span>&lt;span>(&lt;/span>&lt;span style="color: light-dark(#6A737D, #6A737D);">/*&lt;/span>&lt;span style="color: light-dark(#6A737D, #6A737D);"> ... &lt;/span>&lt;span style="color: light-dark(#6A737D, #6A737D);">*/&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);"> returnType&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> =&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);"> myBusinessLogic&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);">.&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);">applySomeLogic&lt;/span>&lt;span>(&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);">input&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);"> assertEquals&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);">expected&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">&amp;#39;&lt;/span>&lt;span>,&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);"> returnType&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);">.&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);">getProperty&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> }&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span>}&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;h3 id="5-puede-que-quieras-afirmar-diferentes-valores-esperados">5. Puede que quieras afirmar diferentes valores esperados.
&lt;a class="heading-anchor" href="#5-puede-que-quieras-afirmar-diferentes-valores-esperados" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;p>Puedes proporcionar fácilmente diferentes argumentos a tu lógica de negocio ya sea a través de la construcción de la lógica o diferentes
argumentos dados. Para hacerlo, usa la anotación @dataProvider. El método “dataProvider” debe ser público y devolver cualquier iterable.&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);">final&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> class&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);"> MyBusinessLogicTest&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> extends&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);"> TestCase&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);"> @dataProvider providerApplySomeLogic &lt;/span>&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);"> public&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> function&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);"> test_apply_some_logic&lt;/span>&lt;span>(&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span> array concreteMapping&lt;/span>&lt;span>,&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span> string argInput&lt;/span>&lt;span>,&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span> string expectedValue&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(#D73A49, #F97583);"> void&lt;/span>&lt;span> {&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#005CC5, #79B8FF);"> myBusinessLogic&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> =&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> new&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);"> MyBusinessLogic&lt;/span>&lt;span>(&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#005CC5, #79B8FF);"> this&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);">.&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);">createMock&lt;/span>&lt;span>(&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);">DependencyInterface&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);">.&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);">class&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);"> ConcreteDependency&lt;/span>&lt;span>(&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);">concreteMapping&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 style="color: light-dark(#6A737D, #6A737D);">*/&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>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#005CC5, #79B8FF);"> input&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> =&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> new&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);"> Input&lt;/span>&lt;span>(&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);">argInput&lt;/span>&lt;span>,&lt;/span>&lt;span style="color: light-dark(#6A737D, #6A737D);"> /*&lt;/span>&lt;span style="color: light-dark(#6A737D, #6A737D);"> ... &lt;/span>&lt;span style="color: light-dark(#6A737D, #6A737D);">*/&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(#005CC5, #79B8FF);"> actual&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> =&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);"> myBusinessLogic&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);">.&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);">applySomeLogic&lt;/span>&lt;span>(&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);">input&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);"> assertEquals&lt;/span>&lt;span>(&lt;/span>&lt;span>$&lt;/span>&lt;span>expectedValue&lt;/span>&lt;span>,&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);"> actual&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);">.&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);">getProperty&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> }&lt;/span>&lt;/span>
&lt;span class="giallo-l">&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(#6F42C1, #B392F0);"> providerApplySomeLogic&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(#005CC5, #79B8FF);"> Generator&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);"> yield&lt;/span>&lt;span> [&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#032F62, #9ECBFF);"> &amp;#39;&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">concreteMapping&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">&amp;#39;&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> =&amp;gt;&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);">key&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">&amp;#39;&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> =&amp;gt;&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);"> &amp;#39;&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">value&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(#032F62, #9ECBFF);"> &amp;#39;&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">argInput&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">&amp;#39;&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> =&amp;gt;&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);"> &amp;#39;&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">something&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">&amp;#39;&lt;/span>&lt;span>,&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#032F62, #9ECBFF);"> &amp;#39;&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">expectedValue&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">&amp;#39;&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> =&amp;gt;&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);"> &amp;#39;&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">expected-value-A&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">&amp;#39;&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>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#D73A49, #F97583);"> yield&lt;/span>&lt;span> [&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#032F62, #9ECBFF);"> &amp;#39;&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">concreteMapping&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">&amp;#39;&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> =&amp;gt;&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);">key2&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">&amp;#39;&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> =&amp;gt;&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);"> &amp;#39;&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">value2&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(#032F62, #9ECBFF);"> &amp;#39;&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">argInput&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">&amp;#39;&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> =&amp;gt;&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);"> &amp;#39;&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">something-else&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">&amp;#39;&lt;/span>&lt;span>,&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#032F62, #9ECBFF);"> &amp;#39;&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">expectedValue&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">&amp;#39;&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> =&amp;gt;&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);"> &amp;#39;&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">expected-value-B&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">&amp;#39;&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> }&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span>}&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;h3 id="por-ultimo-limpia-lo-que-hiciste">Por último: limpia lo que hiciste.
&lt;a class="heading-anchor" href="#por-ultimo-limpia-lo-que-hiciste" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;p>Sí, limpia los tests. Merecen estar tan limpios como tu código de producción. De lo contrario, se pudrirán con el tiempo y
¡permanecerán sucios para tus compañeros y tu yo futuro!&lt;/p>
&lt;p>Por ejemplo, puedes aplicar el refactoring extract method para mover los detalles de implementación (de la creación de los
diferentes objetos) y mantener el mismo nivel de abstracción mientras lees el código del test.&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(#005CC5, #79B8FF);">myBusinessLogic&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> =&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);"> this&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);">.&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);">createBusinessLogic&lt;/span>&lt;span>(&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);">concreteMapping&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);">input&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> =&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);"> this&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);">.&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);">createInput&lt;/span>&lt;span>(&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);">argInput&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);">actual&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> =&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);"> myBusinessLogic&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);">.&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);">applySomeLogic&lt;/span>&lt;span>(&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);">input&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);">assertEquals&lt;/span>&lt;span>(&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);">expectedValue&lt;/span>&lt;span>,&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);"> actual&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);">.&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);">getProperty&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>Por supuesto, todo depende del contexto. ¿Realmente tiene sentido extraer a un método privado
createBusinessLogic() o incluso createInput()? Bueno, eso depende de ti. Depende del número de líneas y, lo más
importante, del nivel de abstracción que pertenece a ese contexto.&lt;/p>
&lt;blockquote>
&lt;p>Solo recuerda: mantén tus métodos pequeños.&lt;/p>
&lt;/blockquote>
&lt;p>Ahora puedes refactorizar el código de producción que cubriste con tests sin ese miedo a romperlo.&lt;/p>
&lt;hr />
&lt;h3 id="todo-junto">Todo junto
&lt;a class="heading-anchor" href="#todo-junto" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;script src="https://gist.github.com/Chemaclass&amp;#x2F;07704606fcb337dbb0881c94197c329e.js">&lt;/script>
&lt;script src="https://gist.github.com/Chemaclass&amp;#x2F;9f7f96242153b696b3f8da5c7fa80461.js">&lt;/script>
&lt;hr />
&lt;h2 id="el-codigo-legacy-es-codigo-sin-tests">El código legacy es código sin tests
&lt;a class="heading-anchor" href="#el-codigo-legacy-es-codigo-sin-tests" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h2>
&lt;p>&lt;img src="/images/blog/2020-08-17/footer.jpg" alt="el código legacy es código sin tests" />&lt;/p>
&lt;p>Por supuesto, hay mucho más que aprender
sobre &lt;a href="/es/readings/working-effectively-with-legacy-code/">testing y trabajo con código legacy&lt;/a>. De hecho, especialmente cuando
tratamos con código legacy, encontrarás situaciones donde el código está acoplado de alguna manera que podrías querer mockear
tus clases concretas porque no hay interfaz (todavía) para ello.&lt;/p>
&lt;p>Este libro te presenta muchas técnicas sobre cuándo, por qué, dónde y cómo puedes aplicar estos cambios.&lt;/p>
&lt;blockquote>
&lt;p>Cuando trabajas con código necesitas &lt;strong>retroalimentación&lt;/strong>. La retroalimentación automatizada es la mejor. Por lo tanto, esto es lo primero que necesitas hacer: escribir los tests.&lt;/p>
&lt;/blockquote>
&lt;h3 id="primero-anade-tests-luego-haz-tus-cambios">Primero, añade tests, luego haz tus cambios.
&lt;a class="heading-anchor" href="#primero-anade-tests-luego-haz-tus-cambios" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;h4 id="cambia-la-menor-cantidad-de-codigo-posible-para-poner-los-tests-en-su-lugar-con-la-receta">Cambia la menor cantidad de código posible para poner los tests en su lugar con la receta:
&lt;a class="heading-anchor" href="#cambia-la-menor-cantidad-de-codigo-posible-para-poner-los-tests-en-su-lugar-con-la-receta" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h4>
&lt;ol>
&lt;li>Identifica “puntos de cambio” para romper las dependencias de tu código.&lt;/li>
&lt;li>Rompe las dependencias.&lt;/li>
&lt;li>Escribe los tests.&lt;/li>
&lt;li>Haz tus cambios.&lt;/li>
&lt;li>Refactoriza.&lt;/li>
&lt;/ol>
&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>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>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>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>El Programador Limpio</title><subtitle>Un código de conducta para programadores profesionales</subtitle><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="tdd" scheme="https://chemaclass.com/tags/tdd/" label="Tdd"/><category term="communication" scheme="https://chemaclass.com/tags/communication/" label="Communication"/><published>2016-08-01T00:00:00+00:00</published><updated>2016-08-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/the-clean-coder/"/><id>https://chemaclass.com/es/readings/the-clean-coder/</id><summary type="html">Guía de conducta para programadores profesionales</summary><content type="html">&lt;p>Los programadores que triunfan bajo presión e incertidumbre comparten algo: les importa de verdad crear buen software. Lo tratan como un oficio. Son profesionales.&lt;/p>
&lt;span id="continue-reading">&lt;/span>&lt;h3 id="aprenderas">Aprenderás
&lt;a class="heading-anchor" href="#aprenderas" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;ul>
&lt;li>Qué significa ser un verdadero artesano del software&lt;/li>
&lt;li>Cómo lidiar con conflictos, plazos ajustados y jefes difíciles&lt;/li>
&lt;li>Cómo entrar en flujo y superar el bloqueo&lt;/li>
&lt;li>Cómo manejar la presión y evitar el agotamiento&lt;/li>
&lt;li>Cómo combinar actitudes clásicas con nuevos paradigmas de desarrollo&lt;/li>
&lt;li>Cómo gestionar tu tiempo y evitar atascos&lt;/li>
&lt;li>Cómo crear entornos donde los programadores y equipos prosperen&lt;/li>
&lt;li>Cuándo decir &lt;strong>No&lt;/strong> y cómo hacerlo&lt;/li>
&lt;li>Cuándo decir &lt;strong>Sí&lt;/strong> y qué implica realmente&lt;/li>
&lt;/ul>
&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-profesionalismo">Capítulo 1: Profesionalismo
&lt;a class="heading-anchor" href="#capitulo-1-profesionalismo" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;ul>
&lt;li>Ser profesional significa asumir responsabilidad total de tus acciones.&lt;/li>
&lt;li>Primera regla: no dañes ni la función ni la estructura del software.&lt;/li>
&lt;li>Siempre cometerás errores, pero aprende de cada uno.&lt;/li>
&lt;li>Confía en el código que liberas. Espera que QA no encuentre nada.
&lt;ul>
&lt;li>Prueba una y otra vez.&lt;/li>
&lt;li>Automatiza tus tests.&lt;/li>
&lt;li>Diseña el código para que sea fácil de probar.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>Sigue la regla del Boy Scout: deja el código un poco más limpio de como lo encontraste.&lt;/li>
&lt;li>Tu carrera es &lt;strong>tu responsabilidad&lt;/strong>, no la de tu jefe.
&lt;ul>
&lt;li>Dedica 20 horas semanales extra a mejorar tus habilidades.&lt;/li>
&lt;li>Lee, experimenta, practica (katas), habla con otros, colabora, mentoriza.&lt;/li>
&lt;li>Que sea divertido.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>Conoce tu dominio e identifícate con tu cliente (nunca “nosotros vs. ellos”).&lt;/li>
&lt;/ul>
&lt;h3 id="capitulo-2-decir-no">Capítulo 2: Decir No
&lt;a class="heading-anchor" href="#capitulo-2-decir-no" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;ul>
&lt;li>Los profesionales tienen el coraje de decir no a sus jefes.&lt;/li>
&lt;li>Managers y desarrolladores a menudo chocan porque sus objetivos a corto plazo entran en conflicto.&lt;/li>
&lt;li>Cuanto mayor el riesgo, más valioso es un “no” y más difícil de decir.&lt;/li>
&lt;li>Los buenos equipos trabajan hacia un sí, pero solo un sí correcto que funcione en la práctica.&lt;/li>
&lt;/ul>
&lt;h3 id="capitulo-3-decir-si">Capítulo 3: Decir Sí
&lt;a class="heading-anchor" href="#capitulo-3-decir-si" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;ul>
&lt;li>Hay tres partes para hacer un compromiso:
&lt;ul>
&lt;li>Dices que lo harás&lt;/li>
&lt;li>Lo dices en serio&lt;/li>
&lt;li>Realmente lo haces&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>Tu compromiso debe respetar los límites de lo que esperas (basado en tu experiencia) poder y no poder hacer.
&lt;ul>
&lt;li>Si reconoces que probablemente no podrás cumplir un compromiso, necesitas levantar una bandera roja inmediatamente.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;h3 id="capitulo-4-codificacion">Capítulo 4: Codificación
&lt;a class="heading-anchor" href="#capitulo-4-codificacion" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;ul>
&lt;li>Programar requiere un nivel de concentración que pocas disciplinas exigen.&lt;/li>
&lt;li>“La zona” (o flujo) no es tan buena como parece: serás productivo localmente, pero puedes perder la visión global y producir diseños mediocres.&lt;/li>
&lt;li>Las interrupciones son malas distracciones.
&lt;ul>
&lt;li>El pair programming ayuda a gestionarlas.&lt;/li>
&lt;li>TDD hace que el contexto pre-interrupción sea reproducible.
&lt;ul>
&lt;li>Minimiza el tiempo de depuración.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>Programar es una &lt;strong>maratón&lt;/strong>, no un sprint. Conserva energía y creatividad.&lt;/li>
&lt;li>Vete cuando sea hora, aunque estés en medio de algo importante.&lt;/li>
&lt;li>Reestima continuamente tu tiempo de finalización y avisa en cuanto veas que llegarás tarde.
&lt;ul>
&lt;li>No dejes que nadie te meta prisa.&lt;/li>
&lt;li>Define bien qué significa “terminado”, con requisitos de calidad altos.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>Programar es difícil para todos. Pide ayuda y ofrécela, especialmente como mentor.
&lt;ul>
&lt;li>No tengas vergüenza de preguntar.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;h3 id="capitulo-5-test-driven-development">Capítulo 5: Test-Driven Development
&lt;a class="heading-anchor" href="#capitulo-5-test-driven-development" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;ul>
&lt;li>&lt;a rel="external" href="https://en.wikipedia.org/wiki/Test-driven_development">TDD&lt;/a> no es una cura milagrosa y es impráctico o inapropiado en algunos casos (raros).&lt;/li>
&lt;li>Ciclo TDD:
&lt;ol>
&lt;li>Añade un test&lt;/li>
&lt;li>Ejecuta todos los tests. El nuevo test debería fallar por razones esperadas&lt;/li>
&lt;li>Escribe el código más simple que pase el nuevo test&lt;/li>
&lt;li>Todos los tests deberían pasar ahora&lt;/li>
&lt;li>Refactoriza según sea necesario&lt;/li>
&lt;li>Repite&lt;/li>
&lt;/ol>
&lt;/li>
&lt;/ul>
&lt;h3 id="capitulo-6-practicar">Capítulo 6: Practicar
&lt;a class="heading-anchor" href="#capitulo-6-practicar" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;ul>
&lt;li>Una Kata de programación es un conjunto preciso de pulsaciones de teclas y movimientos de ratón coreografiados que simula la resolución de algún problema de programación.
&lt;ul>
&lt;li>Una Kata es sobre el proceso, no la solución.&lt;/li>
&lt;li>No estás resolviendo el problema porque ya conoces la solución.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;h3 id="capitulo-7-tests-de-aceptacion">Capítulo 7: Tests de Aceptación
&lt;a class="heading-anchor" href="#capitulo-7-tests-de-aceptacion" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;ul>
&lt;li>Evita “basura entra, basura sale”. Asegúrate de entender los requisitos.
&lt;ul>
&lt;li>Entenderlos bien significa eliminar ambigüedad.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>La mejor forma es definir tests de aceptación:
&lt;ul>
&lt;li>Los tests automatizados verifican que el software cumple las condiciones del cliente.&lt;/li>
&lt;li>Pasar esos tests define “Terminado”.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>Empieza a implementar solo cuando los tests estén definidos.&lt;/li>
&lt;li>Los tests unitarios son para programadores. Los tests de aceptación son para negocio y desarrolladores.&lt;/li>
&lt;li>Ejecuta todos los tests en integración continua y arregla los fallos de inmediato.&lt;/li>
&lt;/ul>
&lt;h3 id="capitulo-8-estrategias-de-testing">Capítulo 8: Estrategias de Testing
&lt;a class="heading-anchor" href="#capitulo-8-estrategias-de-testing" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;ul>
&lt;li>QA es parte del equipo. Escriben tests de aceptación, casos de fallo, casos límite y hacen testing exploratorio.&lt;/li>
&lt;li>Pirámide de testing:
&lt;ul>
&lt;li>La mayoría son tests unitarios: por y para desarrolladores.&lt;/li>
&lt;li>Muchos son tests de componentes o integración: por QA/Negocio con ayuda de desarrolladores, para ambos.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;h3 id="capitulo-9-gestion-del-tiempo">Capítulo 9: Gestión del tiempo
&lt;a class="heading-anchor" href="#capitulo-9-gestion-del-tiempo" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;ul>
&lt;li>En desarrollo de software, gestionar bien el tiempo es esencial.&lt;/li>
&lt;li>Las reuniones son necesarias pero a menudo una pérdida de tiempo. Evita las que no aporten valor claro: es una obligación profesional.&lt;/li>
&lt;li>Las reuniones deben tener agenda y objetivo claro.
&lt;ul>
&lt;li>Las dailies ágiles son un formato eficiente.&lt;/li>
&lt;li>La planificación de iteración debería ocupar el 5% de la iteración.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>La concentración es un recurso escaso.
&lt;ul>
&lt;li>Úsala cuando la tengas y recarga con tareas simples y descansos.&lt;/li>
&lt;li>Para mejorarla:
&lt;ul>
&lt;li>Haz deporte.&lt;/li>
&lt;li>Busca estímulos creativos.&lt;/li>
&lt;li>Toma descansos cortos cada 45 minutos.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;h3 id="capitulo-10-estimacion">Capítulo 10: Estimación
&lt;a class="heading-anchor" href="#capitulo-10-estimacion" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;ul>
&lt;li>Las estimaciones son la mayor fuente de desconfianza entre negocio y desarrolladores. Los desarrolladores dan estimaciones que negocio trata como compromisos.
&lt;ul>
&lt;li>Ambos olvidan que una estimación es una distribución de probabilidad, no un número fijo.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;h3 id="capitulo-11-presion">Capítulo 11: Presión
&lt;a class="heading-anchor" href="#capitulo-11-presion" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;ul>
&lt;li>El profesional mantiene la calma bajo presión. Sigue sus disciplinas porque sabe que es la mejor forma de cumplir plazos.&lt;/li>
&lt;li>Evita situaciones de presión:
&lt;ul>
&lt;li>Haz solo compromisos que puedas cumplir.&lt;/li>
&lt;li>Mantén tu código limpio.&lt;/li>
&lt;li>Trabaja de forma que no necesites cambiar de método en crisis.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>No entres en pánico. Habla con tu equipo. No te aceleres. Confía en tus disciplinas.&lt;/li>
&lt;li>Ofrece hacer pairing a compañeros en crisis.&lt;/li>
&lt;/ul>
&lt;h3 id="capitulo-12-colaboracion">Capítulo 12: Colaboración
&lt;a class="heading-anchor" href="#capitulo-12-colaboracion" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;ul>
&lt;li>A la mayoría de programadores les gusta trabajar solos. Pero hay que entender los objetivos de quienes nos rodean, incluido negocio.
&lt;ul>
&lt;li>Eso requiere &lt;strong>comunicación&lt;/strong>.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>Dentro del equipo: solo la propiedad colectiva del código y el pairing producen buena comunicación.
&lt;ul>
&lt;li>Programar es &lt;strong>comunicarse&lt;/strong>.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;h3 id="capitulo-13-equipos-y-proyectos">Capítulo 13: Equipos y proyectos
&lt;a class="heading-anchor" href="#capitulo-13-equipos-y-proyectos" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;ul>
&lt;li>Los equipos necesitan meses para consolidarse, conocerse y aprender a trabajar juntos.
&lt;ul>
&lt;li>Asignar personas a varios proyectos a la vez es mala idea. Romper un buen equipo también.&lt;/li>
&lt;li>Mejor asignar varios proyectos a un mismo equipo.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;h3 id="capitulo-14-mentoria-aprendizaje-y-artesania">Capítulo 14: Mentoría, aprendizaje y artesanía
&lt;a class="heading-anchor" href="#capitulo-14-mentoria-aprendizaje-y-artesania" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;ul>
&lt;li>Los programadores jóvenes necesitan mentoría, ya sea implícita o explícita.&lt;/li>
&lt;li>El software controla todos los aspectos de nuestras vidas. Un período de entrenamiento y práctica supervisada es más que apropiado.&lt;/li>
&lt;/ul>
&lt;hr />
&lt;p>En esta lección, Uncle Bob explica por qué es necesario escribir código limpio y establece las bases para lograrlo, tanto sociales como técnicas. El futuro de la programación se basa en un código ético y bien educado.&lt;/p>
&lt;div style="position:relative;aspect-ratio:16/9;width:100%;">
&lt;iframe
src="https://www.youtube-nocookie.com/embed/7EmboKQH8lM"
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>En esta segunda lección, Uncle Bob habla del propósito de los comentarios. Rompe la idea de que comentar es algo que “hay que hacer” por ser supuestamente buena práctica. Para él, escribir un comentario es señal de fracaso: el buen código se explica solo. Menos comentarios = mejor código.&lt;/p>
&lt;div style="position:relative;aspect-ratio:16/9;width:100%;">
&lt;iframe
src="https://www.youtube-nocookie.com/embed/2a_ytyt9sf8"
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>En esta tercera lección, Uncle Bob quiere crear conciencia sobre la necesidad de elevar el criterio al producir código. Señala la falta de preparación de muchos programadores como una de las principales causas de la ineficiencia en el desarrollo de software actual.&lt;/p>
&lt;div style="position:relative;aspect-ratio:16/9;width:100%;">
&lt;iframe
src="https://www.youtube-nocookie.com/embed/Qjywrq2gM8o"
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>En esta cuarta lección, Uncle Bob introduce el Test-Driven Development (TDD). Es una práctica con curva de aprendizaje larga, pero produce código más robusto, seguro, mantenible y desarrollado con mayor eficiencia.&lt;/p>
&lt;div style="position:relative;aspect-ratio:16/9;width:100%;">
&lt;iframe
src="https://www.youtube-nocookie.com/embed/58jGpV2Cg50"
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>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>