<?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 : TDD, C Sharp</title><link>http://msmvps.com/blogs/lopez/archive/tags/TDD/C+Sharp/default.aspx</link><description>Tags: TDD, C Sharp</description><dc:language>en</dc:language><generator>CommunityServer 2008.5 SP2 (Build: 40407.4157)</generator><item><title>Mass Lenguaje de Programación (4) Lexer y Parser</title><link>http://msmvps.com/blogs/lopez/archive/2013/05/12/mass-lenguaje-de-programaci-243-n-4-lexer-y-parser.aspx</link><pubDate>Sun, 12 May 2013 08:40:21 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1830015</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=1830015</wfw:commentRss><comments>http://msmvps.com/blogs/lopez/archive/2013/05/12/mass-lenguaje-de-programaci-243-n-4-lexer-y-parser.aspx#comments</comments><description>&lt;p&gt;&lt;a href="http://msmvps.com/blogs/lopez/archive/2013/04/28/mass-lenguaje-de-programaci-243-n-3-comandos.aspx"&gt;Anterior Post&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;En la implementación del lenguaje Mass, tengo una enumeración y una clase:&lt;/p&gt;  &lt;p&gt;&lt;img src="http://www.ajlopez.com/images/articles2/mass0401.jpg" alt="" /&gt; &lt;/p&gt;  &lt;p&gt;Un Token representa una palabra del código a procesar. El encargado de separar el código en palabras es el Lexer. Y con el Parser se transforma esa corriente de Tokens en expresiones y comandos:&lt;/p&gt;  &lt;p&gt;&lt;img src="http://www.ajlopez.com/images/articles2/mass0402.jpg" alt="" /&gt; &lt;/p&gt;  &lt;p&gt;El constructor de Lexer recibe un string:&lt;/p&gt;  &lt;pre style="background-color:black;width:600px;color:white;font-size:10pt;"&gt;&lt;span style="color:orange;"&gt;public&lt;/span&gt; Lexer&lt;span style="color:cyan;"&gt;(&lt;/span&gt;&lt;span style="color:orange;"&gt;string&lt;/span&gt; text&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;.text = text&lt;span style="color:cyan;"&gt;;&lt;/span&gt;
&lt;span style="color:cyan;"&gt;}&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;Y ese string es procesado para separarlo en tokens. Vean que el Lexer distingue entre operadores (como +) y separadores (como los paréntesis). También toma en cuenta al fin de línea como token (en otros lenguajes, como C, un fin de línea se puede tomar como un espacio en blanco en muchas situaciones). El principal método de Lexer es NextToken, que devuelve el próximo Token del texto. En algunas pocas situaciones, se hace necesario devolver el Token consumido, y para eso está PushToken y varianes.&lt;/p&gt;

&lt;p&gt;El Parser interamente maneja un Lexer. Le podemos pedir el próximo comando con ParseCommand, y la próxima expresión con ParseExpression. Cuando el texto en proceso se acaba, esos métodos devuelven null.&lt;/p&gt;

&lt;p&gt;Voy a modificar el Lexer para consumir un stream de texto, para poder procesar, por ejemplo, entrada de consola&lt;/p&gt;

