<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://msmvps.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Angel "Java" Lopez : Desarrollo de Software, C Sharp</title><link>http://msmvps.com/blogs/lopez/archive/tags/Desarrollo+de+Software/C+Sharp/default.aspx</link><description>Tags: Desarrollo de Software, C Sharp</description><dc:language>en</dc:language><generator>CommunityServer 2008.5 SP2 (Build: 40407.4157)</generator><item><title>Escribiendo una Aplicación usando TDD (Part 6) Modificando Vistas</title><link>http://msmvps.com/blogs/lopez/archive/2013/04/07/escribiendo-una-aplicaci-243-n-usando-tdd-part-6-modificando-vistas.aspx</link><pubDate>Sun, 07 Apr 2013 11:33:39 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1826752</guid><dc:creator>lopez</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/lopez/rsscomments.aspx?PostID=1826752</wfw:commentRss><comments>http://msmvps.com/blogs/lopez/archive/2013/04/07/escribiendo-una-aplicaci-243-n-usando-tdd-part-6-modificando-vistas.aspx#comments</comments><description>&lt;p&gt;&lt;a href="http://msmvps.com/blogs/lopez/archive/2011/06/27/writing_2D00_an_2D00_application_2D00_using_2D00_tdd_2D00_part_2D00_5_2D00_adding_2D00_views.aspx"&gt;Anterior Post&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;El post de hoy va a mostrar que, al haber usado MVC (Model-View-Controller) podemos modificar nuestras vistas, sin necesidad de tocar el código. Ni siquiera tenemos que recompilar, en muchos casos.&lt;/p&gt;  &lt;p&gt;Primero, una novedad: he pasado el ejemplo, paso a paso, a ASP.NET MVC 4, usando Visual Studio 2010. Y también lo pasé a mi cuenta de GitHub&lt;/p&gt;  &lt;p&gt;&lt;a href="https://github.com/ajlopez/TddAppAspNetMvc"&gt;https://github.com/ajlopez/TddAppAspNetMvc&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;img src="http://www.ajlopez.com/images/articles2/apptdd0501.png" alt="" /&gt; &lt;/p&gt;  &lt;p&gt;Vean que cada versión (cada entrega por post) está señalada por tags. La de este post es la 0.0.5. Siempre pueden ver en&lt;/p&gt;  &lt;p&gt;&lt;a href="https://github.com/ajlopez/TddAppAspNetMvc/commits/master"&gt;https://github.com/ajlopez/TddAppAspNetMvc/commits/master&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;img src="http://www.ajlopez.com/images/articles2/apptdd0504.png" alt="" /&gt; &lt;/p&gt;  &lt;p&gt;Una de las cosas nuevas que me dió esta versión de ASP.NET MVC es el soporte de Razor, ahora las vistas están escritas con Razor. Como en el anterior post, use los “wizard” de creación de vistas del propio Visual Studio, y luego las modifiqué un poco (apenas algun texto).&lt;/p&gt;  &lt;p&gt;En el paso de este post, lo que hice fue agregar &lt;a href="http://twitter.github.io/bootstrap/"&gt;Twitter Bootstrap&lt;/a&gt;:&lt;/p&gt;  &lt;p&gt;&lt;img src="http://www.ajlopez.com/images/articles2/apptdd0503.png" alt="" /&gt; &lt;/p&gt;  &lt;p&gt;Agregué estilos y javascript que necesita Bootstrap, y armé un _viewstart.chtml que le indica a Razor que todas las vistas usan un _Layout.cshtml&lt;/p&gt;  &lt;p&gt;Vean cómo se ve ahora la página de Subjects:&lt;/p&gt;  &lt;p&gt;&lt;img src="http://www.ajlopez.com/images/articles2/apptdd0502.png" alt="" /&gt; &lt;/p&gt;  &lt;p&gt;Notablemente, no toqué nada de código ni de tests. Esto muestra que hasta se puede trabajar en paralelo, o en distintos tiempos: primero se arma el código de los controladores y acciones con tests. Luego, al mismo tiempo o en algun momento, se agregan y mejoran las vistas.&lt;/p&gt;  &lt;p&gt;Próximos posts: agregar libros, aparición de primeros servicios, modelo de negocio, etc.&lt;/p&gt;  &lt;p&gt;Nos leemos!&lt;/p&gt;  &lt;p&gt;Angel “Java” Lopez   &lt;br /&gt;&lt;a href="http://www.ajlopez.com"&gt;http://www.ajlopez.com&lt;/a&gt;    &lt;br /&gt;&lt;a href="http://twitter.com/ajlopez"&gt;http://twitter.com/ajlopez&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1826752" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/lopez/archive/tags/.NET/default.aspx">.NET</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Desarrollo+de+Software/default.aspx">Desarrollo de Software</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/C+Sharp/default.aspx">C Sharp</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Desarrollo+Agil/default.aspx">Desarrollo Agil</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/TDD/default.aspx">TDD</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/ASP.NET+MVC/default.aspx">ASP.NET MVC</category></item><item><title>TDD y Reglas de Negocio (1)</title><link>http://msmvps.com/blogs/lopez/archive/2012/07/28/tdd_2D00_and_2D00_business_2D00_rules_2D00_1.aspx</link><pubDate>Sat, 28 Jul 2012 09:47:07 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1813748</guid><dc:creator>lopez</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/lopez/rsscomments.aspx?PostID=1813748</wfw:commentRss><comments>http://msmvps.com/blogs/lopez/archive/2012/07/28/tdd_2D00_and_2D00_business_2D00_rules_2D00_1.aspx#comments</comments><description>&lt;p&gt;Este mes estuve trabajando como miembro de un equipo ágil, desarrollando una aplicación privada. Una de las características interesates es que el sistema permite la creación y existencia de entidades del dominio del&amp;#160; negecio, aún cuando estén en algún estado “inválido”. El product owner quiere armar un sistema flexible que refleje la realidad del negocio, en vez de uno más estrcito que no permita ese reflejo porque no se cumple alguna regla de negocio. Pero quiere ver también cuáles son las entidades que están en estado “inválido” y por qué. Así que se le muestra (la parte de interfaz de usuario está en ASP.NET MVC) una página con lo que hemos llamado Findings: una lista de mensajes alertando sobre los estados a revisar. Por ejemplo: que tal factura tiene un importe demasiado bajo o que no tiene renglones asociados.&lt;/p&gt;  &lt;p&gt;Me gustaría explorar el mode TDD de armar esa característica. Para conseguirlo, necesito un dominio de prueba, y en este post voy a describirlo, simplificado, para tener algo en firme sobre el que implementar los Findings.&lt;/p&gt;  &lt;p&gt;Sea una Order. Cada Order tiene uno o más Order Item. Cada Order Item tiene un Product, Quantity, Price (Producto, Cantidad y Precio). Cada Order tiene un Customer (Cliente). Hay reglas de negocio que describen cuáles son los estados “inválidos”. Algunos ejemplos:&lt;/p&gt;  &lt;p&gt;- Una Order para un Customer de categoría Y no puede tener un monto total que supere X.    &lt;br /&gt;- Una Order debe tener uno o más Order Items.     &lt;br /&gt;- Los Order Items deben tener una Cantidad/Quantity &amp;gt; 0.     &lt;br /&gt;- Los Order Items deben tener Precio/Price &amp;gt; 0.     &lt;br /&gt;- El Producto P debe tener Cantidad &amp;gt; Cantidad Mínima en cada Order Item.    &lt;br /&gt;- Producto P tiene un Precio, y cada Order Item que lo incluya no puede tener su Precio &amp;lt; Precio de Producto &amp;lt; 0.80.     &lt;br /&gt;- y así…&lt;/p&gt;  &lt;p&gt;De esta forma, las Ordenes pueden ser creadas y persistidas sin tener que cumplir con todas las reglas. La Order no es RECHAZADA por el sistema. Solamente que hay páginas para pedir (en cualquier momento) cuáles son los Findings, la lista de las reglas que no se cumplen.&lt;/p&gt;  &lt;p&gt;Las reglas de negocio pueden cambiar, y se pueden definir nuevas. No está definido en esta esta etapa del proyecto cómo conseguir esto: puede ser que simplemente agregando código, o escribiendo un DSL (Domain-Specific Languages) de reglas. Por ahora es un tema que no importa. En la aplicación real, el cliente final tiene programadores a disposición, así que la modificación del código sigue siendo una opción aceptable. Bien puede descubrir que 30 reglas bastan, y que no hace falta cambiarlas o se cambian cada 6 meses. Este es un tema a investigar: no siempre crear un DSL de reglas se justifica. En esta versión inicial, las reglas de negocio están en el código, compiladas. En una segunda versión, algunas reglas se aplicarán a algunas órdenes (por ejemplo, a las Orders que tienen clientes de Canadá). El Product Owner quiere tener: Findings por Order, Findings por Producto, Findings por Customer.&lt;/p&gt;  &lt;p&gt;En esta serie de post, quiero entonces explorar y mostrar una forma de armar lo pedido, USANDO TDD. Para simplificar el ejemplo, no habrá UI ni persistencia, solamente objetos del dominio, y su grafo de relaciones. Veremos cómo, usando TDD, las reglas y su forma de ejecución van emergiendo desde los casos de uso planteados. Usaré mi cuenta en GitHub para ir compartiendo el código. Será escrito, como la aplicación original, en C#.&lt;/p&gt;  &lt;p&gt;Nos leemos!&lt;/p&gt;  &lt;p&gt;Angel “Java” Lopez    &lt;br /&gt;&lt;a href="http://www.ajlopez.com"&gt;http://www.ajlopez.com&lt;/a&gt;     &lt;br /&gt;&lt;a href="http://twitter.com/ajlopez"&gt;http://twitter.com/ajlopez&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1813748" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/lopez/archive/tags/Desarrollo+de+Software/default.aspx">Desarrollo de Software</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/C+Sharp/default.aspx">C Sharp</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Desarrollo+Agil/default.aspx">Desarrollo Agil</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/TDD/default.aspx">TDD</category></item><item><title>TDD Paso a Paso (6) La semana del panadero</title><link>http://msmvps.com/blogs/lopez/archive/2012/05/25/tdd-paso-a-paso-6-la-semana-del-panadero.aspx</link><pubDate>Fri, 25 May 2012 22:36:09 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1810311</guid><dc:creator>lopez</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/lopez/rsscomments.aspx?PostID=1810311</wfw:commentRss><comments>http://msmvps.com/blogs/lopez/archive/2012/05/25/tdd-paso-a-paso-6-la-semana-del-panadero.aspx#comments</comments><description>&lt;p&gt;&lt;a href="http://msmvps.com/blogs/lopez/archive/2012/05/09/tdd-paso-a-paso-5-lunes-como-d-237-a-no-laborable.aspx"&gt;Anterior Post&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Sigamos mejorando la clase de calendario de días laborables. Quiero ahora plantear el caso:&lt;/p&gt;  &lt;p&gt;- El sábado y domingo se trabaja    &lt;br /&gt;- El lunes no se trabaja&lt;/p&gt;  &lt;p&gt;Acá en Argentina, es común que así sea la semana del panadero (aunque dado los tiempos que corren, muchos abren todos los días). Este es el test que me armé: configuro al calendario con sábado y domingo como días laborales, y lunes como no laborable. Luego se prueban esos tres días:&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;pre style="background-color:black;color:white;"&gt;&lt;span style="color:cyan;"&gt;[&lt;/span&gt;TestMethod&lt;span style="color:cyan;"&gt;]&lt;/span&gt;
&lt;span style="color:orange;"&gt;public&lt;/span&gt; &lt;span style="color:orange;"&gt;void&lt;/span&gt; SetWeekendAsWorkingDaysAndMondayAsANonWorkingDay&lt;span style="color:cyan;"&gt;()&lt;/span&gt;
&lt;span style="color:cyan;"&gt;{&lt;/span&gt;
	WorkingDaysCalendar calendar = &lt;span style="color:orange;"&gt;new&lt;/span&gt; WorkingDaysCalendar&lt;span style="color:cyan;"&gt;();&lt;/span&gt;

	calendar.AddDayOfWeekAsWorkingDay&lt;span style="color:cyan;"&gt;(&lt;/span&gt;DayOfWeek.Saturday&lt;span style="color:cyan;"&gt;);&lt;/span&gt;
	calendar.AddDayOfWeekAsWorkingDay&lt;span style="color:cyan;"&gt;(&lt;/span&gt;DayOfWeek.Sunday&lt;span style="color:cyan;"&gt;);&lt;/span&gt;
	calendar.AddDayOfWeekAsNonWorkingDay&lt;span style="color:cyan;"&gt;(&lt;/span&gt;DayOfWeek.Monday&lt;span style="color:cyan;"&gt;);&lt;/span&gt;

	DateTime saturday = &lt;span style="color:orange;"&gt;new&lt;/span&gt; DateTime&lt;span style="color:cyan;"&gt;(&lt;/span&gt;2012&lt;span style="color:cyan;"&gt;,&lt;/span&gt; 3&lt;span style="color:cyan;"&gt;,&lt;/span&gt; 10&lt;span style="color:cyan;"&gt;);&lt;/span&gt;
	Assert.AreEqual&lt;span style="color:cyan;"&gt;(&lt;/span&gt;saturday.DayOfWeek&lt;span style="color:cyan;"&gt;,&lt;/span&gt; DayOfWeek.Saturday&lt;span style="color:cyan;"&gt;);&lt;/span&gt;

	Assert.IsTrue&lt;span style="color:cyan;"&gt;(&lt;/span&gt;calendar.IsWorkingDay&lt;span style="color:cyan;"&gt;(&lt;/span&gt;saturday&lt;span style="color:cyan;"&gt;));&lt;/span&gt;
	Assert.IsTrue&lt;span style="color:cyan;"&gt;(&lt;/span&gt;calendar.IsWorkingDay&lt;span style="color:cyan;"&gt;(&lt;/span&gt;saturday.AddDays&lt;span style="color:cyan;"&gt;(&lt;/span&gt;1&lt;span style="color:cyan;"&gt;)));&lt;/span&gt;
	Assert.IsFalse&lt;span style="color:cyan;"&gt;(&lt;/span&gt;calendar.IsWorkingDay&lt;span style="color:cyan;"&gt;(&lt;/span&gt;saturday.AddDays&lt;span style="color:cyan;"&gt;(&lt;/span&gt;2&lt;span style="color:cyan;"&gt;)));&lt;/span&gt;
&lt;span style="color:cyan;"&gt;}&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;Al ejecutar este código, si tenemos la clase calendario del post anterior, da en rojo, porque no tengo contemplado más que un día especial por tipo: sólo un día laborable especial, o sólo un día no laborable especial. Pero al llegar a este test, puedo implementar mejor el algoritmo interno. Llegó la hora de tener una lista de días:&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;pre style="background-color:black;color:white;"&gt;&lt;span style="color:orange;"&gt;public&lt;/span&gt; &lt;span style="color:orange;"&gt;class&lt;/span&gt; WorkingDaysCalendar
&lt;span style="color:cyan;"&gt;{&lt;/span&gt;
	&lt;span style="color:orange;"&gt;private&lt;/span&gt; IList&lt;span style="color:cyan;"&gt;&amp;lt;&lt;/span&gt;DayOfWeek&lt;span style="color:cyan;"&gt;&amp;gt;&lt;/span&gt; nonWorkingDaysOfWeek = &lt;span style="color:orange;"&gt;new&lt;/span&gt; List&lt;span style="color:cyan;"&gt;&amp;lt;&lt;/span&gt;DayOfWeek&lt;span style="color:cyan;"&gt;&amp;gt;()&lt;/span&gt; &lt;span style="color:cyan;"&gt;{&lt;/span&gt; DayOfWeek.Saturday&lt;span style="color:cyan;"&gt;,&lt;/span&gt; DayOfWeek.Sunday &lt;span style="color:cyan;"&gt;};&lt;/span&gt;

	&lt;span style="color:orange;"&gt;public&lt;/span&gt; &lt;span style="color:orange;"&gt;bool&lt;/span&gt; IsWorkingDay&lt;span style="color:cyan;"&gt;(&lt;/span&gt;DateTime day&lt;span style="color:cyan;"&gt;)&lt;/span&gt;
	&lt;span style="color:cyan;"&gt;{&lt;/span&gt;
		&lt;span style="color:orange;"&gt;if&lt;/span&gt; &lt;span style="color:cyan;"&gt;(&lt;/span&gt;&lt;span style="color:orange;"&gt;this&lt;/span&gt;.nonWorkingDaysOfWeek.Contains&lt;span style="color:cyan;"&gt;(&lt;/span&gt;day.DayOfWeek&lt;span style="color:cyan;"&gt;))&lt;/span&gt;
			&lt;span style="color:orange;"&gt;return&lt;/span&gt; &lt;span style="color:orange;"&gt;false&lt;/span&gt;&lt;span style="color:cyan;"&gt;;&lt;/span&gt;

		&lt;span style="color:orange;"&gt;return&lt;/span&gt; &lt;span style="color:orange;"&gt;true&lt;/span&gt;&lt;span style="color:cyan;"&gt;;&lt;/span&gt;
	&lt;span style="color:cyan;"&gt;}&lt;/span&gt;

	&lt;span style="color:orange;"&gt;public&lt;/span&gt; &lt;span style="color:orange;"&gt;void&lt;/span&gt; AddDayOfWeekAsWorkingDay&lt;span style="color:cyan;"&gt;(&lt;/span&gt;DayOfWeek dayOfWeek&lt;span style="color:cyan;"&gt;)&lt;/span&gt;
	&lt;span style="color:cyan;"&gt;{&lt;/span&gt;
		&lt;span style="color:orange;"&gt;if&lt;/span&gt; &lt;span style="color:cyan;"&gt;(&lt;/span&gt;&lt;span style="color:orange;"&gt;this&lt;/span&gt;.nonWorkingDaysOfWeek.Contains&lt;span style="color:cyan;"&gt;(&lt;/span&gt;dayOfWeek&lt;span style="color:cyan;"&gt;))&lt;/span&gt;
			&lt;span style="color:orange;"&gt;this&lt;/span&gt;.nonWorkingDaysOfWeek.Remove&lt;span style="color:cyan;"&gt;(&lt;/span&gt;dayOfWeek&lt;span style="color:cyan;"&gt;);&lt;/span&gt;
	&lt;span style="color:cyan;"&gt;}&lt;/span&gt;

	&lt;span style="color:orange;"&gt;public&lt;/span&gt; &lt;span style="color:orange;"&gt;void&lt;/span&gt; AddDayOfWeekAsNonWorkingDay&lt;span style="color:cyan;"&gt;(&lt;/span&gt;DayOfWeek dayOfWeek&lt;span style="color:cyan;"&gt;)&lt;/span&gt;
	&lt;span style="color:cyan;"&gt;{&lt;/span&gt;
		&lt;span style="color:orange;"&gt;if&lt;/span&gt; &lt;span style="color:cyan;"&gt;(!&lt;/span&gt;&lt;span style="color:orange;"&gt;this&lt;/span&gt;.nonWorkingDaysOfWeek.Contains&lt;span style="color:cyan;"&gt;(&lt;/span&gt;dayOfWeek&lt;span style="color:cyan;"&gt;))&lt;/span&gt;
			&lt;span style="color:orange;"&gt;this&lt;/span&gt;.nonWorkingDaysOfWeek.Add&lt;span style="color:cyan;"&gt;(&lt;/span&gt;dayOfWeek&lt;span style="color:cyan;"&gt;);&lt;/span&gt;
	&lt;span style="color:cyan;"&gt;}&lt;/span&gt;
&lt;span style="color:cyan;"&gt;}&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;Agregué una lista interna de días no laborables, sin cambiar la interfaz pública de la clase. ¿Pero habré cumplido con lo pedido con el test? Ejecuto, y da verde. ¿Pero no habré roto algo? Ejecuto el resto de los tests, también estan en verde. En cualquier caso, seguiría trabajando hasta que todo quede en verde. Luego, vendría refactorización. Por ejemplo, no estoy conforme conque los métodos comienzen con Add. No se agregan días, sólo se informa de su carácter de laborable o no laborable. Pero bueno, eso será para otro post.&lt;/p&gt;

&lt;p&gt;Próximos temas: refactorizar, soporte de días feriados, feriados puentes, etc…&lt;/p&gt;

&lt;p&gt;Nos leemos!&lt;/p&gt;

&lt;p&gt;Angel “Java” Lopez 
  &lt;br /&gt;&lt;a href="http://www.ajlopez.com"&gt;http://www.ajlopez.com&lt;/a&gt; 

  &lt;br /&gt;&lt;a href="http://twitter.com/ajlopez"&gt;http://twitter.com/ajlopez&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1810311" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/lopez/archive/tags/Desarrollo+de+Software/default.aspx">Desarrollo de Software</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/C+Sharp/default.aspx">C Sharp</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Desarrollo+Agil/default.aspx">Desarrollo Agil</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/TDD/default.aspx">TDD</category></item><item><title>TDD Paso a Paso (5) Lunes como día no laborable</title><link>http://msmvps.com/blogs/lopez/archive/2012/05/09/tdd-paso-a-paso-5-lunes-como-d-237-a-no-laborable.aspx</link><pubDate>Wed, 09 May 2012 09:11:00 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1809647</guid><dc:creator>lopez</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/lopez/rsscomments.aspx?PostID=1809647</wfw:commentRss><comments>http://msmvps.com/blogs/lopez/archive/2012/05/09/tdd-paso-a-paso-5-lunes-como-d-237-a-no-laborable.aspx#comments</comments><description>&lt;p&gt;&lt;a href="http://msmvps.com/blogs/lopez/archive/2012/04/24/tdd-paso-a-paso-4-otro-tipo-de-semana.aspx"&gt;Anterior post&lt;/a&gt;&amp;nbsp;&lt;br /&gt;&lt;a href="http://msmvps.com/blogs/lopez/archive/2012/05/25/tdd-paso-a-paso-6-la-semana-del-panadero.aspx"&gt;Siguiente post&lt;/a&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Veamos ahora otro test, que como los anteriores, nos va a obligar a implementar mejor nuestro software en construcci&amp;oacute;n.&lt;/p&gt;
