<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Diario de Programación &#187; tdd</title>
	<atom:link href="http://blog.chuidiang.com/tag/tdd/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.chuidiang.com</link>
	<description>Programación e informática en general</description>
	<lastBuildDate>Wed, 25 Jan 2012 23:17:43 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>¿Qué habría pasado de usar TDD?</title>
		<link>http://blog.chuidiang.com/2010/07/02/%c2%bfque-habria-pasado-de-usar-tdd/</link>
		<comments>http://blog.chuidiang.com/2010/07/02/%c2%bfque-habria-pasado-de-usar-tdd/#comments</comments>
		<pubDate>Fri, 02 Jul 2010 15:08:51 +0000</pubDate>
		<dc:creator>Chuidiang</dc:creator>
				<category><![CDATA[metodologías]]></category>
		<category><![CDATA[scrum]]></category>
		<category><![CDATA[tdd]]></category>
		<category><![CDATA[anécdotas]]></category>

		<guid isPermaLink="false">http://blog.chuidiang.com/?p=832</guid>
		<description><![CDATA[Siguiendo un poco con el post anterior, hace tiempo en Verlo para creerlo coment&#233; un c&#243;digo real de una empresa con el que me hab&#237;a tropezado. En ese c&#243;digo hab&#237;a una clase (llam&#233;mosla Datos) con 16 atributos est&#225;ticos iguales (digamos, atributo1, atributo2, &#8230; atributo16). Pulsando un bot&#243;n (uno por atributo) deb&#237;a mostrarse en una ventana [...]]]></description>
			<content:encoded><![CDATA[<p><img alt="hommer pensando en un programa software" vspace="10" hspace="10" align="right" src="http://img43.imageshack.us/img43/9639/homersimpsondoh.jpg" />Siguiendo un poco con el post anterior, hace tiempo en <a href="http://blog.chuidiang.com/2010/04/26/verlo-para-creerlo/">Verlo para creerlo</a> coment&eacute; un c&oacute;digo real de una empresa con el que me hab&iacute;a tropezado. En ese c&oacute;digo hab&iacute;a una clase (llam&eacute;mosla Datos) con 16 atributos est&aacute;ticos iguales (digamos, atributo1, atributo2, &#8230; atributo16). Pulsando un bot&oacute;n (uno por atributo) deb&iacute;a mostrarse en una ventana nueva algunas cosas relativa a uno de esos atributos. En el c&oacute;digo hab&iacute;a 16 clases Ventana, una por atributo, llamadas Ventana1, Ventana2&#8230;. Ventana16. La &uacute;nica diferencia en el c&oacute;digo de esas clases, aparte del nombre, era que acced&iacute;a a Datos.atributo1, Datos.atributo2 &#8230; Datos.atributo16</p>
<h2>&iquest;Qu&eacute; habr&iacute;a pasado si hubieran usado TDD?</h2>
<p>Supongamos que este mismo programador hubiera hecho este c&oacute;digo usando TDD. &iquest;Qu&eacute; habr&iacute;a pasado?. Pues lo evidente, habr&iacute;a 16 clases de test llamadas TestVentana1, TestVentana2, &#8230; TestVentana16.</p>
<p>Pero TDD no es s&oacute;lo hacer test, es hacerlos antes. Bueno, supongamos que los ha hecho antes.</p>
<p>Y TDD tiene otro tercer paso, refactorizar para quitar todas las repeticiones posibles de c&oacute;digo, incluso las menos evidentes. Bueno, no s&eacute; vosotros, pero yo, independientemente de usar o no TDD, me repatear&iacute;a hacer copy-paste 16 veces de una misma clase y como ser vago a veces es una virtud, habr&iacute;a dado las vueltas necesarias para no hacer esto. Sin TDD se me ocurre simplemente meter los atributos en un array de 16 posiciones y en un m&eacute;todo set() de la &uacute;nica clase VentanaUnica pasarle el &iacute;ndice de la posici&oacute;n que debe tratar. Es lo primero que se me ocurre, nada complejo, seguramente hay m&aacute;s y mejores soluciones.</p>
<p>Sin embargo, este desarrollador no lo ha hecho. &iquest;Por qu&eacute;?. Se me ocurren cuatro posibles motivos:</p>
<ol>
<li>Totalmente inexperto en java, un array es algo complejo de usar y lo del set() ni lo cree posible. Muchos programadores novatos tiene problemas para hacer que los atributos de una clase se vean en otra y por eso tienden a hacerlos est&aacute;ticos (justo como ha hecho este se&ntilde;or).</li>
<li>No tiene cabeza para programar, por m&aacute;s vuelta que le ha dado, no se le ha ocurrido c&oacute;mo evitar hacer las 16 clases.</li>
<li>Le importa tres pepinos. Para qu&eacute; se va a complicar la vida si con 16 clicks de rat&oacute;n (un copy y 15 pastes) lo arregla.</li>
<li>Todas las anteriores.</li>
</ol>
<p>Bueno, pues con este panorama, &iquest;qu&eacute; habr&iacute;a hecho al intentar refactorizar con TDD?</p>
<ol>
<li>Ya tengo mi TestVentana1, as&iacute; que hago mi Ventana1. Ahora mi TestVentana2 y hago mi Ventana2. &iexcl;&iexcl; C&oacute;digo repetido !!. &iexcl;&iexcl; Vamos a refactorizar !!: Imposible, java no permite hacerlo, si java no permite pasar el atributo de la clase Datos a la clase Ventana, Ventana1 y Ventana2 deben ser clases distintas. Y no te digo juntar los dos test en uno solo.</li>
<li>Buff, qu&eacute; dolor de cabeza, no se me ocurre como puedo convertir dos clases distintas que manejan atributos distintos en una sola.</li>
<li>J&oacute;, que rollo refactorizar ahora que me est&aacute; funcionando, voy con los siguientes 14 pastes, que el copy ya lo tengo hecho.</li>
<li>Java no deja, no se me ocurre como hacerlo y voy a correr un mont&oacute;n si reaprovecho el copy para el resto de pastes.</li>
</ol>
<p>Algo como Srcum tampoco evitar&iacute;a estas cosas. En el sprint diario este se&ntilde;or dir&iacute;a &quot;Ya tengo las ventanas de &nbsp;los atributos&quot; y todos felices. Bueno, con un poco de suerte, un d&iacute;a dir&iacute;a &quot;tengo la Ventana1 del atributo1&quot;, al d&iacute;a siguiente &quot;tengo la Ventana2 del atributo2&quot; y alrededor del quinto d&iacute;a, quiz&aacute;s a alguien se le ponga la mosca detr&aacute;s de la oreja y quiera ver qu&eacute; est&aacute; haciendo. De todas formas, no se tardan 16 d&iacute;as en hacer 15 pastes.</p>
<p>Una herramienta de an&aacute;lisis est&aacute;tico de c&oacute;digo integrada en una herramienta de integraci&oacute;n continua cantar&iacute;a esto por la noche, suponiendo que cante cuando encuentra c&oacute;digo repetido y, como hacemos nosotros, el compilado falla si no se cumple alguna m&eacute;trica importante. Desgraciadamente, existe el @SuppressWarnings que la gente se acostumbra a poner por sistema, incluso antes de que cante la m&eacute;trica (conozco al menos dos personas que lo hacen).</p>
<p>La programaci&oacute;n en parejas tambi&eacute;n habr&iacute;a ayudado, salvo que la pareja de nuestro programador fuera el reci&eacute;n entrado al que le han asignado para que le ense&ntilde;e.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.chuidiang.com/2010/07/02/%c2%bfque-habria-pasado-de-usar-tdd/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Metodologías ágiles y tradicionales. ¿De verdad sirven para algo?</title>
		<link>http://blog.chuidiang.com/2010/07/01/metodologias-agiles-y-tradicionales-%c2%bfde-verdad-sirven-para-algo/</link>
		<comments>http://blog.chuidiang.com/2010/07/01/metodologias-agiles-y-tradicionales-%c2%bfde-verdad-sirven-para-algo/#comments</comments>
		<pubDate>Thu, 01 Jul 2010 13:03:18 +0000</pubDate>
		<dc:creator>Chuidiang</dc:creator>
				<category><![CDATA[metodologías]]></category>
		<category><![CDATA[scrum]]></category>
		<category><![CDATA[tdd]]></category>

		<guid isPermaLink="false">http://blog.chuidiang.com/?p=830</guid>
		<description><![CDATA[Bueno, parece que &#250;ltimamente las malas son las metodolog&#237;as tradicionales y las buenas son las metodolog&#237;as &#225;giles, pero a fin de cuentas, ambas son metodolog&#237;as y las metodolog&#237;as, en general, presentan sus problemas. &#191;Por qu&#233;?. Este art&#237;culo de Joel on Software nos da la respuesta. Un cocinero excepcional hace lo siguiente: Ahora bien, el Chef [...]]]></description>
			<content:encoded><![CDATA[<p><img alt="el big-mac de las metodologias" vspace="10" hspace="10" align="right" src="http://img443.imageshack.us/img443/5420/bigmacv.jpg" />Bueno, parece que &uacute;ltimamente las malas son las metodolog&iacute;as tradicionales y las buenas son las metodolog&iacute;as &aacute;giles, pero a fin de cuentas, ambas son metodolog&iacute;as y las metodolog&iacute;as, en general, presentan sus problemas. &iquest;Por qu&eacute;?. <a href="http://spanish.joelonsoftware.com/Articles/BigMacsvs.TheNakedChef.html">Este art&iacute;culo de Joel on Software</a> nos da la respuesta.</p>
<p>Un cocinero excepcional hace lo siguiente:</p>
<blockquote>
<p>Ahora bien, el Chef Desnudo no sigue ning&uacute;n apestoso Manual de Operaciones. No mide nada. Mientras esta cocinando, usted ve un frenes&iacute; de comida sacudida y siendo arrojada por aqu&iacute; y all&aacute;. &quot;Simplemente pondremos una pizca extra de romero por ac&aacute;, que no lo arruinara, y le daremos una buena sacudida&quot;, dice el. &quot;Am&aacute;senlo as&iacute;. Perfecto. Solo esp&aacute;rzanlo por todos lados.&quot; (Si, de verdad se ve como si simplemente lo esparciera por todos lados.</p>
</blockquote>
<p>es decir, una persona brillante (cocinero en este caso), no necesita seguir ninguna metodolog&iacute;a ni medir nada para obtener un producto genial. &iquest;Por qu&eacute; las metodolog&iacute;as?. Pues porque gente brillante hay poca y del resto hay un mont&oacute;n. Para conseguir que el resto de la gente haga un buen producto, la persona brillante escribe una serie de reglas para que la gente del mont&oacute;n sea capaz de hacer lo mismo que &eacute;l &#8230; y eso no funciona. Si se hace, se tienen &quot;Big Macs&quot;. El resumen del proceso es el que indica Joel on Software en el mismo art&iacute;culo</p>
<blockquote>
<p>1. Algunas cosas requieren de talento para hacerse realmente bien.<br />
2. Es dif&iacute;cil tener talento a la medida.<br />
3. Una forma en que la gente intenta igualar el talento es haciendo que el talentoso cree las reglas para que los menos talentosos las sigan.<br />
4. La calidad del producto resultante es muy baja.&nbsp;</p>
</blockquote>
<p>&iquest;Y qu&eacute; pasa con el software?. Pues m&aacute;s o menos lo mismo. Unas personas geniales escribieron unas metodolog&iacute;as para hacer buen software, sean las tradicionales, sea Scrum, sea TDD y el resto de los mortales tratamos de seguirlas. &iquest;Y qu&eacute; pasa?. Pues cosas como esta</p>
<ul>
<li>&quot;Scrum no nos gusta por la reuni&oacute;n diaria de 90 minutos&quot;&nbsp;<a href="http://www.dosideas.com/noticias/metodologias/917-scrum-diario-efectivo.html">http://www.dosideas.com/noticias/metodologias/917-scrum-diario-efectivo.html</a></li>
<li>&quot;Hacer TDD mal es m&aacute;s costoso que no hacerlo&quot;&nbsp;<a href="http://geeks.ms/blogs/lontivero/archive/2009/09/28/unit-tests-contras-de-implementar-test-unitarios.aspx">http://geeks.ms/blogs/lontivero/archive/2009/09/28/unit-tests-contras-de-implementar-test-unitarios.aspx</a></li>
<li>etc, etc.</li>
</ul>
<p>Total, que para hacer bien Scrum o hacer bien TDD o cualquier otra de las metodolog&iacute;as &aacute;giles hay que hacer un cambio importante de mentalidad, ser bueno en muchas materias incluido como programador, tener mucho sentido com&uacute;n, etc, etc.</p>
<p>Y digo yo&#8230; la persona que cumple todo eso y puede hacer realmente bien TDD/Scrum/metodolog&iacute;as &aacute;giles&#8230; &iquest;necesita realmente hacer todo eso?. Estoy totalmente convencido que un programador genial es totalmente capaz de hacer un muy buen software sin preocuparse en absoluto por ninguna metodolog&iacute;a concreta, sino siguiendo simplemente su intuici&oacute;n. Y estoy convencido que el resto de los mortales estamos predestinados a hacer mal software directamente o hacer mal software despu&eacute;s de haber seguido deficientemente una metodolog&iacute;a &aacute;gil.</p>
<p>A pesar de todo, es mejor seguir una metodolog&iacute;a que ninguna. Imagina en el McDonalds si cada uno se hace los BigMac de cualquier manera. Pero aunque lo he dicho&nbsp;muchas veces, me reitero. Si se quiere un buen software que destaque, el punto m&aacute;s importante a tener en cuenta es elegir a los mejores programadores.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.chuidiang.com/2010/07/01/metodologias-agiles-y-tradicionales-%c2%bfde-verdad-sirven-para-algo/feed/</wfw:commentRss>
		<slash:comments>16</slash:comments>
		</item>
		<item>
		<title>Test Driven Development by example, de Kent Beck.</title>
		<link>http://blog.chuidiang.com/2009/06/23/test-driven-develompment-by-example-de-kent-beck/</link>
		<comments>http://blog.chuidiang.com/2009/06/23/test-driven-develompment-by-example-de-kent-beck/#comments</comments>
		<pubDate>Tue, 23 Jun 2009 15:15:37 +0000</pubDate>
		<dc:creator>Chuidiang</dc:creator>
				<category><![CDATA[tdd]]></category>
		<category><![CDATA[libros]]></category>

		<guid isPermaLink="false">http://blog.chuidiang.com/?p=612</guid>
		<description><![CDATA[&#160; Aprovechando mi puente de cuatro d&#237;as (fiestas locales de la ciudad en la que trabajo), me he le&#237;do &#34;Test Driven Development by example&#34;, de Kent Beck. El libro se lee r&#225;pido, ya que hay poco texto en cada hoja, mucho c&#243;digo de ejemplo, mucha hoja en blanco para que pongas tus anotaciones y, sobre [...]]]></description>
			<content:encoded><![CDATA[<p>&nbsp;</p>
<p>Aprovechando mi puente de cuatro d&iacute;as (fiestas locales de la ciudad en la que trabajo), me he le&iacute;do <a href="http://www.amazon.com/Test-Driven-Development-Addison-Wesley-Signature/dp/0321146530">&quot;Test Driven Development by example&quot;, de Kent Beck</a>. El libro se lee r&aacute;pido, ya que hay poco texto en cada hoja, mucho c&oacute;digo de ejemplo, mucha hoja en blanco para que pongas tus anotaciones y, sobre todo, porque al estar en ingl&eacute;s, me he saltado alegremente todo lo que no he entendido <img src='http://blog.chuidiang.com/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
<p>De todos son conocidos los tres famosos pasos que hay que seguir con TDD</p>
<ol>
<li>Escribir un test autom&aacute;tico de prueba y ejecutarlo para ver que falla.</li>
<li>Hacer el c&oacute;digo m&iacute;nimo necesario para que el test pase.</li>
<li>refactorizar el c&oacute;digo.</li>
</ol>
<p>Sin embargo, es necesaria la lectura de un libro como este (o aprender de alguien con experiencia) para poder entender qu&eacute; significan exactamente estos pasos y c&oacute;mo seguirlos de forma eficiente. Paso a continuaci&oacute;n a detallar algunas de las conclusiones pr&aacute;cticas a las que te lleva la lectura del libro.</p>
<p><strong>&iquest;Cu&aacute;nto debemos avanzar cada vez?</strong></p>
<p>Siguiendo los tres pasos anteriores, podemos irnos a dos extremos. Por un lado, podemos hacer un test tonto, que nos lleve un minuto hacerlo. Luego podemos hacer el c&oacute;digo para que pase ese test, que nos lleva otros dos minutos, y luego el refactor, en otros dos minutos. Al final del d&iacute;a podemos haber escrito doscientos tests y docientos trozitos de c&oacute;digo y apenas haber avanzado en nuestro proyecto. El otro extremo es pasarnos dos d&iacute;as haciendo un test, una semana para el c&oacute;digo de ese test y otra semana para hacer el refactor.</p>
<p>Seg&uacute;n el libro, ni lo uno ni lo otro, hay que llegar al punto justo. &iquest;Y cual es ese punto?. Somos nosotros los que debemos decidirlo en funci&oacute;n de nuestras &quot;sensaciones&quot; al ir programando. Los test y el c&oacute;digo que hagamos no nos deben resultar demasiado triviales de forma que nos de la sensaci&oacute;n de estar perdiendo el tiempo. Sin embargo, si deben ser del tama&ntilde;o justo para que no nos cueste demasiado pensar el c&oacute;digo que tenemos que hacer. Debemos ser capaces de hacer con cierta facilidad el c&oacute;digo necesario para el test, sin que nos lleve m&aacute;s de, digamos, media hora conseguir que el test pase.</p>
<p>Si el c&oacute;digo que hacemos para cada test nos resulta demasiado trivial, podemos hacer test un poco m&aacute;s grandes. Si el c&oacute;digo para el test que estamos haciendo nos empieza a dar que pensar, no estamos muy seguros de c&oacute;mo hacerlo o si va a funcionar a la primera, debemos hacer test m&aacute;s peque&ntilde;os. Por ejemplo, si hacemos un test para un m&eacute;todo suma, podemos implementar f&aacute;cilmente el m&eacute;todo. Si hacemos un test para un m&eacute;todo recursivo de factorial, los m&aacute;s experimentados o con mejor cabeza para la programaci&oacute;n pueden hacerlo directamente, pero los m&aacute;s novatos quiz&aacute;s necesiten hacer primero un test para el caso trivial e implementarlo, luego un test para otro n&uacute;mero e implementarlo, etc.</p>
<p>De alguna forma, el libro da a entender que tenemos que tender m&aacute;s al ensayo y error con los test que pasarnos ratos largos pensando c&oacute;mo implementar algo. Una buena medida de que debemos empezar a hacer test m&aacute;s peque&ntilde;os y menos c&oacute;digo en cada paso es cuando los test empiezan a sorprendernos con fallos inesperados, es decir, cuando ya no estamos realmente controlando la situaci&oacute;n.</p>
<p><strong>Centrarse en un test cada vez y hacer s&oacute;lo lo necesario para este test</strong></p>
<p>Este es quiz&aacute;s uno de los puntos que m&aacute;s f&aacute;cilmente nos podemos saltar. Si hacemos un test y nos ponemos a hacer un c&oacute;digo, es muy f&aacute;cil que nos salgan situaciones o c&oacute;digo auxiliar que necesitemos y nos pongamos a hacerlo en condiciones.</p>
<p>Por ejemplo, imagina que para pasar un test que requiere buscar un Alumno en una lista, vemos que necesitamos implementar el m&eacute;todo equals() en la clase Alumno, que ese m&eacute;todo equals() requiere un c&oacute;digo algo rebuscado y adem&aacute;s deber&iacute;amos implementar el m&eacute;todo hashCode() que nos aconseja java siempre que implementemos el equals(). Es muy f&aacute;cil que nos desviemos de nuestro test para hacer ese equals() y ese hashCode() lo m&aacute;s completos posibles y nos olvidemos temporalmente del test que nos ocupa. O quiz&aacute;s, haciendo el c&oacute;digo usemos un m&eacute;todo ya hecho y descubramos que ese m&eacute;todo necesita un arreglo porque hay un caso que no contempla o deber&iacute;a hacer algo m&aacute;s. Es f&aacute;cil que ahora nos pongamos a arreglar ese m&eacute;todo.</p>
<p>Seg&uacute;n el libro, no debemos hacer eso. Debemos implementar &uacute;nicamente un equals() y/o hashCode() m&iacute;nimo que nos permita pasar el test lo antes posible, incluso aunque devuelva directamente true o false y un hashCode cero, si con eso basta para que pase el test. Una vez que pasa nuestro test, podemos dar la siguiente iteraci&oacute;n y hacer un test para el m&eacute;todo equals() y entonces hacer una implementaci&oacute;n correcta de equals().</p>
<p>Y la mejor forma de hacer esto y que no se nos olvide despu&eacute;s y que nos sintamos c&oacute;modos haciendo esas &quot;chapuzas&quot; temporales, es tener un papel al lado del teclado en el que apuntemos los test que creemos que debemos&nbsp; hacer m&aacute;s adelante. Si tenemos que hacer un equals() en condiciones, apuntamos en el papel que tenemos que hacer un test de equals() de la clase Alumno, escribimos ahora un equals() con la implementaci&oacute;n m&iacute;nima necesaria para que funcione el test en el que estamos trabajando, y nos olvidamos del equals() hasta que le toque el turno. Si tenemos que arreglar aquel m&eacute;todo que hemos descubierto, pues apuntamos hacer un test para ese m&eacute;todo y no lo tocamos ahora, nos centramos en el test que estamos actualmente trabajando.</p>
<p><strong>Dejar que TDD nos vaya llevando al dise&ntilde;o m&aacute;s simple</strong></p>
<p>Seg&uacute;n TDD, debemos hacer en cada momento el c&oacute;digo m&aacute;s simple posible que haga pasar el test. En el refactor, seg&uacute;n el libro, debemos sobre todo trata de eliminar repeticiones (<a href="http://es.wikipedia.org/wiki/DRY">DRY, Dont repeat yourself o &quot;no te repitas&quot;</a>, para los amigos) y es precisamente en este paso de refactor, donde debemos &quot;complicar&quot; nuestro dise&ntilde;o s&oacute;lo lo justo para evitar esas repeticiones. Veamos esto con un ejemplo concreto.</p>
<p>Imag&iacute;nate que uno de nuestros test dice que al jefe le podemos fijar el sueldo. Hacemos un test que a la clase Jefe le pone un setSueldo() y comprueba que getSueldo() devuelve el sueldo que hemos pasado. (s&iacute;, ya s&eacute; que es muy tonto y que este tipo de cosas ni siquiera merecen la pena ser testeadas). Bueno, hacemos nuestra clase Jefe y ese par de m&eacute;todos tontos y el test pasa.</p>
<p>Ahora, el siguiente test nos dice que podemos hacer lo mismo con un currito. Hacemos el test, hacemos la clase Currito y le ponemos los dos m&eacute;todos de marras. Los test pasan, pero ahora toca refactorizar. &iquest;C&oacute;digo repetido?. S&iacute;, las dos clases enteras, lo &uacute;nico que cambia es el nombre. Tal cual tenemos ahora, deber&iacute;amos hacer una clase Empleado con todo el c&oacute;digo de setSueldo() y getSueldo() y BORRAR las clases Jefe y Currito. S&iacute;, borrar, no hacer herencia, ni interface com&uacute;n ni nada parecido. Ahora mismo no hay nada que distinga a Jefe de Currito y el dise&ntilde;o m&aacute;s simple es tener una &uacute;nica clase con el c&oacute;digo com&uacute;n (todo el c&oacute;digo) para ambos tipos de personajes. No debemos dejarnos llevar en ning&uacute;n momento por nuestro entusiasmo ni nuestros bastos conocimientos de OO para mantener la clase Jefe y Currito y hacerles una clase padre Empleado. De momento, simplemente no es necesario y por tanto, no lo hacemos.</p>
<p>Sup&oacute;n ahora que un test nos pide que escribamos en pantalla el tipo de personaje que es. Si es jefe o currito. Pues bien, la soluci&oacute;n m&aacute;s simple no es volver a hacer las clases Jefe y Currito. La OO nos lo pide a gritos, pero no es la soluci&oacute;n m&aacute;s simple para los tres test que tenemos. La soluci&oacute;n m&aacute;s simple es hacer un enumerado JEFE, CURRITO y ponerle un atributo a la clase Empleado, que puede rellenarse en el mismo constructor, con el m&eacute;todo getTipoEmpleado() correspondiente.</p>
<p>Ahora, otro test hace que alguna cosa, por ejemplo, comprobar si el Empleado tiene derecho a coche de empresa, y c&oacute;mo no, s&oacute;lo si es jefe tiene derecho a ello. Pues bien, mientras s&oacute;lo este este test, la soluci&oacute;n m&aacute;s simple es poner un if comprobando en el atributo enumerado si es jefe. El m&eacute;todo tieneCocheEmpresa() de empleado simplemente devuelve el restultado del if.</p>
<p>Y finalmente, piensa en otro test que tambi&eacute;n da un privilegio al jefe, como comprobar si Empleado tiene derecho a un sill&oacute;n c&oacute;modo y nuevamente s&oacute;lo si es jefe tiene ese derecho. La soluci&oacute;n m&aacute;s simple que podemos dar en este momento es a&ntilde;adir otro m&eacute;todo tieneSillonComodo() otro if del atributo &#8230; pero cuando llega el momento de refactor vemos que hay c&oacute;digo repetido. Ese if est&aacute; en dos sitios distintos. Ahora, y s&oacute;lo ahora, es el momento donde TDD nos aconseja que empezemos a pensar en la existencia de dos clases separadas, la de Jefe y la de Currito, cuando empezamos a ver que el &quot;si es jefe&quot; empieza a repetirse en varios sitios. Y s&oacute;lo si las nuevas clases Jefe y Currito tienen c&oacute;digo repetido, debemos mantener la clase Empleado y&nbsp; heredar de ella. Si dejara de existir ese c&oacute;digo com&uacute;n, simplemente eliminamos Empleado y no hacemos herencia. O quiz&aacute;s, en este caso concreto, sea m&aacute;s f&aacute;cil mantener una tabla de booleanos/privilegio dentro de la clase Empleado.</p>
<p>De hecho, uno de los ejemplos del libro es precisamente algo parecido a esto. Comienza haciendo dos clases (Dolar y Franco) y acaba descart&aacute;ndolas para hacer una &uacute;nica clase (Dinero) que tiene un atributo que indica el tipo de moneda.</p>
<p><strong>Descansos frecuentes</strong></p>
<p>Y el consejo que m&aacute;s me ha gustado del libro: Tener siempre una botella de agua a mano, de esta forma, la fisiolog&iacute;a te obligar&aacute; a tomarte descansos frecuentes &#8230; para ir al ba&ntilde;o.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.chuidiang.com/2009/06/23/test-driven-develompment-by-example-de-kent-beck/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>Jugando con TDD</title>
		<link>http://blog.chuidiang.com/2009/05/29/jugando-con-tdd/</link>
		<comments>http://blog.chuidiang.com/2009/05/29/jugando-con-tdd/#comments</comments>
		<pubDate>Fri, 29 May 2009 15:50:23 +0000</pubDate>
		<dc:creator>Chuidiang</dc:creator>
				<category><![CDATA[tdd]]></category>
		<category><![CDATA[junit]]></category>

		<guid isPermaLink="false">http://blog.chuidiang.com/?p=600</guid>
		<description><![CDATA[&#160; Hace tiempo que hab&#237;a oido hablar de TDD y hace unos meses que lo poco que codifico intento hacerlo siguiendo esta filosof&#237;a, de momento yo solo, por mi cuenta y riesgo. No me gusta mover a la gente y aconsejarles algo sin haber hecho primero mis pruebas. Pero la verdad es que en ese [...]]]></description>
			<content:encoded><![CDATA[<p>&nbsp;</p>
<p>Hace tiempo que hab&iacute;a oido hablar de <a href="http://www.chuidiang.com/chuwiki/index.php?title=Desarrollo_orientado_a_los_test">TDD</a> y hace unos meses que lo poco que codifico intento hacerlo siguiendo esta filosof&iacute;a, de momento yo solo, por mi cuenta y riesgo. No me gusta mover a la gente y aconsejarles algo sin haber hecho primero mis pruebas. Pero la verdad es que en ese poco tiempo que he estado probando, las ventajas saltan a la vista. Ah&iacute; van algunas cosas que he notado.</p>
<p>La primera es que al pensar primero en hacer el test, te obliga un poco a hacer la/s clases/s con un dise&ntilde;o adecuado para ser testeadas. El ejemplo m&aacute;s t&iacute;pico es una clase que recoge datos de alg&uacute;n sitio, hace cosas con ellos y los deja&nbsp; en otro lado. El dise&ntilde;o para hacer test de esa clase hasta cierto punto obliga a que esa clase se le pasen los datos (o los recoja de una interface que se le pasa) y devuelva los resultados (o se los pase a una interface que se le pasa). Este dise&ntilde;o, pr&aacute;cticamente obligado para poder hacer el test, generalmente es mejor que la clase &quot;mazacote&quot; que ella sola lee sus datos directamente de d&oacute;nde sea, hace las cuentas y deja los resultados directamente en alg&uacute;n sitio. La clase &quot;mazacote&quot; ser&iacute;a muy dif&iacute;cil de testear, puesto que tendr&iacute;amos que acceder directamente a los datos de donde la clase los recoge o los deja (una base de datos, una interface gr&aacute;fica de usuario, un socket, etc). Hacer el test nos ha obligado a, en vez de hacer una clase &quot;mazacote&quot;, hacer tres clases: LeerDatos, EcharCuentas y MostrarResultados, con una clara divis&iacute;&oacute;n de responsabilidades, y adem&aacute;s, con sus interfaces correspondientes.</p>
<p>La segunda ventaja, seg&uacute;n vas haciendo test y codificando m&aacute;s y m&aacute;s, es que me siento con mucha confianza para retocar el c&oacute;digo. El tener unos test detr&aacute;s me hace ser m&aacute;s atrevido a la hora de tocar c&oacute;digo que funciona para mejorarlo. De hecho, lo hago m&aacute;s que antes (aunque para decir la verdad, no lo hago todo lo que debiera por las malditas prisas).</p>
<p>Y otra ventaja verdaderamente importante y que me ha llevado a escribir este post, aunque no est&eacute; hablando estrictamente de TDD, es que ayuda much&iacute;simo a buscar y corregir fallos. Cuento la experiencia de hoy:</p>
<p>En uno de nuestros sistemas enviamos mensajes por sockets entre los distintos ejecutables. Hab&iacute;a un mensaje concreto que al enviarlo por socket aparentemente funcionaba, pero soltaba por el log unas excepciones muy feas y raras. Esas excepciones saltan en el c&oacute;digo que convierte ese mensaje (una clase java) en un array de bytes para env&iacute;o por el socket. Me &quot;encasquetaron&quot; a m&iacute; el problema, as&iacute; que me puse a ello. Pero en vez de hacer lo que se hace tradicionalmente, que es arrancar el sistema con debugger y ponerse a probar, decid&iacute; aplicar alguna de las ideas de TDD: &quot;No se toca c&oacute;digo si no hay un test que falla&quot;. As&iacute; que en vez de eso, me fui a mi sitio y me puse a hacer un test que fuera capaz de provocar ese fallo.</p>
<p>Tras una hora y pico de trabajo y hacer un test relativamente complejo, como abrir un socket cliente y otro servidor, construir el mensaje y enviarlo y jugar con los datos del mensaje a ver qu&eacute; pod&iacute;a provocar el error, consegu&iacute; reproducirlo. Ahora, la parte de debugger sobre el test de junit es mucho m&aacute;s sencilla, que es un programa much&iacute;simo m&aacute;s simple que el sistema completo. Sentado tranquilamente en mi sitio con mi eclipse. Otra horita de debugger y localic&eacute; y correg&iacute; el error. Generar una nueva versi&oacute;n del sitema y prueba con &eacute;xito.</p>
<p>Pues bien, me cost&oacute; casi tres horas localizar y corregir el error. No quiero ni pensar lo que habr&iacute;a tardado si me hubiera dedicado a arrancar el sistema completo una y otra vez, generando, instalando versiones y rearrancando cada vez que hubiera tocado algo para probar, manejando toda la interface gr&aacute;fica (loggeo en el sistema, creaci&oacute;n de unos datos, env&iacute;o por el socket) en cada prueba. Estoy seguro que habr&iacute;a echado un d&iacute;a completo o m&aacute;s, ocupando el sistema e impidiendo a otros trabajar.</p>
<p>Y lo mejor de todo no es que me haya ahorrado varias horas de mi trabajo dejando libre el sistema a los probadores, no. Lo mejor de todo es que ahora hay una prueba que se ejecutar&aacute; autom&aacute;ticamente cada vez que alguien compile el sistema y nuestro sistema de integraci&oacute;n cont&iacute;nua (Hudson), se encargar&aacute; de hacerlo todas las noches.</p>
<p>Y habr&iacute;a tardado mucho menos si hubiesemos hecho TDD desde el principio, ya que o bien no se habr&iacute;a producido el error, o bien ya habr&iacute;a tenido montada la base para el test autom&aacute;tico y s&oacute;lo habr&iacute;a tenido que a&ntilde;adirle m&aacute;s cosas.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.chuidiang.com/2009/05/29/jugando-con-tdd/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Jugando con TDD, MVP, PF, EasyMock y Mockito</title>
		<link>http://blog.chuidiang.com/2009/03/21/jugando-con-tdd-y-easymock/</link>
		<comments>http://blog.chuidiang.com/2009/03/21/jugando-con-tdd-y-easymock/#comments</comments>
		<pubDate>Sat, 21 Mar 2009 15:52:02 +0000</pubDate>
		<dc:creator>Chuidiang</dc:creator>
				<category><![CDATA[java]]></category>
		<category><![CDATA[junit]]></category>
		<category><![CDATA[tdd]]></category>
		<category><![CDATA[easymock]]></category>
		<category><![CDATA[gui]]></category>
		<category><![CDATA[mockito]]></category>
		<category><![CDATA[mvp]]></category>
		<category><![CDATA[pf]]></category>

		<guid isPermaLink="false">http://blog.chuidiang.com/?p=544</guid>
		<description><![CDATA[&#160; Normalmente no codifico, lo he dejado por imposible. Un d&#237;a de trabajo mio normal consiste en atender una cola de gente que viene a preguntarme cosas, algunos pocos sobre java, algunos m&#225;s sobre las herramientas que usamos (maven, archiva, redmine, etc) y muchos (jefes sobre todo) sobre incidencias de los proyectos, c&#243;mo va el [...]]]></description>
			<content:encoded><![CDATA[<p>&nbsp;</p>
<p>Normalmente no codifico, lo he dejado por imposible. Un d&iacute;a de trabajo mio normal consiste en atender una cola de gente que viene a preguntarme cosas, algunos pocos sobre java, algunos m&aacute;s sobre las herramientas que usamos (<a href="http://www.chuidiang.com/java/herramientas/maven.php">maven</a>, <a href="http://www.chuidiang.com/chuwiki/index.php?title=Integraci%C3%B3n_CVS%2C_Hudson%2C_Maven_y_Archiva_en_proyectos_Java">archiva</a>, <a href="http://www.chuidiang.com/chuwiki/index.php?title=Redmine">redmine</a>, etc) y muchos (jefes sobre todo) sobre incidencias de los proyectos, c&oacute;mo va el trabajo, etc. En esas condiciones, es muy dif&iacute;cil concentrarse cinco minutos seguidos y mucho menos diez, por lo que hace tiempo que decid&iacute; no meterme en serio a codificar.</p>
<p>Sin embargo, el viernes de la semana pasada fue un d&iacute;a excepcionalmente tranquilo. Todo el mundo sentado en su sitio, a sus cosas y sin que nadie viniera a decirme nada. Cuando pasan estas cosas, suelo aburrirme un poco, no empiezo a hacer nada en serio por temor a las interrupciones que seguro que est&aacute;n al caer. Pero ese viernes la tranquilidad se estaba prolongando demasiado, hab&iacute;a un m&oacute;dulo nuevo para hacer desde cero y yo <a href="http://www.chuidiang.com/chuwiki/index.php?title=Desarrollo_orientado_a_los_test">acababa de leerme algo sobre TDD</a>, as&iacute; que habl&eacute; con la persona que ten&iacute;a asignada ese m&oacute;dulo y no le molest&oacute; que lo empezara yo (aun a sabiendas de que lo dejar&eacute; a medias y le tocar&aacute; seguir a &eacute;l). As&iacute; que as&iacute; me he tirado casi una semana, codificando y jugando al TDD.</p>
<p>Las primeras historias fueron m&aacute;s o menos sencillas. Hice mis test, luego mi c&oacute;digo, refactoric&eacute; un poco y vuelta a empezar. Pero lleg&oacute; un momento en que el tema se me complic&oacute; m&aacute;s de la cuenta. Lleg&oacute; una historia de usuario en la que hab&iacute;a involucrada una parte de interface de usuario con Swing que no era trivial de probar con un test autom&aacute;tico. Y me puse a investigar en internet.</p>
<p>Primero encontr&eacute; la posibilidad de ponerse con los m&eacute;todos de java getComponents() y similares para tratar de buscar el componente java (el JTextField, el JButton o lo que sea) que necesitas para tu test y a partir de ah&iacute; usar el m&eacute;todo setText(), getText() o doClick() para simular la interacci&oacute;n con el usurio. Aunque eso s&iacute; te puede sacar del apuro en un caso puntual, no parece que sea la mejor forma de hacerlo por sistema. El test se llena de c&oacute;digo rebuscado con bucles y recursiones hasta localizar el componente que te interesa y que por supuesto, tienes que haber dado previamente un nombre con el m&eacute;todo setName() para distinguirlo de otros componentes del mismo tipo.</p>
<p>Segu&iacute; buscando y encontr&eacute; que todo ese proceso se facilita con librer&iacute;as como <a href="http://www.junit.org/node/277">FEST-Swing</a>, que de alguna forma facilitan y eliminan todo el c&oacute;digo raro que mencion&eacute; en el apartado anterior. No llegu&eacute; a probarlo porque no encontr&eacute; un repositorio maven que me permitiera bajarme la librer&iacute;a f&aacute;cilmente.</p>
<p>Y segu&iacute; buscando y encontr&eacute; una cosa interesante: El patr&oacute;n <a href="http://en.wikipedia.org/wiki/Model_View_Presenter">MVP (Model-View-Presenter)</a> y el <a href="http://en.wikipedia.org/wiki/Presenter_First">PF (Presenter First)</a>. La idea de estos patrones es que una interface gr&aacute;fica de usuario es muy compleja de testear autom&aacute;ticamente, por lo que debemos hacerla lo m&aacute;s tonta posible, para no tener que testearla. Es decir, un panel de nuestra interface gr&aacute;fica de usuario &uacute;nicamente debe tener m&eacute;todos set y get para mostrar datos y recogerlos. No debe tener actionListeners para los botones ni ning&uacute;n tipo de inteligencia. Toda la inteligencia de esa interface se hace en otra clase, llamada Presenter. Esta clase debe recibir dos interfaces en el constructor, una de la interface gr&aacute;fica de usuario y otra correspondiente al modelo de datos. La clase Presenter debe hacer ella misma de listener de los botones y encargarse de interactuar con el modelo y la interface de usuario. Haci&eacute;ndolo as&iacute;, es f&aacute;cil testear toda esta l&oacute;gica, ya que podemos instanciar en nuestro test el Presenter y pasarle dos <a href="http://es.wikipedia.org/wiki/Mock_object">mock-objects</a>, el del modelo y el de la interface del usuario.</p>
<p>Me gust&oacute; la idea, as&iacute; que r&aacute;pidamente me puse a modificar mi c&oacute;digo para usar un Presenter y quitarle el m&aacute;ximo posible de c&oacute;digo (todo) a los componentes swing. Por supuesto, siguiendo TDD, primero comenc&eacute; a hacer test y modificar los ya hechos.</p>
<p>Pero llegu&oacute; el momento de usar los mock-objects. Por un lado, pod&iacute;a hac&eacute;rmelos a mano, pero por otro lado hace tiempo que conozco y nunca he usado la librer&iacute;a <a href="http://easymock.org/">EasyMock</a>. Supuestamente (y en la realidad) facilita la creaci&oacute;n de los mock-objects, haci&eacute;ndolo autom&aacute;ticamente. Viendo la documentaci&oacute;n me pareci&oacute; f&aacute;cil de usar y encontr&eacute; adem&aacute;s la librer&iacute;a en los repositorios maven, as&iacute; que me puse con ello. Sin embargo, me ha decepcionado un poco. Los EasyMock est&aacute;n bien para determinadas cosas, pero les veo dos pegas que no los hacen ideales en todas las circunstancias:</p>
<ul>
<li>La filosof&iacute;a de un EasyMock en el test es crear el mock-object, decirle a qu&eacute; m&eacute;todos se van a llamar durante el test y con qu&eacute; par&aacute;metros, luego llamar a su m&eacute;todo replay() para indicarle que empieza el test de verdad y hacer el test. Si durante el test no se sigue la secuencia de llamadas indicada anteriormente, el test falla. &iquest;Cual es la pega que le veo a esto?. Pues sobre todo para cosas como TDD, en que las clases se refactorizan y van evolucionando seg&uacute;n se van desarrollando nuevas historias. Es muy f&aacute;cil que sin modificar el funcionamiento de la clase, la secuencia de llamadas cambie, porque se hagan m&aacute;s llamadas, o se reemplacen algunas por otras o lo que sea. Esto obliga a ir rehaciendo los test, aunque la funcionalidad no cambie, simplemente porque cambia el orden o el n&uacute;mero de llamadas que se hacen.</li>
<li>Los EasyMock, aunque no lo puedo asegurar porque no lo he mirado en profundidad, no permiten que un mock-object genere alg&uacute;n tipo de eventos. En el caso concreto del patr&oacute;n MVP y PF mencionados antes, un Presenter a&ntilde;ade un ActionListener a un bot&oacute;n de la interface de usuario. Si estoy testeando el Presenter y le paso un mock de la interface de usuario, no puedo simular un click en el bot&oacute;n o hacer la llamada al actionListener. Unicamente puedo ver que el Presenter efectivamente se suscribe llamando al addActionListener() correspondiente.</li>
</ul>
<p>Tratando de solucionar algunas de estas pegas (la primera sobre todo), hay otra librer&iacute;a, <a href="http://mockito.org/">Mockito</a>, que se basa en EasyMock, pero trata de darle una API m&aacute;s sencilla y vers&aacute;til. Tengo pendiente echarle un ojo, pero creo que la segunda pega no me la va a solucionar. Supongo que para cosas como los listener, no me quedar&aacute; m&aacute;s remedio que hacerme los mock-object a medida &#8230; y a mano.</p>
<p>Lo que me da realmente pena de todo esto, es la persona que va a seguir con este c&oacute;digo, cuando a m&iacute; empiecen a agobiarme con otros temas. Veamos que cara pone cuando empiece a ver Presenters y Mockitos. O lo tira todo a la basura, o aprovecha para aprender una nueva forma de hacer las cosas y as&iacute;, al menos, tendr&eacute; alguna opini&oacute;n m&aacute;s sobre el tema, aparte de la m&iacute;a propia. Esto es, nuevamente, <a href="http://blog.chuidiang.com/2009/02/27/%C2%BFsopa-de-piedras-o-capitan-arana/">una sopa de piedras o un capit&aacute;n ara&ntilde;a</a>. Ya veremos en qu&eacute; acaba.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.chuidiang.com/2009/03/21/jugando-con-tdd-y-easymock/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>¿TDD requiere memoria de elefante?</title>
		<link>http://blog.chuidiang.com/2008/10/18/%c2%bftdd-requiere-memoria-de-elefante/</link>
		<comments>http://blog.chuidiang.com/2008/10/18/%c2%bftdd-requiere-memoria-de-elefante/#comments</comments>
		<pubDate>Sat, 18 Oct 2008 21:01:10 +0000</pubDate>
		<dc:creator>Chuidiang</dc:creator>
				<category><![CDATA[metodologías]]></category>
		<category><![CDATA[tdd]]></category>

		<guid isPermaLink="false">http://blog.chuidiang.com/?p=414</guid>
		<description><![CDATA[&#160; A m&#237; siempre me ha gustado programar de poco en poco, haciendo un trozo de c&#243;digo que se puede arrancar y ver, luego a&#241;adir otro trozo que tambi&#233;n se puede arrancar y ver y as&#237; sucesivamente. Nunca me ha gustado liarme a escribir c&#243;digo durante varios d&#237;as, sin probar nada, y luego arrancarlo y [...]]]></description>
			<content:encoded><![CDATA[<p>&nbsp;</p>
<p>A m&iacute; siempre me ha gustado programar de poco en poco, haciendo un trozo de c&oacute;digo que se puede arrancar y ver, luego a&ntilde;adir otro trozo que tambi&eacute;n se puede arrancar y ver y as&iacute; sucesivamente. Nunca me ha gustado liarme a escribir c&oacute;digo durante varios d&iacute;as, sin probar nada, y luego arrancarlo y pasarme otros varios d&iacute;as haci&eacute;ndolo funcionar. No s&eacute; qu&eacute; es mejor, pero desde luego, me gusta m&aacute;s lo primero, es m&aacute;s entretenido. Tiene la pega de que &quot;pierdes&quot;, sobre todo en proyectos grandes, mucho tiempo compilando. Haces algo en uno o dos d&iacute;as, compilas y pruebas, repites, y repites.</p>
<p>Por todo esto, TDD es una metodolog&iacute;a que me gust&oacute; desde que la descubr&iacute;. B&aacute;sicamente dice que hay que hacer lo que yo hago, implementar un poco y probar. Sin embargo, TDD es por supuesto m&aacute;s estricto y organizado. Antes de programar, debes hacer unos test para ver que fallan. Luego debes implementar tu c&oacute;digo para que no falle y finalmente debes refactorizar para que tu c&oacute;digo si adapte bien al resto del c&oacute;digo y viceversa.</p>
<p>As&iacute; que he tratado de adaptar mi forma de trabajo a TDD. Pero me encuentro con un problema con la refactorizaci&oacute;n. No es lo mismo ir haciendo c&oacute;digo y refactorizar seg&uacute;n vas viendo c&oacute;digo chapucero, que esperar a tener algo funcionando y luego refactorizar para adaptar tu c&oacute;digo o el c&oacute;digo ya hecho el uno al otro. Mi principial problema es la memoria de mosquito. Una vez tengo mi c&oacute;digo, ya no me acuerdo con detalle de c&oacute;mo estaba hecho el anterior, y no s&eacute; qu&eacute; tengo que refactorizar para que se adapten el uno al otro. No me queda m&aacute;s remedio que dar un repaso a lo ya hecho para ver qu&eacute; juntar.</p>
<p>Supongo que a la larga incluso es mejor, ya que el repaso del c&oacute;digo para mejorarlo tiene que ser bueno, pero no deja de ser un poquito pesado.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.chuidiang.com/2008/10/18/%c2%bftdd-requiere-memoria-de-elefante/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