&lt;p&gt;Tengo que seguir pensando si internamente, unifico comandos y expresiones, como pasa en Ruby, donde cada “comando” tiene un valor (en Mass también es así), y no solamente eso, sino que puede ser usado como expresión en el contexto de un comando.&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=1830015" 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/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/TDD/default.aspx">TDD</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><category domain="http://msmvps.com/blogs/lopez/archive/tags/Mass/default.aspx">Mass</category></item><item><title>Mass Lenguaje de Programación (3) Comandos</title><link>http://msmvps.com/blogs/lopez/archive/2013/04/28/mass-lenguaje-de-programaci-243-n-3-comandos.aspx</link><pubDate>Sun, 28 Apr 2013 11:24:00 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1828666</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=1828666</wfw:commentRss><comments>http://msmvps.com/blogs/lopez/archive/2013/04/28/mass-lenguaje-de-programaci-243-n-3-comandos.aspx#comments</comments><description>&lt;p&gt;&lt;a href="http://msmvps.com/blogs/lopez/archive/2013/04/27/mass-lenguaje-de-programaci-243-n-2-primeras-expresiones.aspx"&gt;Anterior Post&amp;nbsp;&lt;/a&gt;&amp;nbsp;&lt;br /&gt;&lt;a href="http://msmvps.com/blogs/lopez/archive/2013/05/12/mass-lenguaje-de-programaci-243-n-4-lexer-y-parser.aspx"&gt;Siguiente Post&lt;/a&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Veamos hoy c&amp;oacute;mo est&amp;aacute;n implementados los comandos en Mass (&lt;a href="http://github.com/ajlopez/Mass"&gt;ver repo&lt;/a&gt;). En el proyecto de librer&amp;iacute;a de clases, tengo:&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.ajlopez.com/images/articles2/mass0301.png" alt="" /&gt; &lt;/p&gt;
&lt;p&gt;Hay comandos para if, while, for, for each, etc&amp;hellip;. Todos implementan la interfaz ICommand:&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;interface&lt;/span&gt; ICommand
&lt;span style="color:cyan;"&gt;{&lt;/span&gt;
    &lt;span style="color:orange;"&gt;object&lt;/span&gt; Execute&lt;span style="color:cyan;"&gt;(&lt;/span&gt;Context context&lt;span style="color:cyan;"&gt;);&lt;/span&gt;
&lt;span style="color:cyan;"&gt;}&lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;Vean que es muy parecido a IExpression. Igual quise mantener comandos y expresiones por separado, por lo menos en esta primera implementaci&amp;oacute;n, para tener un claro delineamiento de los conceptos de base del lenguaje.&lt;/p&gt;
&lt;p&gt;Un ejemplo t&amp;iacute;pico de comando es el WhileCommand (parte del c&amp;oacute;digo):&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; WhileCommand : ICommand
&lt;span style="color:cyan;"&gt;{&lt;/span&gt;
    &lt;span style="color:orange;"&gt;private&lt;/span&gt; &lt;span style="color:orange;"&gt;static&lt;/span&gt; &lt;span style="color:orange;"&gt;int&lt;/span&gt; hashcode = &lt;span style="color:orange;"&gt;typeof&lt;/span&gt;&lt;span style="color:cyan;"&gt;(&lt;/span&gt;WhileCommand&lt;span style="color:cyan;"&gt;)&lt;/span&gt;.GetHashCode&lt;span style="color:cyan;"&gt;();&lt;/span&gt;

    &lt;span style="color:orange;"&gt;private&lt;/span&gt; IExpression condition&lt;span style="color:cyan;"&gt;;&lt;/span&gt;
    &lt;span style="color:orange;"&gt;private&lt;/span&gt; ICommand command&lt;span style="color:cyan;"&gt;;&lt;/span&gt;

    &lt;span style="color:orange;"&gt;public&lt;/span&gt; WhileCommand&lt;span style="color:cyan;"&gt;(&lt;/span&gt;IExpression condition&lt;span style="color:cyan;"&gt;,&lt;/span&gt; ICommand command&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;.condition = condition&lt;span style="color:cyan;"&gt;;&lt;/span&gt;
        &lt;span style="color:orange;"&gt;this&lt;/span&gt;.command = command&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;object&lt;/span&gt; Execute&lt;span style="color:cyan;"&gt;(&lt;/span&gt;Context context&lt;span style="color:cyan;"&gt;)&lt;/span&gt;
    &lt;span style="color:cyan;"&gt;{&lt;/span&gt;
        &lt;span style="color:orange;"&gt;for&lt;/span&gt; &lt;span style="color:cyan;"&gt;(&lt;/span&gt;&lt;span style="color:orange;"&gt;object&lt;/span&gt; value = &lt;span style="color:orange;"&gt;this&lt;/span&gt;.condition.Evaluate&lt;span style="color:cyan;"&gt;(&lt;/span&gt;context&lt;span style="color:cyan;"&gt;);&lt;/span&gt; 
            value &lt;span style="color:cyan;"&gt;!&lt;/span&gt;= &lt;span style="color:orange;"&gt;null&lt;/span&gt; &lt;span style="color:cyan;"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span style="color:cyan;"&gt;!&lt;/span&gt;&lt;span style="color:orange;"&gt;false&lt;/span&gt;.Equals&lt;span style="color:cyan;"&gt;(&lt;/span&gt;value&lt;span style="color:cyan;"&gt;);&lt;/span&gt;
            value = &lt;span style="color:orange;"&gt;this&lt;/span&gt;.condition.Evaluate&lt;span style="color:cyan;"&gt;(&lt;/span&gt;context&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;.command.Execute&lt;span style="color:cyan;"&gt;(&lt;/span&gt;context&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;context.HasContinue&lt;span style="color:cyan;"&gt;())&lt;/span&gt;
                context.ClearContinue&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;context.HasBreak&lt;span style="color:cyan;"&gt;())&lt;/span&gt;
            &lt;span style="color:cyan;"&gt;{&lt;/span&gt;
                context.ClearBreak&lt;span style="color:cyan;"&gt;();&lt;/span&gt;
                &lt;span style="color:orange;"&gt;break&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:cyan;"&gt;}&lt;/span&gt;

        &lt;span style="color:orange;"&gt;return&lt;/span&gt; &lt;span style="color:orange;"&gt;null&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:cyan;"&gt;}&lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;Para Mass: cualquier valor null o false es falso. Todo lo dem&amp;aacute;s es verdadero. Un tema a refactorizar: poner un m&amp;eacute;todo IsFalse para se usado tanto en la implementaci&amp;oacute;n de While como de If.&lt;/p&gt;
&lt;p&gt;Otro ejemplo es el ForEachCommand (parte del c&amp;oacute;digo):&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; ForEachCommand : ICommand
&lt;span style="color:cyan;"&gt;{&lt;/span&gt;
    &lt;span style="color:orange;"&gt;private&lt;/span&gt; &lt;span style="color:orange;"&gt;string&lt;/span&gt; name&lt;span style="color:cyan;"&gt;;&lt;/span&gt;
    &lt;span style="color:orange;"&gt;private&lt;/span&gt; IExpression expression&lt;span style="color:cyan;"&gt;;&lt;/span&gt;
    &lt;span style="color:orange;"&gt;private&lt;/span&gt; ICommand command&lt;span style="color:cyan;"&gt;;&lt;/span&gt;

    &lt;span style="color:orange;"&gt;public&lt;/span&gt; ForEachCommand&lt;span style="color:cyan;"&gt;(&lt;/span&gt;&lt;span style="color:orange;"&gt;string&lt;/span&gt; name&lt;span style="color:cyan;"&gt;,&lt;/span&gt; IExpression expression&lt;span style="color:cyan;"&gt;,&lt;/span&gt; ICommand command&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;.name = name&lt;span style="color:cyan;"&gt;;&lt;/span&gt;
        &lt;span style="color:orange;"&gt;this&lt;/span&gt;.expression = expression&lt;span style="color:cyan;"&gt;;&lt;/span&gt;
        &lt;span style="color:orange;"&gt;this&lt;/span&gt;.command = command&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;object&lt;/span&gt; Execute&lt;span style="color:cyan;"&gt;(&lt;/span&gt;Context context&lt;span style="color:cyan;"&gt;)&lt;/span&gt;
    &lt;span style="color:cyan;"&gt;{&lt;/span&gt;
        var values = &lt;span style="color:cyan;"&gt;(&lt;/span&gt;IEnumerable&lt;span style="color:cyan;"&gt;)&lt;/span&gt;&lt;span style="color:orange;"&gt;this&lt;/span&gt;.expression.Evaluate&lt;span style="color:cyan;"&gt;(&lt;/span&gt;context&lt;span style="color:cyan;"&gt;);&lt;/span&gt;

        &lt;span style="color:orange;"&gt;foreach&lt;/span&gt; &lt;span style="color:cyan;"&gt;(&lt;/span&gt;var value &lt;span style="color:orange;"&gt;in&lt;/span&gt; values&lt;span style="color:cyan;"&gt;)&lt;/span&gt;
        &lt;span style="color:cyan;"&gt;{&lt;/span&gt;
            context.Set&lt;span style="color:cyan;"&gt;(&lt;/span&gt;&lt;span style="color:orange;"&gt;this&lt;/span&gt;.name&lt;span style="color:cyan;"&gt;,&lt;/span&gt; value&lt;span style="color:cyan;"&gt;);&lt;/span&gt;
            &lt;span style="color:orange;"&gt;this&lt;/span&gt;.command.Execute&lt;span style="color:cyan;"&gt;(&lt;/span&gt;context&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;context.HasContinue&lt;span style="color:cyan;"&gt;())&lt;/span&gt;
                context.ClearContinue&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;context.HasBreak&lt;span style="color:cyan;"&gt;())&lt;/span&gt;
            &lt;span style="color:cyan;"&gt;{&lt;/span&gt;
                context.ClearBreak&lt;span style="color:cyan;"&gt;();&lt;/span&gt;
                &lt;span style="color:orange;"&gt;break&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:cyan;"&gt;}&lt;/span&gt;

        &lt;span style="color:orange;"&gt;return&lt;/span&gt; &lt;span style="color:orange;"&gt;null&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:cyan;"&gt;}&lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;Vean que para Mass, todo lo que sea IEnumerable se puede usar para ser consumido por este comando. Tuve que poner algunos datos en el contexto, para saber si se hab&amp;iacute;a hecho un break o un continue.&lt;/p&gt;
&lt;p&gt;Y como siempre, todo esto desarrollado con TDD: pueden &lt;a href="https://github.com/ajlopez/Mass/commits/master"&gt;ver los commits del repo&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Pr&amp;oacute;ximos posts: Lexer y Parser, ejemplos de Mass para scripting.&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=1828666" 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/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/TDD/default.aspx">TDD</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><category domain="http://msmvps.com/blogs/lopez/archive/tags/Mass/default.aspx">Mass</category></item><item><title>Mass Lenguaje de Programación (2) Primeras Expresiones</title><link>http://msmvps.com/blogs/lopez/archive/2013/04/27/mass-lenguaje-de-programaci-243-n-2-primeras-expresiones.aspx</link><pubDate>Sat, 27 Apr 2013 13:26:00 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1828597</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=1828597</wfw:commentRss><comments>http://msmvps.com/blogs/lopez/archive/2013/04/27/mass-lenguaje-de-programaci-243-n-2-primeras-expresiones.aspx#comments</comments><description>&lt;p&gt;&lt;a href="http://msmvps.com/blogs/lopez/archive/2013/04/08/mass-lenguaje-de-programaci-243-n-1-or-237-genes.aspx"&gt;Anterior Post&amp;nbsp;&lt;/a&gt;&amp;nbsp;&lt;br /&gt;&lt;a href="http://msmvps.com/blogs/lopez/archive/2013/04/28/mass-lenguaje-de-programaci-243-n-3-comandos.aspx"&gt;Siguiente Post&lt;/a&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Antes de ver c&amp;oacute;mo usar el lenguaje Mass (&lt;a href="http://github.com/ajlopez/Mass"&gt;ver repo&lt;/a&gt;), quisiera tratar algunos temas de implementaci&amp;oacute;n. Primero, una novedad: ahora hay una soluci&amp;oacute;n (en &lt;a href="https://github.com/ajlopez/Mass/blob/master/Src/Mass.sln"&gt;https://github.com/ajlopez/Mass/blob/master/Src/Mass.sln&lt;/a&gt;) que puede compilarse con alg&amp;uacute;n Visual Studio C# Express, de libre bajada e instalaci&amp;oacute;n.&lt;/p&gt;
&lt;p&gt;La soluci&amp;oacute;n Mass tiene un proyecto de librer&amp;iacute;a de clases. Ah&amp;iacute; hay un namespace dedicado a expresiones:&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.ajlopez.com/images/articles2/mass0201.png" alt="" /&gt; &lt;/p&gt;
&lt;p&gt;Una expresi&amp;oacute;n es algo que cumple con IExpression:&lt;/p&gt;
&lt;pre style="background-color:black;width:600px;color:white;"&gt;&lt;span&gt;&amp;nbsp; &lt;/span&gt;
&lt;span style="color:orange;"&gt;public&lt;/span&gt; &lt;span style="color:orange;"&gt;interface&lt;/span&gt; IExpression
&lt;span style="color:cyan;"&gt;{&lt;/span&gt;
	&lt;span style="color:orange;"&gt;object&lt;/span&gt; Evaluate&lt;span style="color:cyan;"&gt;(&lt;/span&gt;Context context&lt;span style="color:cyan;"&gt;);&lt;/span&gt;
&lt;span style="color:cyan;"&gt;}&lt;/span&gt;
&lt;span&gt;&amp;nbsp; &lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;Un Context mantiene un diccionario de nombre/valor, para guardar las variables actuales:&lt;/p&gt;
&lt;pre style="background-color:black;width:600px;color:white;"&gt;&lt;span&gt;&amp;nbsp; &lt;/span&gt;
&lt;span style="color:orange;"&gt;public&lt;/span&gt; &lt;span style="color:orange;"&gt;void&lt;/span&gt; Set&lt;span style="color:cyan;"&gt;(&lt;/span&gt;&lt;span style="color:orange;"&gt;string&lt;/span&gt; name&lt;span style="color:cyan;"&gt;,&lt;/span&gt; &lt;span style="color:orange;"&gt;object&lt;/span&gt; value&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;.values&lt;span style="color:cyan;"&gt;[&lt;/span&gt;name&lt;span style="color:cyan;"&gt;]&lt;/span&gt; = value&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;object&lt;/span&gt; Get&lt;span style="color:cyan;"&gt;(&lt;/span&gt;&lt;span style="color:orange;"&gt;string&lt;/span&gt; name&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;.values.ContainsKey&lt;span style="color:cyan;"&gt;(&lt;/span&gt;name&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;this&lt;/span&gt;.values&lt;span style="color:cyan;"&gt;[&lt;/span&gt;name&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;.parent &lt;span style="color:cyan;"&gt;!&lt;/span&gt;= &lt;span style="color:orange;"&gt;null&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;this&lt;/span&gt;.parent.Get&lt;span style="color:cyan;"&gt;(&lt;/span&gt;name&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;null&lt;/span&gt;&lt;span style="color:cyan;"&gt;;&lt;/span&gt;
&lt;span style="color:cyan;"&gt;}&lt;/span&gt;
&lt;span&gt;&amp;nbsp; &lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;(vean de refil&amp;oacute;n, que soporta contextos anidados: cada contexto puede &amp;ldquo;heredar&amp;rdquo; de un contexto parent).&lt;/p&gt;
&lt;p&gt;La expresi&amp;oacute;n m&amp;aacute;s simple es la que devuelve una constante, que puede ser cualquier valor/objecto .NET:&lt;/p&gt;
&lt;pre style="background-color:black;width:600px;color:white;"&gt;&lt;span&gt;&amp;nbsp; &lt;/span&gt;
&lt;span style="color:orange;"&gt;public&lt;/span&gt; &lt;span style="color:orange;"&gt;class&lt;/span&gt; ConstantExpression : IExpression
&lt;span style="color:cyan;"&gt;{&lt;/span&gt;
	// ...

	&lt;span style="color:orange;"&gt;private&lt;/span&gt; &lt;span style="color:orange;"&gt;object&lt;/span&gt; value&lt;span style="color:cyan;"&gt;;&lt;/span&gt;

	&lt;span style="color:orange;"&gt;public&lt;/span&gt; ConstantExpression&lt;span style="color:cyan;"&gt;(&lt;/span&gt;&lt;span style="color:orange;"&gt;object&lt;/span&gt; value&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;.value = value&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;object&lt;/span&gt; Evaluate&lt;span style="color:cyan;"&gt;(&lt;/span&gt;Context context&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;this&lt;/span&gt;.value&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;span&gt;&amp;nbsp; &lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;La siguiente expresi&amp;oacute;n m&amp;aacute;s simple es la evaluaci&amp;oacute;n de un nombre de variable en el contexto actual:&lt;/p&gt;
&lt;pre style="background-color:black;width:600px;color:white;"&gt;&lt;span&gt;&amp;nbsp; &lt;/span&gt;
&lt;span style="color:orange;"&gt;public&lt;/span&gt; &lt;span style="color:orange;"&gt;class&lt;/span&gt; NameExpression : IExpression
&lt;span style="color:cyan;"&gt;{&lt;/span&gt;
	// ...
	
	&lt;span style="color:orange;"&gt;private&lt;/span&gt; &lt;span style="color:orange;"&gt;string&lt;/span&gt; name&lt;span style="color:cyan;"&gt;;&lt;/span&gt;

	&lt;span style="color:orange;"&gt;public&lt;/span&gt; NameExpression&lt;span style="color:cyan;"&gt;(&lt;/span&gt;&lt;span style="color:orange;"&gt;string&lt;/span&gt; name&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;.name = name&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;object&lt;/span&gt; Evaluate&lt;span style="color:cyan;"&gt;(&lt;/span&gt;Context context&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; context.Get&lt;span style="color:cyan;"&gt;(&lt;/span&gt;&lt;span style="color:orange;"&gt;this&lt;/span&gt;.name&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;span&gt;&amp;nbsp; &lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;Es necesario especificar el contexto (por ejemplo, el contexto de la funci&amp;oacute;n actual, de una clausura, del objeto actual, del m&amp;oacute;dulo actual, etc), porque un mismo nombre puede tener distintas variables asociadas, como pasa en otros lenguajes.&lt;/p&gt;
&lt;p&gt;Como siempre, cada una de estas clases (Expresiones, Contexto, &amp;hellip;) fue armada usando el flujo de trabajo de TDD (ver el proyecto de tests, y la &lt;a href="https://github.com/ajlopez/Mass/commits/master"&gt;historia de commits del repo&lt;/a&gt; donde dej&amp;eacute; evidencia de c&amp;oacute;mo fue el desarrollo en el tiempo).&lt;/p&gt;
&lt;p&gt;Pr&amp;oacute;ximos posts: algunas expresiones adicionales, comandos, usando Mass para scripting, usando Mass desde nuestro programa .NET, etc..&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=1828597" 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/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/TDD/default.aspx">TDD</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><category domain="http://msmvps.com/blogs/lopez/archive/tags/Mass/default.aspx">Mass</category></item><item><title>TDD Kata (4): La cortadora de césped</title><link>http://msmvps.com/blogs/lopez/archive/2013/04/20/tdd-kata-4-la-cortadora-de-c-233-sped.aspx</link><pubDate>Sat, 20 Apr 2013 17:42:46 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1827888</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=1827888</wfw:commentRss><comments>http://msmvps.com/blogs/lopez/archive/2013/04/20/tdd-kata-4-la-cortadora-de-c-233-sped.aspx#comments</comments><description>&lt;p&gt;&lt;a href="http://msmvps.com/blogs/lopez/archive/2013/04/15/tdd-kata-3-tatet-237-tomek.aspx"&gt;Anterior Post&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Como comentaba en el anterior post, hace una semana participé de la ronda preliminar del &lt;a href="https://code.google.com/codejam"&gt;Google Code Jam&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;El ejercicio B fue el Lawnmover:&lt;/p&gt;  &lt;p&gt;&lt;a title="https://code.google.com/codejam/contest/2270488/dashboard#s=p1" href="https://code.google.com/codejam/contest/2270488/dashboard#s=p1"&gt;https://code.google.com/codejam/contest/2270488/dashboard#s=p1&lt;/a&gt;&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;Problem &lt;/p&gt;    &lt;p&gt;Alice and Bob have a lawn in front of their house, shaped like an N metre by M metre rectangle. Each year, they try to cut the lawn in some interesting pattern. They used to do their cutting with shears, which was very time-consuming; but now they have a new automatic lawnmower with multiple settings, and they want to try it out. &lt;/p&gt;    &lt;p&gt;The new lawnmower has a height setting - you can set it to any height h between 1 and 100 millimetres, and it will cut all the grass higher than h it encounters to height h. You run it by entering the lawn at any part of the edge of the lawn; then the lawnmower goes in a straight line, perpendicular to the edge of the lawn it entered, cutting grass in a swath 1m wide, until it exits the lawn on the other side. The lawnmower&amp;#39;s height can be set only when it is not on the lawn. &lt;/p&gt;    &lt;p&gt;Alice and Bob have a number of various patterns of grass that they could have on their lawn. For each of those, they want to know whether it&amp;#39;s possible to cut the grass into this pattern with their new lawnmower. Each pattern is described by specifying the height of the grass on each 1m x 1m square of the lawn. &lt;/p&gt;    &lt;p&gt;The grass is initially 100mm high on the whole lawn.&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Lo pude solucionar, ver:&lt;/p&gt;  &lt;p&gt;&lt;a href="https://github.com/ajlopez/TddOnTheRocks/tree/master/Lawnmover"&gt;https://github.com/ajlopez/TddOnTheRocks/tree/master/Lawnmover&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Como siempre, la historia, prácticamente por test:&lt;/p&gt;  &lt;p&gt;&lt;a href="https://github.com/ajlopez/TddOnTheRocks/commits/master/Lawnmover"&gt;https://github.com/ajlopez/TddOnTheRocks/commits/master/Lawnmover&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Pude resolver el primer “set” pequeño de problemas que me entregó Google. No pude resolver el “set” grande, porque me equivoqué de algoritmo a seguir, y no cumplí en resolverlo en 8 minutos. Mi algoritmo inicial (pueden ver los commits) resolvía el problema partiendo de los números mayores. Lo cambié para que comenzara a resolver los números menores primero, y ahí anduvo más rápido. Un tema que aprendí: algunos problemas de Google Code Jam son difíciles de probar a mano, como no tenemos los casos de uso (entrada y salida esperada), hay que trabajar con cuidado en esos temas.&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=1827888" 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/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/Google/default.aspx">Google</category></item><item><title>TDD Kata (3): TaTeTíTomek</title><link>http://msmvps.com/blogs/lopez/archive/2013/04/15/tdd-kata-3-tatet-237-tomek.aspx</link><pubDate>Mon, 15 Apr 2013 10:41:00 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1827351</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=1827351</wfw:commentRss><comments>http://msmvps.com/blogs/lopez/archive/2013/04/15/tdd-kata-3-tatet-237-tomek.aspx#comments</comments><description>&lt;p&gt;&lt;a href="http://msmvps.com/blogs/lopez/archive/2013/04/12/tdd-kata-2-lenguaje-alien-237-gena.aspx"&gt;Anterior Post&amp;nbsp;&lt;/a&gt;&amp;nbsp;&lt;br /&gt;&lt;a href="http://msmvps.com/blogs/lopez/archive/2013/04/20/tdd-kata-4-la-cortadora-de-c-233-sped.aspx"&gt;Siguiente Post&lt;/a&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;El s&amp;aacute;bado pasado estuve participando del Google Code Jam. El ejercicio A fue TicTacToeTomek:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://code.google.com/codejam/contest/2270488/dashboard"&gt;https://code.google.com/codejam/contest/2270488/dashboard&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;h5&gt;Problem&lt;/h5&gt;
&lt;p&gt;Tic-Tac-Toe-Tomek is a game played on a 4 x 4 square board. The board starts empty, except that a single &amp;#39;T&amp;#39; symbol may appear in one of the 16 squares. There are two players: X and O. They take turns to make moves, with X starting. In each move a player puts her symbol in one of the empty squares. Player X&amp;#39;s symbol is &amp;#39;X&amp;#39;, and player O&amp;#39;s symbol is &amp;#39;O&amp;#39;.&lt;/p&gt;
&lt;p&gt;After a player&amp;#39;s move, if there is a row, column or a diagonal containing 4 of that player&amp;#39;s symbols, or containing 3 of her symbols and the &amp;#39;T&amp;#39; symbol, she wins and the game ends. Otherwise the game continues with the other player&amp;#39;s move. If all of the fields are filled with symbols and nobody won, the game ends in a draw. See the sample input for examples of various winning positions.&lt;/p&gt;
&lt;p&gt;Given a 4 x 4 board description containing &amp;#39;X&amp;#39;, &amp;#39;O&amp;#39;, &amp;#39;T&amp;#39; and &amp;#39;.&amp;#39; characters (where &amp;#39;.&amp;#39; represents an empty square), describing the current state of a game, determine the status of the Tic-Tac-Toe-Tomek game going on. The statuses to choose from are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&amp;quot;X won&amp;quot; (the game is over, and X won) &lt;/li&gt;
&lt;li&gt;&amp;quot;O won&amp;quot; (the game is over, and O won) &lt;/li&gt;
&lt;li&gt;&amp;quot;Draw&amp;quot; (the game is over, and it ended in a draw) &lt;/li&gt;
&lt;li&gt;&amp;quot;Game has not completed&amp;quot; (the game is not over yet)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If there are empty cells, and the game is not over, you should output &amp;quot;Game has not completed&amp;quot;, even if the outcome of the game is inevitable.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Se nos da un archivo de entrada con distintas posiciones de tablero, y tenemos que producir una salida diciendo si X gan&amp;oacute;, O gan&amp;oacute;, empate, o todav&amp;iacute;a falta completar el juego.&lt;/p&gt;
&lt;p&gt;Lo resolv&amp;iacute; usando TDD, y pueden ver el resultado en:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/ajlopez/TddOnTheRocks/tree/master/TicTacToeTomek"&gt;https://github.com/ajlopez/TddOnTheRocks/tree/master/TicTacToeTomek&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Y la historia, pr&amp;aacute;cticamente con commits por tests, en:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/ajlopez/TddOnTheRocks/commits/master/TicTacToeTomek"&gt;https://github.com/ajlopez/TddOnTheRocks/commits/master/TicTacToeTomek&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Fue un ejercicio sencillo, y bien adaptado para TDD. Google me acept&amp;oacute; tanto la soluci&amp;oacute;n de un archivo de entrada peque&amp;ntilde;o, y de otro grande. Tengo que escribir sobre los otros ejercicios (B, C, D), que se complican por:&lt;/p&gt;
&lt;p&gt;- Hay que resolver el problema en un tiempo adecuado&lt;/p&gt;
&lt;p&gt;- El algoritmo a implementar no es evidente, o no se puede implementar &amp;ldquo;de a poco&amp;rdquo;, con &amp;ldquo;baby steps&amp;rdquo;, con lo que a veces hay grandes refactor&lt;/p&gt;
&lt;p&gt;- A veces, dada la entrada, es dif&amp;iacute;cil calcular la salida correcta, a&amp;uacute;n manualmente. Entonces, muchos de mis intentos fueron rechazados al subir el archivo soluci&amp;oacute;n a Google.&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=1827351" 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/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/Google/default.aspx">Google</category></item><item><title>TDD Kata (2): Lenguaje Alienígena</title><link>http://msmvps.com/blogs/lopez/archive/2013/04/12/tdd-kata-2-lenguaje-alien-237-gena.aspx</link><pubDate>Fri, 12 Apr 2013 13:03:00 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1827165</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=1827165</wfw:commentRss><comments>http://msmvps.com/blogs/lopez/archive/2013/04/12/tdd-kata-2-lenguaje-alien-237-gena.aspx#comments</comments><description>&lt;p&gt;&lt;a href="http://msmvps.com/blogs/lopez/archive/2013/04/10/tdd-kata-1-piedra-papel-tijera-lagarto-spock.aspx"&gt;Anterior Post&lt;/a&gt;&amp;nbsp;&lt;br /&gt;&lt;a href="http://msmvps.com/blogs/lopez/archive/2013/04/15/tdd-kata-3-tatet-237-tomek.aspx"&gt;Siguiente Post&lt;/a&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;En la lista &lt;a href="https://groups.google.com/group/tddev-sp?hl=es&amp;amp;pli=1"&gt;TDDev en espa&amp;ntilde;ol&lt;/a&gt; se mencion&amp;oacute; hace poco el &lt;a href="https://code.google.com/codejam/"&gt;Google Code Jam&lt;/a&gt;. Uno de los &lt;a href="https://code.google.com/codejam/contests.html"&gt;pasados desaf&amp;iacute;os&lt;/a&gt; de esa competencia, es el &lt;a href="https://code.google.com/codejam/contest/90101/dashboard#s=p0"&gt;Alien Language&lt;/a&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;After years of study, scientists at Google Labs have discovered an alien language transmitted from a faraway planet. The alien language is very unique in that every word consists of exactly L lowercase letters. Also, there are exactly D words in this language. &lt;/p&gt;
&lt;p&gt;Once the dictionary of all the words in the alien language was built, the next breakthrough was to discover that the aliens have been transmitting messages to Earth for the past decade. Unfortunately, these signals are weakened due to the distance between our two planets and some of the words may be misinterpreted. In order to help them decipher these messages, the scientists have asked you to devise an algorithm that will determine the number of possible interpretations for a given pattern. &lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;A pattern consists of exactly L tokens. Each token is either a single lowercase letter (the scientists are very sure that this is the letter) or a group of unique lowercase letters surrounded by parenthesis ( and ). For example: (ab)d(dc) means the first letter is either a or b, the second letter is definitely d and the last letter is either d or c. Therefore, the pattern (ab)d(dc) can stand for either one of these 4 possibilities: add, adc, bdd, bdc.&lt;/p&gt;
&lt;p&gt;Me gust&amp;oacute; como problema. Vean en la p&amp;aacute;gina que tambi&amp;eacute;n se pide leer un archivo de entrada con las palabras y los patrones a procesar. Se pueden bajar archivos de entrada desde la p&amp;aacute;gina del problema, y se debe entregar un archivo de salida para que Google nos diga si est&amp;aacute; bien. Hoy escrib&amp;iacute; una soluci&amp;oacute;n usando TDD:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/ajlopez/TddOnTheRocks/tree/master/AlienLanguage"&gt;https://github.com/ajlopez/TddOnTheRocks/tree/master/AlienLanguage&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Pueden ver la historia de los commits, pr&amp;aacute;cticamente por test:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/ajlopez/TddOnTheRocks/commits/master/AlienLanguage"&gt;https://github.com/ajlopez/TddOnTheRocks/commits/master/AlienLanguage&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Una de las &amp;uacute;ltimas cosas que hice fue refactorizar, para mejorar, si fuera necesario, la detecci&amp;oacute;n de palabras que cumplen con un patr&amp;oacute;n. Podr&amp;iacute;a mejorarlo m&amp;aacute;s, por ejemplo, haciendo que en vez de tener una lista de palabras, mantener un &amp;aacute;rbol de palabras con ramas por letra, como hice en &lt;a href="https://github.com/ajlopez/SimpleBoggle"&gt;SimpleBoggle&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Al final, escrib&amp;iacute; un programa de consola que acepta un archivo de entrada y produce un archivo de salida como pide Google. Me baj&amp;eacute; un archivo grande de Google, lo proces&amp;eacute;, y la salida obtenida lo sub&amp;iacute; a Google, para que lo revise autom&amp;aacute;tica. Y di&amp;oacute; bien:&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.ajlopez.com/images/articles2/tddkata0201.png" alt="" /&gt; &lt;/p&gt;
&lt;p&gt;Otro triunfo de TDD ;-)&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=1827165" 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/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 Kata (1): Piedra Papel Tijera Lagarto Spock</title><link>http://msmvps.com/blogs/lopez/archive/2013/04/10/tdd-kata-1-piedra-papel-tijera-lagarto-spock.aspx</link><pubDate>Wed, 10 Apr 2013 14:43:00 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1826997</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=1826997</wfw:commentRss><comments>http://msmvps.com/blogs/lopez/archive/2013/04/10/tdd-kata-1-piedra-papel-tijera-lagarto-spock.aspx#comments</comments><description>&lt;p&gt;&lt;a href="http://msmvps.com/blogs/lopez/archive/2013/04/12/tdd-kata-2-lenguaje-alien-237-gena.aspx"&gt;Siguiente Post&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;En estos d&amp;iacute;as, le&amp;iacute; en la lista de &lt;a href="https://groups.google.com/group/tddev-sp?hl=es&amp;amp;pli=1"&gt;TDDev&lt;/a&gt; en espa&amp;ntilde;ol una &lt;a href="https://groups.google.com/group/tddev-sp/browse_thread/thread/3b1877112d2c5de2?hl=es"&gt;nueva kata&lt;/a&gt; publicada en el blog de &lt;a href="https://aprendiendotdd.wordpress.com/"&gt;Aprendiendo TDD&lt;/a&gt;:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://aprendiendotdd.wordpress.com/2013/04/08/kata-tdd-piedra-papel-tijera-lagarto-spock/"&gt;Piedra Papel Tijera Lagarto Spock&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;basado en el problema publicado en&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.solveet.com/exercises/Kata-Piedra-Papel-Tijera-Lagarto-Spock/20" title="http://www.solveet.com/exercises/Kata-Piedra-Papel-Tijera-Lagarto-Spock/20"&gt;http://www.solveet.com/exercises/Kata-Piedra-Papel-Tijera-Lagarto-Spock/20&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Tom&amp;eacute; la descripci&amp;oacute;n del art&amp;iacute;culo de la Wikipedia:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://en.wikipedia.org/wiki/Rock-paper-scissors-lizard-Spock"&gt;http://en.wikipedia.org/wiki/Rock-paper-scissors-lizard-Spock&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The rules of Rock-paper-scissors-lizard-Spock are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://en.wikipedia.org/wiki/Scissors"&gt;Scissors&lt;/a&gt; cut &lt;a href="http://en.wikipedia.org/wiki/Paper"&gt;paper&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Paper covers &lt;a href="http://en.wikipedia.org/wiki/Rock_(geology)"&gt;rock&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Rock crushes &lt;a href="http://en.wikipedia.org/wiki/Lizard"&gt;lizard&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Lizard poisons &lt;a href="http://en.wikipedia.org/wiki/Spock"&gt;Spock&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Spock smashes (or melts) scissors &lt;/li&gt;
&lt;li&gt;Scissors decapitate lizard &lt;/li&gt;
&lt;li&gt;Lizard eats paper &lt;/li&gt;
&lt;li&gt;Paper disproves Spock &lt;/li&gt;
&lt;li&gt;Spock vaporizes rock &lt;/li&gt;
&lt;li&gt;Rock breaks scissors&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;Y entonces me puse a codificarla usando TDD. Pueden ver el resultado en:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/ajlopez/TddOnTheRocks/tree/master/SpockGame"&gt;https://github.com/ajlopez/TddOnTheRocks/tree/master/SpockGame&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;La historia, casi por tests:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/ajlopez/TddOnTheRocks/commits/master/SpockGame"&gt;https://github.com/ajlopez/TddOnTheRocks/commits/master/SpockGame&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.ajlopez.com/images/articles2/tddkata0103.png" alt="" /&gt; &lt;/p&gt;
&lt;p&gt;Vean el primer test/commit: todav&amp;iacute;a no compilaba. Luego, comenz&amp;oacute; a compilar pero con estado rojo. Luego, lo pas&amp;eacute; a verde y as&amp;iacute;.&lt;/p&gt;
&lt;p&gt;Tambi&amp;eacute;n decid&amp;iacute; ter dos tests por cada combinaci&amp;oacute;n de arriba: una que prueba que Scissors cut Paper, y otra que prueba Paper is cut by Scissors&lt;/p&gt;
&lt;p&gt;El dise&amp;ntilde;o inicial fue basado en:&lt;/p&gt;
&lt;p&gt;- Tener una instancia de Game (la alternativa era tener la clase, sin instancia)&lt;/p&gt;
&lt;p&gt;- Tener una enumeraci&amp;oacute;n para las opciones de juego (Play.Scissors, etc&amp;hellip;)&lt;/p&gt;
&lt;p&gt;- Tener una enumeraci&amp;oacute;n para el resultado (PlayResult.Tie, PlayResult.FirstPlayer&amp;hellip;)&lt;/p&gt;
&lt;p&gt;En vez de tener resultado de juego, podr&amp;iacute;a haber puesto un m&amp;eacute;todo que comparara dos opciones de juego, y devolviera cu&amp;aacute;l es la que gana. Incluso hoy podr&amp;iacute;a poner este m&amp;eacute;todo como refactorizaci&amp;oacute;n. &lt;/p&gt;
&lt;p&gt;Vean la &amp;uacute;ltima refactorizaci&amp;oacute;n: podr&amp;iacute;a haber dejado el c&amp;oacute;digo de implementaci&amp;oacute;n tal como estaba, con &lt;a href="https://github.com/ajlopez/TddOnTheRocks/blob/8bbf7cdf7978a067574c4aaed250a2cb29c852f7/SpockGame/SpockGame/Game.cs"&gt;if para decidir cu&amp;aacute;ndo gana el primer jugador&lt;/a&gt;:&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.ajlopez.com/images/articles2/tddkata0101.png" alt="" /&gt; &lt;/p&gt;
&lt;p&gt;Por esta &lt;a href="https://github.com/ajlopez/TddOnTheRocks/blob/723f9dc6c8755ab7f56a4160cf9ca6f3dabe7ec0/SpockGame/SpockGame/Game.cs"&gt;otra forma&lt;/a&gt;:&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.ajlopez.com/images/articles2/tddkata0102.png" alt="" /&gt; &lt;/p&gt;
&lt;p&gt;sugerida por el art&amp;iacute;culo de la Wikipedia:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;One way to remember the rules is to remember the standard &amp;quot;rock-paper-scissors&amp;quot; ordering, where each gesture defeats the one before it, and is defeated by the one after. But then add the two novel gestures near the word they approximately rhyme with:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Rock &lt;/li&gt;
&lt;li&gt;Spock &lt;/li&gt;
&lt;li&gt;Paper &lt;/li&gt;
&lt;li&gt;Lizard &lt;/li&gt;
&lt;li&gt;Scissors&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;In this expanded list, each gesture is defeated by the following &lt;i&gt;two&lt;/i&gt; options, and defeats the preceding two.&lt;/p&gt;
&lt;/blockquote&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=1826997" 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/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>Mass Lenguaje de Programación (1) Orígenes</title><link>http://msmvps.com/blogs/lopez/archive/2013/04/08/mass-lenguaje-de-programaci-243-n-1-or-237-genes.aspx</link><pubDate>Mon, 08 Apr 2013 10:43:00 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1826814</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=1826814</wfw:commentRss><comments>http://msmvps.com/blogs/lopez/archive/2013/04/08/mass-lenguaje-de-programaci-243-n-1-or-237-genes.aspx#comments</comments><description>&lt;p&gt;&lt;a href="http://msmvps.com/blogs/lopez/archive/2013/04/27/mass-lenguaje-de-programaci-243-n-2-primeras-expresiones.aspx"&gt;Siguiente Post&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Durante estos d&amp;iacute;as, estuve trabajando en la implementaci&amp;oacute;n de un lenguaje interpretado, sobre C#, llamado Mass (dedicado al bueno de &lt;a href="http://twitter.com/martinsalias"&gt;@MArtinSaliaS&lt;/a&gt;):&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/ajlopez/Mass"&gt;https://github.com/ajlopez/Mass&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.ajlopez.com/images/articles2/mass0101.png" alt="" /&gt; &lt;/p&gt;
&lt;p&gt;La soluci&amp;oacute;n actual se compone de tres proyectos: una librer&amp;iacute;a de clases, sus tests, y un programa de consola, mass.exe, para lanzar programas Mass&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.ajlopez.com/images/articles2/mass0102.png" alt="" /&gt; &lt;/p&gt;
&lt;p&gt;Pueden lanzar un programa escrito en un archivo hello.ms con&lt;/p&gt;
&lt;pre style="background-color:black;width:600px;color:white;"&gt;mass hello.ms&lt;/pre&gt;
&lt;p&gt;El cl&amp;aacute;sico Hello world es entonces&lt;/p&gt;
&lt;pre style="background-color:black;width:600px;color:white;"&gt;println&lt;span style="color:cyan;"&gt;(&lt;/span&gt;&lt;span style="color:lightgreen;"&gt;&amp;quot;Hello, world&amp;quot;&lt;/span&gt;&lt;span style="color:cyan;"&gt;)&lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;Un ejemplo con clases y objetos&lt;/p&gt;
&lt;pre style="background-color:black;width:600px;color:white;"&gt;&lt;span style="color:orange;"&gt;class&lt;/span&gt; Person
	&lt;span style="color:orange;"&gt;define&lt;/span&gt; initialize&lt;span style="color:cyan;"&gt;(&lt;/span&gt;firstname&lt;span style="color:cyan;"&gt;,&lt;/span&gt; lastname&lt;span style="color:cyan;"&gt;)&lt;/span&gt;
		self.firstname = firstname
		self.lastname = lastname
	&lt;span style="color:orange;"&gt;end&lt;/span&gt;
	
	&lt;span style="color:orange;"&gt;define&lt;/span&gt; getName&lt;span style="color:cyan;"&gt;()&lt;/span&gt;
		&lt;span style="color:orange;"&gt;return&lt;/span&gt; self.lastname + &lt;span style="color:lightgreen;"&gt;&amp;quot;, &amp;quot;&lt;/span&gt; + self.firstname
	&lt;span style="color:orange;"&gt;end&lt;/span&gt;
&lt;span style="color:orange;"&gt;end&lt;/span&gt;

adam = new Person&lt;span style="color:cyan;"&gt;(&lt;/span&gt;&lt;span style="color:lightgreen;"&gt;&amp;quot;Adam&amp;quot;&lt;/span&gt;&lt;span style="color:cyan;"&gt;,&lt;/span&gt; &lt;span style="color:lightgreen;"&gt;&amp;quot;TheFirst&amp;quot;&lt;/span&gt;&lt;span style="color:cyan;"&gt;)&lt;/span&gt;

println&lt;span style="color:cyan;"&gt;(&lt;/span&gt;adam.getName&lt;span style="color:cyan;"&gt;())&lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;Un ejemplo con acceso a tipos y objectos .NET:&lt;/p&gt;
&lt;pre style="background-color:black;width:600px;color:white;"&gt;dirinfo = new System.IO.DirectoryInfo&lt;span style="color:cyan;"&gt;(&lt;/span&gt;&lt;span style="color:lightgreen;"&gt;&amp;quot;.&amp;quot;&lt;/span&gt;&lt;span style="color:cyan;"&gt;)&lt;/span&gt;

&lt;span style="color:orange;"&gt;for&lt;/span&gt; fileinfo in dirinfo.GetFiles&lt;span style="color:cyan;"&gt;()&lt;/span&gt;
	println&lt;span style="color:cyan;"&gt;(&lt;/span&gt;fileinfo.Name&lt;span style="color:cyan;"&gt;)&lt;/span&gt;
&lt;span style="color:orange;"&gt;end&lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;La idea es (como en AjSharp y otras implementaciones) tener un lenguaje din&amp;aacute;mico montado sobre un lenguaje/librer&amp;iacute;a de clases. Y poder acceder a esa librer&amp;iacute;a de clases desde el nuevo lenguaje. Me llev&amp;oacute; a escribir Mass de la forma en que lo hice, el haber trabajado antes en:&lt;/p&gt;
&lt;p&gt;- Implementar Python en C# (ver &lt;a href="https://github.com/ajlopez/PythonSharp"&gt;PythonSharp&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;- Implementar Ruby en C# (ver &lt;a href="https://github.com/ajlopez/RubySharp"&gt;RubySharp&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;- El ya mencionado AjSharp (ver &lt;a href="https://github.com/ajlopez/AjSharp"&gt;repo&lt;/a&gt; y &lt;a href="http://msmvps.com/blogs/lopez/archive/tags/AjSharp/default.aspx"&gt;posts&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;Pero esta vez quer&amp;iacute;a implementar algo que tuviera sintaxis y sem&amp;aacute;ntica simple. Ya estuve pensando en eso de &amp;ldquo;simple&amp;rdquo; para implementar un compilador de lenguaje simple a JavaScript &lt;a href="http://msmvps.com/blogs/lopez/archive/2013/01/03/simplescript-1-primeras-ideas.aspx"&gt;ver SimpleScript&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Entonces con Mass me propuse evitar:&lt;/p&gt;
&lt;p&gt;- M&amp;uacute;ltiples comandos en la misma l&amp;iacute;nea (descart&amp;eacute; el &amp;lsquo;;&amp;rsquo; de Ruby)&lt;/p&gt;
&lt;p&gt;- Sintaxis basada en espacios en blanco, indentaci&amp;oacute;n (descartado Python)&lt;/p&gt;
&lt;p&gt;- Llamadas a funciones con simplemente el nombre: se necesita expl&amp;iacute;citamente los par&amp;eacute;ntesis (descartado el Ruby cl&amp;aacute;sico)&lt;/p&gt;
&lt;p&gt;- Que las clases/valores de base (por ejemplo, enteros, strings, arreglos, etc&amp;hellip;) tuvieran multitud de m&amp;eacute;todos (tienen los dados por la librer&amp;iacute;a de clases de implementaci&amp;oacute;n, en este caso .NET) (descartado Ruby, que tiene casi tantos m&amp;eacute;todos nativos como PHP)&lt;/p&gt;
&lt;p&gt;Y quise tener:&lt;/p&gt;
&lt;p&gt;- Valores funcionales, como ciudadanos de primera clase, como en JavaScript. Vean que al tener que invocar una funci&amp;oacute;n con par&amp;eacute;ntesis, si o si, entonces la variable func tiene el valor funcional, y func() es la invocaci&amp;oacute;n expl&amp;iacute;cita&lt;/p&gt;
&lt;p&gt;- Objectos din&amp;aacute;micos: cada objeto puede extenderse en cualquier momento, con nuevas variables de instancia, funciones propias del objeto, como JavaScript&lt;/p&gt;
&lt;p&gt;- Sintaxis basada en l&amp;iacute;neas: cada comando va en una l&amp;iacute;nea distinta&lt;/p&gt;
&lt;p&gt;- Sintaxis basada en palabras claves: para los comandos compuestos se usa &amp;lsquo;end&amp;rsquo; para terminar un bloque&lt;/p&gt;
&lt;p&gt;- En lo posible, una sola forma de hacer algo, en vez de m&amp;uacute;ltiples maneras&lt;/p&gt;
&lt;p&gt;- Palabras claves completas, &amp;lsquo;define&amp;rsquo; en vez de &amp;lsquo;def&amp;rsquo;&lt;/p&gt;
&lt;p&gt;- Clases con herencia simple (aunque la esencia de Mass bien puede expresarse sin clases, y usar librer&amp;iacute;as de clases ya escritas en .NET)&lt;/p&gt;
&lt;p&gt;- Modificaci&amp;oacute;n expl&amp;iacute;cita de variables fuera del alcance local (para explicar en pr&amp;oacute;ximos posts)&lt;/p&gt;
&lt;p&gt;- Alcance de variables por archivo, como en JavaScript/NodeJs/CommonJS&lt;/p&gt;
&lt;p&gt;- M&amp;oacute;dulos por archivo, con un require que permite buscar en directorios autom&amp;aacute;ticamente, como en NodeJs/CommonJS&lt;/p&gt;
&lt;p&gt;- Empaquetamiento, manejo de dependencias e instalaci&amp;oacute;n de esos m&amp;oacute;dulos usando algo ya dado, como NPM, el manejador de paquetes de Node.js&lt;/p&gt;
&lt;p&gt;En pr&amp;oacute;ximos posts, m&amp;aacute;s detalles de implementaci&amp;oacute;n, ideas que guiaron el dise&amp;ntilde;o, ejemplos. Pero ya pueden ver el c&amp;oacute;digo, y los ejemplos que est&amp;aacute;n en los tests (s&amp;iacute;, est&amp;aacute; todo construido paso a paso usando TDD).&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=1826814" 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/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/TDD/default.aspx">TDD</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><category domain="http://msmvps.com/blogs/lopez/archive/tags/Mass/default.aspx">Mass</category></item><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>Escribiendo un Intérprete en .NET (Parte 10)</title><link>http://msmvps.com/blogs/lopez/archive/2013/03/18/escribiendo-un-int-233-rprete-en-net-parte-10.aspx</link><pubDate>Mon, 18 Mar 2013 09:50:56 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1825406</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=1825406</wfw:commentRss><comments>http://msmvps.com/blogs/lopez/archive/2013/03/18/escribiendo-un-int-233-rprete-en-net-parte-10.aspx#comments</comments><description>&lt;p&gt;Anteriores posts de la serie:&lt;/p&gt;  &lt;p&gt;&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;Escribiendo un Intérprete en .NET (Parte 9)&lt;/a&gt;    &lt;br /&gt;&lt;a href="http://msmvps.com/blogs/lopez/archive/2011/01/20/writing_2D00_an_2D00_interpreter_2D00_in_2D00_net_2D00_part_2D00_8.aspx"&gt;Escribiendo un Intérprete en .NET (Parte 8)&lt;/a&gt;    &lt;br /&gt;&lt;a href="http://msmvps.com/blogs/lopez/archive/2010/10/05/escribiendo-un-int-233-rprete-en-net-parte-7.aspx"&gt;Escribiendo un Intérprete en .NET (Parte 7)&lt;/a&gt;    &lt;br /&gt;&lt;a href="http://msmvps.com/blogs/lopez/archive/2010/09/21/escribiendo-un-int-233-rprete-en-net-parte-6.aspx"&gt;Escribiendo un Intérprete en .NET (Parte 6)&lt;/a&gt;    &lt;br /&gt;&lt;a href="http://msmvps.com/blogs/lopez/archive/2010/09/20/escribiendo-un-int-233-rprete-en-net-parte-5.aspx"&gt;Escribiendo un Intérprete en .NET (Parte 5)&lt;/a&gt;    &lt;br /&gt;&lt;a href="http://msmvps.com/blogs/lopez/archive/2010/09/18/escribiendo-un-int-233-rprete-en-net.aspx"&gt;Escribiendo un Intérprete en .NET (Parte 4)&lt;/a&gt;    &lt;br /&gt;&lt;a href="http://msmvps.com/blogs/lopez/archive/2010/09/17/escribiendo-un-int-233-rprete-en-net-parte-3.aspx"&gt;Escribiendo un Intérprete en .NET (Parte 3)&lt;/a&gt;    &lt;br /&gt;&lt;a href="http://msmvps.com/blogs/lopez/archive/2010/09/16/escribiendo-un-int-233-rprete-en-net-parte-2.aspx"&gt;Escribiendo un Intérprete en .NET (Parte 2)&lt;/a&gt;    &lt;br /&gt;&lt;a href="http://msmvps.com/blogs/lopez/archive/2010/09/15/escribiendo-un-int-233-rprete-en-net-parte-1.aspx"&gt;Escribiendo un Intérprete en .NET (Parte 1)&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Hace unos meses que no escribo en esta serie, pero es porque he directamente escrito varios intérpretes, usando TDD, y haciendo “commits” prácticamente por tests en &lt;a href="https://github.com/ajlopez"&gt;mi cuenta de GitHub&lt;/a&gt;, siguiendo las ideas de esos posts.&lt;/p&gt;  &lt;p&gt;Intérpretes que estoy escribiendo, parecidos al descripto en los posts, son:&lt;/p&gt;  &lt;p&gt;&lt;a href="https://github.com/ajlopez/PythonSharp"&gt;PythonSharp&lt;/a&gt; (ver &lt;a href="https://github.com/ajlopez/PythonSharp/commits/master"&gt;los commits&lt;/a&gt;) (lo presenté en la PyCon Argentina 2012)&lt;/p&gt;  &lt;p&gt;&lt;a href="https://github.com/ajlopez/RubySharp"&gt;RubySharp&lt;/a&gt; (ver &lt;a href="https://github.com/ajlopez/RubySharp/commits/master"&gt;los commits&lt;/a&gt;)&lt;/p&gt;  &lt;p&gt;Y para un ejemplo de un lenguaje diferente, vean una implementación de &lt;a href="http://clojure.org/"&gt;Clojure&lt;/a&gt; que estoy escribiendo en C#:&lt;/p&gt;  &lt;p&gt;&lt;a href="https://github.com/ajlopez/ClojSharp"&gt;ClojSharp&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Por ejemplo, hoy escribi un nuevo verbo de ClojSharp, la que se llama “let special form”, tienen los commits por tests de hoy:&lt;/p&gt;  &lt;p&gt;&lt;a title="https://github.com/ajlopez/ClojSharp/commits/master" href="https://github.com/ajlopez/ClojSharp/commits/master"&gt;https://github.com/ajlopez/ClojSharp/commits/master&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;img src="http://www.ajlopez.com/images/articles2/interpreter50.png" alt="" /&gt; &lt;/p&gt;  &lt;p&gt;Pueden ver uno en:&lt;/p&gt;  &lt;p&gt;&lt;a title="https://github.com/ajlopez/ClojSharp/commit/51c678ece96d6d1cef92f36afda8d8fc711ffd8c" href="https://github.com/ajlopez/ClojSharp/commit/51c678ece96d6d1cef92f36afda8d8fc711ffd8c"&gt;https://github.com/ajlopez/ClojSharp/commit/51c678ece96d6d1cef92f36afda8d8fc711ffd8c&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;donde GitHub nos muestra los cambios en el código. &lt;/p&gt;  &lt;p&gt;Otro ejemplo, lo que hice ayer, test por test, en RubySharp:&lt;/p&gt;  &lt;p&gt;&lt;a title="https://github.com/ajlopez/RubySharp/commits/master" href="https://github.com/ajlopez/RubySharp/commits/master"&gt;https://github.com/ajlopez/RubySharp/commits/master&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;img src="http://www.ajlopez.com/images/articles2/interpreter51.png" alt="" /&gt; &lt;/p&gt;  &lt;p&gt;Espero que estos ejemplos les sirvan para ir viendo cómo se puede usar TDD para este tipo de proyectos. Tengo más ejemplos de otros tipos de aplicaciones &lt;a href="http://msmvps.com/blogs/lopez/archive/tags/TDD/default.aspx"&gt;en mis posts de TDD&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=1825406" 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/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/TDD/default.aspx">TDD</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>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>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 3) Primer Detalle</title><link>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</link><pubDate>Thu, 31 Mar 2011 09:55:00 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1790946</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=1790946</wfw:commentRss><comments>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#comments</comments><description>&lt;p&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;Primer post de la serie&lt;/a&gt; &lt;br /&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;Pr&amp;oacute;ximo post de la serie&lt;/a&gt; &lt;br /&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;Anterior post de la serie&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Desde el anterior post, he aplicado las sugerencias que dejaron en comentarios &lt;a href="http://twitter.com/MartinSalias"&gt;@MartinSalias&lt;/a&gt; y &lt;a href="http://twitter.com/theHumanFlag"&gt;@theHumanFlag&lt;/a&gt;, gracias! (las dejaron en el &lt;a href="http://ajlopez.wordpress.com/2011/03/22/writing-an-application-using-tdd-part-2-first-list/"&gt;post en ingl&amp;eacute;s&lt;/a&gt;). Primero, renombr&amp;eacute; la clase Genre a Subject, usando las capacidades de refactoring de Visual Studio:&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; Subject
{
    &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;Segundo, ahora el controlador recibe y procesa un&amp;nbsp; IEnumerable&amp;lt;Subject&amp;gt;:&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; SubjectController : Controller
{
    &lt;span style="color:#0000ff;"&gt;private&lt;/span&gt; IEnumerable&amp;lt;Subject&amp;gt; subjects;
    &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; SubjectController()
    {
    }
    &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; SubjectController(IEnumerable&amp;lt;Subject&amp;gt; subjects)
    {
        &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.subjects = subjects;
    }
    &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;Hice los cambios con confianza, gracias a los tests.&lt;/p&gt;
&lt;p&gt;Ahora, en este nuevo paso, agregu&amp;eacute; una acci&amp;oacute;n: dado un Id, obtener el Subject. La propiedad Id agregada en Subjec:&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; Subject
{
    &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;int&lt;/span&gt; Id { &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; &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;Escrib&amp;iacute; 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;[TestMethod]
&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;void&lt;/span&gt; GetSubjectForDetail()
{
    IEnumerable&amp;lt;Subject&amp;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; }
    };
    SubjectController controller = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; SubjectController(subjects);
    ActionResult result = controller.Details(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;El test no compila. Agregu&amp;eacute; la acci&amp;oacute;n en el controler:&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 Details(&lt;span style="color:#0000ff;"&gt;int&lt;/span&gt; id)
{
    &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; View();
}
&lt;/pre&gt;
&lt;/pre&gt;
&lt;p&gt;El test compila, pero da en rojo. Vamos por el verde:&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 Details(&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;En este punto, ten&amp;iacute;a dos tests, que daban una lista de Subjects al controlador. Hice refactoreo de los test para separar la creaci&amp;oacute;n de la lista. Extraje el m&amp;eacute;todo:&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;private&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;static&lt;/span&gt; IEnumerable&amp;lt;Subject&amp;gt; GetSubjects()
{
    IEnumerable&amp;lt;Subject&amp;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;return&lt;/span&gt; subjects;
}
&lt;/pre&gt;
&lt;/pre&gt;
&lt;p&gt;Ahora, el c&amp;oacute;digo del test 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;[TestMethod]
&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;void&lt;/span&gt; GetSubjectInDetail()
{
    IEnumerable&amp;lt;Subject&amp;gt; subjects = GetSubjects();
    SubjectController controller = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; SubjectController(subjects);
    ActionResult result = controller.Details(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;Todo en verde!&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.ajlopez.com/images/articles2/apptdd0201.png" alt="" /&gt; &lt;/p&gt;
&lt;p&gt;Como siempre, el c&amp;oacute;digo est&amp;aacute; en mi &lt;a href="http://code.google.com/p/ajcodekatas/"&gt;AjCodeKatas Google Project&lt;/a&gt;, esta vez en&amp;nbsp; trunk/AppTdd/Step02)&lt;/p&gt;
&lt;p&gt;Pr&amp;oacute;ximos pasos: m&amp;aacute;s acciones, integrar alguna vista. &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=1790946" 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/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></channel></rss>