&lt;p&gt;Queremos configurar, sobre la semana b&amp;aacute;sica, cu&amp;aacute;les son los d&amp;iacute;as laborables y cu&amp;aacute;les son no laborables. En el anterior post, agregu&amp;eacute; la capacidad de especificar un nuevo d&amp;iacute;a laboral. Ahora, quiero poder especificar que los lunes son no laborables. Este es el test que escrib&amp;iacute;:&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre style="background-color:black;color:white;"&gt;&lt;span style="color:cyan;"&gt;[&lt;/span&gt;TestMethod&lt;span style="color:cyan;"&gt;]&lt;/span&gt;
&lt;span style="color:orange;"&gt;public&lt;/span&gt; &lt;span style="color:orange;"&gt;void&lt;/span&gt; SetMondayAsANonWorkingDay&lt;span style="color:cyan;"&gt;()&lt;/span&gt;
&lt;span style="color:cyan;"&gt;{&lt;/span&gt;
	WorkingDaysCalendar calendar = &lt;span style="color:orange;"&gt;new&lt;/span&gt; WorkingDaysCalendar&lt;span style="color:cyan;"&gt;();&lt;/span&gt;

	calendar.AddDayOfWeekAsNonWorkingDay&lt;span style="color:cyan;"&gt;(&lt;/span&gt;DayOfWeek.Monday&lt;span style="color:cyan;"&gt;);&lt;/span&gt;

	DateTime monday = &lt;span style="color:orange;"&gt;new&lt;/span&gt; DateTime&lt;span style="color:cyan;"&gt;(&lt;/span&gt;2012&lt;span style="color:cyan;"&gt;,&lt;/span&gt; 3&lt;span style="color:cyan;"&gt;,&lt;/span&gt; 12&lt;span style="color:cyan;"&gt;);&lt;/span&gt;
	Assert.AreEqual&lt;span style="color:cyan;"&gt;(&lt;/span&gt;monday.DayOfWeek&lt;span style="color:cyan;"&gt;,&lt;/span&gt; DayOfWeek.Monday&lt;span style="color:cyan;"&gt;);&lt;/span&gt;

	Assert.IsFalse&lt;span style="color:cyan;"&gt;(&lt;/span&gt;calendar.IsWorkingDay&lt;span style="color:cyan;"&gt;(&lt;/span&gt;monday&lt;span style="color:cyan;"&gt;));&lt;/span&gt;
&lt;span style="color:cyan;"&gt;}&lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Primero, no compila. Porque usa el m&amp;eacute;todo no existente, &lt;strong&gt;AddDayOfWeekAsNonWorkingDay &lt;/strong&gt;. Lo creo, lanzando una excepci&amp;oacute;n de no implementado, ejecuto el test, y da rojo. Pongamos el m&amp;iacute;nimo c&amp;oacute;digo que hace que esto funcione, con alg&amp;uacute;n refactor de nombre de par&amp;aacute;metros.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre style="background-color:black;color:white;"&gt;&lt;span style="color:orange;"&gt;private&lt;/span&gt; DayOfWeek&lt;span style="color:cyan;"&gt;?&lt;/span&gt; workingDay&lt;span style="color:cyan;"&gt;;&lt;/span&gt;
&lt;span style="color:orange;"&gt;private&lt;/span&gt; DayOfWeek&lt;span style="color:cyan;"&gt;?&lt;/span&gt; nonWorkingDay&lt;span style="color:cyan;"&gt;;&lt;/span&gt;

&lt;span style="color:orange;"&gt;public&lt;/span&gt; &lt;span style="color:orange;"&gt;bool&lt;/span&gt; IsWorkingDay&lt;span style="color:cyan;"&gt;(&lt;/span&gt;DateTime day&lt;span style="color:cyan;"&gt;)&lt;/span&gt;
&lt;span style="color:cyan;"&gt;{&lt;/span&gt;
	&lt;span style="color:orange;"&gt;if&lt;/span&gt; &lt;span style="color:cyan;"&gt;(&lt;/span&gt;&lt;span style="color:orange;"&gt;this&lt;/span&gt;.workingDay.HasValue &lt;span style="color:cyan;"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span style="color:orange;"&gt;this&lt;/span&gt;.workingDay.Value == day.DayOfWeek&lt;span style="color:cyan;"&gt;)&lt;/span&gt;
		&lt;span style="color:orange;"&gt;return&lt;/span&gt; &lt;span style="color:orange;"&gt;true&lt;/span&gt;&lt;span style="color:cyan;"&gt;;&lt;/span&gt;

	&lt;span style="color:orange;"&gt;if&lt;/span&gt; &lt;span style="color:cyan;"&gt;(&lt;/span&gt;&lt;span style="color:orange;"&gt;this&lt;/span&gt;.nonWorkingDay.HasValue &lt;span style="color:cyan;"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span style="color:orange;"&gt;this&lt;/span&gt;.nonWorkingDay.Value == day.DayOfWeek&lt;span style="color:cyan;"&gt;)&lt;/span&gt;
		&lt;span style="color:orange;"&gt;return&lt;/span&gt; &lt;span style="color:orange;"&gt;false&lt;/span&gt;&lt;span style="color:cyan;"&gt;;&lt;/span&gt;

	&lt;span style="color:orange;"&gt;if&lt;/span&gt; &lt;span style="color:cyan;"&gt;(&lt;/span&gt;day.DayOfWeek == DayOfWeek.Sunday &lt;span style="color:cyan;"&gt;||&lt;/span&gt; day.DayOfWeek == DayOfWeek.Saturday&lt;span style="color:cyan;"&gt;)&lt;/span&gt;
		&lt;span style="color:orange;"&gt;return&lt;/span&gt; &lt;span style="color:orange;"&gt;false&lt;/span&gt;&lt;span style="color:cyan;"&gt;;&lt;/span&gt;

	&lt;span style="color:orange;"&gt;return&lt;/span&gt; &lt;span style="color:orange;"&gt;true&lt;/span&gt;&lt;span style="color:cyan;"&gt;;&lt;/span&gt;
&lt;span style="color:cyan;"&gt;}&lt;/span&gt;

&lt;span style="color:orange;"&gt;public&lt;/span&gt; &lt;span style="color:orange;"&gt;void&lt;/span&gt; AddDayOfWeekAsWorkingDay&lt;span style="color:cyan;"&gt;(&lt;/span&gt;DayOfWeek dayOfWeek&lt;span style="color:cyan;"&gt;)&lt;/span&gt;
&lt;span style="color:cyan;"&gt;{&lt;/span&gt;
	&lt;span style="color:orange;"&gt;this&lt;/span&gt;.workingDay = dayOfWeek&lt;span style="color:cyan;"&gt;;&lt;/span&gt;
&lt;span style="color:cyan;"&gt;}&lt;/span&gt;

&lt;span style="color:orange;"&gt;public&lt;/span&gt; &lt;span style="color:orange;"&gt;void&lt;/span&gt; AddDayOfWeekAsNonWorkingDay&lt;span style="color:cyan;"&gt;(&lt;/span&gt;DayOfWeek dayOfWeek&lt;span style="color:cyan;"&gt;)&lt;/span&gt;
&lt;span style="color:cyan;"&gt;{&lt;/span&gt;
	&lt;span style="color:orange;"&gt;this&lt;/span&gt;.nonWorkingDay = dayOfWeek&lt;span style="color:cyan;"&gt;;&lt;/span&gt;
&lt;span style="color:cyan;"&gt;}&lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Ahora el test est&amp;aacute; en verde. Agregu&amp;eacute; una nueva variable interna &amp;ldquo;nullable&amp;rdquo; &lt;strong&gt;nonWorkingDay&lt;/strong&gt;. Ciertamente que la clase escrita s&amp;oacute;lo soporta un s&amp;oacute;lo d&amp;iacute;a laborable configurable y un s&amp;oacute;lo d&amp;iacute;a no laborable configurable. Pero los tests que escribimos pasan. Voy por &amp;ldquo;baby steps&amp;rdquo;, de a &amp;ldquo;pasos de beb&amp;eacute;&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;Pero van viendo la aplicaci&amp;oacute;n de TDD: en cada test, hay una nueva especificaci&amp;oacute;n de c&amp;oacute;mo queremos que act&amp;uacute;e nuestro software en construcci&amp;oacute;n. Y s&amp;oacute;lo implementamos lo que necesitamos para pasar el test. Poco a poco, va emergiendo la implementaci&amp;oacute;n interna, donde ponemos lo que conocemos como programadores. Pero sin caer en la tentanci&amp;oacute;n de &amp;ldquo;Ah! ac&amp;aacute; pongo esto que lo voy a necesitar&amp;rdquo;. Si el test no lo necesita, nosotros tampoco :-)&lt;/p&gt;
&lt;p&gt;Nos leemos!&lt;/p&gt;
&lt;p&gt;Angel &amp;ldquo;Java&amp;rdquo; Lopez 
  &lt;br /&gt;&lt;a href="http://www.ajlopez.com"&gt;http://www.ajlopez.com&lt;/a&gt; 
  &lt;br /&gt;&lt;a href="http://twitter.com/ajlopez"&gt;http://twitter.com/ajlopez&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1809647" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/lopez/archive/tags/Desarrollo+de+Software/default.aspx">Desarrollo de Software</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/C+Sharp/default.aspx">C Sharp</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Desarrollo+Agil/default.aspx">Desarrollo Agil</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/TDD/default.aspx">TDD</category></item><item><title>TDD Paso a Paso (4) Otro tipo de Semana</title><link>http://msmvps.com/blogs/lopez/archive/2012/04/24/tdd-paso-a-paso-4-otro-tipo-de-semana.aspx</link><pubDate>Tue, 24 Apr 2012 10:05:00 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1809150</guid><dc:creator>lopez</dc:creator><slash:comments>2</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/lopez/rsscomments.aspx?PostID=1809150</wfw:commentRss><comments>http://msmvps.com/blogs/lopez/archive/2012/04/24/tdd-paso-a-paso-4-otro-tipo-de-semana.aspx#comments</comments><description>&lt;p&gt;&lt;a href="http://msmvps.com/blogs/lopez/archive/2012/04/18/tdd-paso-a-paso-3-domingo-y-semana-t-237-pica.aspx"&gt;Anterior Post&lt;/a&gt;&amp;nbsp;&lt;br /&gt;&lt;a href="http://msmvps.com/blogs/lopez/archive/2012/05/09/tdd-paso-a-paso-5-lunes-como-d-237-a-no-laborable.aspx"&gt;Siguiente Post&lt;/a&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Ahora veamos de tratar uno de los requerimientos: que los d&amp;iacute;as laborables/no laborables sean configurables, ya sea por feriados puntuales, feriados que se repiten a&amp;ntilde;o a a&amp;ntilde;o, o porque la propia semana tenga otro reparto de d&amp;iacute;as laborables.&lt;/p&gt;
&lt;p&gt;El primero que se me ocurre es contemplar que el s&amp;aacute;bado sea d&amp;iacute;a laboral. Escribo el test:&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre style="background-color:black;color:white;"&gt;&lt;span style="color:cyan;"&gt;[&lt;/span&gt;TestMethod&lt;span style="color:cyan;"&gt;]&lt;/span&gt;
&lt;span style="color:orange;"&gt;public&lt;/span&gt; &lt;span style="color:orange;"&gt;void&lt;/span&gt; SetSaturdayAsAWorkingDay&lt;span style="color:cyan;"&gt;()&lt;/span&gt;
&lt;span style="color:cyan;"&gt;{&lt;/span&gt;
	WorkingDaysCalendar calendar = &lt;span style="color:orange;"&gt;new&lt;/span&gt; WorkingDaysCalendar&lt;span style="color:cyan;"&gt;();&lt;/span&gt;

	calendar.AddDayOfWeekAsWorkingDay&lt;span style="color:cyan;"&gt;(&lt;/span&gt;DayOfWeek.Saturday&lt;span style="color:cyan;"&gt;);&lt;/span&gt;

	DateTime saturday = &lt;span style="color:orange;"&gt;new&lt;/span&gt; DateTime&lt;span style="color:cyan;"&gt;(&lt;/span&gt;2012&lt;span style="color:cyan;"&gt;,&lt;/span&gt; 3&lt;span style="color:cyan;"&gt;,&lt;/span&gt; 10&lt;span style="color:cyan;"&gt;);&lt;/span&gt;
	Assert.AreEqual&lt;span style="color:cyan;"&gt;(&lt;/span&gt;saturday.DayOfWeek&lt;span style="color:cyan;"&gt;,&lt;/span&gt; DayOfWeek.Saturday&lt;span style="color:cyan;"&gt;);&lt;/span&gt;        

	Assert.IsTrue&lt;span style="color:cyan;"&gt;(&lt;/span&gt;calendar.IsWorkingDay&lt;span style="color:cyan;"&gt;(&lt;/span&gt;saturday&lt;span style="color:cyan;"&gt;));&lt;/span&gt;
&lt;span style="color:cyan;"&gt;}&lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Al ejecutarlo, da rojo, porque el c&amp;oacute;digo que tengo hasta ahora pone a los s&amp;aacute;bados como d&amp;iacute;as no laborables. Siguiendo la idea de poner el m&amp;iacute;nimo c&amp;oacute;digo necesario para pasar el test, y que sigan dando verde los anteriores, &amp;eacute;ste es el c&amp;oacute;digo que agregu&amp;eacute; (y luego refactoric&amp;eacute; un poco):&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre style="background-color:black;color:white;"&gt;&lt;span style="color:orange;"&gt;private&lt;/span&gt; DayOfWeek&lt;span style="color:cyan;"&gt;?&lt;/span&gt; workingDay&lt;span style="color:cyan;"&gt;;&lt;/span&gt;

&lt;span style="color:orange;"&gt;public&lt;/span&gt; &lt;span style="color:orange;"&gt;bool&lt;/span&gt; IsWorkingDay&lt;span style="color:cyan;"&gt;(&lt;/span&gt;DateTime day&lt;span style="color:cyan;"&gt;)&lt;/span&gt;
&lt;span style="color:cyan;"&gt;{&lt;/span&gt;
	&lt;span style="color:orange;"&gt;if&lt;/span&gt; &lt;span style="color:cyan;"&gt;(&lt;/span&gt;&lt;span style="color:orange;"&gt;this&lt;/span&gt;.workingDay.HasValue &lt;span style="color:cyan;"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span style="color:orange;"&gt;this&lt;/span&gt;.workingDay.Value == day.DayOfWeek&lt;span style="color:cyan;"&gt;)&lt;/span&gt;
		&lt;span style="color:orange;"&gt;return&lt;/span&gt; &lt;span style="color:orange;"&gt;true&lt;/span&gt;&lt;span style="color:cyan;"&gt;;&lt;/span&gt;

	&lt;span style="color:orange;"&gt;if&lt;/span&gt; &lt;span style="color:cyan;"&gt;(&lt;/span&gt;day.DayOfWeek == DayOfWeek.Sunday &lt;span style="color:cyan;"&gt;||&lt;/span&gt; day.DayOfWeek == DayOfWeek.Saturday&lt;span style="color:cyan;"&gt;)&lt;/span&gt;
		&lt;span style="color:orange;"&gt;return&lt;/span&gt; &lt;span style="color:orange;"&gt;false&lt;/span&gt;&lt;span style="color:cyan;"&gt;;&lt;/span&gt;

	&lt;span style="color:orange;"&gt;return&lt;/span&gt; &lt;span style="color:orange;"&gt;true&lt;/span&gt;&lt;span style="color:cyan;"&gt;;&lt;/span&gt;
&lt;span style="color:cyan;"&gt;}&lt;/span&gt;

&lt;span style="color:orange;"&gt;public&lt;/span&gt; &lt;span style="color:orange;"&gt;void&lt;/span&gt; AddDayOfWeekAsWorkingDay&lt;span style="color:cyan;"&gt;(&lt;/span&gt;DayOfWeek dayOfWeek&lt;span style="color:cyan;"&gt;)&lt;/span&gt;
&lt;span style="color:cyan;"&gt;{&lt;/span&gt;
	&lt;span style="color:orange;"&gt;this&lt;/span&gt;.workingDay = dayOfWeek&lt;span style="color:cyan;"&gt;;&lt;/span&gt;
&lt;span style="color:cyan;"&gt;}&lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Con esto, el test da en verde. Ejecuto toda la bater&amp;iacute;a de test y sigue dando verde.&lt;/p&gt;
&lt;p&gt;Noten que la variable adicional es &amp;ldquo;nulleable&amp;rdquo;. Podr&amp;iacute;a haber puesto un arreglo, una lista de d&amp;iacute;as laborables o algo as&amp;iacute;. PERO NINGUN TEST ME LO PIDIO. Es decir, no hay caso de uso del c&amp;oacute;digo que estamos desarrollando que necesite esa flexibilidad. Seguramente en los pr&amp;oacute;ximos test tendr&amp;eacute; que agregarlo. Pero no cruzar el puente ANTES de llegar al puente. &lt;/p&gt;
&lt;p&gt;Nos leemos!&lt;/p&gt;
&lt;p&gt;Angel &amp;ldquo;Java&amp;rdquo; Lopez 
  &lt;br /&gt;&lt;a href="http://www.ajlopez.com"&gt;http://www.ajlopez.com&lt;/a&gt; 
  &lt;br /&gt;&lt;a href="http://twitter.com/ajlopez"&gt;http://twitter.com/ajlopez&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1809150" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/lopez/archive/tags/Desarrollo+de+Software/default.aspx">Desarrollo de Software</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/C+Sharp/default.aspx">C Sharp</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Desarrollo+Agil/default.aspx">Desarrollo Agil</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/TDD/default.aspx">TDD</category></item><item><title>TDD Paso a Paso (3) Domingo y Semana Típica</title><link>http://msmvps.com/blogs/lopez/archive/2012/04/18/tdd-paso-a-paso-3-domingo-y-semana-t-237-pica.aspx</link><pubDate>Wed, 18 Apr 2012 14:25:00 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1808977</guid><dc:creator>lopez</dc:creator><slash:comments>2</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/lopez/rsscomments.aspx?PostID=1808977</wfw:commentRss><comments>http://msmvps.com/blogs/lopez/archive/2012/04/18/tdd-paso-a-paso-3-domingo-y-semana-t-237-pica.aspx#comments</comments><description>&lt;p&gt;&lt;a href="http://msmvps.com/blogs/lopez/archive/2012/03/20/tdd-paso-a-paso-2-d-237-as-no-laborables.aspx"&gt;Anterior Post&lt;/a&gt;&amp;nbsp;&lt;br /&gt;&lt;a href="http://msmvps.com/blogs/lopez/archive/2012/04/24/tdd-paso-a-paso-4-otro-tipo-de-semana.aspx"&gt;Siguiente Post&lt;/a&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Sigo con la descripci&amp;oacute;n de los tests que fui escribiendo para este problema. Ahora que ya tengo un test para ver si s&amp;aacute;bado es d&amp;iacute;a laborable, agregu&amp;eacute; un test para ver si cada domingo es d&amp;iacute;a laborable:&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre style="color:white;background-color:black;"&gt;&lt;span style="color:cyan;"&gt;[&lt;/span&gt;TestMethod&lt;span style="color:cyan;"&gt;]&lt;/span&gt;
&lt;span style="color:orange;"&gt;public&lt;/span&gt; &lt;span style="color:orange;"&gt;void&lt;/span&gt; TypicalSaturdayIsANonWorkingDay&lt;span style="color:cyan;"&gt;()&lt;/span&gt;
&lt;span style="color:cyan;"&gt;{&lt;/span&gt;
    WorkingDaysCalendar calendar = &lt;span style="color:orange;"&gt;new&lt;/span&gt; WorkingDaysCalendar&lt;span style="color:cyan;"&gt;();&lt;/span&gt;

    DateTime saturday = &lt;span style="color:orange;"&gt;new&lt;/span&gt; DateTime&lt;span style="color:cyan;"&gt;(&lt;/span&gt;2012&lt;span style="color:cyan;"&gt;,&lt;/span&gt; 3&lt;span style="color:cyan;"&gt;,&lt;/span&gt; 10&lt;span style="color:cyan;"&gt;);&lt;/span&gt;
    Assert.AreEqual&lt;span style="color:cyan;"&gt;(&lt;/span&gt;saturday.DayOfWeek&lt;span style="color:cyan;"&gt;,&lt;/span&gt; DayOfWeek.Saturday&lt;span style="color:cyan;"&gt;);&lt;/span&gt;

    Assert.IsFalse&lt;span style="color:cyan;"&gt;(&lt;/span&gt;calendar.IsWorkingDay&lt;span style="color:cyan;"&gt;(&lt;/span&gt;saturday&lt;span style="color:cyan;"&gt;));&lt;/span&gt;
&lt;span style="color:cyan;"&gt;}&lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Inicialmente, el test qued&amp;oacute; en rojo. El problema es que el c&amp;oacute;digo que llevo escrito solamente reconoce como no laborable a los S&amp;aacute;bados. Modifiqu&amp;eacute; la funci&amp;oacute;n que determina eso a:&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre style="color:white;background-color:black;"&gt;&lt;span style="color:orange;"&gt;public&lt;/span&gt; &lt;span style="color:orange;"&gt;bool&lt;/span&gt; IsWorkingDay&lt;span style="color:cyan;"&gt;(&lt;/span&gt;DateTime day&lt;span style="color:cyan;"&gt;)&lt;/span&gt;
&lt;span style="color:cyan;"&gt;{&lt;/span&gt;
    &lt;span style="color:orange;"&gt;if&lt;/span&gt; &lt;span style="color:cyan;"&gt;(&lt;/span&gt;day.DayOfWeek == DayOfWeek.Sunday &lt;span style="color:cyan;"&gt;||&lt;/span&gt; day.DayOfWeek == DayOfWeek.Saturday&lt;span style="color:cyan;"&gt;)&lt;/span&gt;
        &lt;span style="color:orange;"&gt;return&lt;/span&gt; &lt;span style="color:orange;"&gt;false&lt;/span&gt;&lt;span style="color:cyan;"&gt;;&lt;/span&gt;

    &lt;span style="color:orange;"&gt;return&lt;/span&gt; &lt;span style="color:orange;"&gt;true&lt;/span&gt;&lt;span style="color:cyan;"&gt;;&lt;/span&gt;
&lt;span style="color:cyan;"&gt;}&lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Y el test pas&amp;oacute;. Vean que aparecen dos constantes en el c&amp;oacute;digo interno. No me preocupa por ahora, porque refleja lo que tengo hasta ahora en los tests. En alg&amp;uacute;n momento, tendr&amp;eacute; que contemplar (como ped&amp;iacute;a el problema original) que hay otras semanas t&amp;iacute;picas: por ejemplo, para un peluquero el s&amp;aacute;bado puede ser d&amp;iacute;a laborable, y para una panader&amp;iacute;a el domingo es laborable pero el lunes no.&lt;/p&gt;
&lt;p&gt;Llegado a este punto, escrib&amp;iacute; un test que sale un poco de TDD &amp;ldquo;estricto&amp;rdquo;. Es un tests que me di&amp;oacute; en verde desde el comienzo. Es el que prueba los d&amp;iacute;as de una semana t&amp;iacute;pica:&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre style="color:white;background-color:black;"&gt;&lt;span style="color:cyan;"&gt;[&lt;/span&gt;TestMethod&lt;span style="color:cyan;"&gt;]&lt;/span&gt;
&lt;span style="color:orange;"&gt;public&lt;/span&gt; &lt;span style="color:orange;"&gt;void&lt;/span&gt; TypicalWeek&lt;span style="color:cyan;"&gt;()&lt;/span&gt;
&lt;span style="color:cyan;"&gt;{&lt;/span&gt;
    WorkingDaysCalendar calendar = &lt;span style="color:orange;"&gt;new&lt;/span&gt; WorkingDaysCalendar&lt;span style="color:cyan;"&gt;();&lt;/span&gt;

    DateTime monday = &lt;span style="color:orange;"&gt;new&lt;/span&gt; DateTime&lt;span style="color:cyan;"&gt;(&lt;/span&gt;2012&lt;span style="color:cyan;"&gt;,&lt;/span&gt; 3&lt;span style="color:cyan;"&gt;,&lt;/span&gt; 12&lt;span style="color:cyan;"&gt;);&lt;/span&gt;
    Assert.AreEqual&lt;span style="color:cyan;"&gt;(&lt;/span&gt;monday.DayOfWeek&lt;span style="color:cyan;"&gt;,&lt;/span&gt; DayOfWeek.Monday&lt;span style="color:cyan;"&gt;);&lt;/span&gt;

    Assert.IsTrue&lt;span style="color:cyan;"&gt;(&lt;/span&gt;calendar.IsWorkingDay&lt;span style="color:cyan;"&gt;(&lt;/span&gt;monday&lt;span style="color:cyan;"&gt;));&lt;/span&gt;
    Assert.IsTrue&lt;span style="color:cyan;"&gt;(&lt;/span&gt;calendar.IsWorkingDay&lt;span style="color:cyan;"&gt;(&lt;/span&gt;monday.AddDays&lt;span style="color:cyan;"&gt;(&lt;/span&gt;1&lt;span style="color:cyan;"&gt;)));&lt;/span&gt;
    Assert.IsTrue&lt;span style="color:cyan;"&gt;(&lt;/span&gt;calendar.IsWorkingDay&lt;span style="color:cyan;"&gt;(&lt;/span&gt;monday.AddDays&lt;span style="color:cyan;"&gt;(&lt;/span&gt;2&lt;span style="color:cyan;"&gt;)));&lt;/span&gt;
    Assert.IsTrue&lt;span style="color:cyan;"&gt;(&lt;/span&gt;calendar.IsWorkingDay&lt;span style="color:cyan;"&gt;(&lt;/span&gt;monday.AddDays&lt;span style="color:cyan;"&gt;(&lt;/span&gt;3&lt;span style="color:cyan;"&gt;)));&lt;/span&gt;
    Assert.IsTrue&lt;span style="color:cyan;"&gt;(&lt;/span&gt;calendar.IsWorkingDay&lt;span style="color:cyan;"&gt;(&lt;/span&gt;monday.AddDays&lt;span style="color:cyan;"&gt;(&lt;/span&gt;4&lt;span style="color:cyan;"&gt;)));&lt;/span&gt;
    Assert.IsFalse&lt;span style="color:cyan;"&gt;(&lt;/span&gt;calendar.IsWorkingDay&lt;span style="color:cyan;"&gt;(&lt;/span&gt;monday.AddDays&lt;span style="color:cyan;"&gt;(&lt;/span&gt;5&lt;span style="color:cyan;"&gt;)));&lt;/span&gt;
    Assert.IsFalse&lt;span style="color:cyan;"&gt;(&lt;/span&gt;calendar.IsWorkingDay&lt;span style="color:cyan;"&gt;(&lt;/span&gt;monday.AddDays&lt;span style="color:cyan;"&gt;(&lt;/span&gt;6&lt;span style="color:cyan;"&gt;)));&lt;/span&gt;
&lt;span style="color:cyan;"&gt;}&lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Me gusta tener ese test, para que alguien pueda ver, en un solo lugar, lo que considero para esta API como semana t&amp;iacute;pica. Otros &amp;ldquo;approach&amp;rdquo;: no escribir este test, o escribirlo y eliminar los anteriores. Pero yo me &amp;ldquo;encari&amp;ntilde;o&amp;rdquo; :-) con los tests, y es raro que los elimine. Tambi&amp;eacute;n dan una idea de la historia, de la evoluci&amp;oacute;n de la API. As&amp;iacute; que agregu&amp;eacute; este test de arriba, nacido pr&amp;iacute;stinamente en verde, y dej&amp;eacute; los anteriores.&lt;/p&gt;
&lt;p&gt;Pr&amp;oacute;ximos posts: c&amp;oacute;mo admitir otro tipo de semanas &amp;ldquo;t&amp;iacute;picas&amp;rdquo;, feriados, etc.&lt;/p&gt;
&lt;p&gt;Como siempre, toda esta serie de cambios qued&amp;oacute; reflejado en el log del proyecto. Ver &lt;a href="https://github.com/ajlopez/TddOnTheRocks"&gt;https://github.com/ajlopez/TddOnTheRocks&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Nos leemos!&lt;/p&gt;
&lt;p&gt;Angel &amp;ldquo;Java&amp;rdquo; Lopez 
  &lt;br /&gt;&lt;a href="http://www.ajlopez.com"&gt;http://www.ajlopez.com&lt;/a&gt; 
  &lt;br /&gt;&lt;a href="http://twitter.com/ajlopez"&gt;http://twitter.com/ajlopez&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1808977" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/lopez/archive/tags/Desarrollo+de+Software/default.aspx">Desarrollo de Software</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/C+Sharp/default.aspx">C Sharp</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Desarrollo+Agil/default.aspx">Desarrollo Agil</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/TDD/default.aspx">TDD</category></item><item><title>TDD Paso a Paso (2) Días No Laborables</title><link>http://msmvps.com/blogs/lopez/archive/2012/03/20/tdd-paso-a-paso-2-d-237-as-no-laborables.aspx</link><pubDate>Tue, 20 Mar 2012 16:20:00 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1807651</guid><dc:creator>lopez</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/lopez/rsscomments.aspx?PostID=1807651</wfw:commentRss><comments>http://msmvps.com/blogs/lopez/archive/2012/03/20/tdd-paso-a-paso-2-d-237-as-no-laborables.aspx#comments</comments><description>&lt;p&gt;&lt;a target="_blank" href="http://msmvps.com/blogs/lopez/archive/2012/03/18/tdd-paso-a-paso-1-primer-test.aspx"&gt;Anterior Post&lt;/a&gt;&amp;nbsp;&lt;br /&gt;&lt;a href="http://msmvps.com/blogs/lopez/archive/2012/04/18/tdd-paso-a-paso-3-domingo-y-semana-t-237-pica.aspx"&gt;Siguiente Post&lt;/a&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;En el primer post de esta serie, expliqu&amp;eacute; el problema y el primer test, que va quedando en &lt;a target="_blank" href="https://github.com/ajlopez/TddOnTheRocks/tree/master/MySrc"&gt;el repositorio del proyecto&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Veamos ahora el segundo test. Me decid&amp;iacute; por probar que un domingo t&amp;iacute;pico es d&amp;iacute;a no laborable, que implica un cambio con respecto al anterior test. En el primer test que&amp;nbsp; escribimos, pregunt&amp;aacute;bamos por un caso positivo de d&amp;iacute;a laborable. Ahora cambiamos a probar un caso negativo.&lt;/p&gt;
&lt;p&gt;El nuevo test:&lt;/p&gt;
&lt;pre style="color:white;background-color:black;"&gt;&lt;span style="color:cyan;"&gt;[&lt;/span&gt;TestMethod&lt;span style="color:cyan;"&gt;]&lt;/span&gt;
&lt;span style="color:orange;"&gt;public&lt;/span&gt; &lt;span style="color:orange;"&gt;void&lt;/span&gt; TypicalSundayIsANonWorkingDay&lt;span style="color:cyan;"&gt;()&lt;/span&gt;
&lt;span style="color:cyan;"&gt;{&lt;/span&gt;
    WorkingDaysCalendar calendar = &lt;span style="color:orange;"&gt;new&lt;/span&gt; WorkingDaysCalendar&lt;span style="color:cyan;"&gt;();&lt;/span&gt;

    DateTime sunday = &lt;span style="color:orange;"&gt;new&lt;/span&gt; DateTime&lt;span style="color:cyan;"&gt;(&lt;/span&gt;2012&lt;span style="color:cyan;"&gt;,&lt;/span&gt; 3&lt;span style="color:cyan;"&gt;,&lt;/span&gt; 11&lt;span style="color:cyan;"&gt;);&lt;/span&gt;
    Assert.AreEqual&lt;span style="color:cyan;"&gt;(&lt;/span&gt;sunday.DayOfWeek&lt;span style="color:cyan;"&gt;,&lt;/span&gt; DayOfWeek.Sunday&lt;span style="color:cyan;"&gt;);&lt;/span&gt;

    Assert.IsFalse&lt;span style="color:cyan;"&gt;(&lt;/span&gt;calendar.IsWorkingDay&lt;span style="color:cyan;"&gt;(&lt;/span&gt;sunday&lt;span style="color:cyan;"&gt;));&lt;/span&gt;
&lt;span style="color:cyan;"&gt;}&lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;Al ejecutarlo, da rojo. El problema es que la actual implementaci&amp;oacute;n retorna que todos los d&amp;iacute;as de la semana son laborables. El m&amp;iacute;nimo cambio en el c&amp;oacute;digo que hace que todo funcione es:&lt;/p&gt;
&lt;pre style="color:white;background-color:black;"&gt;&lt;span style="color:orange;"&gt;public&lt;/span&gt; &lt;span style="color:orange;"&gt;bool&lt;/span&gt; IsWorkingDay&lt;span style="color:cyan;"&gt;(&lt;/span&gt;DateTime day&lt;span style="color:cyan;"&gt;)&lt;/span&gt;
&lt;span style="color:cyan;"&gt;{&lt;/span&gt;
    &lt;span style="color:orange;"&gt;if&lt;/span&gt; &lt;span style="color:cyan;"&gt;(&lt;/span&gt;day.DayOfWeek == DayOfWeek.Sunday&lt;span style="color:cyan;"&gt;)&lt;/span&gt;
        &lt;span style="color:orange;"&gt;return&lt;/span&gt; &lt;span style="color:orange;"&gt;false&lt;/span&gt;&lt;span style="color:cyan;"&gt;;&lt;/span&gt;

    &lt;span style="color:orange;"&gt;return&lt;/span&gt; &lt;span style="color:orange;"&gt;true&lt;/span&gt;&lt;span style="color:cyan;"&gt;;&lt;/span&gt;
&lt;span style="color:cyan;"&gt;}&lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;Ahora s&amp;iacute; funciona, habiendo agregado el if del comienzo. El pr&amp;oacute;ximo test que se me ocurre es probar que un s&amp;aacute;bado t&amp;iacute;pico (m&amp;aacute;s adelante veremos otros calendarios, por ejemplo, el de un peluquero, que ac&amp;aacute; en Argentina tienen como d&amp;iacute;a no laborable el lunes, y muchos trabajan el s&amp;aacute;bado Y el domingo; era parte de los requerimientos, poder configurar el calendario). El tercer test, entonces, es:&lt;/p&gt;
&lt;pre style="color:white;background-color:black;"&gt;&lt;span style="color:cyan;"&gt;[&lt;/span&gt;TestMethod&lt;span style="color:cyan;"&gt;]&lt;/span&gt;
&lt;span style="color:orange;"&gt;public&lt;/span&gt; &lt;span style="color:orange;"&gt;void&lt;/span&gt; TypicalSaturdayIsANonWorkingDay&lt;span style="color:cyan;"&gt;()&lt;/span&gt;
&lt;span style="color:cyan;"&gt;{&lt;/span&gt;
    WorkingDaysCalendar calendar = &lt;span style="color:orange;"&gt;new&lt;/span&gt; WorkingDaysCalendar&lt;span style="color:cyan;"&gt;();&lt;/span&gt;

    DateTime saturday = &lt;span style="color:orange;"&gt;new&lt;/span&gt; DateTime&lt;span style="color:cyan;"&gt;(&lt;/span&gt;2012&lt;span style="color:cyan;"&gt;,&lt;/span&gt; 3&lt;span style="color:cyan;"&gt;,&lt;/span&gt; 10&lt;span style="color:cyan;"&gt;);&lt;/span&gt;
    Assert.AreEqual&lt;span style="color:cyan;"&gt;(&lt;/span&gt;saturday.DayOfWeek&lt;span style="color:cyan;"&gt;,&lt;/span&gt; DayOfWeek.Saturday&lt;span style="color:cyan;"&gt;);&lt;/span&gt;

    Assert.IsFalse&lt;span style="color:cyan;"&gt;(&lt;/span&gt;calendar.IsWorkingDay&lt;span style="color:cyan;"&gt;(&lt;/span&gt;saturday&lt;span style="color:cyan;"&gt;));&lt;/span&gt;
&lt;span style="color:cyan;"&gt;}&lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;M&amp;iacute;nimo c&amp;oacute;digo que hace que el test pase a verde:&lt;/p&gt;
&lt;pre style="color:white;background-color:black;"&gt;&lt;span style="color:orange;"&gt;public&lt;/span&gt; &lt;span style="color:orange;"&gt;bool&lt;/span&gt; IsWorkingDay&lt;span style="color:cyan;"&gt;(&lt;/span&gt;DateTime day&lt;span style="color:cyan;"&gt;)&lt;/span&gt;
&lt;span style="color:cyan;"&gt;{&lt;/span&gt;
    &lt;span style="color:orange;"&gt;if&lt;/span&gt; &lt;span style="color:cyan;"&gt;(&lt;/span&gt;day.DayOfWeek == DayOfWeek.Sunday &lt;span style="color:cyan;"&gt;||&lt;/span&gt; day.DayOfWeek == DayOfWeek.Saturday&lt;span style="color:cyan;"&gt;)&lt;/span&gt;
        &lt;span style="color:orange;"&gt;return&lt;/span&gt; &lt;span style="color:orange;"&gt;false&lt;/span&gt;&lt;span style="color:cyan;"&gt;;&lt;/span&gt;

    &lt;span style="color:orange;"&gt;return&lt;/span&gt; &lt;span style="color:orange;"&gt;true&lt;/span&gt;&lt;span style="color:cyan;"&gt;;&lt;/span&gt;
&lt;span style="color:cyan;"&gt;}&lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;Agregu&amp;eacute; un d&amp;iacute;a m&amp;aacute;s no laborable en la condici&amp;oacute;n del if.&lt;/p&gt;
&lt;p&gt;Vean que quedaron dos constantes el c&amp;oacute;digo de implementaci&amp;oacute;n. Por ahora, no me preocupa. Es m&amp;aacute;s: me parece que son constantes que reflejan algo b&amp;aacute;sico del sistema que estamos armando, no son constantes arbitrarias. Comienza a surgir lo que entiendo como calendario t&amp;iacute;pico: semana laborable, excepto s&amp;aacute;bados y domingo.&lt;/p&gt;
&lt;p&gt;No hice mucho refactoring en estos test. Diferencias con el &lt;a target="_blank" href="http://msmvps.com/blogs/lopez/archive/2012/03/14/coding-dojo-tdd-on-the-rocks.aspx"&gt;Coding Dojo&lt;/a&gt;: sigo usando nombres significativos para los tests (si hay que cambiarlos, los cambio). Tampoco us&amp;eacute; m&amp;eacute;todos auxiliares que me devuelvan un lunes o un domingo o un s&amp;aacute;bado. Si necesito esos m&amp;eacute;todos, ser&amp;aacute; porque surjan de refactor de c&amp;oacute;digo de tests (probablemente, si necesito obtener un lunes desde m&amp;aacute;s de 2 tests, digamos).&lt;/p&gt;
&lt;p&gt;Pr&amp;oacute;ximos pasos: ver qu&amp;eacute; es una semana t&amp;iacute;pica, plasmarla en un test; comenzar a configurar el calendario (tal vez, s&amp;aacute;bado es laborable, para algunas profesiones, que usaran un calendario configurable para ellas).&lt;/p&gt;
&lt;p&gt;Nos leemos!&lt;/p&gt;
&lt;p&gt;Angel &amp;ldquo;Java&amp;rdquo; Lopez 
  &lt;br /&gt;&lt;a href="http://www.ajlopez.com"&gt;http://www.ajlopez.com&lt;/a&gt; 
  &lt;br /&gt;&lt;a href="http://twitter.com/ajlopez"&gt;http://twitter.com/ajlopez&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1807651" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/lopez/archive/tags/Desarrollo+de+Software/default.aspx">Desarrollo de Software</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/C+Sharp/default.aspx">C Sharp</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Desarrollo+Agil/default.aspx">Desarrollo Agil</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/TDD/default.aspx">TDD</category></item><item><title>TDD Paso a Paso (1) Primer Test</title><link>http://msmvps.com/blogs/lopez/archive/2012/03/18/tdd-paso-a-paso-1-primer-test.aspx</link><pubDate>Sun, 18 Mar 2012 16:15:00 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1807536</guid><dc:creator>lopez</dc:creator><slash:comments>2</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/lopez/rsscomments.aspx?PostID=1807536</wfw:commentRss><comments>http://msmvps.com/blogs/lopez/archive/2012/03/18/tdd-paso-a-paso-1-primer-test.aspx#comments</comments><description>&lt;p&gt;&lt;a href="http://msmvps.com/blogs/lopez/archive/2012/03/20/tdd-paso-a-paso-2-d-237-as-no-laborables.aspx"&gt;Siguiente Post&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Coment&amp;eacute; en el post &lt;a href="http://msmvps.com/blogs/lopez/archive/2012/03/14/coding-dojo-tdd-on-the-rocks.aspx"&gt;Coding Dojo &amp;ndash; TDD on the Rocks&lt;/a&gt; el ejercicio que hicimos en conjunto con el bueno de &lt;a href="http://twitter.com/hernanwilkinson"&gt;@HernanWilkinson&lt;/a&gt;. Quisiera hoy comenzar una serie explicando un poco mi estilo de programar ese ejercicio, para ir viendo las diferencias con lo visto en el coding dojo. No digo que sea mejor o peor, pero s&amp;iacute; que es la forma en la que me siento m&amp;aacute;s c&amp;oacute;modo. Esta forma de encarar TDD (Test-Driven Development) la estoy publicando en &lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/ajlopez/TddOnTheRocks/tree/master/MySrc"&gt;https://github.com/ajlopez/TddOnTheRocks/tree/master/MySrc&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Pueden ver ah&amp;iacute; el log de lo que fui escribiendo: estuve enviando commit al repositorio Git pr&amp;aacute;cticamente por cada paso. Les recuerdo el problema:&lt;/p&gt;
&lt;p&gt;- Calendario de d&amp;iacute;as laborables y no laborables&lt;/p&gt;
&lt;p&gt;- Se debe saber si una fecha particular es laborable o no&lt;/p&gt;
&lt;p&gt;- Se debe configurar con:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;- d&amp;iacute;a de la semana no laboral (ej. Domingo)&lt;/p&gt;
&lt;p&gt;- d&amp;iacute;a de mes no laboral (ej. Primero de Enero)&lt;/p&gt;
&lt;p&gt;- fecha particular no laboral (ej. 4 de Abril de 2012)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Primero, constru&amp;iacute; una soluci&amp;oacute;n en C# con Visual Studio, con dos proyectos: uno de librer&amp;iacute;a de clases, y otro de test:&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.ajlopez.com/images/articles2/tddsbs01.png" alt="" /&gt; &lt;/p&gt;
&lt;p&gt;Vean que fui creando una clase para los tests, y otra clase para lo que quieron implementar. Ah&amp;iacute; difiero del &amp;ldquo;approach&amp;rdquo; de @HernanWilkinson, que llam&amp;oacute; a la clase de tests con un nombre no significativo. Yo prefiero empezar con un nombre m&amp;aacute;s relacionado con el problema, aunque puede que despu&amp;eacute;s lo cambie.&lt;/p&gt;
&lt;p&gt;El primer tests, para m&amp;iacute;, es probar que los lunes, en general, son un d&amp;iacute;a laborable. Este fue mi primer test:&lt;/p&gt;
&lt;pre style="background-color:black;color:white;"&gt;&lt;span style="color:cyan;"&gt;[&lt;/span&gt;TestMethod&lt;span style="color:cyan;"&gt;]&lt;/span&gt;
&lt;span style="color:orange;"&gt;public&lt;/span&gt; &lt;span style="color:orange;"&gt;void&lt;/span&gt; TypicalMondayIsAWorkingDay&lt;span style="color:cyan;"&gt;()&lt;/span&gt;
&lt;span style="color:cyan;"&gt;{&lt;/span&gt;
	WorkingDaysCalendar calendar = &lt;span style="color:orange;"&gt;new&lt;/span&gt; WorkingDaysCalendar&lt;span style="color:cyan;"&gt;();&lt;/span&gt;
	
	DateTime monday = &lt;span style="color:orange;"&gt;new&lt;/span&gt; DateTime&lt;span style="color:cyan;"&gt;(&lt;/span&gt;2012&lt;span style="color:cyan;"&gt;,&lt;/span&gt; 3&lt;span style="color:cyan;"&gt;,&lt;/span&gt; 12&lt;span style="color:cyan;"&gt;);&lt;/span&gt;

	Assert.IsTrue&lt;span style="color:cyan;"&gt;(&lt;/span&gt;calendar.IsWorkingDay&lt;span style="color:cyan;"&gt;(&lt;/span&gt;monday&lt;span style="color:cyan;"&gt;));&lt;/span&gt;
&lt;span style="color:cyan;"&gt;}&lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;Ac&amp;aacute; otra &amp;ldquo;departure&amp;rdquo; del ejercicio del coding dojo. Mientras que aquel d&amp;iacute;a codificamos el test poni&amp;eacute;ndole un nombre neutro como test1, yo prefiero darle un nombre significativo desde el principio, aunque despu&amp;eacute;s lo cambie. Me queda claro qu&amp;eacute; estoy intentando hacer, y tambi&amp;eacute;n para cualquiera que lo vea. No me ha pasado con frecuencia que tenga que cambiar radicalmente el nombre a un test. Pueden ver los logs de proyectos de c&amp;oacute;digo abierto (por ejemplo los &lt;a href="https://github.com/ajlopez"&gt;de GitHub&lt;/a&gt;), para notar que no he necesitado mucho el &amp;ldquo;renaming&amp;rdquo; de nombre de test.&lt;/p&gt;
&lt;p&gt;Pero este test no compila. Arm&amp;eacute; una primera clase:&lt;/p&gt;
&lt;pre style="background-color:black;color:white;"&gt;&lt;span style="color:orange;"&gt;public&lt;/span&gt; &lt;span style="color:orange;"&gt;class&lt;/span&gt; WorkingDaysCalendar
&lt;span style="color:cyan;"&gt;{&lt;/span&gt;
	&lt;span style="color:orange;"&gt;public&lt;/span&gt; &lt;span style="color:orange;"&gt;bool&lt;/span&gt; IsWorkingDay&lt;span style="color:cyan;"&gt;(&lt;/span&gt;DateTime day&lt;span style="color:cyan;"&gt;)&lt;/span&gt;
	&lt;span style="color:cyan;"&gt;{&lt;/span&gt;
		&lt;span style="color:orange;"&gt;throw&lt;/span&gt; &lt;span style="color:orange;"&gt;new&lt;/span&gt; NotImplementedException&lt;span style="color:cyan;"&gt;();&lt;/span&gt;
	&lt;span style="color:cyan;"&gt;}&lt;/span&gt;
&lt;span style="color:cyan;"&gt;}&lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;que consigue que el test compile, pero al ejecutarlo, da rojo. El c&amp;oacute;digo m&amp;iacute;nimo que consigui&amp;oacute; que pase a verde:&lt;/p&gt;
&lt;pre style="background-color:black;color:white;"&gt;&lt;span style="color:orange;"&gt;public&lt;/span&gt; &lt;span style="color:orange;"&gt;bool&lt;/span&gt; IsWorkingDay&lt;span style="color:cyan;"&gt;(&lt;/span&gt;DateTime day&lt;span style="color:cyan;"&gt;)&lt;/span&gt;
&lt;span style="color:cyan;"&gt;{&lt;/span&gt;
	&lt;span style="color:orange;"&gt;return&lt;/span&gt; &lt;span style="color:orange;"&gt;true&lt;/span&gt;&lt;span style="color:cyan;"&gt;;&lt;/span&gt;
&lt;span style="color:cyan;"&gt;}&lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;No hay mucho lugar para hacer refactor, en este punto. Pero mejor&amp;eacute; el c&amp;oacute;digo de test, para afirmar/controlar expl&amp;iacute;citamente que la fecha que estoy usando es un lunes:&lt;/p&gt;
&lt;pre style="background-color:black;color:white;"&gt;&lt;span style="color:cyan;"&gt;[&lt;/span&gt;TestMethod&lt;span style="color:cyan;"&gt;]&lt;/span&gt;
&lt;span style="color:orange;"&gt;public&lt;/span&gt; &lt;span style="color:orange;"&gt;void&lt;/span&gt; TypicalMondayIsAWorkingDay&lt;span style="color:cyan;"&gt;()&lt;/span&gt;
&lt;span style="color:cyan;"&gt;{&lt;/span&gt;
	WorkingDaysCalendar calendar = &lt;span style="color:orange;"&gt;new&lt;/span&gt; WorkingDaysCalendar&lt;span style="color:cyan;"&gt;();&lt;/span&gt;
	
	DateTime monday = &lt;span style="color:orange;"&gt;new&lt;/span&gt; DateTime&lt;span style="color:cyan;"&gt;(&lt;/span&gt;2012&lt;span style="color:cyan;"&gt;,&lt;/span&gt; 3&lt;span style="color:cyan;"&gt;,&lt;/span&gt; 12&lt;span style="color:cyan;"&gt;);&lt;/span&gt;
	Assert.AreEqual&lt;span style="color:cyan;"&gt;(&lt;/span&gt;monday.DayOfWeek&lt;span style="color:cyan;"&gt;,&lt;/span&gt; DayOfWeek.Monday&lt;span style="color:cyan;"&gt;);&lt;/span&gt;

	Assert.IsTrue&lt;span style="color:cyan;"&gt;(&lt;/span&gt;calendar.IsWorkingDay&lt;span style="color:cyan;"&gt;(&lt;/span&gt;monday&lt;span style="color:cyan;"&gt;));&lt;/span&gt;
&lt;span style="color:cyan;"&gt;}&lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;En el coding dojo usamos una funci&amp;oacute;n someSunday() (en este caso ser&amp;iacute;a someMonday()), pero todav&amp;iacute;a no la necesit&amp;eacute;. As&amp;iacute; que para mantener el test simple, me bast&amp;oacute; crear una fecha de lunes directamente en el c&amp;oacute;digo del test. Para cualquiera que lea el test dentro de un a&amp;ntilde;o, me aseguro que la fecha elegida sea la de un lunes.&lt;/p&gt;
&lt;p&gt;En el pr&amp;oacute;ximo post comentar&amp;eacute; los siguientes tests que se me ocurrieron: probar que un domingo t&amp;iacute;pico es no laborable, y que un s&amp;aacute;bado t&amp;iacute;pico tampoco. Veremos c&amp;oacute;mo fue emergiendo la implementaci&amp;oacute;n interna, y al llegar a nuevos tests, c&amp;oacute;mo esta implementaci&amp;oacute;n fue siendo mejorada y refactorizada.&lt;/p&gt;
&lt;p&gt;Jeje&amp;hellip; &amp;ldquo;dog fooding&amp;rdquo;, el c&amp;oacute;digo de arriba fue &amp;ldquo;coloreado&amp;rdquo; con &lt;a href="https://github.com/ajlopez/Acquarella"&gt;Acquarella&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Nos leemos!&lt;/p&gt;
&lt;p&gt;Angel &amp;ldquo;Java&amp;rdquo; Lopez 
  &lt;br /&gt;&lt;a href="http://www.ajlopez.com"&gt;http://www.ajlopez.com&lt;/a&gt; 
  &lt;br /&gt;&lt;a href="http://twitter.com/ajlopez"&gt;http://twitter.com/ajlopez&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1807536" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/lopez/archive/tags/Desarrollo+de+Software/default.aspx">Desarrollo de Software</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/C+Sharp/default.aspx">C Sharp</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Desarrollo+Agil/default.aspx">Desarrollo Agil</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/TDD/default.aspx">TDD</category></item><item><title>AjModel: Modelo por Código (Parte 2) Modelos y Repositorios</title><link>http://msmvps.com/blogs/lopez/archive/2011/06/30/ajmodel_2D00_model_2D00_by_2D00_code_2D00_part_2D00_2_2D00_models_2D00_and_2D00_repositories.aspx</link><pubDate>Thu, 30 Jun 2011 10:04:26 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1795510</guid><dc:creator>lopez</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/lopez/rsscomments.aspx?PostID=1795510</wfw:commentRss><comments>http://msmvps.com/blogs/lopez/archive/2011/06/30/ajmodel_2D00_model_2D00_by_2D00_code_2D00_part_2D00_2_2D00_models_2D00_and_2D00_repositories.aspx#comments</comments><description>&lt;p&gt;&lt;a href="http://msmvps.com/blogs/lopez/archive/2011/06/17/ajmodel_2D00_model_2D00_by_2D00_code_2D00_part_2D00_1_2D00_inception.aspx"&gt;Anterior Post&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Estuve trabajando en mi projecto AjModel. Pueden bajar el avance del código desde mi &lt;a href="http://code.google.com/p/ajcodekatas/"&gt;AjCodeKatas Project&lt;/a&gt; dentro de trunk/AjModel. Agregué una clase Model, y mejoré EntityModel y PropertyModel:&lt;/p&gt;  &lt;p&gt;&lt;img src="http://www.ajlopez.com/images/articles2/ajmodel04.png" alt="" /&gt; &lt;/p&gt;  &lt;p&gt;El modelo referencia a todos los modelos de entidades que quiero tomar de mi modelo ya codificado. Recordemos: AjModel se basa y enriquece un modelo ya codificado de clases, permitiendo agregar información como descripciones para humanos, leyendas, etc. La idea es generar automáticamente la UI desde el modelo en código, para diferentes tecnologías. El modelo de AjModel permite establecer ese puente entre nuestro modelo en código y las distintas UI. El modelo enriquecido debería servir para esa función AUN cuando no se le agregue nada. Y servir de base para generar la UI en ejecución. El modelo enriquecido debe ser poder consumido por distintas tecnologías de UI: la aplicación “prueba de concepto” que incluyo en el código es ASP.NET MVC.&lt;/p&gt;  &lt;p&gt;Como anticipaba en el post anterior, agregué una interfaz “fluent” a EntityModel y PropertyModel. Hay métodos de extensión, wrappers/builders, como:&lt;/p&gt;  &lt;p&gt;&lt;img src="http://www.ajlopez.com/images/articles2/ajmodel06.png" alt="" /&gt; &lt;/p&gt;  &lt;p&gt;Algunos ejemplos de uso, tomados de los tests:&lt;/p&gt;  &lt;pre&gt;&lt;pre style="background-color:#ffffff;margin:0em;width:100%;font-family:consolas,courier,monospace;font-size:12px;"&gt;EntityModel&amp;lt;Customer&amp;gt; model = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; EntityModel&amp;lt;Customer&amp;gt;();
FluentEntityModel&amp;lt;Customer&amp;gt; fluentModel = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; FluentEntityModel&amp;lt;Customer&amp;gt;(model);
fluentModel.Name(&amp;quot;&lt;span style="color:#8b0000;"&gt;BusinessCustomer&lt;/span&gt;&amp;quot;)
    .SetName(&amp;quot;&lt;span style="color:#8b0000;"&gt;BusinessCustomers&lt;/span&gt;&amp;quot;)
    .Descriptor(&amp;quot;&lt;span style="color:#8b0000;"&gt;Business Customer&lt;/span&gt;&amp;quot;)
    .SetDescriptor(&amp;quot;&lt;span style="color:#8b0000;"&gt;Business Customers&lt;/span&gt;&amp;quot;);
&lt;span style="color:#008000;"&gt;//..&lt;/span&gt;
Model model = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; Model();
var entityModel = model.ForEntity&amp;lt;Customer&amp;gt;();
entityModel.Descriptor(&amp;quot;&lt;span style="color:#8b0000;"&gt;Business Customer&lt;/span&gt;&amp;quot;)
    .SetDescriptor(&amp;quot;&lt;span style="color:#8b0000;"&gt;Business Customers&lt;/span&gt;&amp;quot;);
&lt;span style="color:#008000;"&gt;//..&lt;/span&gt;
Model model = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; Model();
model.ForEntity&amp;lt;Customer&amp;gt;().Property(
    c =&amp;gt; c.Name,
    pm =&amp;gt; pm.Descriptor(&amp;quot;&lt;span style="color:#8b0000;"&gt;Customer Name&lt;/span&gt;&amp;quot;)
            .Description(&amp;quot;&lt;span style="color:#8b0000;"&gt;The Customer Name&lt;/span&gt;&amp;quot;)
);
&lt;/pre&gt;&lt;/pre&gt;

&lt;p&gt;donde pm es un FluentPropertyModel.&lt;/p&gt;

&lt;p&gt;En el proceso de la UI, quiero recuperar una entidad por su identidad, para poder mostrar su detalle. Y también, quiero obtener una lista de entidades para alimentar una grilla. Entonces, necesito algo para manejar entidades, como una lista, y que se implemente por abajo en distintas tecnologías. La actual implementación se basa en una lista en memoria:&lt;/p&gt;

&lt;p&gt;&lt;img src="http://www.ajlopez.com/images/articles2/ajmodel05.png" alt="" /&gt; &lt;/p&gt;

&lt;p&gt;En mis planes está escribir ejemplos de adapter para NHibernate, Entity Framework, pero eso todavía está solo en papel y en mi mente ;-)&lt;/p&gt;

&lt;p&gt;Ejemplos de uso:&lt;/p&gt;

&lt;pre&gt;&lt;pre style="background-color:#ffffff;margin:0em;width:100%;font-family:consolas,courier,monospace;font-size:12px;"&gt;&lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.entityModel = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; EntityModel&amp;lt;Customer&amp;gt;();
&lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.domain = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; SimpleDomain();
&lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.repository = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; Repository&amp;lt;Customer&amp;gt;(&lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.entityModel, &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.domain.Customers);
&lt;/pre&gt;&lt;/pre&gt;

&lt;p&gt;Noten que hay repositorios con tipo, usando generics. Y necesita para manejarse un EntityModel, y (en la actual implementación) un IList de entidades. El Context contiene una lista de todos los repositorios:&lt;/p&gt;

&lt;pre&gt;&lt;pre style="background-color:#ffffff;margin:0em;width:100%;font-family:consolas,courier,monospace;font-size:12px;"&gt;var entityModel = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; EntityModel&amp;lt;Customer&amp;gt;();
var domain = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; SimpleDomain();
var repository = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; Repository&amp;lt;Customer&amp;gt;(entityModel, domain.Customers);
var context = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; Context();
context.AddRepository(&lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.repository);
var repo = context.GetRepository(&amp;quot;&lt;span style="color:#8b0000;"&gt;Customer&lt;/span&gt;&amp;quot;);
&lt;/pre&gt;&lt;/pre&gt;

&lt;p&gt;SimpleDomain es una clase que creé para los tests:&lt;/p&gt;

&lt;pre&gt;&lt;pre style="background-color:#ffffff;margin:0em;width:100%;font-family:consolas,courier,monospace;font-size:12px;"&gt;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;class&lt;/span&gt; SimpleDomain
{
    &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; SimpleDomain()
    {
        &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.Customers = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; List&amp;lt;Customer&amp;gt;();
        &lt;span style="color:#0000ff;"&gt;for&lt;/span&gt; (&lt;span style="color:#0000ff;"&gt;int&lt;/span&gt; k = 1; k &amp;lt;= 10; k++)
        {
            Customer customer = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; Customer()
            {
                Id = k,
                Name = &lt;span style="color:#0000ff;"&gt;string&lt;/span&gt;.Format(&amp;quot;&lt;span style="color:#8b0000;"&gt;Customer {0}&lt;/span&gt;&amp;quot;, k)
            };
            &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.Customers.Add(customer);
        }
    }
    &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; IList&amp;lt;Customer&amp;gt; Customers { &lt;span style="color:#0000ff;"&gt;get&lt;/span&gt;; &lt;span style="color:#0000ff;"&gt;set&lt;/span&gt;; }
    &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; ProductList Products { &lt;span style="color:#0000ff;"&gt;get&lt;/span&gt;; &lt;span style="color:#0000ff;"&gt;set&lt;/span&gt;; }
}
&lt;/pre&gt;&lt;/pre&gt;

&lt;p&gt;Un modelo puede ser creado alimentándose de la estructura de una clase como SimpleDomain. Descubre las propiedades públicas que implementan IList (por ahora):&lt;/p&gt;

&lt;pre&gt;&lt;pre style="background-color:#ffffff;margin:0em;width:100%;font-family:consolas,courier,monospace;font-size:12px;"&gt;var model = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; Model(&lt;span style="color:#0000ff;"&gt;typeof&lt;/span&gt;(SimpleDomain));
var entityModel = model.GetEntityModel(&amp;quot;&lt;span style="color:#8b0000;"&gt;Customer&lt;/span&gt;&amp;quot;);
Assert.IsNotNull(entityModel);
entityModel = model.GetEntityModel(&amp;quot;&lt;span style="color:#8b0000;"&gt;Product&lt;/span&gt;&amp;quot;);
Assert.IsNotNull(entityModel);
&lt;/pre&gt;&lt;/pre&gt;
Planeo agregar automáticamente todos los tipos de un assembly que satisfagan un predicado, como tener “Entities” en su namespaces. new Model(IEnumerable&amp;lt;Type&amp;gt; types) debería bastar. 

&lt;p&gt;Las entidades (objetos) pueden ser agregadas y recuperadas usando un repositorio:&lt;/p&gt;

&lt;pre&gt;&lt;pre style="background-color:#ffffff;margin:0em;width:100%;font-family:consolas,courier,monospace;font-size:12px;"&gt;Customer entity = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; Customer() { Id = 1000 };
&lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.repository.AddEntity(entity);
Customer newEntity = &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.repository.GetEntity(1000);&lt;/pre&gt;&lt;/pre&gt;

&lt;p&gt;Y pueden ser removidas, también.&lt;/p&gt;

&lt;p&gt;El modelo de entidad tiene la información para crear nuevas entidades desde valores (en un diccionario con pares nombre/valor). Una capacidad que necesito para usar en la creación de entidades desde la UI:&lt;/p&gt;

&lt;pre&gt;&lt;pre style="background-color:#ffffff;margin:0em;width:100%;font-family:consolas,courier,monospace;font-size:12px;"&gt;EntityModel&amp;lt;Person&amp;gt; model = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; EntityModel&amp;lt;Person&amp;gt;();
IDictionary&amp;lt;&lt;span style="color:#0000ff;"&gt;string&lt;/span&gt;, &lt;span style="color:#0000ff;"&gt;object&lt;/span&gt;&amp;gt; values = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; Dictionary&amp;lt;&lt;span style="color:#0000ff;"&gt;string&lt;/span&gt;, &lt;span style="color:#0000ff;"&gt;object&lt;/span&gt;&amp;gt;()
{
    { &amp;quot;&lt;span style="color:#8b0000;"&gt;Id&lt;/span&gt;&amp;quot;, 1 },
    { &amp;quot;&lt;span style="color:#8b0000;"&gt;FirstName&lt;/span&gt;&amp;quot;, &amp;quot;&lt;span style="color:#8b0000;"&gt;Joe&lt;/span&gt;&amp;quot; },
    { &amp;quot;&lt;span style="color:#8b0000;"&gt;LastName&lt;/span&gt;&amp;quot;, &amp;quot;&lt;span style="color:#8b0000;"&gt;Doe&lt;/span&gt;&amp;quot; },
    { &amp;quot;&lt;span style="color:#8b0000;"&gt;Age&lt;/span&gt;&amp;quot;, &amp;quot;&lt;span style="color:#8b0000;"&gt;30&lt;/span&gt;&amp;quot; }
};
&lt;span style="color:#0000ff;"&gt;object&lt;/span&gt; entity = model.NewEntity(values);
&lt;/pre&gt;&lt;/pre&gt;

&lt;p&gt;En próximos posts, discutiré alguna implementación de la UI en MVC. Todo es “work in progress”, pero el proyecto ya va tomando forma. Y me divieggtto como loco ;-)&lt;/p&gt;

&lt;p&gt;Nos leemos!&lt;/p&gt;

&lt;p&gt;Angel “Java” Lopez 
  &lt;br /&gt;&lt;a href="http://www.ajlopez.com"&gt;http://www.ajlopez.com&lt;/a&gt; 

  &lt;br /&gt;&lt;a href="http://twitter.com/ajlopez"&gt;http://twitter.com/ajlopez&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1795510" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/lopez/archive/tags/.NET/default.aspx">.NET</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Desarrollo+de+Software/default.aspx">Desarrollo de Software</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/C+Sharp/default.aspx">C Sharp</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Proyectos+de+C_26002300_243_3B00_digo+Abierto/default.aspx">Proyectos de C&amp;#243;digo Abierto</category></item><item><title>Escribiendo una Aplicación usando TDD (Part 5) Agregando Vistas</title><link>http://msmvps.com/blogs/lopez/archive/2011/06/27/writing_2D00_an_2D00_application_2D00_using_2D00_tdd_2D00_part_2D00_5_2D00_adding_2D00_views.aspx</link><pubDate>Mon, 27 Jun 2011 10:21:00 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1795259</guid><dc:creator>lopez</dc:creator><slash:comments>3</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/lopez/rsscomments.aspx?PostID=1795259</wfw:commentRss><comments>http://msmvps.com/blogs/lopez/archive/2011/06/27/writing_2D00_an_2D00_application_2D00_using_2D00_tdd_2D00_part_2D00_5_2D00_adding_2D00_views.aspx#comments</comments><description>&lt;p&gt;&lt;a href="http://msmvps.com/blogs/lopez/archive/2011/06/02/writing_2D00_an_2D00_application_2D00_using_2D00_tdd_2D00_part_2D00_4_2D00_update_2D00_and_2D00_insert.aspx"&gt;Anterior Post&lt;/a&gt;     &lt;br /&gt;&lt;a href="http://msmvps.com/blogs/lopez/archive/2013/04/07/escribiendo-una-aplicaci-243-n-usando-tdd-part-6-modificando-vistas.aspx"&gt;Pr&amp;oacute;ximo Post&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Ahora ya tengo algunos tests y en verde. Voy a agregar algunas vistas MVC en este paso de hoy. Pueden bajar el c&amp;oacute;digo desde mi &lt;a href="http://code.google.com/p/ajcodekatas/"&gt;AjCodeKatas Google Project&lt;/a&gt;, en trunk/AppTdd/Step04. As&amp;iacute; que este post tiene pocos nuevos tests: muestra que podemos agregar interfaz de usuario DESPUES de los tests, y (para destacar) SIN TENER una base de datos a&amp;uacute;n, ni siquiera una capa de servicios (&amp;ldquo;service layer&amp;rdquo;).&lt;/p&gt;
&lt;p&gt;Primero, agregu&amp;eacute; una master page Site.master y un estilo style.css (que tom&amp;eacute; de otro proyecto ASP.NET MVC 2)&lt;/p&gt;
&lt;p&gt;Agregu&amp;eacute; un nuevo controlador Home:&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.ajlopez.com/images/articles2/apptdd0401.png" alt="" /&gt; &lt;/p&gt;
&lt;p&gt;Y usando el men&amp;uacute; de contexto sobre el m&amp;eacute;todo Index agregu&amp;eacute; una vista asociada al m&amp;eacute;todo:&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.ajlopez.com/images/articles2/apptdd0402.png" alt="" /&gt; &lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Modifiqu&amp;eacute; el c&amp;oacute;digo de la master page para tener una nueva opci&amp;oacute;n en el men&amp;uacute;:&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.ajlopez.com/images/articles2/apptdd0403.png" alt="" /&gt; &lt;/p&gt;
&lt;p&gt;Entonces, agregu&amp;eacute; una vista, esta vez asociada al m&amp;eacute;todo Index del controlador Subject:&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.ajlopez.com/images/articles2/apptdd0404.png" alt="" /&gt; &lt;/p&gt;
&lt;p&gt;Seleccion&amp;eacute; a &amp;ldquo;List&amp;rdquo; como &amp;ldquo;Vien Content&amp;rdquo;, y a &amp;ldquo;Subject&amp;rdquo; como el tipo a usar como base del modelo.&lt;/p&gt;
&lt;p&gt;Pero el m&amp;eacute;todo del controlador es:&lt;/p&gt;
&lt;pre&gt;&lt;pre style="background-color:#ffffff;margin:0em;width:100%;font-family:consolas,courier,monospace;font-size:12px;"&gt;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; ActionResult Index()
{
    &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; View(subjects);
}&lt;/pre&gt;
&lt;/pre&gt;
&lt;p&gt;Usa una lista de temas (&amp;ldquo;subjects&amp;rdquo;) que ha sido inyectada hasta ahora en un constructor por los tests:&lt;/p&gt;
&lt;pre&gt;&lt;pre style="background-color:#ffffff;margin:0em;width:100%;font-family:consolas,courier,monospace;font-size:12px;"&gt;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; SubjectController(IList&amp;lt;Subject&amp;gt; subjects)
{
    &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.subjects = subjects;
}
&lt;/pre&gt;
&lt;/pre&gt;
&lt;p&gt;Pero esperen! Esa lista es inyectada por los tests. Ahora, necesito que est&amp;eacute; disponible en el proceso normal de un controlador. As&amp;iacute; que agregu&amp;eacute; un constructor sin par&amp;aacute;metros:&lt;/p&gt;
&lt;pre&gt;&lt;pre style="background-color:#ffffff;margin:0em;width:100%;font-family:consolas,courier,monospace;font-size:12px;"&gt;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; SubjectController()
    : &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;(Domain.Instance.Subjects)
{
}
&lt;/pre&gt;
&lt;/pre&gt;
&lt;p&gt;El Domain.Instance es un dominio en memoria:&lt;/p&gt;
&lt;pre&gt;&lt;pre style="background-color:#ffffff;margin:0em;width:100%;font-family:consolas,courier,monospace;font-size:12px;"&gt;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;class&lt;/span&gt; Domain
{
    &lt;span style="color:#0000ff;"&gt;private&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;static&lt;/span&gt; Domain instance = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; Domain();
    &lt;span style="color:#0000ff;"&gt;private&lt;/span&gt; Domain()
    {
        &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.Subjects = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; List&amp;lt;Subject&amp;gt;()
        {
            &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; Subject() { Id = 1, Name = &amp;quot;&lt;span style="color:#8b0000;"&gt;Mathematics&lt;/span&gt;&amp;quot; },
            &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; Subject() { Id = 2, Name = &amp;quot;&lt;span style="color:#8b0000;"&gt;Physics&lt;/span&gt;&amp;quot; },
            &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; Subject() { Id = 3, Name = &amp;quot;&lt;span style="color:#8b0000;"&gt;Biology&lt;/span&gt;&amp;quot; },
            &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; Subject() { Id = 4, Name = &amp;quot;&lt;span style="color:#8b0000;"&gt;Literature&lt;/span&gt;&amp;quot; }
        };
    }
    &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;static&lt;/span&gt; Domain Instance { &lt;span style="color:#0000ff;"&gt;get&lt;/span&gt; { &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; instance; } }
    &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; IList&amp;lt;Subject&amp;gt; Subjects { &lt;span style="color:#0000ff;"&gt;get&lt;/span&gt;; &lt;span style="color:#0000ff;"&gt;set&lt;/span&gt;; }
}
&lt;/pre&gt;
&lt;/pre&gt;
&lt;p&gt;Ahora s&amp;iacute; el controlador de Subject puede manejar el m&amp;eacute;todo Index. Cambio enlaces en la vista que me agreg&amp;oacute; el wizard. Los cambio de:&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.ajlopez.com/images/articles2/apptdd0406.png" alt="" /&gt; &lt;/p&gt;
&lt;p&gt;a que usen la propiedad Id como clave primaria:&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.ajlopez.com/images/articles2/apptdd0407.png" alt="" /&gt; &lt;/p&gt;
&lt;p&gt;Este es el resultado:&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.ajlopez.com/images/articles2/apptdd0405.png" alt="" /&gt; &lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Cre&amp;eacute; entonces otras vistas, para los otros m&amp;eacute;todos del controlador Subject. Segu&amp;iacute; usando el wizard de Visual Studio &amp;ldquo;Add View &amp;hellip; &amp;ldquo;:&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.ajlopez.com/images/articles2/apptdd0408.png" alt="" /&gt; &lt;/p&gt;
&lt;p&gt;Me encontr&amp;eacute; que me faltaban algunas acciones. Escrib&amp;iacute; una nueva:&lt;/p&gt;
&lt;pre&gt;&lt;pre style="background-color:#ffffff;margin:0em;width:100%;font-family:consolas,courier,monospace;font-size:12px;"&gt;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; ActionResult Edit(&lt;span style="color:#0000ff;"&gt;int&lt;/span&gt; id)
{
    var model = &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.subjects.Where(s =&amp;gt; s.Id == id).FirstOrDefault();
    &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; View(model);
}
&lt;/pre&gt;
&lt;/pre&gt;
&lt;p&gt;con tests! ;-)&lt;/p&gt;
&lt;pre&gt;&lt;pre style="background-color:#ffffff;margin:0em;width:100%;font-family:consolas,courier,monospace;font-size:12px;"&gt;[TestMethod]
&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;void&lt;/span&gt; GetSubjectForEdit()
{
    IList&amp;lt;Subject&amp;gt; subjects = GetSubjects();
    SubjectController controller = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; SubjectController(subjects);
    ActionResult result = controller.Edit(1);
    Assert.IsNotNull(result);
    Assert.IsInstanceOfType(result, &lt;span style="color:#0000ff;"&gt;typeof&lt;/span&gt;(ViewResult));
    ViewResult viewResult = (ViewResult)result;
    Assert.IsInstanceOfType(viewResult.ViewData.Model, &lt;span style="color:#0000ff;"&gt;typeof&lt;/span&gt;(Subject));
    Subject model = (Subject)viewResult.ViewData.Model;
    Assert.AreEqual(1, model.Id);
    Assert.AreEqual(&amp;quot;&lt;span style="color:#8b0000;"&gt;Mathematics&lt;/span&gt;&amp;quot;, model.Name);
}
&lt;/pre&gt;
&lt;/pre&gt;
&lt;p&gt;Curiosamente, detect&amp;eacute; un test &amp;ldquo;malo&amp;rdquo;. Yo hab&amp;iacute;a escrito en test AddSubject:&lt;/p&gt;
&lt;pre&gt;&lt;pre style="background-color:#ffffff;margin:0em;width:100%;font-family:consolas,courier,monospace;font-size:12px;"&gt;Assert.IsTrue(subjects.Any(s =&amp;gt; s.Name == &amp;quot;&lt;span style="color:#8b0000;"&gt;Chemistry&lt;/span&gt;&amp;quot;));
Assert.AreEqual(4, subject.Id);&lt;/pre&gt;
&lt;/pre&gt;
&lt;p&gt;Pero el nuevo Id deber&amp;iacute;a dar 5 (mi lista usada en los tests tiene 4 temas predefinidos (&amp;ldquo;subjects&amp;rdquo;)):&lt;/p&gt;
&lt;pre&gt;&lt;pre style="background-color:#ffffff;margin:0em;width:100%;font-family:consolas,courier,monospace;font-size:12px;"&gt;Assert.IsTrue(subjects.Any(s =&amp;gt; s.Name == &amp;quot;&lt;span style="color:#8b0000;"&gt;Chemistry&lt;/span&gt;&amp;quot;));
Assert.AreEqual(5, subject.Id);&lt;/pre&gt;
&lt;/pre&gt;
&lt;p&gt;Arregl&amp;eacute; el c&amp;oacute;digo y la acci&amp;oacute;n del controler, ejecut&amp;eacute; la aplicaci&amp;oacute;n web, y&amp;nbsp; voila! Todo funcion&amp;oacute;.&lt;/p&gt;
&lt;p&gt;Puntos principales:&lt;/p&gt;
&lt;p&gt;- Estoy usando un dominio en memoria. &lt;/p&gt;
&lt;p&gt;- Las vistas se ejecutan sobre las acciones YA probadas con tests&lt;/p&gt;
&lt;p&gt;No hay capa l&amp;oacute;gica de servicios ni persistencia, a&amp;uacute;n. Vean que no son necesarias al principio. Voy a agregar una &amp;ldquo;service layer&amp;rdquo; como gran refactor. Otros pr&amp;oacute;ximos pasos: agregar m&amp;aacute;s clases al dominio (libros en clase Book), escribir esa capa de servicio usando tests, &amp;ldquo;enchufarla&amp;rdquo; en los controladores. Y en alg&amp;uacute;n momento agregar persistencia.&lt;/p&gt;
&lt;p&gt;Pueden leer posts interesantes sobre TDD sin una base de datos (o agreg&amp;aacute;ndola despu&amp;eacute;s) escritos por &lt;a href="http://twitter.com/RonJeffries"&gt;@RonJeffries&lt;/a&gt;:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://xprogramming.com/articles/but-we-need-a-database-dont-we/"&gt;But We Need a Database &amp;hellip; Don&amp;rsquo;t We? | xProgramming.com&lt;/a&gt; 
  &lt;br /&gt;&lt;a href="http://xprogramming.com/articles/but-we-need-a-database-dont-we/"&gt;See? We Don&amp;rsquo;t Need a Database &amp;hellip; Yet | xProgramming.com&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Nos leemos!&lt;/p&gt;
&lt;p&gt;Angel &amp;ldquo;Java&amp;rdquo; Lopez 
  &lt;br /&gt;&lt;a href="http://www.ajlopez.com"&gt;http://www.ajlopez.com&lt;/a&gt; 
  &lt;br /&gt;&lt;a href="http://twitter.com/ajlopez"&gt;http://twitter.com/ajlopez&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1795259" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/lopez/archive/tags/.NET/default.aspx">.NET</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Desarrollo+de+Software/default.aspx">Desarrollo de Software</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/C+Sharp/default.aspx">C Sharp</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Desarrollo+Agil/default.aspx">Desarrollo Agil</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/TDD/default.aspx">TDD</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/ASP.NET+MVC/default.aspx">ASP.NET MVC</category></item><item><title>Escribiendo una Aplicación usando TDD (Parte 4) Alta y Actualización</title><link>http://msmvps.com/blogs/lopez/archive/2011/06/02/writing_2D00_an_2D00_application_2D00_using_2D00_tdd_2D00_part_2D00_4_2D00_update_2D00_and_2D00_insert.aspx</link><pubDate>Thu, 02 Jun 2011 10:05:00 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1794129</guid><dc:creator>lopez</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/lopez/rsscomments.aspx?PostID=1794129</wfw:commentRss><comments>http://msmvps.com/blogs/lopez/archive/2011/06/02/writing_2D00_an_2D00_application_2D00_using_2D00_tdd_2D00_part_2D00_4_2D00_update_2D00_and_2D00_insert.aspx#comments</comments><description>&lt;p&gt;&lt;a href="http://msmvps.com/blogs/lopez/archive/2011/03/31/writing_2D00_an_2D00_application_2D00_using_2D00_tdd_2D00_part_2D00_3_2D00_first_2D00_detail.aspx"&gt;Anterior Post&lt;/a&gt; &lt;br /&gt;&lt;a href="http://msmvps.com/blogs/lopez/archive/2011/06/27/writing_2D00_an_2D00_application_2D00_using_2D00_tdd_2D00_part_2D00_5_2D00_adding_2D00_views.aspx"&gt;Siguiente Post&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;En el anterior post, implement&amp;eacute; la recuperaci&amp;oacute;n de los datos de un Tema de libros. No implement&amp;eacute; a&amp;uacute;n ninguna vista. Estoy escribiendo los tests, e implementando el c&amp;oacute;digo del controlador. Es hora de agregar un nuevo Tema (Subject), usando una acci&amp;oacute;n del controlador.&lt;/p&gt;
&lt;p&gt;Este fue mi primer test:&lt;/p&gt;
&lt;pre&gt;&lt;pre style="background-color:#ffffff;margin:0em;width:100%;font-family:consolas,courier,monospace;font-size:12px;"&gt;[TestMethod]
&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;void&lt;/span&gt; AddSubject()
{
    IList&amp;lt;Subject&amp;gt; subjects = GetSubjects();
    Subject subject = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; Subject() { Name = &amp;quot;&lt;span style="color:#8b0000;"&gt;Chemistry&lt;/span&gt;&amp;quot; };
    SubjectController controller = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; SubjectController(subjects);
    ActionResult result = controller.Create(subject);
    Assert.IsNotNull(result);
    Assert.IsTrue(subjects.Any(s =&amp;gt; s.Name == &amp;quot;&lt;span style="color:#8b0000;"&gt;Chemistry&lt;/span&gt;&amp;quot;));
    Assert.AreNotEqual(0, subject.Id);
}
&lt;/pre&gt;
&lt;/pre&gt;
&lt;p&gt;GetSubjects() es un m&amp;eacute;todo ayudante que present&amp;eacute; en el anterior posts. Retorna una lista de temas para tests. Agregu&amp;eacute; una nueva acci&amp;oacute;n en la clase controladora, para que la soluci&amp;oacute;n compile:&lt;/p&gt;
&lt;pre&gt;&lt;pre style="background-color:#ffffff;margin:0em;width:100%;font-family:consolas,courier,monospace;font-size:12px;"&gt;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; ActionResult Create(Subject subject)
{
    &lt;span style="color:#0000ff;"&gt;throw&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; NotImplementedException();
}
&lt;/pre&gt;
&lt;/pre&gt;
&lt;p&gt;Compil&amp;oacute;, y el test qued&amp;oacute; en rojo:&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.ajlopez.com/images/articles2/apptdd0301.png" alt="" /&gt; &lt;/p&gt;
&lt;p&gt;Entonces, complet&amp;eacute; el m&amp;eacute;todo de acci&amp;oacute;n con el c&amp;oacute;digo m&amp;iacute;nimo para que pase el test:&lt;/p&gt;
&lt;pre&gt;&lt;pre style="background-color:#ffffff;margin:0em;width:100%;font-family:consolas,courier,monospace;font-size:12px;"&gt;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; ActionResult Create(Subject subject)
{
   subject.Id = &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.subjects.Max(s =&amp;gt; s.Id);
   subjects.Add(subject);
   &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; RedirectToAction(&amp;quot;&lt;span style="color:#8b0000;"&gt;Index&lt;/span&gt;&amp;quot;);
}
&lt;/pre&gt;
&lt;/pre&gt;
&lt;p&gt;Pero quiero redireccionar a la vista de detalle luego de haber dado de alta un item. Agrego el test:&lt;/p&gt;
&lt;pre&gt;&lt;pre style="background-color:#ffffff;margin:0em;width:100%;font-family:consolas,courier,monospace;font-size:12px;"&gt;RedirectToRouteResult redirect = (RedirectToRouteResult)result;
Assert.IsTrue(&lt;span style="color:#0000ff;"&gt;string&lt;/span&gt;.IsNullOrEmpty(redirect.RouteName));
Assert.IsTrue(redirect.RouteValues.ContainsKey(&amp;quot;&lt;span style="color:#8b0000;"&gt;id&lt;/span&gt;&amp;quot;));
Assert.AreEqual(subject.Id, redirect.RouteValues[&amp;quot;&lt;span style="color:#8b0000;"&gt;id&lt;/span&gt;&amp;quot;]);
Assert.IsTrue(redirect.RouteValues.ContainsKey(&amp;quot;&lt;span style="color:#8b0000;"&gt;action&lt;/span&gt;&amp;quot;));
Assert.AreEqual(&amp;quot;&lt;span style="color:#8b0000;"&gt;Details&lt;/span&gt;&amp;quot;, redirect.RouteValues[&amp;quot;&lt;span style="color:#8b0000;"&gt;action&lt;/span&gt;&amp;quot;]);
&lt;/pre&gt;
&lt;/pre&gt;
&lt;p&gt;Cambio el c&amp;oacute;digo de la acci&amp;oacute;n para que cumpla con el nuevo requerimiento:&lt;/p&gt;
&lt;pre&gt;&lt;pre style="background-color:#ffffff;margin:0em;width:100%;font-family:consolas,courier,monospace;font-size:12px;"&gt;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; ActionResult Create(Subject subject)
{
    subject.Id = &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.subjects.Max(s =&amp;gt; s.Id);
    subjects.Add(subject);
    &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; RedirectToAction(&amp;quot;&lt;span style="color:#8b0000;"&gt;Details&lt;/span&gt;&amp;quot;, &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; { id = subject.Id });
}
&lt;/pre&gt;
&lt;/pre&gt;
&lt;p&gt;Ahora, el test en verde:&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.ajlopez.com/images/articles2/apptdd0302.png" alt="" /&gt; &lt;/p&gt;
&lt;p&gt;Segu&amp;iacute; un camino similar para escribir el test de actualizaci&amp;oacute;n de un Tema existente. Esta es la versi&amp;oacute;n actual de ese test:&lt;/p&gt;
&lt;pre&gt;&lt;pre style="background-color:#ffffff;margin:0em;width:100%;font-family:consolas,courier,monospace;font-size:12px;"&gt;[TestMethod]
&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;void&lt;/span&gt; UpdateSubject()
{
    IList&amp;lt;Subject&amp;gt; subjects = GetSubjects();
    Subject literature = subjects.Where(s =&amp;gt; s.Name == &amp;quot;&lt;span style="color:#8b0000;"&gt;Literature&lt;/span&gt;&amp;quot;).FirstOrDefault();
    Subject subject = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; Subject() { Name = &amp;quot;&lt;span style="color:#8b0000;"&gt;SciFi&lt;/span&gt;&amp;quot; };
    SubjectController controller = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; SubjectController(subjects);
    ActionResult result = controller.Update(literature.Id, subject);
    Assert.IsNotNull(result);
    Assert.IsInstanceOfType(result, &lt;span style="color:#0000ff;"&gt;typeof&lt;/span&gt;(RedirectToRouteResult));
    RedirectToRouteResult redirect = (RedirectToRouteResult)result;
    Assert.IsTrue(&lt;span style="color:#0000ff;"&gt;string&lt;/span&gt;.IsNullOrEmpty(redirect.RouteName));
    Assert.IsTrue(redirect.RouteValues.ContainsKey(&amp;quot;&lt;span style="color:#8b0000;"&gt;id&lt;/span&gt;&amp;quot;));
    Assert.AreEqual(literature.Id, redirect.RouteValues[&amp;quot;&lt;span style="color:#8b0000;"&gt;id&lt;/span&gt;&amp;quot;]);
    Assert.IsTrue(redirect.RouteValues.ContainsKey(&amp;quot;&lt;span style="color:#8b0000;"&gt;action&lt;/span&gt;&amp;quot;));
    Assert.AreEqual(&amp;quot;&lt;span style="color:#8b0000;"&gt;Details&lt;/span&gt;&amp;quot;, redirect.RouteValues[&amp;quot;&lt;span style="color:#8b0000;"&gt;action&lt;/span&gt;&amp;quot;]);
    Assert.IsTrue(subjects.Any(s =&amp;gt; s.Name == &amp;quot;&lt;span style="color:#8b0000;"&gt;SciFi&lt;/span&gt;&amp;quot;));
    Assert.AreEqual(literature.Id, subjects.Where(s =&amp;gt; s.Name == &amp;quot;&lt;span style="color:#8b0000;"&gt;SciFi&lt;/span&gt;&amp;quot;).Single().Id);
}
&lt;/pre&gt;
&lt;/pre&gt;
&lt;p&gt;La acci&amp;oacute;n del controlador:&lt;/p&gt;
&lt;pre&gt;&lt;pre style="background-color:#ffffff;margin:0em;width:100%;font-family:consolas,courier,monospace;font-size:12px;"&gt;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; ActionResult Update(&lt;span style="color:#0000ff;"&gt;int&lt;/span&gt; id, Subject subject)
{
    Subject toupdate = &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.subjects.Where(s =&amp;gt; s.Id == id).Single();
    toupdate.Name = subject.Name;
    &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; RedirectToAction(&amp;quot;&lt;span style="color:#8b0000;"&gt;Details&lt;/span&gt;&amp;quot;, &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; { id = id });
}
&lt;/pre&gt;
&lt;/pre&gt;
&lt;p&gt;Todos los tests en verde:&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.ajlopez.com/images/articles2/apptdd0303.png" alt="" /&gt; &lt;/p&gt;
&lt;p&gt;Algunas advertencias: los tests est&amp;aacute;n revisando dos salidas: los cambios en el dominio (por ahor auna simple lista) y los resultados de las acciones (un tema MVC). Deber&amp;iacute;a hacer refactor (seguramente en un futuro post) de la implementaci&amp;oacute;n del controlador, para separar las actualizaciones del dominio de los resultados de la navegaci&amp;oacute;n. Escrib&amp;iacute; el ejemplo de esta manera para mostrar c&amp;oacute;mo hacer refactor m&amp;aacute;s adelante para conseguir una mejor implementaci&amp;oacute;n. Mi idea es tener un servicio de manejo de temas, y escribir con tests. Luego usarlo desde el controlador. Deber&amp;iacute;a tambien tratar los casos de actualizaci&amp;oacute;n de un item inexistente o la creaci&amp;oacute;n de un item ya existente.&lt;/p&gt;
&lt;p&gt;Otra nota: no puse ninguna vista MVC todav&amp;iacute;a. Pero ahora ya tengo los tests como para agregarlas con confianza. Cuando las agregue, la conducta esperada del controlador ya estar&amp;aacute; probada.&lt;/p&gt;
&lt;p&gt;Nos leemos!&lt;/p&gt;
&lt;p&gt;Angel &amp;ldquo;Java&amp;rdquo; Lopez &lt;br /&gt;&lt;a href="http://www.ajlopez.com"&gt;http://www.ajlopez.com&lt;/a&gt; &lt;br /&gt;&lt;a href="http://twitter.com/ajlopez"&gt;http://twitter.com/ajlopez&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1794129" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/lopez/archive/tags/.NET/default.aspx">.NET</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Desarrollo+de+Software/default.aspx">Desarrollo de Software</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/C+Sharp/default.aspx">C Sharp</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Desarrollo+Agil/default.aspx">Desarrollo Agil</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/TDD/default.aspx">TDD</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/ASP.NET+MVC/default.aspx">ASP.NET MVC</category></item><item><title>Escribiendo una Aplicación usando TDD (Parte 2) Primera lista</title><link>http://msmvps.com/blogs/lopez/archive/2011/03/25/writing_2D00_an_2D00_application_2D00_using_2D00_tdd_2D00_part_2D00_2_2D00_first_2D00_list.aspx</link><pubDate>Fri, 25 Mar 2011 14:48:00 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1790545</guid><dc:creator>lopez</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/lopez/rsscomments.aspx?PostID=1790545</wfw:commentRss><comments>http://msmvps.com/blogs/lopez/archive/2011/03/25/writing_2D00_an_2D00_application_2D00_using_2D00_tdd_2D00_part_2D00_2_2D00_first_2D00_list.aspx#comments</comments><description>&lt;p&gt;&lt;a href="http://msmvps.com/blogs/lopez/archive/2011/03/31/writing_2D00_an_2D00_application_2D00_using_2D00_tdd_2D00_part_2D00_3_2D00_first_2D00_detail.aspx"&gt;Siguiente post en esta serie &lt;/a&gt;&lt;br /&gt;&lt;a href="http://msmvps.com/blogs/lopez/archive/2011/03/01/writing_2D00_an_2D00_application_2D00_using_2D00_tdd_2D00_part_2D00_1_2D00_introduction.aspx"&gt;Anterior post en esta serie&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Gracias a un comentario de &lt;a href="http://twitter.com/MartinSalias"&gt;@MartinSalias&lt;/a&gt;, en mi post anterior, eleg&amp;iacute; para desarrollar este ejemplo un dominio simple: mi biblioteca personal, mis libros. En esta primera iteraci&amp;oacute;n de c&amp;oacute;digo, quiero listar los temas de los libros: F&amp;iacute;sica, Matem&amp;aacute;ticas, Biolog&amp;iacute;a, Literatura&amp;hellip; (similar a los g&amp;eacute;nereos del ejemplo &lt;a href="http://mvcmusicstore.codeplex.com/"&gt;MvcMusicStore&lt;/a&gt; de &lt;a href="http://twitter.com/jongalloway"&gt;@jongalloway&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;Primero, cre&amp;eacute; una soluci&amp;oacute;n ASP.NET MVC 2 (estoy usando Visual Studio 2008) (el c&amp;oacute;digo de este post, como siempre, queda en mi &lt;a href="http://code.google.com/p/ajcodekatas/"&gt;AjCodeKatas Google Project&lt;/a&gt;, en el directorio trunk/AppTdd/Step01)&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.ajlopez.com/images/articles2/apptdd0101.png" alt="" /&gt; &lt;/p&gt;
&lt;p&gt;Luego, agregu&amp;eacute; un proyecto de test:&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.ajlopez.com/images/articles2/apptdd0102.png" alt="" /&gt; &lt;/p&gt;
&lt;p&gt;A este proyecto le agregu&amp;eacute; referencias a System.Web.Mvc and MyLibrary.Web.&lt;/p&gt;
&lt;p&gt;Agregu&amp;eacute; un test:&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.ajlopez.com/images/articles2/apptdd0103.png" alt="" /&gt; &lt;/p&gt;
&lt;p&gt;Limpi&amp;eacute; el c&amp;oacute;digo de la clase generada por el wizard, removiendo c&amp;oacute;digo no usado. Qued&amp;oacute;:&lt;/p&gt;
&lt;pre&gt;&lt;pre style="background-color:#ffffff;margin:0em;width:100%;font-family:consolas,courier,monospace;font-size:12px;"&gt;&lt;span style="color:#0000ff;"&gt;namespace&lt;/span&gt; MyLibrary.Web.Tests.Controllers
{
    &lt;span style="color:#0000ff;"&gt;using&lt;/span&gt; System;
    &lt;span style="color:#0000ff;"&gt;using&lt;/span&gt; System.Text;
    &lt;span style="color:#0000ff;"&gt;using&lt;/span&gt; System.Collections.Generic;
    &lt;span style="color:#0000ff;"&gt;using&lt;/span&gt; System.Linq;
    &lt;span style="color:#0000ff;"&gt;using&lt;/span&gt; Microsoft.VisualStudio.TestTools.UnitTesting;
    [TestClass]
    &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;class&lt;/span&gt; GenreControllerTests
    {
    }
}
&lt;/pre&gt;
&lt;/pre&gt;
&lt;p&gt;Ahora, agregu&amp;eacute; mi primer test:&lt;/p&gt;
&lt;pre&gt;&lt;pre style="background-color:#ffffff;margin:0em;width:100%;font-family:consolas,courier,monospace;font-size:12px;"&gt;        [TestMethod]
        &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;void&lt;/span&gt; GetGenres()
        {
            IList&amp;lt;Genre&amp;gt; genres = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; List&amp;lt;Genre&amp;gt;()
            {
                &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; Genre() { Name = &amp;quot;&lt;span style="color:#8b0000;"&gt;Mathematics&lt;/span&gt;&amp;quot; },
                &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; Genre() { Name = &amp;quot;&lt;span style="color:#8b0000;"&gt;Physics&lt;/span&gt;&amp;quot; },
                &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; Genre() { Name = &amp;quot;&lt;span style="color:#8b0000;"&gt;Biology&lt;/span&gt;&amp;quot; },
                &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; Genre() { Name = &amp;quot;&lt;span style="color:#8b0000;"&gt;Literature&lt;/span&gt;&amp;quot; }
            };
            GenreController controller = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; GenreController(genres);
            ActionResult result = controller.Index();
            Assert.IsNotNull(result);
            Assert.IsInstanceOfType(result, &lt;span style="color:#0000ff;"&gt;typeof&lt;/span&gt;(ViewResult));
            ViewResult viewResult = (ViewResult)result;
            Assert.IsInstanceOfType(viewResult.ViewData.Model, &lt;span style="color:#0000ff;"&gt;typeof&lt;/span&gt;(IList&amp;lt;Genre&amp;gt;));
            Assert.AreSame(genres, viewResult.ViewData.Model);
        }
		&lt;/pre&gt;
&lt;/pre&gt;
&lt;p&gt;La idea del test: crear el controlador, alimentarlo de una lista de temas, y luego invocar su acci&amp;oacute;n Index. Hecho eso, controlar el resultado. A esta altura, el c&amp;oacute;digo no compilaba: el controlador no exist&amp;iacute;a, no hab&amp;iacute;a clase Genre. As&amp;iacute; que escrib&amp;iacute; esas clases. La clase Genre, en el directorio Model del proyecto MyLibrary.Web:&lt;/p&gt;
&lt;pre&gt;&lt;pre style="background-color:#ffffff;margin:0em;width:100%;font-family:consolas,courier,monospace;font-size:12px;"&gt;    &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;class&lt;/span&gt; Genre
    {
        &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;string&lt;/span&gt; Name { &lt;span style="color:#0000ff;"&gt;get&lt;/span&gt;; &lt;span style="color:#0000ff;"&gt;set&lt;/span&gt;; }
    }
&lt;/pre&gt;
&lt;/pre&gt;
&lt;p&gt;Un controlador simple GenreController (agregado con click derecho sobre el directorio Controllers):&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.ajlopez.com/images/articles2/apptdd0104.png" alt="" /&gt; &lt;/p&gt;
&lt;p&gt;El wizard produjo este c&amp;oacute;digo:&lt;/p&gt;
&lt;pre&gt;&lt;pre style="background-color:#ffffff;margin:0em;width:100%;font-family:consolas,courier,monospace;font-size:12px;"&gt;    &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;class&lt;/span&gt; GenreController : Controller
    {
        &lt;span style="color:#008000;"&gt;//&lt;/span&gt;
        &lt;span style="color:#008000;"&gt;// GET: /Genre/&lt;/span&gt;
        &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; ActionResult Index()
        {
            &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; View();
        }
    }
&lt;/pre&gt;
&lt;/pre&gt;
&lt;p&gt;Lo modifiqu&amp;eacute; para que tenga el constructor que necesito en el test:&lt;/p&gt;
&lt;pre&gt;&lt;pre style="background-color:#ffffff;margin:0em;width:100%;font-family:consolas,courier,monospace;font-size:12px;"&gt;    &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;class&lt;/span&gt; GenreController : Controller
    {
        &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; GenreController()
        {
        }
        &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; GenreController(IList&amp;lt;Genre&amp;gt; genres)
        {
        }
        &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; ActionResult Index()
        {
            &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; View();
        }
    }
	&lt;/pre&gt;
&lt;/pre&gt;
&lt;p&gt;Noten que mi intenci&amp;oacute;n es compilar el test, no que fuencione: la lista de temas no es usada por esta primer implementaci&amp;oacute;n de controlador. Con todos estos cambios, pude compilar la soluci&amp;oacute;n y ejecutar el test:&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.ajlopez.com/images/articles2/apptdd0105.png" alt="" /&gt; &lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;El resultado:&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.ajlopez.com/images/articles2/apptdd0106.png" alt="" /&gt; &lt;/p&gt;
&lt;p&gt;El problema:&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.ajlopez.com/images/articles2/apptdd0107.png" alt="" /&gt; &lt;/p&gt;
&lt;p&gt;Como esperaba. Esto es parte del ciclo TDD: compilar, rojo, y ahora, hay que ir por el verde.&lt;/p&gt;
&lt;p&gt;Cambi&amp;eacute; el controlador (su interfaz ya estaba completa):&lt;/p&gt;
&lt;pre&gt;&lt;pre style="background-color:#ffffff;margin:0em;width:100%;font-family:consolas,courier,monospace;font-size:12px;"&gt;    &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;class&lt;/span&gt; GenreController : Controller
    {
        &lt;span style="color:#0000ff;"&gt;private&lt;/span&gt; IList&amp;lt;Genre&amp;gt; genres;
        &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; GenreController()
        {
        }
        &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; GenreController(IList&amp;lt;Genre&amp;gt; genres)
        {
            &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.genres = genres;
        }
        &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; ActionResult Index()
        {
            &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; View(genres);
        }
    }
&lt;/pre&gt;
&lt;/pre&gt;
&lt;p&gt;Y ahora, el resultado es:&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.ajlopez.com/images/articles2/apptdd0108.png" alt="" /&gt; &lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Triunfo de la mente sobre la materia! ;-)&lt;/p&gt;
&lt;p&gt;Ahora, es tiempo de refactoring. Bien, no tengo mucho para hacer ahora (me llega un comentario en &lt;a href="http://ajlopez.wordpress.com/2011/03/22/writing-an-application-using-tdd-part-2-first-list/"&gt;mi post en ingl&amp;eacute;s&lt;/a&gt; de &lt;a href="http://twitter.com/MartinSalias"&gt;@MartinSalias&lt;/a&gt;, sugiriendo cambios en la nomenclatura, bien, quedar&amp;aacute; para el pr&amp;oacute;ximo paso). Podr&amp;iacute;a mejorar alguna variable, nombre. La principal pieza faltante: la vista. Nota: el controlador no est&amp;aacute; preparado, a&amp;uacute;n, para ser consumido por una vista. No hay quien le provea los temas en ejecuci&amp;oacute;n. En el test, us&amp;eacute; un constructor que se los provee, pero ASP.NET MVC crear&amp;iacute;a la instancia del controlador usando el constructor sin par&amp;aacute;metros.&lt;/p&gt;
&lt;p&gt;Pr&amp;oacute;ximos pasos: mejorar el controlador para usar una vista, algunas acciones CRUD con tests, y vistas.&lt;/p&gt;
&lt;p&gt;Podr&amp;iacute;an preguntar: &amp;iquest;d&amp;oacute;nde est&amp;aacute; el repositorio de los temas? &amp;iquest;d&amp;oacute;nde est&amp;aacute;n los libros? &amp;iquest;y la base de datos? &amp;iquest;y la capa de servicios (service layer)? &amp;iquest;separaci&amp;oacute;n del dominio? Ok, son todas preguntas v&amp;aacute;lidas y temas a tratar. Pero mi idea es mostrar, de forma incremental, con TDD, c&amp;oacute;mo podemos ir agregando todo eso a medida que aparezcan m&amp;aacute;s requerimientos y especificaciones. Quiero que cada cosa que se agregue provenga del proceso de escribir test (ya sea de la especificaci&amp;oacute;n del test, o de la etapa de refactoring). Como escrib&amp;iacute; en &lt;a href="http://msmvps.com/blogs/lopez/archive/2011/03/01/writing_2D00_an_2D00_application_2D00_using_2D00_tdd_2D00_part_2D00_1_2D00_introduction.aspx"&gt;mi anterior post&lt;/a&gt;, esta es una clase de aproximaci&amp;oacute;n arriba-abajo (top-down). En este caso, el dominio es simple, as&amp;iacute; que comienzo desde el tope de la presentaci&amp;oacute;n. Luego de este ejemplo simple, a desarrollar en varios post, cambiar&amp;eacute; a un dominio menos simple. En ese caso, comenzar&amp;eacute; por construir por tests al propio dominio, en lugar de la presentaci&amp;oacute;n.&lt;/p&gt;
&lt;p&gt;Nos leemos!&lt;/p&gt;
&lt;p&gt;Angel &amp;ldquo;Java&amp;rdquo; Lopez &lt;br /&gt;&lt;a href="http://www.ajlopez.com"&gt;http://www.ajlopez.com&lt;/a&gt; &lt;br /&gt;&lt;a href="http://twitter.com/ajlopez"&gt;http://twitter.com/ajlopez&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1790545" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/lopez/archive/tags/.NET/default.aspx">.NET</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Desarrollo+de+Software/default.aspx">Desarrollo de Software</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/C+Sharp/default.aspx">C Sharp</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Desarrollo+Agil/default.aspx">Desarrollo Agil</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/TDD/default.aspx">TDD</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/ASP.NET+MVC/default.aspx">ASP.NET MVC</category></item><item><title>Escribiendo una Aplicación usando TDD (Part 1) Introducción</title><link>http://msmvps.com/blogs/lopez/archive/2011/03/01/writing_2D00_an_2D00_application_2D00_using_2D00_tdd_2D00_part_2D00_1_2D00_introduction.aspx</link><pubDate>Tue, 01 Mar 2011 09:21:00 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1789109</guid><dc:creator>lopez</dc:creator><slash:comments>4</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/lopez/rsscomments.aspx?PostID=1789109</wfw:commentRss><comments>http://msmvps.com/blogs/lopez/archive/2011/03/01/writing_2D00_an_2D00_application_2D00_using_2D00_tdd_2D00_part_2D00_1_2D00_introduction.aspx#comments</comments><description>&lt;p&gt;&lt;a href="http://msmvps.com/blogs/lopez/archive/2011/03/25/writing_2D00_an_2D00_application_2D00_using_2D00_tdd_2D00_part_2D00_2_2D00_first_2D00_list.aspx"&gt;Siguiente Post&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;Estoy escribiendo una serie de posts &lt;a href="http://msmvps.com/blogs/lopez/archive/2011/01/28/writing_2D00_an_2D00_interpreter_2D00_in_2D00_net_2D00_part_2D00_9.aspx"&gt;sobre escribir un int&amp;eacute;rprete usando TDD&lt;/a&gt; (&lt;a href="http://msmvps.com/blogs/lopez/archive/tags/TDD/default.aspx"&gt;Test-Driven Developement&lt;/a&gt;). Mi intenci&amp;oacute;n es mostrar el uso de TDD en c&amp;oacute;digo de producci&amp;oacute;n. Desde mi adopci&amp;oacute;n de TDD, produzco mejor c&amp;oacute;digo (eso espero ;-) y en menos tiempo (no m&amp;aacute;s largas sesiones de depuraci&amp;oacute;n ;-). Hay otros beneficios: si tenemos una aplicaci&amp;oacute;n con TDD, tenemos un buen code coverage (cubrimiento de c&amp;oacute;digo), y escribimos los casos de uso del c&amp;oacute;digo de la aplicaci&amp;oacute;n y los resultados esperados. Todo esto da confianza para mejorar la aplicaci&amp;oacute;n, posiblemente por otro equipo. Pienso que entregar una aplicaci&amp;oacute;n con TDD es un plus para el cliente final y para la evoluci&amp;oacute;n saludable de software exitosa. Podemos tener lo mismo con simples tests, pero TDD agregar el correcto proceso iterativo para armar c&amp;oacute;digo de producci&amp;oacute;n, en vez de dejar los tests &amp;ldquo;para despu&amp;eacute;s&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;Pero el ejemplo de int&amp;eacute;rprete que estoy armando es una especie de &amp;ldquo;largo code kata&amp;rdquo;. Podr&amp;iacute;an decir: &amp;ldquo;Eh! No es la clase de c&amp;oacute;digo que escribo todos los d&amp;iacute;as&amp;rdquo;. S&amp;iacute;, es verdad. Entonces, es tiempo de comenzar una serie de posts escribiendo una aplicaci&amp;oacute;n.&lt;/p&gt;
&lt;p&gt;Eleg&amp;iacute; estas tecnolog&amp;iacute;as para usar:&lt;/p&gt;
&lt;p&gt;- .NET 3.5 (puede que pase en alg&amp;uacute;n momento a 4.0)&lt;/p&gt;
&lt;p&gt;- ASP.NET MVC 2 (podr&amp;iacute;a usar la versi&amp;oacute;n 3)&lt;/p&gt;
&lt;p&gt;- Visual Studio 2008 (el otro candidato es VS 2010), usando su soporte de tests, como en mis anteriores posts.&lt;/p&gt;
&lt;p&gt;Tengo que seleccionar una tecnolog&amp;iacute;a de persistencia. Esoy pensando en &lt;a href="http://www.nhforge.org/"&gt;NHibernate 3.x&lt;/a&gt; + &lt;a href="http://fluentnhibernate.org/"&gt;Fluent NHibernate&lt;/a&gt; o con &lt;a href="http://fabiomaulo.blogspot.com/2010/02/conform-nhibernate-un-mapping.html"&gt;ConfORM&lt;/a&gt;; La alternativa es &lt;a href="http://weblogs.asp.net/scottgu/archive/2010/07/16/code-first-development-with-entity-framework-4.aspx"&gt;Entity Framework 4 with Code First&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Hay dos caminos a seguir, en este ejemplo iterativo:&lt;/p&gt;
&lt;p&gt;- Dominio simple: comenzar escribiendo c&amp;oacute;digo de presentaci&amp;oacute;n y tests, entonces pasar a una capa de aplicaci&amp;oacute;n/servicios, y de ah&amp;iacute;, pasar a la capa de persistencia&lt;/p&gt;
&lt;p&gt;- Un dominio m&amp;aacute;s complejo: escribir el c&amp;oacute;digo del dominio con tests, reci&amp;eacute;n ah&amp;iacute; pasar a la presentaci&amp;oacute;n y a la persistencia.&lt;/p&gt;
&lt;p&gt;El primer camino es un tipo de aproximaci&amp;oacute;n &amp;ldquo;top-down&amp;rdquo;. Es opuesto a lo que he usado en mi serie de int&amp;eacute;rprete (noten la ausencia de mocks, stubs, en mi camino &amp;ldquo;bottom-up&amp;rdquo;, escribiendo expresiones, comandos, pasando a parte del lexer, luego al parser, etc&amp;hellip;). Ahora, con esta nueva forma de hacer TDD, quiero mostrar el armado incremental de funcionalidad, a&amp;uacute;n sin tener una base de datos, modelo de persistencia, y otros detalles tecnol&amp;oacute;gicos desde el principio. ASP.NET MVC y TDD nos permiten escribir los casos de uso iniciales de una manera simple, en un dominio simple, abrazando un desarrollo &amp;aacute;gil e incremental. Otro beneficio es que podemos entregar algo &amp;ldquo;que funciona&amp;rdquo; para obtener &amp;quot;feedback&amp;quot; temprano del usuario.&lt;/p&gt;
&lt;p&gt;Luego de explorar esta forma de hacer desarrollo con TDD, cambiar&amp;eacute; a un dominio un poco m&amp;aacute;s complejo. En esos casos, yo prefiero comenzar escribiendo el dominio con tests, enfoc&amp;aacute;ndome en el n&amp;uacute;cleo de la aplicaci&amp;oacute;n, agregarn en el camino algo de presentaci&amp;oacute;n, para mostrar algo al usuario final, pero sin gastar mucho tiempo en temas complejos de interfaz (AJAX, javascript, interfaz din&amp;aacute;mica en el browser).&lt;/p&gt;
&lt;p&gt;El formato de escribir una serie de post es importante: hay muchos ejemplos de c&amp;oacute;digo de aplicaciones con TDD (por ejemplo, muchos proyectos de c&amp;oacute;digo abierto), pero muchos de esos ejemplos muestran &amp;ldquo;la etapa final&amp;rdquo; de un largo camino. Escribiendo un ejemplo m&amp;aacute;s simple, incrementalmente, es una mejor forma de comenzar a comprender el estilo TDD de hacer desarrollo de software.&lt;/p&gt;
&lt;p&gt;Bueno, suficiente por hoy. Este es un post de introducci&amp;oacute;n, para presentar la idea, y comenzar a calentar motores! Comentarios, sugerencias, bienvenidas!.&lt;/p&gt;
&lt;p&gt;Nos leemos!&lt;/p&gt;
&lt;p&gt;Angel &amp;ldquo;Java&amp;rdquo; Lopez &lt;br /&gt;&lt;a href="http://www.ajlopez.com"&gt;http://www.ajlopez.com&lt;/a&gt; &lt;br /&gt;&lt;a href="http://twitter.com/ajlopez"&gt;http://twitter.com/ajlopez&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1789109" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/lopez/archive/tags/.NET/default.aspx">.NET</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Desarrollo+de+Software/default.aspx">Desarrollo de Software</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/C+Sharp/default.aspx">C Sharp</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Desarrollo+Agil/default.aspx">Desarrollo Agil</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/TDD/default.aspx">TDD</category></item><item><title>Popularidad de Lenguajes de Programación</title><link>http://msmvps.com/blogs/lopez/archive/2009/07/08/popularidad-de-lenguajes-de-programaci-243-n.aspx</link><pubDate>Wed, 08 Jul 2009 09:50:06 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1698705</guid><dc:creator>lopez</dc:creator><slash:comments>3</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/lopez/rsscomments.aspx?PostID=1698705</wfw:commentRss><comments>http://msmvps.com/blogs/lopez/archive/2009/07/08/popularidad-de-lenguajes-de-programaci-243-n.aspx#comments</comments><description>&lt;p&gt;Me temo que &lt;a href="http://en.wordpress.com/tag/ajlisp/" target="_blank"&gt;AjLisp&lt;/a&gt; y &lt;a href="http://en.wordpress.com/tag/ajbasic" target="_blank"&gt;AjBasic&lt;/a&gt; lo usamos yo y nadie más… snif… :-). Pero hay lenguajes más populares que esos. Ya es clásica la lista de TIOBE Software:&lt;/p&gt;  &lt;p&gt;&lt;a title="http://www.tiobe.com/index.php/content/paperinfo/tpci/index.html" href="http://www.tiobe.com/index.php/content/paperinfo/tpci/index.html"&gt;http://www.tiobe.com/index.php/content/paperinfo/tpci/index.html&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;img src="http://www.todocontenidos.com/images/articles/langpop01.png" alt="" /&gt; &lt;/p&gt;  &lt;p&gt;donde aparece Java como el lenguaje más popular, lo que no me asombra. Pero sí me llama la atención la popularidad de C y C++, que deben tener su gran uso en el ambiente Unix, Linux, y otros. Como cuarto, encuentro hoy, Julio de 2009, a PHP, que lo entiendo: la mayor parte del código de sitios dinámicos está en PHP, lejos quedaron los años del predominio del venerable Perl. Y recién en sexto y séptimo lugar, está Visual Basic (parece que agrupan el de .NET y el clásico), y C#. Vean que al final de la lista, aparecen lenguajes con mínimos porcentajes, pero aparecen: RPG, Pascal, Abap, Lisp/Scheme. Más abajo, en la misma página encontraran la lista de posición 21 a 50, donde aparecen COBOL, Objective-C, Fortran, Logo, Prolog, Ada (todavía anda por ahí? :-), Scala, Erlang…. y esta es la lista de 51 a 100:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;ABC, AD, Algol, Alpha, Applescript, Beta, Boo, C shell, cg, Clean, Cobra, cT, Curl, Dylan, Eiffel, Euphoria, Factor, Fan, Icon, IDL, Inform, Io, Lingo, MAD, Magic, Maple, Mathematica, MAX/MSP, MOO, MUMPS, Natural, Oberon, Occam, Oz, PL/I, Postscript, PowerBuilder, Progress, Q, R, Revolution, REXX, S-lang, SIGNAL, SPSS, SuperCollider, VBScript, Verilog, VHDL, XSLT&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Notable lista, recomendaría tantos lenguajes de esa lista, simplemente para aprender nuevas formas de programar (notable que aparezca todavía MUMPS, REXX, tendría que ver con más detalle a Io). Esta lista de popularidad se basa en el examen de búsquedas en Google, hace un tiempo pasaron a agregar MSN y Yahoo.&lt;/p&gt;  &lt;p&gt;Pero en estos días, encontré otra página:&lt;/p&gt;  &lt;p&gt;&lt;a title="http://langpop.com/" href="http://langpop.com/"&gt;http://langpop.com/&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;img src="http://www.todocontenidos.com/images/articles/langpop02.png" alt="" /&gt; &lt;/p&gt;  &lt;p&gt;con información de ranking de popularidad, pero con agrupadas con distintas fuentes, como Yahoo Search, search en Google Code, Freshmeat, Craiglist, Amazon.&lt;/p&gt;  &lt;p&gt;En lo que veo hoy ahí, julio de 2009, según Yahoo Search C es más popular que Java. Pero para Craiglist, primero PHP, segundo SQL (!!!), en Amazon ganan C, C++ y C#, por encima de Java. Y así, noto dispersión de los resultados, dependiendo de la fuente.&lt;/p&gt;  &lt;p&gt;La popularidad de un lenguaje importa. No tanto para entender el lenguaje (muchos lenguajes “boutique” tienen interesantes conceptos, a estudiar con detalle), sino para tener una idea de qué tecnología ha sido adoptada por la comunidad, pero habría que ver más allá: por qué la eligieron, y en qué tipo de proyectos. Dudo que haya muchas aplicaciones desktop, en PHP.&lt;/p&gt;  &lt;p&gt;Resumen: gran cantidad de lenguajes, hay lenguajes viejos, desde COBOL y Smalltalk, y más “nuevos” como Boo, Ruby, Python. Y `cuatros grandes grupos: Java, C/C++, lenguajes .NET (VB.NET, C#), PHP, como claros grupos líderes.&lt;/p&gt;  &lt;p&gt;Pienso que, como desarrolladores de software, debemos tener contacto con esos cuatro grupos, y además, con alguno de los “otros”, para aprender otras ideas y formas de programar.&lt;/p&gt;  &lt;p&gt;No&amp;#160; me enojo si intentan ver &lt;a href="http://en.wordpress.com/tag/ajlisp" target="_blank"&gt;AjLisp&lt;/a&gt; o &lt;a href="http://en.wordpress.com/tag/ajbasic" target="_blank"&gt;AjBasic&lt;/a&gt;… :-)&lt;/p&gt;  &lt;p&gt;Nos leemos!&lt;/p&gt;  &lt;p&gt;Angel “Java” Lopez   &lt;br /&gt;&lt;a href="http://www.ajlopez.com"&gt;http://www.ajlopez.com&lt;/a&gt;    &lt;br /&gt;&lt;a href="http://twitter.com/ajlopez"&gt;http://twitter.com/ajlopez&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1698705" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/lopez/archive/tags/.NET/default.aspx">.NET</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Java/default.aspx">Java</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/PHP/default.aspx">PHP</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Smalltalk/default.aspx">Smalltalk</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Desarrollo+de+Software/default.aspx">Desarrollo de Software</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/C+Sharp/default.aspx">C Sharp</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/AjLisp/default.aspx">AjLisp</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/AjBasic/default.aspx">AjBasic</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Lenguajes+de+Programaci_26002300_243_3B00_n/default.aspx">Lenguajes de Programaci&amp;#243;n</category></item><item><title>Presentando AjCat</title><link>http://msmvps.com/blogs/lopez/archive/2009/04/29/presenting_2D00_ajcat.aspx</link><pubDate>Wed, 29 Apr 2009 10:24:00 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1691539</guid><dc:creator>lopez</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/lopez/rsscomments.aspx?PostID=1691539</wfw:commentRss><comments>http://msmvps.com/blogs/lopez/archive/2009/04/29/presenting_2D00_ajcat.aspx#comments</comments><description>&lt;p&gt;Hace algo m&amp;aacute;s de un mes, estuve trabajando en un int&amp;eacute;rprete del lenguaje Cat:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.cat-language.com/" title="The Cat Programming Language"&gt;The Cat Programming Language&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Cat is a functional stack-based programming language inspired by the &lt;/em&gt;&lt;a href="http://www.latrobe.edu.au/philosophy/phimvt/"&gt;&lt;em&gt;Joy programming language&lt;/em&gt;&lt;/a&gt;&lt;em&gt;. The primary differences is that Cat provides a static type system with type inferencing (like ML or Haskell), and a term rewriting macro language extension language called &lt;/em&gt;&lt;a href="https://ajlopez.wordpress.com/wp-admin/metacat.html"&gt;&lt;em&gt;MetaCat&lt;/em&gt;&lt;/a&gt;&lt;em&gt;. &lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Cat is a high-level intermediate language translation that can also be used as a stand alone language for simple application development. In this way it occupies a similar niche to PostScript. Cat is also an appropriate language for teaching of basic programming concepts. &lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="http://todocontenidos.com/images/articles/ajcat01.png" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;Si no conocen el lenguaje Cat, recomiendar&amp;iacute;a leer:&lt;/p&gt;
&lt;p&gt;&lt;a target="_blank" href="http://www.cat-language.com/tutorial.html"&gt;Cat Tutorial&lt;/a&gt; &lt;br /&gt;&lt;a target="_blank" href="http://www.cat-language.com/manual.html"&gt;Cat Specification&lt;/a&gt; &lt;br /&gt;&lt;a target="_blank" href="http://www.cat-language.com/primitives.html"&gt;Cat Primitives&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Publiqu&amp;eacute; el c&amp;oacute;digo como parte de mi proyecto Code Katas en Google Code. El nombre que us&amp;eacute; es AjCat:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://code.google.com/p/ajcodekatas/source/browse/#svn/trunk/AjCat" title="http://code.google.com/p/ajcodekatas/source/browse/#svn/trunk/AjCat"&gt;http://code.google.com/p/ajcodekatas/source/browse/#svn/trunk/AjCat&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;La soluci&amp;oacute;n tiene tres proyectos:&lt;/p&gt;
&lt;p&gt;&lt;img src="http://todocontenidos.com/images/articles/ajcat02.png" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;La actual implementaci&amp;oacute;n no es completa. Solo soporta enteros, todav&amp;iacute;a no soporta objetos .NET, y no hay primitivas de gr&amp;aacute;ficos. Pero est&amp;aacute; implementado gran parte de las primitivas y funciones definidas en Cat.&lt;/p&gt;
&lt;p&gt;Corriendo el programa de consola, pueden ingresar y evaluar expresiones:&lt;/p&gt;
&lt;p&gt;&lt;img src="http://todocontenidos.com/images/articles/ajcat05.png" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;Este c&amp;oacute;digo est&amp;aacute; dedicado a &lt;a href="http://weblogs.shockbyte.com.ar/"&gt;Rodolfo Finocchieti&lt;/a&gt; (&lt;a href="http://twitter.com/rodolfof"&gt;@rodolfof&lt;/a&gt; en Twitter) quien me dej&amp;oacute; un comentario ac&amp;aacute; en este blog, coment&amp;aacute;ndome de este lenguaje Cat, una idea fascinante.&lt;/p&gt;
&lt;p&gt;Los tests est&amp;aacute;n en verdes:&lt;/p&gt;
&lt;p&gt;&lt;img src="http://todocontenidos.com/images/articles/ajcat03.png" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;Y hay un buen code coverage&lt;/p&gt;
&lt;p&gt;&lt;img src="http://todocontenidos.com/images/articles/ajcat04.png" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;Como siempre, me divert&amp;iacute; escribiendo este c&amp;oacute;digo.&lt;/p&gt;
&lt;p&gt;Nos leemos!&lt;/p&gt;
&lt;p&gt;Angel &amp;ldquo;Java&amp;rdquo; Lopez &lt;br /&gt;&lt;a href="http://www.ajlopez.com/"&gt;http://www.ajlopez.com/&lt;/a&gt; &lt;br /&gt;&lt;a href="http://twitter.com/ajlopez"&gt;http://twitter.com/ajlopez&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Enjoying &lt;a href="http://ajlopez.zoomblog.com/archivo/2009/04/08/eric-Clapton-Everyday-I-Have-the-Blues.html" title="Eric Clapton Everyday I Have the Blues Live"&gt;Eric Clapton Everyday I Have the Blues Live&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1691539" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/lopez/archive/tags/.NET/default.aspx">.NET</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Desarrollo+de+Software/default.aspx">Desarrollo de Software</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/C+Sharp/default.aspx">C Sharp</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Lenguajes+de+Programaci_26002300_243_3B00_n/default.aspx">Lenguajes de Programaci&amp;#243;n</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Programaci_26002300_243_3B00_n+Funcional/default.aspx">Programaci&amp;#243;n Funcional</category></item><item><title>CodeRun plataforma de desarrollo en línea</title><link>http://msmvps.com/blogs/lopez/archive/2009/03/24/coderun-plataforma-de-desarrollo-en-l-237-nea.aspx</link><pubDate>Tue, 24 Mar 2009 11:54:50 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1680972</guid><dc:creator>lopez</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/lopez/rsscomments.aspx?PostID=1680972</wfw:commentRss><comments>http://msmvps.com/blogs/lopez/archive/2009/03/24/coderun-plataforma-de-desarrollo-en-l-237-nea.aspx#comments</comments><description>&lt;p&gt;El bueno de &lt;a href="http://blog.salias.com.ar/" target="_blank"&gt;Martín Salías&lt;/a&gt; (@MartinSalias) me avisa de este sitio y aplicación notable:&lt;/p&gt; &lt;p&gt;&lt;a title="http://www.coderun.com/" href="http://www.coderun.com/"&gt;http://www.coderun.com/&lt;/a&gt;&lt;/p&gt; &lt;p&gt;&lt;img src="http://www.todocontenidos.com/images/articles/coderun03.png" alt="" /&gt; &lt;/p&gt; &lt;p&gt;Pueden registrarse, el servicio básico es gratuito.&lt;/p&gt; &lt;p&gt;Al ingresar, se encuentran con algo parecido al Visual Studio:&lt;/p&gt; &lt;p&gt;&lt;img src="http://www.todocontenidos.com/images/articles/coderun02.png" alt="" /&gt; &lt;/p&gt; &lt;p&gt;Si vamos a crear un nuevo proyecto, vemos los distintos tipos de soluciones soportadas:&lt;/p&gt; &lt;p&gt;&lt;img src="http://www.todocontenidos.com/images/articles/coderun01.png" alt="" /&gt; &lt;/p&gt; &lt;p&gt;Hasta tienen para desarrollar una aplicación para Facebook. Eligiendo el ejemplo de Hello World, clásico desde el Kernighan y Ritchie, obtenemos:&lt;/p&gt; &lt;p&gt;&lt;img src="http://www.todocontenidos.com/images/articles/coderun04.png" alt="" /&gt; &lt;/p&gt; &lt;p&gt;Lo podemos compilar y ejecutar:&lt;/p&gt; &lt;p&gt;&lt;img src="http://www.todocontenidos.com/images/articles/coderun05.png" alt="" /&gt; &lt;/p&gt; &lt;p&gt;Era algo que yo estaba esperando: tener un entorno de desarrollo en línea (no solamente una máquina a la que pueda acceder, sino todo instalado para cumplir con una función). Veremos hasta dónde llega esta tendencia, pero veo que tendremos cada vez más poder de procesamiento, sin tener que actualizar el hardware local o el software nuestro. En vez de menú de programas, iremos a favoritos en el browser.&lt;/p&gt; &lt;p&gt;Ya me veo programando un Code Kata desde un ciber, como en mis tiempos de PHP ... ;-)&lt;/p&gt; &lt;p&gt;Debe haber un Eclipse en línea, ¿conocen algún enlace?&lt;/p&gt; &lt;p&gt;Nos leemos!&lt;/p&gt; &lt;p&gt;Angel &amp;quot;Java&amp;quot; Lopez&lt;br /&gt;&lt;a href="http://www.ajlopez.com/"&gt;http://www.ajlopez.com/&lt;/a&gt;&lt;br /&gt;&lt;a href="http://twitter.com/ajlopez"&gt;http://twitter.com/ajlopez&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1680972" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/lopez/archive/tags/.NET/default.aspx">.NET</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Desarrollo+de+Software/default.aspx">Desarrollo de Software</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/C+Sharp/default.aspx">C Sharp</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/ASP.NET/default.aspx">ASP.NET</category></item><item><title>Test-driven development en acción, usando Visual Studio</title><link>http://msmvps.com/blogs/lopez/archive/2009/03/18/test-driven-development-en-acci-243-n-usando-visual-studio.aspx</link><pubDate>Wed, 18 Mar 2009 09:09:42 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1678959</guid><dc:creator>lopez</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/lopez/rsscomments.aspx?PostID=1678959</wfw:commentRss><comments>http://msmvps.com/blogs/lopez/archive/2009/03/18/test-driven-development-en-acci-243-n-usando-visual-studio.aspx#comments</comments><description>&lt;p&gt;Estoy preparando una charla para el jueves de la semana que viene, 26 de Marzo, en el &lt;a href="http://www.mug.org.ar/"&gt;Microsoft User Group&lt;/a&gt; de Argentina. Pueden inscribirse en:&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.mug.org.ar/Eventos/3234.aspx" target="_blank"&gt;MEDIA JORNADA &amp;quot;Test-driven development en acción, usando Visual Studio&amp;quot;&lt;/a&gt;.&lt;/p&gt; &lt;p&gt;&lt;img src="http://www.todocontenidos.com/images/articles/mugtdd.png" alt="" /&gt; &lt;/p&gt; &lt;p&gt;El horario es de 18:30 a 21:30. La idea es ir armando ejemplos usando los principios de TDD, con código que muestre:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Documentar el código con tests, en vez de en papel  &lt;li&gt;Usar listas de test para generar requerimientos explícitos  &lt;li&gt;Refactorear y mejorar el diseño del código  &lt;li&gt;Test bajo una UI delgada  &lt;li&gt;Test para cambios incrementales, minimizando la depuración  &lt;li&gt;Entregar software que sea verificable y robusto&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Lo que veremos estará basado en .NET y Visual Studio, pero se puede aplicar a otros entornos, lenguajes y tecnologías. Las ideas de base son las mismas.&lt;/p&gt; &lt;p&gt;Como siempre, preparar una charla sirve para aclarar los puntos que uno va aplicando en el día a día. Explicar algo, nos permite entenderlo mejor.&lt;/p&gt; &lt;p&gt;Es gratis PARA LOS SOCIOS DEL MUG. Los demás, ¿qué esperan para asociarse? ;-)&lt;/p&gt; &lt;p&gt;Como en otras ocasiones, publicaré en mi sitio el material que utilice en el curso, y probablemente, aparecerán posts por este blog, explicando algunos puntos.&lt;/p&gt; &lt;p&gt;¿Sugerencias a incluir en el temario? ¿Otros temas interesantes para armar una charla-serie de posts?&lt;/p&gt; &lt;p&gt;(Gracias a la gente del MUG, en especial a Gustavo Bachrach, que me han pedido un post para publicar en la revista que entregan a los socios).&lt;/p&gt; &lt;p&gt;Nos leemos!&lt;/p&gt; &lt;p&gt;Angel &amp;quot;Java&amp;quot; Lopez&lt;br /&gt;&lt;a href="http://www.ajlopez.com/"&gt;http://www.ajlopez.com/&lt;/a&gt;&lt;br /&gt;&lt;a href="http://twitter.com/ajlopez"&gt;http://twitter.com/ajlopez&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1678959" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/lopez/archive/tags/.NET/default.aspx">.NET</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Cursos/default.aspx">Cursos</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Desarrollo+de+Software/default.aspx">Desarrollo de Software</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/C+Sharp/default.aspx">C Sharp</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/VB.NET/default.aspx">VB.NET</category></item><item><title>TDD and Code Kata: Writing a Lexer for AjRuby</title><link>http://msmvps.com/blogs/lopez/archive/2009/03/12/tdd_2D00_and_2D00_code_2D00_kata_2D00_writing_2D00_a_2D00_lexer_2D00_for_2D00_ajruby.aspx</link><pubDate>Thu, 12 Mar 2009 05:11:00 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1677718</guid><dc:creator>lopez</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/lopez/rsscomments.aspx?PostID=1677718</wfw:commentRss><comments>http://msmvps.com/blogs/lopez/archive/2009/03/12/tdd_2D00_and_2D00_code_2D00_kata_2D00_writing_2D00_a_2D00_lexer_2D00_for_2D00_ajruby.aspx#comments</comments><description>&lt;p&gt;Muchas veces, escribo programas tipo code kata, para entrenarme en algún tema de desarrollo de software. En estos últimos meses, escribí varios mini intérpretes, usando TDD, code coverage, y C#. La semana pasada, estuve trabajando en el lanzamiento de otro pet project, AjRuby. El punto de inicio: el analizador léxico, el lexer.&lt;/p&gt;  &lt;p&gt;Un lexer es un programa que analiza el código fuente de un programa, y retorna sus tokens, las “palabras” que componen el programa. En el caso de AjRuby, escribí un lexer que sigue la gramática de Ruby. No está completo aún, pero funciona.&lt;/p&gt;  &lt;p&gt;Pueden ver el progreso del proyecto, en el repositorio de Google Code:&lt;/p&gt;  &lt;p&gt;&lt;a title="http://code.google.com/p/ajcodekatas/source/browse#svn/trunk/AjRuby" href="http://code.google.com/p/ajcodekatas/source/browse#svn/trunk/AjRuby"&gt;http://code.google.com/p/ajcodekatas/source/browse#svn/trunk/AjRuby&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;La solución tiene un proyecto de librería de clases, y otro de tests:&lt;/p&gt;  &lt;p&gt;&lt;img src="http://www.todocontenidos.com/images/articles/ajruby02.png" alt="" /&gt; &lt;/p&gt;  &lt;p&gt;Hay una clase Token, que representa cada token:&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;div class="wlWriterSmartContent" id="57F11A72-B0E5-49c7-9094-E3A15BD5B5E7:3556dfda-95db-4216-8c88-ba67a9266e51" style="padding-right:0px;display:inline;padding-left:0px;float:none;padding-bottom:0px;margin:0px;padding-top:0px;"&gt;   &lt;pre style="background-color:white;"&gt;&lt;div&gt;&lt;span style="color:#000000;"&gt;    &lt;/span&gt;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000ff;"&gt;class&lt;/span&gt;&lt;span style="color:#000000;"&gt; Token
    {
        &lt;/span&gt;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000ff;"&gt;string&lt;/span&gt;&lt;span style="color:#000000;"&gt; Value { &lt;/span&gt;&lt;span style="color:#0000ff;"&gt;get&lt;/span&gt;&lt;span style="color:#000000;"&gt;; &lt;/span&gt;&lt;span style="color:#0000ff;"&gt;set&lt;/span&gt;&lt;span style="color:#000000;"&gt;; }

        &lt;/span&gt;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; TokenType TokenType { &lt;/span&gt;&lt;span style="color:#0000ff;"&gt;get&lt;/span&gt;&lt;span style="color:#000000;"&gt;; &lt;/span&gt;&lt;span style="color:#0000ff;"&gt;set&lt;/span&gt;&lt;span style="color:#000000;"&gt;; }
    }
&lt;/span&gt;&lt;/div&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;El TokenType es una enumeración:&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;div class="wlWriterSmartContent" id="57F11A72-B0E5-49c7-9094-E3A15BD5B5E7:b030a353-46ec-4f15-be42-fe729deaca08" style="padding-right:0px;display:inline;padding-left:0px;float:none;padding-bottom:0px;margin:0px;padding-top:0px;"&gt;
  &lt;pre style="background-color:white;"&gt;&lt;div&gt;&lt;span style="color:#000000;"&gt;    &lt;/span&gt;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000ff;"&gt;enum&lt;/span&gt;&lt;span style="color:#000000;"&gt; TokenType
    {
        Name,
        Integer,
        Real,
        Boolean,
        String,
        Operator,
        Separator
    }
&lt;/span&gt;&lt;/div&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;Hay una clase LexerTest.cs, conteniendo tests como:&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;div class="wlWriterSmartContent" id="57F11A72-B0E5-49c7-9094-E3A15BD5B5E7:3acb3099-f7eb-417e-b132-9927cd84a1f9" style="padding-right:0px;display:inline;padding-left:0px;float:none;padding-bottom:0px;margin:0px;padding-top:0px;"&gt;
  &lt;pre style="background-color:white;"&gt;&lt;div&gt;&lt;span style="color:#000000;"&gt;        [TestMethod]
        &lt;/span&gt;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000ff;"&gt;void&lt;/span&gt;&lt;span style="color:#000000;"&gt; ShouldProcessName()
        {
            Lexer lexer &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000ff;"&gt;new&lt;/span&gt;&lt;span style="color:#000000;"&gt; Lexer(&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;name&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;);

            Token token;

            token &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; lexer.NextToken();

            Assert.IsNotNull(token);
            Assert.AreEqual(TokenType.Name, token.TokenType);
            Assert.AreEqual(&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;name&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;, token.Value);

            token &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; lexer.NextToken();

            Assert.IsNull(token);
        }
&lt;/span&gt;&lt;/div&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;Hay un test para cada tipo de token a ser procesado. Otro ejemplo:&lt;/p&gt;

&lt;div class="wlWriterSmartContent" id="57F11A72-B0E5-49c7-9094-E3A15BD5B5E7:9b11e40f-18a3-4bce-9d93-6d349df8b74d" style="padding-right:0px;display:inline;padding-left:0px;float:none;padding-bottom:0px;margin:0px;padding-top:0px;"&gt;
  &lt;pre style="background-color:white;"&gt;&lt;div&gt;&lt;span style="color:#000000;"&gt;        [TestMethod]
        &lt;/span&gt;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000ff;"&gt;void&lt;/span&gt;&lt;span style="color:#000000;"&gt; ShouldProcessNameWithInitialUnderscore()
        {
            Lexer lexer &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000ff;"&gt;new&lt;/span&gt;&lt;span style="color:#000000;"&gt; Lexer(&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;_name&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;);

            Token token;

            token &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; lexer.NextToken();

            Assert.IsNotNull(token);
            Assert.AreEqual(TokenType.Name, token.TokenType);
            Assert.AreEqual(&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;_name&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;, token.Value);

            token &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; lexer.NextToken();

            Assert.IsNull(token);
        }
&lt;/span&gt;&lt;/div&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Escribí los tests usando ideas TDD: escribir el test, compilar con error, arreglar los problemas de compilación, ejecutar los tests en rojo, arreglarlos, conseguir el verde para los tests. No estuve haciendo tanto refactoring. El código merece algún refactor, pero por ahora, estoy tratando de conseguir un lexer que trabaje. Los tests quedaron en verde:&lt;/p&gt;

&lt;p&gt;&lt;img src="http://www.todocontenidos.com/images/articles/ajruby01.png" alt="" /&gt; &lt;/p&gt;

&lt;p&gt;Mi objetivo es tener más del 80% de code coverage, en cualquier momento del desarrollo del proyecto:&lt;/p&gt;

&lt;p&gt;&lt;img src="http://www.todocontenidos.com/images/articles/ajruby03.png" alt="" /&gt; &lt;/p&gt;

&lt;p&gt;Es bueno escribir algo sólo por diversión y aprendizaje. Para mí, es parte de la mejora continua que todo desarrollador de software debe perseguir.&lt;/p&gt;

&lt;p&gt;Nos leemos!&lt;/p&gt;

&lt;p&gt;Angel &amp;quot;Java&amp;quot; Lopez 
  &lt;br /&gt;&lt;a href="http://www.ajlopez.com"&gt;http://www.ajlopez.com&lt;/a&gt;

  &lt;br /&gt;&lt;a href="http://twitter.com/ajlopez"&gt;http://twitter.com/ajlopez&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1677718" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/lopez/archive/tags/.NET/default.aspx">.NET</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Desarrollo+de+Software/default.aspx">Desarrollo de Software</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/C_26002300_243_3B00_digo+Abierto/default.aspx">C&amp;#243;digo Abierto</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/C+Sharp/default.aspx">C Sharp</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Lenguajes+de+Programaci_26002300_243_3B00_n/default.aspx">Lenguajes de Programaci&amp;#243;n</category></item><item><title>AjGa: una librería de algoritmos genéticos</title><link>http://msmvps.com/blogs/lopez/archive/2009/01/28/ajga-una-librer-237-a-de-algoritmos-gen-233-ticos.aspx</link><pubDate>Wed, 28 Jan 2009 07:33:03 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1666502</guid><dc:creator>lopez</dc:creator><slash:comments>2</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/lopez/rsscomments.aspx?PostID=1666502</wfw:commentRss><comments>http://msmvps.com/blogs/lopez/archive/2009/01/28/ajga-una-librer-237-a-de-algoritmos-gen-233-ticos.aspx#comments</comments><description>&lt;p&gt;Estuve codificando una librería de algoritmos genéticos, usando C#. El código está en mi proyecto &lt;a href="http://code.google.com/p/ajcodekatas/" target="_blank"&gt;AjCodeKatas en Google Code&lt;/a&gt;&amp;nbsp;dentro de:&lt;/p&gt; &lt;p&gt;&lt;a title="http://code.google.com/p/ajcodekatas/source/browse/#svn/trunk/AjGa" href="http://code.google.com/p/ajcodekatas/source/browse/#svn/trunk/AjGa"&gt;http://code.google.com/p/ajcodekatas/source/browse/#svn/trunk/AjGa&lt;/a&gt;&lt;/p&gt; &lt;p&gt;El proyecto principal es AjGa (con AjGa.Tests para testing):&lt;/p&gt; &lt;p&gt;&lt;img src="http://www.todocontenidos.com/images/articles/ajgasln.png" alt="" /&gt; &lt;/p&gt; &lt;p&gt;Las principales interfaces son:&lt;/p&gt; &lt;p&gt;&lt;img src="http://www.todocontenidos.com/images/articles/ajgaint.png" alt="" /&gt;&lt;/p&gt; &lt;p&gt;Uso generics, con dos tipos genéricos: G, que es el tipo de implementación de un gen, y V como el tipo al que se evalúa un genoma (por ejemplo, int, double). Con ese valor se catalogan los genomas.&lt;/p&gt; &lt;p&gt;IPopulation es una colección de genomas.&lt;/p&gt; &lt;p&gt;IGenome &amp;nbsp;es una colección&amp;nbsp;de genes, que&amp;nbsp;es evaluado a un valor de tipo V.&lt;/p&gt; &lt;p&gt;IEvaluator está a cargo de evaluar un genoma.&lt;/p&gt; &lt;p&gt;La implementación de IEvolution ejecuta generaciones sobre una población, que va cambiando, usando mutadores, operadores de cruzamiento, para irla modificando después de cada ejecución.&lt;/p&gt; &lt;p&gt;Hay interfaces para generar un genoma, mutar uno existente o hacer cruzamiento de dos genomas.&lt;/p&gt; &lt;p&gt;&lt;img src="http://www.todocontenidos.com/images/articles/ajgacd.png" alt="" /&gt; &lt;/p&gt; &lt;p&gt;Para probar estas ideas, implementé un proyecto con gen, genoma, y operadores, que ataca el clásico problema del Travelling Salesman Problem, el vendedor que tiene que visitar una serie de ciudades, minimazando la distancia a recorrrer:&lt;/p&gt; &lt;p&gt;&lt;img src="http://www.todocontenidos.com/images/articles/ajgatspprj.png" alt="" /&gt; &lt;/p&gt; &lt;p&gt;En este ejemplo, el evaluador tiene una lista de posiciones de ciudades a visitar:&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;div class="wlWriterSmartContent" id="57F11A72-B0E5-49c7-9094-E3A15BD5B5E7:d2ccf8d5-26f7-4c4f-9980-20d15c5489ec" style="padding-right:0px;display:inline;padding-left:0px;float:none;padding-bottom:0px;margin:0px;padding-top:0px;"&gt;&lt;pre style="background-color:White;"&gt;&lt;div&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;class&lt;/span&gt;&lt;span style="color:#000000;"&gt; Evaluator : IEvaluator&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;int&lt;/span&gt;&lt;span style="color:#000000;"&gt;, &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;int&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    {
        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;private&lt;/span&gt;&lt;span style="color:#000000;"&gt; List&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;Position&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt; positions;

        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; Evaluator(List&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;Position&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt; positions)
        {
            &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;this&lt;/span&gt;&lt;span style="color:#000000;"&gt;.positions &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; positions;
        }
&lt;/span&gt;&lt;/div&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;El tipo de gen acá es int, y cada valor de genoma se expresa como un int. El genoma mantiene una lista de enteros, que representan el&amp;nbsp;número ordinal de las ciudades a visitar:&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;div class="wlWriterSmartContent" id="57F11A72-B0E5-49c7-9094-E3A15BD5B5E7:2ba01ca7-37cc-404b-9b73-a7bb089f9ef0" style="padding-right:0px;display:inline;padding-left:0px;float:none;padding-bottom:0px;margin:0px;padding-top:0px;"&gt;&lt;pre style="background-color:White;"&gt;&lt;div&gt;&lt;span style="color:#000000;"&gt;    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;using&lt;/span&gt;&lt;span style="color:#000000;"&gt; AjGa;

    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;class&lt;/span&gt;&lt;span style="color:#000000;"&gt; Genome : BaseGenome&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;int&lt;/span&gt;&lt;span style="color:#000000;"&gt;, &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;int&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    {        
        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; Genome(&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;int&lt;/span&gt;&lt;span style="color:#000000;"&gt; size)
        {
            &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;for&lt;/span&gt;&lt;span style="color:#000000;"&gt; (&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;int&lt;/span&gt;&lt;span style="color:#000000;"&gt; k &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#000000;"&gt;0&lt;/span&gt;&lt;span style="color:#000000;"&gt;; k &lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#000000;"&gt; size; k&lt;/span&gt;&lt;span style="color:#000000;"&gt;++&lt;/span&gt;&lt;span style="color:#000000;"&gt;)
            {
                AddGene(k);
            }
        }&lt;/span&gt;&lt;/div&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Esto es, cada gen es un int, y un genoma con genes 2, 0, 1, representa un viaje que visita la tercera ciudad, pasa por la primera, y termina en la segunda.&lt;/p&gt;
&lt;p&gt;Podemos ejecutar el proyecto WinForm, para probar esta implementación:&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.todocontenidos.com/images/articles/ajgatsp1.png" alt="" /&gt; &lt;/p&gt;
&lt;p&gt;En la ejecución de arriba, la distribución de ciudades es al azar. Las ciudades pueden ser distribuidas en una grilla:&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.todocontenidos.com/images/articles/ajgatsp2.png" alt="" /&gt; &lt;/p&gt;
&lt;p&gt;De esta forma, podemos probar la eficiencia del algoritmo para encontrar un solución óptima, que en el caso de disponer las ciudades en grilla, se conoce de antemano.&lt;/p&gt;
&lt;p&gt;Si queremos implementar un nuevo proyecto GA, tenemos que:&lt;/p&gt;
&lt;p&gt;- Definir el tipo que tendrán los genes&lt;/p&gt;
&lt;p&gt;- Definir el tipo valor a usar&lt;/p&gt;
&lt;p&gt;- Escribir operadores (creadores, mutadores, cruzadores) de genomas&lt;/p&gt;
&lt;p&gt;Los tests que tengo están en verde:&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.todocontenidos.com/images/articles/ajgatests.png" alt="" /&gt; &lt;/p&gt;
&lt;p&gt;Buen Code coverage:&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.todocontenidos.com/images/articles/ajgacc.png" alt="" /&gt; &lt;/p&gt;
&lt;p&gt;En 4 horas tuve la primera versión, gasté 3 horas explorando TSP, y cerca de 8 horas preparando y &amp;quot;tuneando&amp;quot; la aplicación WinForm.&lt;/p&gt;
&lt;p&gt;Como de costumbre, ¡me divertí escribiendo este ejemplo!&lt;/p&gt;
&lt;p&gt;Nos leemos!&lt;/p&gt;
&lt;p&gt;Angel &amp;quot;Java&amp;quot; Lopez&lt;br /&gt;&lt;a href="http://www.ajlopez.com"&gt;http://www.ajlopez.com&lt;/a&gt;&lt;br /&gt;&lt;a href="http://twitter.com/ajlopez"&gt;http://twitter.com/ajlopez&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1666502" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/lopez/archive/tags/Inteligencia+Artificial/default.aspx">Inteligencia Artificial</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Desarrollo+de+Software/default.aspx">Desarrollo de Software</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/C+Sharp/default.aspx">C Sharp</category></item><item><title>Clean Code Talks -- Herencia, Polimorfismo y Tests</title><link>http://msmvps.com/blogs/lopez/archive/2009/01/13/clean-code-talks-herencia-polimorfismo-y-tests.aspx</link><pubDate>Tue, 13 Jan 2009 09:15:54 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1661311</guid><dc:creator>lopez</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/lopez/rsscomments.aspx?PostID=1661311</wfw:commentRss><comments>http://msmvps.com/blogs/lopez/archive/2009/01/13/clean-code-talks-herencia-polimorfismo-y-tests.aspx#comments</comments><description>&lt;p&gt;Son un usuario fanático de &lt;a href="http://twitter.com" target="_blank"&gt;Twitter&lt;/a&gt;. Una cuenta a la que sigo es &lt;a href="http://twitter.com/delicious_prog" target="_blank"&gt;@delicious_prog&lt;/a&gt;, que envía varios mensajes por día, relacionados con programación, desarrollo de software en general. En uno de esos tweets, encontré el post&lt;/p&gt; &lt;p&gt;&lt;a title="The Clean Code Talks -- Inheritance, Polymorphism, &amp;amp; Testing" href="http://danielwildt.blogspot.com/2008/12/clean-code-talks-inheritance.html"&gt;The Clean Code Talks -- Inheritance, Polymorphism, &amp;amp; Testing&lt;/a&gt;&lt;/p&gt; &lt;p&gt;de &lt;a href="http://danielwildt.blogspot.com/" target="_blank"&gt;Daniel Wild&lt;/a&gt;, donde incluye el vidio de una&amp;nbsp; Google Talk:&lt;/p&gt; &lt;p&gt;(Please visit the site to view this media)&lt;/p&gt; &lt;p&gt;de &lt;a title="Misko Hevery" href="http://misko.hevery.com/"&gt;Misko Hevery&lt;/a&gt;&amp;nbsp;en &lt;a title="Google Tech Talks" href="http://www.youtube.com/user/googletechtalks"&gt;Google Tech Talks&lt;/a&gt;.&lt;/p&gt; &lt;p&gt;Es claro e interesante. Es una charla explicando los usos del polimorfismo, y también, las formas de realizar test sobre métodos polimórficos. Me gusta encontrara en este vido varios argumentos similares a los que uso en mis charlas de desarrollo. Hace unos días, estuve usando polimorfirsmo en mi intérprete AjCat (un intérprete del lenguaje cat que me hizo conocer el bueno de &lt;a href="http://twitter.com/rodolfof" target="_blank"&gt;@rodolfof&lt;/a&gt;):&lt;/p&gt; &lt;p&gt;&lt;a title="http://code.google.com/p/ajcodekatas/source/browse/#svn/trunk/AjCat" href="http://code.google.com/p/ajcodekatas/source/browse/#svn/trunk/AjCat"&gt;http://code.google.com/p/ajcodekatas/source/browse/#svn/trunk/AjCat&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Esta es mi implmentación de Integer Binary Operation:&amp;nbsp;&lt;/p&gt; &lt;p&gt;&lt;/p&gt; &lt;div class="wlWriterSmartContent" id="57F11A72-B0E5-49c7-9094-E3A15BD5B5E7:cdb4759a-0b2e-4dd0-baba-262fca4716a3" style="padding-right:0px;display:inline;padding-left:0px;float:none;padding-bottom:0px;margin:0px;padding-top:0px;"&gt;&lt;pre style="background-color:White;white-space:-moz-pre-wrap;white-space:-pre-wrap;white-space:-o-pre-wrap;white-space:pre-wrap;word-wrap:break-word;"&gt;&lt;div&gt;&lt;span style="color:#000000;"&gt;    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;abstract&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;class&lt;/span&gt;&lt;span style="color:#000000;"&gt; IntegerBinaryOperation : Expression
    {
        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;abstract&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;int&lt;/span&gt;&lt;span style="color:#000000;"&gt; Apply(&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;int&lt;/span&gt;&lt;span style="color:#000000;"&gt; op1, &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;int&lt;/span&gt;&lt;span style="color:#000000;"&gt; op2);

        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;override&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;void&lt;/span&gt;&lt;span style="color:#000000;"&gt; Evaluate(Machine machine)
        {
            &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;int&lt;/span&gt;&lt;span style="color:#000000;"&gt; op2 &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; (&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;int&lt;/span&gt;&lt;span style="color:#000000;"&gt;) machine.Pop();
            &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;int&lt;/span&gt;&lt;span style="color:#000000;"&gt; op1 &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; (&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;int&lt;/span&gt;&lt;span style="color:#000000;"&gt;) machine.Pop();

            machine.Push(&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;this&lt;/span&gt;&lt;span style="color:#000000;"&gt;.Apply(op1, op2));
        }
    }
&lt;/span&gt;&lt;/div&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Las operaciones Add y Subtract sobreescriben el método Apply:&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;div class="wlWriterSmartContent" id="57F11A72-B0E5-49c7-9094-E3A15BD5B5E7:b267ea20-7c62-4901-aa2d-613a963a5602" style="padding-right:0px;display:inline;padding-left:0px;float:none;padding-bottom:0px;margin:0px;padding-top:0px;"&gt;&lt;pre style="background-color:White;white-space:-moz-pre-wrap;white-space:-pre-wrap;white-space:-o-pre-wrap;white-space:pre-wrap;word-wrap:break-word;"&gt;&lt;div&gt;&lt;span style="color:#000000;"&gt;    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;class&lt;/span&gt;&lt;span style="color:#000000;"&gt; IntegerAddOperation : IntegerBinaryOperation
    {
        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;private&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;static&lt;/span&gt;&lt;span style="color:#000000;"&gt; IntegerAddOperation instance &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;new&lt;/span&gt;&lt;span style="color:#000000;"&gt; IntegerAddOperation();

        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;private&lt;/span&gt;&lt;span style="color:#000000;"&gt; IntegerAddOperation()
        {
        }

        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;static&lt;/span&gt;&lt;span style="color:#000000;"&gt; IntegerAddOperation Instance
        {
            &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;get&lt;/span&gt;&lt;span style="color:#000000;"&gt;
            {
                &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;return&lt;/span&gt;&lt;span style="color:#000000;"&gt; instance;
            }
        }

        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;override&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;int&lt;/span&gt;&lt;span style="color:#000000;"&gt; Apply(&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;int&lt;/span&gt;&lt;span style="color:#000000;"&gt; op1, &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;int&lt;/span&gt;&lt;span style="color:#000000;"&gt; op2)
        {
            &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;return&lt;/span&gt;&lt;span style="color:#000000;"&gt; op1 &lt;/span&gt;&lt;span style="color:#000000;"&gt;+&lt;/span&gt;&lt;span style="color:#000000;"&gt; op2;
        }

        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;override&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;string&lt;/span&gt;&lt;span style="color:#000000;"&gt; ToString()
        {
            &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;return&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;add_int&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;;
        }
    }
&lt;/span&gt;&lt;/div&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;/p&gt;
&lt;div class="wlWriterSmartContent" id="57F11A72-B0E5-49c7-9094-E3A15BD5B5E7:5019eb84-44e9-4e8c-b22c-d7d28428c75e" style="padding-right:0px;display:inline;padding-left:0px;float:none;padding-bottom:0px;margin:0px;padding-top:0px;"&gt;&lt;pre style="background-color:White;white-space:-moz-pre-wrap;white-space:-pre-wrap;white-space:-o-pre-wrap;white-space:pre-wrap;word-wrap:break-word;"&gt;&lt;div&gt;&lt;span style="color:#000000;"&gt;    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;class&lt;/span&gt;&lt;span style="color:#000000;"&gt; IntegerSubtractOperation : IntegerBinaryOperation
    {
        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;private&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;static&lt;/span&gt;&lt;span style="color:#000000;"&gt; IntegerSubtractOperation instance &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;new&lt;/span&gt;&lt;span style="color:#000000;"&gt; IntegerSubtractOperation();

        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;private&lt;/span&gt;&lt;span style="color:#000000;"&gt; IntegerSubtractOperation()
        {
        }

        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;static&lt;/span&gt;&lt;span style="color:#000000;"&gt; IntegerSubtractOperation Instance
        {
            &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;get&lt;/span&gt;&lt;span style="color:#000000;"&gt;
            {
                &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;return&lt;/span&gt;&lt;span style="color:#000000;"&gt; instance;
            }
        }

        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;override&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;int&lt;/span&gt;&lt;span style="color:#000000;"&gt; Apply(&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;int&lt;/span&gt;&lt;span style="color:#000000;"&gt; op1, &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;int&lt;/span&gt;&lt;span style="color:#000000;"&gt; op2)
        {
            &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;return&lt;/span&gt;&lt;span style="color:#000000;"&gt; op1 &lt;/span&gt;&lt;span style="color:#000000;"&gt;-&lt;/span&gt;&lt;span style="color:#000000;"&gt; op2;
        }

        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;override&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;string&lt;/span&gt;&lt;span style="color:#000000;"&gt; ToString()
        {
            &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;return&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;sub_int&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;;
        }
    }
&lt;/span&gt;&lt;/div&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Es muy similar al ejemplo presentado en el video. Estuve algo más perezoso en mi implementación de operadores en&amp;nbsp; AjPython (otro intérprete, de nuevo en&amp;nbsp;C#, trabajo en progreso):&lt;/p&gt;
&lt;p&gt;&lt;a title="http://code.google.com/p/ajcodekatas/source/browse/#svn/trunk/AjPython" href="http://code.google.com/p/ajcodekatas/source/browse/#svn/trunk/AjPython"&gt;http://code.google.com/p/ajcodekatas/source/browse/#svn/trunk/AjPython&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;div class="wlWriterSmartContent" id="57F11A72-B0E5-49c7-9094-E3A15BD5B5E7:c1ceebe0-dcbd-4655-b75c-cab5830acc73" style="padding-right:0px;display:inline;padding-left:0px;float:none;padding-bottom:0px;margin:0px;padding-top:0px;"&gt;&lt;pre style="background-color:White;white-space:-moz-pre-wrap;white-space:-pre-wrap;white-space:-o-pre-wrap;white-space:pre-wrap;word-wrap:break-word;"&gt;&lt;div&gt;&lt;span style="color:#000000;"&gt;    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;class&lt;/span&gt;&lt;span style="color:#000000;"&gt; BinaryOperatorExpression : BinaryExpression
    {
        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;private&lt;/span&gt;&lt;span style="color:#000000;"&gt; Operator @operator;

        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; BinaryOperatorBLOCKED EXPRESSION;
        }
    }
&lt;/span&gt;&lt;/div&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Pero confío en refactorearlo, tengo espaldas para hacerlo, gracias una buena base de test ya escritos.&lt;/p&gt;
&lt;p&gt;Es bueno encontrar este tipo de material, como esta charla, la recomiendo, gracias a&amp;nbsp; @delicious_prog y a Daniel Wild!&lt;/p&gt;
&lt;p&gt;Nos leemos!&lt;/p&gt;
&lt;p&gt;Angel &amp;quot;Java&amp;quot; Lopez&lt;br /&gt;&lt;a href="http://www.ajlopez.com"&gt;http://www.ajlopez.com&lt;/a&gt;&lt;br /&gt;&lt;a href="http://twitter.com/ajlopez"&gt;http://twitter.com/ajlopez&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1661311" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/lopez/archive/tags/Desarrollo+de+Software/default.aspx">Desarrollo de Software</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/C+Sharp/default.aspx">C Sharp</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Lenguajes+de+Programaci_26002300_243_3B00_n/default.aspx">Lenguajes de Programaci&amp;#243;n</category></item></channel></rss>