<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-2425636995525834170</id><updated>2012-02-16T05:09:00.700-06:00</updated><category term='Personal'/><category term='c#'/><category term='NUnit'/><category term='Regex'/><category term='string.Format'/><category term='TDD'/><category term='moq'/><category term='MVC'/><category term='Tip'/><category term='Castle Windsor'/><category term='IoC'/><category term='notepad++'/><category term='mock'/><category term='.net'/><category term='Spring.NET'/><category term='Expresiones Regulares'/><category term='ASP.Net'/><category term='Inyección de dependencias'/><category term='Test'/><category term='StringBuilder'/><category term='DI'/><title type='text'>iHenry</title><subtitle type='html'>Programación y más</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://ihenrysmith.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2425636995525834170/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://ihenrysmith.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Henry Smith</name><uri>http://www.blogger.com/profile/02246731323260602803</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_7QbB368NSo0/SMrdY7POsGI/AAAAAAAAFEg/F0bpFLjNqik/S220/SP_A0121.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>8</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-2425636995525834170.post-3792787514305250344</id><published>2010-06-06T17:15:00.016-06:00</published><updated>2010-06-06T22:28:55.924-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='string.Format'/><category scheme='http://www.blogger.com/atom/ns#' term='.net'/><category scheme='http://www.blogger.com/atom/ns#' term='StringBuilder'/><category scheme='http://www.blogger.com/atom/ns#' term='c#'/><title type='text'>String Format  más bonito pero más lento....</title><content type='html'>&lt;div style="text-align: justify;"&gt;&lt;link rel="stylesheet" type="text/css" href="http://www.manoli.net/csharpformat/csharp.css"&gt;Antes, cuando escribíamos nuestro código en general lo hacíamos pensando en que funcionara como se debe, al menos esa era la "fe".   Ahora sabemos que existen una serie de buenas prácticas que debemos seguir, lo cierto es que esas buenas practicas aveces se toman como una tautología y las utilizamos sin siquiera cuestionar si aplican o no a nuestro proyecto.&lt;br /&gt;&lt;br /&gt;Sabemos que en &lt;span style="font-weight: bold; font-style: italic;"&gt;.Net&lt;/span&gt; los objetos  &lt;span style="font-weight: bold; font-style: italic;"&gt;string&lt;/span&gt; son inmutables, lo que quiere decir que una vez creados &lt;span style="font-weight: bold; font-style: italic;"&gt;"nunca" &lt;/span&gt;se podrán cambiar.  Al hacer concatenaciones con el operador &lt;span style="font-weight: bold;"&gt;+&lt;/span&gt; lo que hace el &lt;span style="font-weight: bold; font-style: italic;"&gt;runtime&lt;/span&gt; es "abandonar" el viejo &lt;span style="font-style: italic; font-weight: bold;"&gt;string&lt;/span&gt; y crear uno nuevo, esperando que el &lt;span style="font-weight: bold; font-style: italic;"&gt;garbage collector&lt;/span&gt;&lt;span style="font-style: italic;"&gt; &lt;/span&gt;pase a recoger esa memoria sin referencia que dejamos tirada.  Para evitar esto usamos ya sea los métodos &lt;span style="font-weight: bold; font-style: italic;"&gt;Join&lt;/span&gt;, &lt;span style="font-weight: bold; font-style: italic;"&gt;Concat&lt;/span&gt;, &lt;span style="font-weight: bold; font-style: italic;"&gt;Format&lt;/span&gt;, entre otros, o, utilizamos la clase &lt;span style="font-style: italic; font-weight: bold;"&gt;StringBuilder&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;El método &lt;span style="font-weight: bold; font-style: italic;"&gt;string.Format&lt;/span&gt; ha tomado mucha popularidad ya que es muy útil, entre otras cosas, permite  aplicar localización, simplifica el formateo y facilita la lectura del código.  Es por ello que muchos han comenzado a abandonar las clásicas concatenaciones, sin detenerse a pensar que hay detrás de esté método tan útil. Pero ¿Será más lento?&lt;br /&gt;&lt;br /&gt;La respuesta es sí, &lt;span style="font-weight: bold; font-style: italic;"&gt;string.Format&lt;/span&gt; es más lento que las concatenación.  Para demostrarlo hice un pequeño test en el cual se itera 1000000 veces la misma prueba, una con &lt;span style="font-weight: bold; font-style: italic;"&gt;string.Format&lt;/span&gt; y otra usando concatenaciones con el operador +.&lt;br /&gt;&lt;/div&gt;&lt;div class="csharpcode"&gt;&lt;br /&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   1:  &lt;/span&gt;&lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;double&lt;/span&gt; PruebaConcat()&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   2:  &lt;/span&gt;{&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   3:  &lt;/span&gt;    DateTime inicioConcat = DateTime.Now;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   4:  &lt;/span&gt;    &lt;span class="kwrd"&gt;for&lt;/span&gt; (&lt;span class="kwrd"&gt;int&lt;/span&gt; i = 0; i &amp;lt; 1000000; i++)&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   5:  &lt;/span&gt;    {&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   6:  &lt;/span&gt;        &lt;span class="kwrd"&gt;string&lt;/span&gt; s = &lt;span class="str"&gt;"Test suma i = "&lt;/span&gt; + i + &lt;span class="str"&gt;" Mas i * 2 "&lt;/span&gt; + i * 2;&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   7:  &lt;/span&gt;    }&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   8:  &lt;/span&gt;    DateTime finConcat = DateTime.Now;&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   9:  &lt;/span&gt;    &lt;span class="kwrd"&gt;return&lt;/span&gt; finConcat.Subtract(inicioConcat).TotalMilliseconds;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  10:  &lt;/span&gt;}&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  11:  &lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  12:  &lt;/span&gt;&lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;double&lt;/span&gt; PruebaFormat()&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  13:  &lt;/span&gt;{&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  14:  &lt;/span&gt;    DateTime inicioFormat = DateTime.Now;&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  15:  &lt;/span&gt;    &lt;span class="kwrd"&gt;for&lt;/span&gt; (&lt;span class="kwrd"&gt;int&lt;/span&gt; i = 0; i &amp;lt; 1000000; i++)&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  16:  &lt;/span&gt;    {&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  17:  &lt;/span&gt;        &lt;span class="kwrd"&gt;string&lt;/span&gt; s = &lt;span class="kwrd"&gt;string&lt;/span&gt;.Format(&lt;span class="str"&gt;"Suma i {0} Mas i * 2 {1}"&lt;/span&gt;, i, i * 2);&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  18:  &lt;/span&gt;    }&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  19:  &lt;/span&gt;    DateTime finFormat = DateTime.Now;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  20:  &lt;/span&gt;    &lt;span class="kwrd"&gt;return&lt;/span&gt; finFormat.Subtract(inicioFormat).TotalMilliseconds;&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  21:  &lt;/span&gt;}&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  22:  &lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  23:  &lt;/span&gt;&lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;double&lt;/span&gt;[] CorrerPruebas(Func&amp;lt;&lt;span class="kwrd"&gt;double&lt;/span&gt;&amp;gt; test)&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  24:  &lt;/span&gt;{&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  25:  &lt;/span&gt;    &lt;span class="kwrd"&gt;double&lt;/span&gt;[] arrayTest = &lt;span class="kwrd"&gt;new&lt;/span&gt; &lt;span class="kwrd"&gt;double&lt;/span&gt;[numeroPruebas];&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  26:  &lt;/span&gt;    &lt;span class="kwrd"&gt;for&lt;/span&gt; (&lt;span class="kwrd"&gt;int&lt;/span&gt; pruebas = 0; pruebas &amp;lt; numeroPruebas; pruebas++)&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  27:  &lt;/span&gt;    {&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  28:  &lt;/span&gt;        arrayTest[pruebas] = test();&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  29:  &lt;/span&gt;    }&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  30:  &lt;/span&gt;    &lt;span class="kwrd"&gt;return&lt;/span&gt; arrayTest;&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  31:  &lt;/span&gt;}&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;La prueba se corre  100 veces y los resultados se dan en mili segundos:&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;&lt;img style="display: block; margin: 0px auto 10px; text-align: center; cursor: pointer; width: 269px; height: 187px;" src="http://2.bp.blogspot.com/_7QbB368NSo0/TAxl7yGI7CI/AAAAAAAAJ3w/4uzrYpjMF3s/s400/FormatVsConcat.PNG" alt="" id="BLOGGER_PHOTO_ID_5479866924337261602" border="0" /&gt;Nota:&lt;br /&gt;&lt;/div&gt;&lt;ul style="text-align: justify;"&gt;&lt;li&gt;La diferencia es simplemente la resta del menor dato al mayor. Con algún software como Fathom se calcula fácilmente la diferencia de promedios  para dos poblaciones independientes cuando la varianzas son diferentes.  Incluso a "pata" es simple, pero siendo sincero me ganó el sueño.&lt;/li&gt;&lt;li&gt;Los cálculos fueron hechos con el .&lt;span style="font-weight: bold; font-style: italic;"&gt;Net Framework 4&lt;/span&gt; ya que las implementaciones pueden variar entre las versiones del &lt;span style="font-weight: bold; font-style: italic;"&gt;Framework&lt;/span&gt;.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div style="text-align: justify;"&gt;Estadísticamente los datos no representan mucho, ni son muy confiables por las condiciones, pero si nos dan una idea de las diferencias.&lt;br /&gt;En la prueba se ve como las concatenaciones son más eficientes.  Si bien un promedio de 298 mili segundos no parece significativo, es algo muy relativo al proyecto.&lt;br /&gt;&lt;br /&gt;Algunas alternativas podrían ser: crear nuestro propio método &lt;span style="font-weight: bold; font-style: italic;"&gt;Format&lt;/span&gt; (usando métodos de extensión sería más elegante) o saber diferenciar cuando usar cada uno de los estilos (para ello encontré este bonito &lt;a href="http://www.codeproject.com/KB/cs/StringBuilder_vs_String.aspx"&gt;post&lt;/a&gt; en code project ).  Un ejemplo aparte del rendimiento donde las concatenaciones nos ayudan es que aceptan nulo mientras que &lt;span style="font-weight: bold; font-style: italic;"&gt;Format&lt;/span&gt;  lanza una excepción, pero este ya es un hecho meramente de diseño.&lt;br /&gt;&lt;br /&gt;Es probable que este &lt;span style="font-weight: bold; font-style: italic;"&gt;overhead&lt;/span&gt; no tenga mucha incidencia en la mayoría de nuestros proyectos, pero nos ayuda a pensar en la necesidad de revisar con detalle las buenas prácticas que aplicamos y en más esencialmente que metemos en nuestro código.&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2425636995525834170-3792787514305250344?l=ihenrysmith.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ihenrysmith.blogspot.com/feeds/3792787514305250344/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2425636995525834170&amp;postID=3792787514305250344' title='2 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2425636995525834170/posts/default/3792787514305250344'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2425636995525834170/posts/default/3792787514305250344'/><link rel='alternate' type='text/html' href='http://ihenrysmith.blogspot.com/2010/06/string-format-mas-bonito-pero-mas-lento.html' title='String Format  más bonito pero más lento....'/><author><name>Henry Smith</name><uri>http://www.blogger.com/profile/02246731323260602803</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_7QbB368NSo0/SMrdY7POsGI/AAAAAAAAFEg/F0bpFLjNqik/S220/SP_A0121.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_7QbB368NSo0/TAxl7yGI7CI/AAAAAAAAJ3w/4uzrYpjMF3s/s72-c/FormatVsConcat.PNG' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2425636995525834170.post-5258092464653389016</id><published>2010-05-29T10:43:00.016-06:00</published><updated>2010-05-30T19:52:15.620-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.net'/><category scheme='http://www.blogger.com/atom/ns#' term='c#'/><title type='text'>Mapeo de Delegados</title><content type='html'>&lt;link rel="stylesheet" type="text/css" href="http://www.manoli.net/csharpformat/csharp.css"&gt;&lt;span style="font-size:120%;"&gt;&lt;b&gt;El Problema&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Bien, hace unos días trabaja en la implementación de una clase en la cual uno de sus miembros recibe una clase base abstracta.  Al momento de instanciar un objeto de este tipo, el constructor "customizado" debía decidir de acuerdo a un tipo específico, de un &lt;span style="font-weight: bold; font-style: italic;"&gt;Enum&lt;/span&gt;, que recibe como parámetro, cuál era la clase concreta adecuada para dicha propiedad.&lt;br /&gt;&lt;br /&gt;Ante el hecho, de que por las peculiaridades de la clase, el volverla genérica no implicaba beneficio alguno, la prima opción sería implementar un &lt;span style="font-weight: bold; font-style: italic;"&gt;switch&lt;/span&gt;, lo cual era simplificado por la existencia del &lt;span style="font-weight: bold; font-style: italic;"&gt;Enum&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Hablando un poco con un compañero de trabajo (Pablo Guerrero, mejor conocido como Chino), me comentó que había leído sobre el mapeo de delegados, el cual se convierte en una elegante opción al switch.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:120%;"&gt;&lt;b&gt;El Ejemplo&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Suponiendo que tenemos una biblioteca la cual tiene libros digitales, de audio y de papel.  Existe una clase base abstracta Libro y clases concretas para cada tipo de libro.&lt;br /&gt;&lt;br /&gt;El problema es que al ingresar un libro, recibimos información indiscriminada, con el único detalle que se nos indican el tipo de libro que es.&lt;br /&gt;&lt;br /&gt;Las Clases&lt;br /&gt;&lt;br /&gt;&lt;div class="csharpcode"&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   1:  &lt;/span&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;enum&lt;/span&gt; TipoLibro&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   2:  &lt;/span&gt;    {&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   3:  &lt;/span&gt;        Digital,&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   4:  &lt;/span&gt;        Audio,&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   5:  &lt;/span&gt;        Papel&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   6:  &lt;/span&gt;    }&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   7:  &lt;/span&gt; &lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   8:  &lt;/span&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;abstract&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; Libro&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   9:  &lt;/span&gt;    {&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  10:  &lt;/span&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;int&lt;/span&gt; IdLibro { get; set; }&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  11:  &lt;/span&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; Nombre { get; set; }&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  12:  &lt;/span&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; Autor { get; set; }&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  13:  &lt;/span&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;int&lt;/span&gt; NumeroCapitulos { get; set; }&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  14:  &lt;/span&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; DateTime FechaPublicacion { get; set; }&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  15:  &lt;/span&gt; &lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  16:  &lt;/span&gt;    }&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  17:  &lt;/span&gt; &lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  18:  &lt;/span&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; LibroDigital : Libro&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  19:  &lt;/span&gt;    {&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  20:  &lt;/span&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; Formato { get; set; }&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  21:  &lt;/span&gt;    }&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  22:  &lt;/span&gt; &lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  23:  &lt;/span&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; LibroPapel : Libro&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  24:  &lt;/span&gt;    {&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  25:  &lt;/span&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; TipoPapel { get; set; }&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  26:  &lt;/span&gt;    }&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  27:  &lt;/span&gt; &lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  28:  &lt;/span&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; LibroAudio : Libro&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  29:  &lt;/span&gt;    {&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  30:  &lt;/span&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;int&lt;/span&gt; NumeroVoces { get; set; }&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  31:  &lt;/span&gt;    }&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;La magia será crear un mapa de delgados, para ello nos valemos del delegado &lt;span style="font-weight: bold; font-style: italic;"&gt;Func&lt;/span&gt; para no tener que declarar ningún tipo de delegados personalizado, simplemente utilizando métodos que correspondan a la firma del método definida por el delegado. Este delegado en particular recibe un un &lt;span style="font-weight: bold; font-style: italic;"&gt;string&lt;/span&gt; y retorna un tipo Libro.&lt;br /&gt;&lt;div class="csharpcode"&gt;&lt;br /&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   1:  &lt;/span&gt;        &lt;span class="kwrd"&gt;private&lt;/span&gt; Dictionary&amp;lt;TipoLibro, Func&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;, Libro&amp;gt;&amp;gt;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   2:  &lt;/span&gt;            _mapaTipoLibro = &lt;span class="kwrd"&gt;new&lt;/span&gt; Dictionary&amp;lt;TipoLibro, Func&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;, Libro&amp;gt;&amp;gt;()&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   3:  &lt;/span&gt;        {&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   4:  &lt;/span&gt;           { TipoLibro.Digital, CrearLibroDigital },&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   5:  &lt;/span&gt;           { TipoLibro.Audio, CrearLibroAudio },&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   6:  &lt;/span&gt;           { TipoLibro.Papel, CrearLibroPapel }&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   7:  &lt;/span&gt;          &lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   8:  &lt;/span&gt;        };&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;Nótese que lo que se hace es crear un diccionario en donde la llave es un&lt;span style="font-weight: bold;"&gt; Enum &lt;/span&gt; y el &lt;span style="font-weight: bold;"&gt;delegado&lt;/span&gt; es el valor.  Para accederlo simplemente llamamos el diccionario.&lt;br /&gt;&lt;div class="csharpcode"&gt;&lt;br /&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   1:  &lt;/span&gt;        List&amp;lt;Libro&amp;gt; Libros = &lt;span class="kwrd"&gt;new&lt;/span&gt; List&amp;lt;Libro&amp;gt;();&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   2:  &lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   3:  &lt;/span&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; AgregarLibro(&lt;span class="kwrd"&gt;string&lt;/span&gt; nombre, TipoLibro tipoLibro)&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   4:  &lt;/span&gt;        {&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   5:  &lt;/span&gt;            Libros.Add(_mapaTipoLibro[tipoLibro](nombre));&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   6:  &lt;/span&gt;        }&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;Este método además de elegante simplifica el código y nos evita algunos &lt;span style="font-weight: bold;"&gt;switch&lt;span style="font-style: italic;"&gt;&lt;/span&gt;&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Referencias&lt;br /&gt;&lt;br /&gt;Aquí pueden encontrar un poco más sobre los delegados &lt;a href="http://msdn.microsoft.com/en-us/library/bb549151%28v=VS.100%29.aspx"&gt;Func&lt;/a&gt; y el blog original&lt;a href="http://simpleprogrammer.com/201002/25/super-combo-map-function-pointer/"&gt; Making The Complex Simple&lt;/a&gt; donde el buen chino encontró la info.&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2425636995525834170-5258092464653389016?l=ihenrysmith.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ihenrysmith.blogspot.com/feeds/5258092464653389016/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2425636995525834170&amp;postID=5258092464653389016' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2425636995525834170/posts/default/5258092464653389016'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2425636995525834170/posts/default/5258092464653389016'/><link rel='alternate' type='text/html' href='http://ihenrysmith.blogspot.com/2010/05/mapeo-de-delegados.html' title='Mapeo de Delegados'/><author><name>Henry Smith</name><uri>http://www.blogger.com/profile/02246731323260602803</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_7QbB368NSo0/SMrdY7POsGI/AAAAAAAAFEg/F0bpFLjNqik/S220/SP_A0121.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2425636995525834170.post-2380390554019114594</id><published>2010-04-09T00:41:00.003-06:00</published><updated>2010-04-09T00:50:28.477-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Tip'/><category scheme='http://www.blogger.com/atom/ns#' term='.net'/><category scheme='http://www.blogger.com/atom/ns#' term='notepad++'/><category scheme='http://www.blogger.com/atom/ns#' term='Regex'/><category scheme='http://www.blogger.com/atom/ns#' term='Expresiones Regulares'/><title type='text'>Tip: Expresión Regular para remover el número de línea</title><content type='html'>Algunas veces encontramos un código interesante en algún &lt;i&gt;&lt;b&gt;web&lt;/b&gt;&lt;/i&gt;, pero viene con la útil pero molesta numeración de línea, que al copiarlo se viene en combo.&lt;br /&gt;&lt;br /&gt;Algo que solemos hacer cuando hacemos una búsqueda es ignorar las expresiones regulares, lo cuál es una pena, ya que aplica en muchas situaciones que pueden volvernos la vida mucho más fácil y el caso de las líneas es un ejemplo claro ya que con una simple expresión regular nos deshacemos ellas al instante.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;&lt;b&gt;Ejemplo&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Yo uso el editor &lt;a href="http://notepad-plus.sourceforge.net/uk/site.htm"&gt;notepad++&lt;/a&gt; (el cual recomiendo sobre manera) y la expresión a usar sería:&lt;br /&gt;&lt;span style="font-size: large;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;b&gt;&lt;span style="font-size: large;"&gt;^[\s*+\d]+: &lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;br /&gt;Si usamos Visual Studio sería similar en forma:&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;b&gt;&lt;span style="font-size: large;"&gt;^ *[0-9]+\:&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;br /&gt;(Notese que hay &lt;b&gt;un espacio en blanco&lt;/b&gt; entre &lt;b&gt;^&lt;/b&gt; y &lt;b&gt;*&lt;/b&gt; )&lt;br /&gt;Otro sencillo ejemplo que lo complementa, es remover las líneas en blanco para lo cuál usamos en el Visual Studio: &lt;span style="font-size: large;"&gt;&lt;b&gt;^$\n&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Las expresiones regulares son un arte, y es bueno que las incluyamos con más frecuencia en nuestro que hacer diario.&amp;nbsp; Si bien, poco a poco, las herramientas nos facilitan mucho más la vida, &lt;b&gt;no&lt;/b&gt; debemos olvidar las expresiones, recordemos el poder de &lt;a href="http://www.gnu.org/software/grep/"&gt;grep&lt;/a&gt; y &lt;a href="http://www.perl.org/"&gt;perl&lt;/a&gt;, todo lo que podemos hacer con unas simples lineas bien escritas.&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: right;"&gt;&lt;span style="font-size: x-large;"&gt;&lt;b&gt;&lt;span id="main" style="visibility: visible;"&gt;&lt;span id="search" style="visibility: visible;"&gt; /(bb|[^b]{2})/ &lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2425636995525834170-2380390554019114594?l=ihenrysmith.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ihenrysmith.blogspot.com/feeds/2380390554019114594/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2425636995525834170&amp;postID=2380390554019114594' title='1 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2425636995525834170/posts/default/2380390554019114594'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2425636995525834170/posts/default/2380390554019114594'/><link rel='alternate' type='text/html' href='http://ihenrysmith.blogspot.com/2010/04/tip-expresion-regular-para-remover-el.html' title='Tip: Expresión Regular para remover el número de línea'/><author><name>Henry Smith</name><uri>http://www.blogger.com/profile/02246731323260602803</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_7QbB368NSo0/SMrdY7POsGI/AAAAAAAAFEg/F0bpFLjNqik/S220/SP_A0121.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2425636995525834170.post-7255792698843676142</id><published>2010-03-21T21:55:00.093-06:00</published><updated>2010-04-07T14:55:43.086-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='mock'/><category scheme='http://www.blogger.com/atom/ns#' term='Test'/><category scheme='http://www.blogger.com/atom/ns#' term='NUnit'/><category scheme='http://www.blogger.com/atom/ns#' term='moq'/><category scheme='http://www.blogger.com/atom/ns#' term='TDD'/><title type='text'>Mock objects (Objetos Simulados)</title><content type='html'>&lt;link href="http://www.manoli.net/csharpformat/csharp.css" rel="stylesheet" type="text/css"&gt;&lt;/link&gt; &lt;br /&gt;Con &lt;span style="font-style: italic; font-weight: bold;"&gt;Mock Objects&lt;/span&gt; lo que hacemos es simular el comportamiento de los objetos "reales" pero de manera "controlada". &lt;br /&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;Muchas veces cuando queremos crear pruebas para algún objeto nos topamos con el problema de que tiene dependencias, esto nos obliga a buscar la forma para proveerlas, esta situación se puede complicar más cuando estas dependencias aún no han sido programadas, inclusive , tendiéndolas, nos va a llevar mucho trabajo configurar el contexto y conocer que exactamente se les está suministrando y que es lo que nos están proveyendo. Poco a poco nos vamos metiendo en un desorden de miedo, por ejemplo al fallar una prueba nos va costar determinar si fue el objeto "&lt;span style="font-style: italic; font-weight: bold;"&gt;target&lt;/span&gt;" el que falló o alguna de sus dependencias y de ser este el caso, es algo que realmente &lt;span style="font-style: italic; font-weight: bold;"&gt;no&lt;/span&gt; nos interesa mucho, ya que &lt;span style="font-weight: bold;"&gt;NO&lt;/span&gt; son las dependencias las que estamos probando. &lt;br /&gt;&lt;br /&gt;Para aislar las pruebas, al punto que las podamos hacer realmente unitarias, utilizamos "&lt;span style="font-style: italic; font-weight: bold;"&gt;mocks&lt;/span&gt;", que permitan grabar el comportamiento del objeto con aquellos con los que tiene relación.   Con los "&lt;span style="font-style: italic; font-weight: bold;"&gt;mocks&lt;/span&gt;" proveemos datos y comportamiento totalmente controlados de manera tal que sabemos exactamente que es lo que le estamos proveyendo al objeto, que nos está mandando y que deberíamos esperar. &lt;br /&gt;&lt;br /&gt;En la teoría siempre citan el ejemplo de las pruebas de carros, en donde ponen maniquíes especiales que simulan ("&lt;span style="font-style: italic; font-weight: bold;"&gt;mock&lt;/span&gt;") personas reales para ver como reaccionan al choque, esto, dado que es imposible probar con personas reales. &lt;br /&gt;&lt;br /&gt;Cuando vamos a implementar mocks, salta la pregunta de cuál framework deberíamos usar.  Como es de esperar existen varias opciones, no hay un consenso ya que cada quien tiene su sabor favorito.  Entre los principales frameworks actualmente se encuentran &lt;a href="http://www.nmock.org/"&gt;NMock2&lt;/a&gt;, &lt;a href="http://code.google.com/p/moq/"&gt;Moq&lt;/a&gt;, &lt;a href="http://www.ayende.com/projects/rhino-mocks.aspx"&gt;Rhino&lt;/a&gt;, &lt;a href="http://site.typemock.com/"&gt;Isolator&lt;/a&gt;. Existen varias comparaciones &lt;a href="http://codevanced.net/post/Mocking-frameworks-comparison.aspx"&gt;esta&lt;/a&gt; particularmente  es corta y concisa. Lo que puedo decir rápidamente basado en la comparativa: NMock2 es &lt;span style="font-style: italic; font-weight: bold;"&gt;"Type unsafe&lt;/span&gt;" lo que implica que espera &lt;span style="font-style: italic; font-weight: bold;"&gt;strings&lt;/span&gt; lo cual es algo que particularmente no me gusta ya se vuelve muy desordenado y delicado, además no hay apoyo del &lt;span style="font-style: italic; font-weight: bold;"&gt;Intelicense&lt;/span&gt;, Moq es el que usamos actualmente y es simple y fácil de aprender ya que es muy intuitivo, recientemente me topé con el problema de que no soporta &lt;span style="font-style: italic; font-weight: bold;"&gt;output parameters&lt;/span&gt; y los &lt;span style="font-style: italic; font-weight: bold;"&gt;callbacks&lt;/span&gt; tienen un límite de cuatro parámetros, actualmente hay una versión  en beta.  Rhino si bien no lo he usado mucho he visto que tiene buena aceptación en los foros aunque desde la aparición de Moq ha ido perdiendo terreno.  Isolator no es open source y no es gratuito lo que le hace perder muchos puntos cuando el presupuesto es importante, además, según la comparativa es el más lento. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: 130%;"&gt;&lt;span style="font-weight: bold;"&gt;Ejemplo con Moq&lt;/span&gt;&lt;/span&gt; &lt;br /&gt;&lt;br /&gt;Moq es relativamente nuevo, pero ha tenido buena aceptación.  Para el ejemplo estoy usando la versión 3.1.416.3 junto con &lt;a href="http://www.nunit.org/"&gt;&lt;span style="font-style: italic; font-weight: bold;"&gt;NUnit &lt;/span&gt;&lt;/a&gt;2.5.9222 y el .Net Framework 3.5 &lt;br /&gt;&lt;br /&gt;Supongamos que tenemos un pequeño web que registra usuarios tomando alguna información mínima. Existen dos servicios uno de datos (&lt;span style="font-style: italic; font-weight: bold;"&gt;IUserDataService&lt;/span&gt;) y otro de formato (&lt;span style="font-style: italic; font-weight: bold;"&gt;IUserFormatingService&lt;/span&gt;) los cuales son utilizados por un  tercer servicio (&lt;span style="font-style: italic; font-weight: bold;"&gt;IUserService&lt;/span&gt;) que funciona como un &lt;span style="font-style: italic; font-weight: bold;"&gt;facade&lt;/span&gt; para juntarlos y dar acceso a las operaciones. &lt;br /&gt;&lt;br /&gt;&lt;div class="csharpcode"&gt;&lt;br /&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   1:  &lt;/span&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;interface&lt;/span&gt; IUserFormatingService&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   2:  &lt;/span&gt;{&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   3:  &lt;/span&gt;    User FormatUserRaw(DataRow row);&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   4:  &lt;/span&gt;}&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   5:  &lt;/span&gt;    &lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   6:  &lt;/span&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;interface&lt;/span&gt; IUserService&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   7:  &lt;/span&gt;{&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   8:  &lt;/span&gt;    &lt;span class="kwrd"&gt;int&lt;/span&gt; Add(User user);&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   9:  &lt;/span&gt;}&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  10:  &lt;/span&gt;&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  11:  &lt;/span&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;interface&lt;/span&gt; IUserDataService&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  12:  &lt;/span&gt;{&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  13:  &lt;/span&gt;    &lt;span class="kwrd"&gt;int&lt;/span&gt; AddToDB(User user);&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  14:  &lt;/span&gt;    &lt;span class="kwrd"&gt;bool&lt;/span&gt; IsLoginNameAvailable(&lt;span class="kwrd"&gt;string&lt;/span&gt; LoginName);&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  15:  &lt;/span&gt;}    &lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  16:  &lt;/span&gt; &lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;span style="font-style: italic; font-weight: bold;"&gt;IUserService&lt;/span&gt; se encarga de validar el &lt;span style="font-style: italic; font-weight: bold;"&gt;DTO User &lt;/span&gt;e insertarlo en la Base de Datos, para ello utiliza el método &lt;span style="font-style: italic; font-weight: bold;"&gt; IsLoginNameAvailable&lt;/span&gt; para verificar que el Login está disponible y &lt;span style="font-style: italic; font-weight: bold;"&gt;AddToDB&lt;/span&gt; que se encarga de la inserción propiamente dicha. &lt;br /&gt;&lt;br /&gt;La entidad &lt;span style="font-style: italic; font-weight: bold;"&gt;User&lt;/span&gt; tiene unas pocas propiedades &lt;br /&gt;&lt;br /&gt;&lt;div class="csharpcode"&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   1: &lt;/span&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; User&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   2: &lt;/span&gt;    {&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   3: &lt;/span&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;int&lt;/span&gt; ID { get; set; }&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   4:        &lt;/span&gt; &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; Name{ get; set; }&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   5: &lt;/span&gt; &lt;span class="kwrd"&gt;       public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; Login { get; set; }&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   6: &lt;/span&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; Password { get; set; }&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   7: &lt;/span&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; Email { get; set; }&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   8: &lt;/span&gt; &lt;span class="kwrd"&gt;       public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; Country { get; set; }&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   9: &lt;/span&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;double&lt;/span&gt; Balance { get; set; }&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  10: &lt;/span&gt; &lt;span class="kwrd"&gt;       public&lt;/span&gt; DateTime BirthDate { get; set; }&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  11: &lt;/span&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; DateTime SingUpDate { get; set; }&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  12: &lt;/span&gt;    }&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;La implementación &lt;span style="font-style: italic; font-weight: bold;"&gt;UserService&lt;/span&gt;, como curiosidad, podríamos pensar que los dos servicios que está esperando en el constructor son provistos por una entidad aparte que se encarga de inyectarlos y por tanto estamos usando &lt;a href="http://ihenrysmith.blogspot.com/2010/03/inversion-de-control-e-inyeccion-de.html"&gt;&lt;span style="font-style: italic; font-weight: bold;"&gt;IoC&lt;/span&gt;&lt;/a&gt;. &lt;br /&gt;&lt;br /&gt;&lt;div class="csharpcode"&gt;&lt;br /&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   1:  &lt;/span&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; UserService : IUserService&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   2:  &lt;/span&gt;{&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   3:  &lt;/span&gt;    &lt;span class="kwrd"&gt;private&lt;/span&gt; IUserDataService _userDataService;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   4:  &lt;/span&gt;    &lt;span class="kwrd"&gt;private&lt;/span&gt; IUserFormatingService _userFormatingService;&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   5:  &lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   6:  &lt;/span&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; UserService(IUserDataService userDataService, &lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   7:  &lt;/span&gt;                       IUserFormatingService userFormatingService)&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   8:  &lt;/span&gt;    {&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   9:  &lt;/span&gt;        &lt;span class="kwrd"&gt;this&lt;/span&gt;._userDataService = userDataService;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  10:  &lt;/span&gt;        &lt;span class="kwrd"&gt;this&lt;/span&gt;._userFormatingService = userFormatingService;&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  11:  &lt;/span&gt;    }&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  12:  &lt;/span&gt;&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  13:  &lt;/span&gt;    &lt;span class="preproc"&gt;#region&lt;/span&gt; IUserService Members&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  14:  &lt;/span&gt;&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  15:  &lt;/span&gt;    &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  16:  &lt;/span&gt;    &lt;span class="rem"&gt;/// Adds the specified user.&lt;/span&gt;&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  17:  &lt;/span&gt;    &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  18:  &lt;/span&gt;    &lt;span class="rem"&gt;/// &amp;lt;param name="user"&amp;gt;The user.&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  19:  &lt;/span&gt;    &lt;span class="rem"&gt;/// &amp;lt;returns&amp;gt;The user id&amp;lt;/returns&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  20:  &lt;/span&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;int&lt;/span&gt; Add(User user)&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  21:  &lt;/span&gt;    {&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  22:  &lt;/span&gt;        &lt;span class="kwrd"&gt;if&lt;/span&gt; (user == &lt;span class="kwrd"&gt;null&lt;/span&gt;)&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  23:  &lt;/span&gt;        {&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  24:  &lt;/span&gt;            &lt;span class="kwrd"&gt;throw&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; ArgumentException(&lt;span class="str"&gt;"No se ha provisto un usuario"&lt;/span&gt;);&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  25:  &lt;/span&gt;        }&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  26:  &lt;/span&gt;        &lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  27:  &lt;/span&gt;        &lt;span class="rem"&gt;//NOTE: Si propiedad Login es nula, habrá una&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  28:  &lt;/span&gt;        &lt;span class="rem"&gt;//      excepción no esperada.&lt;/span&gt;&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  29:  &lt;/span&gt;        &lt;span class="kwrd"&gt;if&lt;/span&gt; (user.Login.Length &amp;lt; 5)&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  30:  &lt;/span&gt;        {&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  31:  &lt;/span&gt;            &lt;span class="kwrd"&gt;throw&lt;/span&gt; &lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  32:  &lt;/span&gt;            &lt;span class="kwrd"&gt;new&lt;/span&gt; ArgumentException(&lt;span class="str"&gt;"Login deber ser mayor a 5 caracteres."&lt;/span&gt;);&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  33:  &lt;/span&gt;        }&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  34:  &lt;/span&gt;&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  35:  &lt;/span&gt;        &lt;span class="kwrd"&gt;if&lt;/span&gt; (&lt;span class="kwrd"&gt;string&lt;/span&gt;.IsNullOrEmpty(user.Name))&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  36:  &lt;/span&gt;        {&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  37:  &lt;/span&gt;            &lt;span class="kwrd"&gt;throw&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; ArgumentException(&lt;span class="str"&gt;"Debe Proveer un Nombre."&lt;/span&gt;);&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  38:  &lt;/span&gt;        }&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  39:  &lt;/span&gt;        &lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  40:  &lt;/span&gt;        &lt;span class="kwrd"&gt;if&lt;/span&gt; (CalculateAge(user.BirthDate) &amp;lt; 18)&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  41:  &lt;/span&gt;        {&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  42:  &lt;/span&gt;            &lt;span class="kwrd"&gt;throw&lt;/span&gt; &lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  43:  &lt;/span&gt;            &lt;span class="kwrd"&gt;new&lt;/span&gt; ArgumentException(&lt;span class="str"&gt;"Debe ser mayor de 18 años "&lt;/span&gt; + &lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  44:  &lt;/span&gt;                                  &lt;span class="str"&gt;" para poder registrarse."&lt;/span&gt;);&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  45:  &lt;/span&gt;        }&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  46:  &lt;/span&gt;&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  47:  &lt;/span&gt;        &lt;span class="kwrd"&gt;if&lt;/span&gt; (!_userDataService.IsLoginNameAvailable(user.Login))&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  48:  &lt;/span&gt;        {&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  49:  &lt;/span&gt;            &lt;span class="kwrd"&gt;throw&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; ArgumentException(&lt;span class="str"&gt;"Login no disponible"&lt;/span&gt;);&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  50:  &lt;/span&gt;        }&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  51:  &lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  52:  &lt;/span&gt;        &lt;span class="kwrd"&gt;if&lt;/span&gt; (!IsEmail(user.Email))&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  53:  &lt;/span&gt;        {&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  54:  &lt;/span&gt;            &lt;span class="kwrd"&gt;throw&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; ArgumentException(&lt;span class="str"&gt;"Email Inválido"&lt;/span&gt;);&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  55:  &lt;/span&gt;        }&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  56:  &lt;/span&gt;&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  57:  &lt;/span&gt;        &lt;span class="kwrd"&gt;return&lt;/span&gt; _userDataService.AddToDB(user);&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  58:  &lt;/span&gt;    }&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  59:  &lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  60:  &lt;/span&gt;    &lt;span class="preproc"&gt;#endregion&lt;/span&gt;               &lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  61:  &lt;/span&gt;}&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Queremos asegurar que &lt;span style="font-style: italic; font-weight: bold;"&gt;UserService &lt;/span&gt;funciona correctamente, pero para ello ocuparíamos las dependencias &lt;span style="font-style: italic; font-weight: bold;"&gt;IUserDataService &lt;/span&gt;y &lt;span style="font-style: italic; font-weight: bold;"&gt;IUserFormatingService&lt;/span&gt;, que por cierto aún no han sido implementadas y ni siquiera existe una base de datos.  Es, en este punto donde entra &lt;span style="font-style: italic; font-weight: bold;"&gt;Moq&lt;/span&gt;.  Para ello creamos un proyecto y agregamos una clase &lt;span style="font-style: italic; font-weight: bold;"&gt;UserServiceTest &lt;/span&gt;que tendrá los tests relacionados con &lt;span style="font-style: italic; font-weight: bold;"&gt;UserService&lt;/span&gt;, para las dependencias creamos dos "&lt;span style="font-style: italic; font-weight: bold;"&gt;mocks&lt;/span&gt;" con los cuales controlamos que le pasaremos a la clase y que nos está mandando ella. &lt;br /&gt;&lt;br /&gt;El método &lt;span style="font-style: italic; font-weight: bold;"&gt; GetUserForTest &lt;/span&gt;lo que hace es regresar un usuario válido el cual modificaremos según sea requerido en cada uno de los test.  En el constructor inicializamos el servicio y proveemos los "&lt;span style="font-style: italic; font-weight: bold;"&gt;mocks&lt;/span&gt;". &lt;br /&gt;&lt;br /&gt;&lt;div class="csharpcode"&gt;&lt;br /&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   1:  &lt;/span&gt;[TestFixture]&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   2:  &lt;/span&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; UserServiceTest&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   3:  &lt;/span&gt;{&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   4:  &lt;/span&gt;    &lt;span class="kwrd"&gt;private&lt;/span&gt; Mock&amp;lt;IUserDataService&amp;gt; _userDataService =&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   5:  &lt;/span&gt;        &lt;span class="kwrd"&gt;new&lt;/span&gt; Mock&amp;lt;IUserDataService&amp;gt;();&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   6:  &lt;/span&gt; &lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   7:  &lt;/span&gt;    &lt;span class="kwrd"&gt;private&lt;/span&gt; Mock&amp;lt;IUserFormatingService&amp;gt; _userFormatingService =&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   8:  &lt;/span&gt;        &lt;span class="kwrd"&gt;new&lt;/span&gt; Mock&amp;lt;IUserFormatingService&amp;gt;();&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   9:  &lt;/span&gt;    &lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  10:  &lt;/span&gt;    &lt;span class="kwrd"&gt;private&lt;/span&gt; IUserService _userService;&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  11:  &lt;/span&gt; &lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  12:  &lt;/span&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; UserServiceTest()&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  13:  &lt;/span&gt;    {&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  14:  &lt;/span&gt;        _userService = &lt;span class="kwrd"&gt;new&lt;/span&gt; UserService&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  15:  &lt;/span&gt;            (_userDataService.Object, _userFormatingService.Object);&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  16:  &lt;/span&gt;    }&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  17:  &lt;/span&gt; &lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  18:  &lt;/span&gt; &lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  19:  &lt;/span&gt;    &lt;span class="kwrd"&gt;private&lt;/span&gt; User GetUserForTest()&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  20:  &lt;/span&gt;    {&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  21:  &lt;/span&gt;        User user = &lt;span class="kwrd"&gt;new&lt;/span&gt; User();&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  22:  &lt;/span&gt;        user.Login = &lt;span class="str"&gt;"elvis"&lt;/span&gt;;&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  23:  &lt;/span&gt;        user.Name = &lt;span class="str"&gt;"David"&lt;/span&gt;;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  24:  &lt;/span&gt;        user.Password = &lt;span class="str"&gt;"un_password_compliCAdo"&lt;/span&gt;;&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  25:  &lt;/span&gt;        user.Email = &lt;span class="str"&gt;"test@test.com"&lt;/span&gt;;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  26:  &lt;/span&gt;        user.Country = &lt;span class="str"&gt;"Costa Rica"&lt;/span&gt;;&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  27:  &lt;/span&gt;        user.SingUpDate = DateTime.Now;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  28:  &lt;/span&gt;        user.BirthDate = &lt;span class="kwrd"&gt;new&lt;/span&gt; DateTime(1966, 06, 06);&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  29:  &lt;/span&gt; &lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  30:  &lt;/span&gt;        &lt;span class="kwrd"&gt;return&lt;/span&gt; user;&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  31:  &lt;/span&gt; &lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  32:  &lt;/span&gt;    }&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  33:  &lt;/span&gt; &lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  34:  &lt;/span&gt;    [Test]&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  35:  &lt;/span&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Add_User_Test()&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  36:  &lt;/span&gt;    { &lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  37:  &lt;/span&gt;        User user = GetUserForTest();&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  38:  &lt;/span&gt; &lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  39:  &lt;/span&gt;        _userDataService.Setup(x =&amp;gt; x.IsLoginNameAvailable(user.Login)).&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  40:  &lt;/span&gt;            Returns(&lt;span class="kwrd"&gt;true&lt;/span&gt;);&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  41:  &lt;/span&gt;        _userDataService.Setup(x =&amp;gt; x.AddToDB(user)).Returns(1);&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  42:  &lt;/span&gt; &lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  43:  &lt;/span&gt;        &lt;span class="kwrd"&gt;try&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  44:  &lt;/span&gt;        {&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  45:  &lt;/span&gt;            &lt;span class="kwrd"&gt;int&lt;/span&gt; userId = _userService.Add(user);&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  46:  &lt;/span&gt;            Assert.AreEqual(1, userId);&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  47:  &lt;/span&gt;        }&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  48:  &lt;/span&gt;        &lt;span class="kwrd"&gt;catch&lt;/span&gt; (Exception)&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  49:  &lt;/span&gt;        {&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  50:  &lt;/span&gt;            Assert.Fail(&lt;span class="str"&gt;"No se esperaba ninguna excepción"&lt;/span&gt;);&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  51:  &lt;/span&gt;        }&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  52:  &lt;/span&gt;    }&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  53:  &lt;/span&gt; &lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  54:  &lt;/span&gt;    [Test]&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  55:  &lt;/span&gt;    [ExpectedException(&lt;span class="kwrd"&gt;typeof&lt;/span&gt;(ArgumentException))]&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  56:  &lt;/span&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Add_User_Login_Short_Lenght()&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  57:  &lt;/span&gt;    {&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  58:  &lt;/span&gt;        User user = GetUserForTest();&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  59:  &lt;/span&gt; &lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  60:  &lt;/span&gt;        user.Login = &lt;span class="str"&gt;"zord"&lt;/span&gt;;&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  61:  &lt;/span&gt; &lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  62:  &lt;/span&gt;        _userDataService.Setup(x =&amp;gt;&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  63:  &lt;/span&gt;            x.IsLoginNameAvailable(It.IsAny&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;&amp;gt;()))&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  64:  &lt;/span&gt;            .Returns(&lt;span class="kwrd"&gt;true&lt;/span&gt;);&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  65:  &lt;/span&gt;        _userDataService.Setup(x =&amp;gt; x.AddToDB(user)).Returns(1);&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  66:  &lt;/span&gt; &lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  67:  &lt;/span&gt;        &lt;span class="kwrd"&gt;try&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  68:  &lt;/span&gt;        {&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  69:  &lt;/span&gt;            &lt;span class="kwrd"&gt;int&lt;/span&gt; userId = _userService.Add(user);&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  70:  &lt;/span&gt;            Assert.Fail(&lt;span class="str"&gt;"Se esperaba una excepción"&lt;/span&gt;);&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  71:  &lt;/span&gt;        }&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  72:  &lt;/span&gt;        &lt;span class="kwrd"&gt;catch&lt;/span&gt; (Exception)&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  73:  &lt;/span&gt;        {&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  74:  &lt;/span&gt;            &lt;span class="kwrd"&gt;throw&lt;/span&gt;;&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  75:  &lt;/span&gt;        }&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  76:  &lt;/span&gt;    }&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  77:  &lt;/span&gt;    &lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  78:  &lt;/span&gt;    [Test]&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  79:  &lt;/span&gt;    [ExpectedException(&lt;span class="kwrd"&gt;typeof&lt;/span&gt;(ArgumentException))]&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  80:  &lt;/span&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Add_User_Login_Short_Lenght_BUG()&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  81:  &lt;/span&gt;    {&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  82:  &lt;/span&gt;        User user = GetUserForTest();&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  83:  &lt;/span&gt;        user.Login = &lt;span class="kwrd"&gt;null&lt;/span&gt;;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  84:  &lt;/span&gt;         _userDataService.Setup(x =&amp;gt; &lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  85:  &lt;/span&gt;             x.IsLoginNameAvailable(user.Login))&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  86:  &lt;/span&gt;             .Returns(&lt;span class="kwrd"&gt;true&lt;/span&gt;);&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  87:  &lt;/span&gt; &lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  88:  &lt;/span&gt;        _userDataService.Setup(x =&amp;gt; x.AddToDB(user)).Returns(1);&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  89:  &lt;/span&gt; &lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  90:  &lt;/span&gt;        &lt;span class="kwrd"&gt;try&lt;/span&gt;&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  91:  &lt;/span&gt;        {&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  92:  &lt;/span&gt;            &lt;span class="kwrd"&gt;int&lt;/span&gt; userId = _userService.Add(user);&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  93:  &lt;/span&gt;            Assert.Fail(&lt;span class="str"&gt;"Se esperaba una excepción"&lt;/span&gt;);&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  94:  &lt;/span&gt;        }&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  95:  &lt;/span&gt;        &lt;span class="kwrd"&gt;catch&lt;/span&gt; (Exception)&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  96:  &lt;/span&gt;        {&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  97:  &lt;/span&gt;            &lt;span class="kwrd"&gt;throw&lt;/span&gt;;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;  98:  &lt;/span&gt;        }&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  99:  &lt;/span&gt;    }    &lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt; 100:  &lt;/span&gt; &lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt; 101:  &lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt; 102:  &lt;/span&gt;}&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;En &lt;span style="font-style: italic; font-weight: bold;"&gt;Add_User_Test()&lt;/span&gt;  y para cada test configuramos los "&lt;span style="font-style: italic; font-weight: bold;"&gt;mocks&lt;/span&gt;" para establecer los  comportamientos requeridos, así por ejemplo &lt;span style="font-style: italic; font-weight: bold;"&gt;UserService.Add(User)&lt;/span&gt; utiliza de &lt;span style="font-style: italic; font-weight: bold;"&gt;IUserDataService &lt;/span&gt;los métodos&lt;span style="font-style: italic; font-weight: bold;"&gt; IsLoginNameAvailable &lt;/span&gt;que recibe un &lt;span style="font-style: italic; font-weight: bold;"&gt;string&lt;/span&gt; y regresa un &lt;span style="font-weight: bold;"&gt;booleano&lt;/span&gt;  y &lt;span style="font-style: italic; font-weight: bold;"&gt;AddToDB &lt;/span&gt;que recibe un &lt;span style="font-style: italic; font-weight: bold;"&gt;User&lt;/span&gt; y regresa un entero, el cual es el ID asignado.  Para la configuración llamamos el método &lt;span style="font-style: italic; font-weight: bold;"&gt;Setup&lt;/span&gt; del moq.  Note que en la expresión lambda decimos que de "x" vamos a configurar el método  &lt;span style="font-style: italic; font-weight: bold;"&gt;IsLoginNameAvailable&lt;/span&gt; he indicamos que esperamos en sus parámetros,  cuando reciba &lt;span style="font-style: italic; font-weight: bold;"&gt;user.login&lt;/span&gt;, se refiere al valor exacto que contenga al momento de la configuración, si el valor &lt;span style="font-weight: bold;"&gt;no&lt;/span&gt; interesa como en &lt;span style="font-style: italic; font-weight: bold;"&gt;Add_User_Login_Short_Lenght &lt;/span&gt;usamos un "&lt;span style="font-style: italic; font-weight: bold;"&gt;wildcard&lt;/span&gt;" que indica que cualquier valor &lt;span style="font-style: italic; font-weight: bold;"&gt;string &lt;/span&gt;es válido =&amp;gt; &lt;span style="font-style: italic; font-weight: bold;"&gt;It.IsAny&lt;/span&gt;&lt;string&gt;&lt;span style="font-style: italic; font-weight: bold;"&gt;()&lt;/span&gt;, y finalmente con &lt;span style="font-style: italic; font-weight: bold;"&gt;Returns&lt;/span&gt; indicamos que siempre que se cumplan las condiciones retornaremos &lt;span style="font-style: italic; font-weight: bold;"&gt;True&lt;/span&gt;. &lt;br /&gt;&lt;br /&gt;&lt;/string&gt;&lt;br /&gt;&lt;div class="csharpcode"&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   1: &lt;/span&gt;_userDataService.Setup(x =&amp;gt; x.IsLoginNameAvailable(user.Login)).Returns(&lt;span class="kwrd"&gt;true&lt;/span&gt;);&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;Lo mismo sucede con &lt;span style="font-style: italic; font-weight: bold;"&gt;AddToDB &lt;/span&gt;que retornará el id 1 siempre que sea invocada con la instancia "user" &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="csharpcode"&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   2: &lt;/span&gt;_userDataService.Setup(x =&amp;gt; x.AddToDB(user)).Returns(1);&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Finalmente implementamos los &lt;span style="font-style: italic; font-weight: bold;"&gt;Asserts &lt;/span&gt;de &lt;span style="font-style: italic; font-weight: bold;"&gt;NUnit&lt;/span&gt;&lt;span style="font-style: italic;"&gt; &lt;/span&gt;para asegurar los valores. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: 130%; font-weight: bold;"&gt;Un BUG&lt;/span&gt; &lt;br /&gt;&lt;br /&gt;El método &lt;span style="font-style: italic; font-weight: bold;"&gt;Add_User_Login_Short_Lenght_BUG&lt;/span&gt; intencionalmente contiene un bug, ya que está diseñado para fallar cuando cuando la longitud de la propiedad LoginName es vacía o menor a 5, en cuyo caso se producirá una excepción tipo &lt;span style="font-style: italic; font-weight: bold;"&gt;ArgumentException&lt;/span&gt;.  Sin embargo la propiedad está nula y al intentar accederla se produce &lt;span style="font-style: italic; font-weight: bold;"&gt;System.NullReferenceException&lt;/span&gt; lo cual no es un comportamiento esperado y por tanto un BUG del sistema. &lt;br /&gt;&lt;br /&gt;&lt;a href="http://4.bp.blogspot.com/_7QbB368NSo0/S7wPdrgDJ8I/AAAAAAAAJ3o/6mzZoAyiXqo/s1600/Capture.PNG" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img alt="" border="0" id="BLOGGER_PHOTO_ID_5457253851033970626" src="http://4.bp.blogspot.com/_7QbB368NSo0/S7wPdrgDJ8I/AAAAAAAAJ3o/6mzZoAyiXqo/s400/Capture.PNG" style="cursor: pointer; display: block; height: 78px; margin: 0px auto 10px; text-align: center; width: 400px;" /&gt;&lt;/a&gt; &lt;br /&gt;Lo primero que debemos hacer al encontrar un bug, antes de arreglarlo es crearle un test, luego corregirlo y de esta manera queda asegurado que si el bug vuelve a aparecer existirá un prueba que nos va decir con anterioridad de la existencia del problema. &lt;br /&gt;&lt;br /&gt;Gran parte de la idea de tener pruebas es que nos estén asegurando que el sistema está funcionando correctamente y que los cambios que vamos introduciendo no lo están quebrando.  Si logramos tomar nuestro sistema por unidades y atomizar cada una de las pruebas aseguramos que si cada una funciona como debe en forma individual deben funcionar de manera conjunta y de no ser así, implica que alguna de las partes está fallando y las pruebas no son correctas o  no son las suficientes. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: 130%;"&gt;&lt;span style="font-weight: bold;"&gt;Más Moq &lt;/span&gt;&lt;/span&gt; &lt;br /&gt;&lt;string&gt; &lt;br /&gt;Algunas otras cosas que podemos hacer con moq. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Parámetros&lt;/span&gt; &lt;br /&gt;&lt;br /&gt;Accesando los parámetros con los cuales se hizo el llamado para el retorno.&lt;/string&gt; &lt;br /&gt;&lt;string&gt;&lt;/string&gt;&lt;br /&gt;&lt;div class="csharpcode"&gt;&lt;br /&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   1: &lt;/span&gt;_userDataService.Setup(x =&amp;gt; x.AddID(It.IsAny()))&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   2: &lt;/span&gt;.Returns((&lt;span class="kwrd"&gt;string&lt;/span&gt; login) =&amp;gt; &lt;span class="kwrd"&gt;string&lt;/span&gt;.Format(&lt;span class="str"&gt;"{0}ID"&lt;/span&gt;, login));&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;CallBacks&lt;/span&gt; &lt;br /&gt;&lt;br /&gt;En la línea 2 se llama el callback antes de la invocación del return  y se accesa el argumento miertras en la línea 3 se invoca despues del return &lt;br /&gt;&lt;br /&gt;&lt;div class="csharpcode"&gt;&lt;br /&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   1: &lt;/span&gt;_userDataService.Setup(x =&amp;gt; x.AddToDB(It.IsAny()))&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   2: &lt;/span&gt;.Callback((User inserUser) =&amp;gt; &lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   3: &lt;/span&gt;  Console.WriteLine(&lt;span class="kwrd"&gt;string&lt;/span&gt;.Format(&lt;span class="str"&gt;"Adding user {0}"&lt;/span&gt;, inserUser.Login)))&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   4: &lt;/span&gt;.Returns(1)&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   5: &lt;/span&gt;.Callback(()=&amp;gt; Console.WriteLine(&lt;span class="str"&gt;"User Inserted"&lt;/span&gt;));&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;span style="font-weight: bold;"&gt; &lt;br /&gt;Excepciones&lt;/span&gt; &lt;br /&gt;&lt;br /&gt;Moq puede configurar excepciones según la condición &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="csharpcode"&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   1: &lt;/span&gt;_userDataService.Setup(x =&amp;gt; x.IsLoginNameAvailable(&lt;span class="kwrd"&gt;null&lt;/span&gt;))&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   2: &lt;/span&gt;.Throws(&lt;span class="kwrd"&gt;new&lt;/span&gt; ArgumentException(&lt;span class="str"&gt;"Valor no puede ser nulo"&lt;/span&gt;))&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Matching&lt;/span&gt; &lt;br /&gt;&lt;br /&gt;Como en el ejemplo se pueden usar "&lt;span style="font-weight: bold;"&gt;Matchings&lt;/span&gt;" que indiquen los valores esperados. &lt;br /&gt;&lt;br /&gt;Indicar que espera cualquier objeto de tipo User &lt;br /&gt;&lt;div class="csharpcode"&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   1: &lt;/span&gt;_userDataService.Setup(x =&amp;gt; x.AddToDB(It.IsAny&amp;lt;User&amp;gt;())).Returns(1);&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Valida los valores que cumplan con el predicado dado, ósea el valor esperado deber ser string y deber ser igual a "test" &lt;br /&gt;&lt;div class="csharpcode"&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   1: &lt;/span&gt;_userDataService.Setup(x =&amp;gt; x.IsLoginNameAvailable(It.Is&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;&amp;gt;(l =&amp;gt; l.Equals(&lt;span class="str"&gt;"Test"&lt;/span&gt;))))&lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   2: &lt;/span&gt;.Returns(&lt;span class="kwrd"&gt;true&lt;/span&gt;);&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Expresiones Regulares &lt;br /&gt;&lt;div class="csharpcode"&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   1: &lt;/span&gt;_userDataService.Setup(x =&amp;gt; &lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   2: &lt;/span&gt;x.IsLoginNameAvailable(It.IsRegex(&lt;span class="str"&gt;@"^([a-zA-Z0-9_\-\.]+)"&lt;/span&gt;, RegexOptions.IgnoreCase)))&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   3: &lt;/span&gt;.Returns(&lt;span class="kwrd"&gt;true&lt;/span&gt;);&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Rangos, ejemplo si queremos usar un número entero que no sea ni el mínimo, ni el máximo &lt;br /&gt;&lt;div class="csharpcode"&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   1: &lt;/span&gt;moq.Setup(x =&amp;gt; &lt;/pre&gt;&lt;pre&gt;&lt;span class="lnum"&gt;   2: &lt;/span&gt; x.Ejemplo(It.IsInRange&amp;lt;&lt;span class="kwrd"&gt;int&lt;/span&gt;&amp;gt;(&lt;span class="kwrd"&gt;int&lt;/span&gt;.MinValue, &lt;span class="kwrd"&gt;int&lt;/span&gt;.MaxValue, Range.Exclusive)))&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   3: &lt;/span&gt;.Return(&lt;span class="kwrd"&gt;true&lt;/span&gt;);&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Son algunas pocas opciones del framework aun quedan eventos, propiedades, verificaciones, comportamientos, avanzados, etc.  Ejemplos conceptuales los podemos encontrar en &lt;a href="http://code.google.com/p/moq/wiki/QuickStart"&gt;QuickStart&lt;/a&gt; de la pagina. &lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2425636995525834170-7255792698843676142?l=ihenrysmith.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ihenrysmith.blogspot.com/feeds/7255792698843676142/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2425636995525834170&amp;postID=7255792698843676142' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2425636995525834170/posts/default/7255792698843676142'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2425636995525834170/posts/default/7255792698843676142'/><link rel='alternate' type='text/html' href='http://ihenrysmith.blogspot.com/2010/03/mock-objects-objetos-simulados.html' title='Mock objects (Objetos Simulados)'/><author><name>Henry Smith</name><uri>http://www.blogger.com/profile/02246731323260602803</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_7QbB368NSo0/SMrdY7POsGI/AAAAAAAAFEg/F0bpFLjNqik/S220/SP_A0121.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_7QbB368NSo0/S7wPdrgDJ8I/AAAAAAAAJ3o/6mzZoAyiXqo/s72-c/Capture.PNG' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2425636995525834170.post-632922192749693207</id><published>2010-03-14T14:32:00.004-06:00</published><updated>2010-04-04T13:32:28.702-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='IoC'/><category scheme='http://www.blogger.com/atom/ns#' term='Inyección de dependencias'/><category scheme='http://www.blogger.com/atom/ns#' term='DI'/><category scheme='http://www.blogger.com/atom/ns#' term='Castle Windsor'/><title type='text'>Inversión de Control e Inyección de dependencias</title><content type='html'>&lt;style type="text/css"&gt;  &lt;!--   @page { margin: 0.79in }   P { margin-bottom: 0.08in }  --&gt;&lt;/style&gt;&lt;p style="margin-bottom: 0in;"&gt;Inversión  de control e inyección de dependencia son términos que se confunden constantemente, vale la pena aclarar desde el inicio que la inyección de dependencia es una forma de implementar la inversión de control, de la misma forma existen otras implementaciones con, por ejemplo, el patrón “&lt;i&gt;&lt;b&gt;Factory&lt;/b&gt;&lt;/i&gt;” o el “&lt;i&gt;&lt;b&gt;service locator&lt;/b&gt;&lt;/i&gt;”.&lt;br /&gt;&lt;/p&gt;  &lt;p style="margin-bottom: 0in;"&gt;La característica principal de la inversión de control es que el control del flujo es invertido con respecto a los métodos tradicionales.  En vez de tener un código central que lo controle, indicamos que es lo que estamos esperando, para que una entidad aparte se encargue de proveerlo, así, es esta entidad quien decide como y cuando proveer lo esperado. En pocas palabras, nuestro código es el llamado, y no como  ocurre comúnmente, cuando nuestro código es quien tiene el control del flujo y lo que hace es hacer llamadas. Se dice que es una implementación del Principio de Hollywood “No llame, nosotros le llamamos”.&lt;/p&gt;  &lt;p style="margin-bottom: 0in;"&gt;Para obtener flexibilidad, “&lt;i&gt;testeabilidad&lt;/i&gt;” y reutilización, debemos buscar siempre el menor acoplamiento posible.  Si hacemos este acoplamiento por medio de interfaces y utilizamos una entidad aparte para que nos provea la implementación concreta, nos simplificamos sobre manera cambios futuros,  ya que solo deberíamos cambiar la implementación sin tener que modificar en lo absoluto el objeto dependiente.&lt;/p&gt;  &lt;p style="margin-bottom: 0in;"&gt;Estando claros que la inyección de dependencia es una forma específica de implementar inversión de control.  Podríamos decir que lo que haremos es “inyectar” los objetos necesarios, según una configuración previa, evitando que sea la misma clase quien se encargue de crearlos u obtenerlos, así nos desentendemos de manejar su implementación por completo, ósea, no nos preocupamos por su ciclo de vida del todo.  Usualmente utilizaremos un contenedor que se encargue de todo lo referente a la inyección propiamente dicha (creación, inyección, dependencias, destrucción, etc), si este contenedor esta externo podríamos decir que estamos utilizando inversión de control.&lt;/p&gt;&lt;p style="margin-bottom: 0in;"&gt;    &lt;style type="text/css"&gt;  &lt;!--   @page { margin: 0.79in }   P { margin-bottom: 0.08in }  --&gt;  &lt;/style&gt;  &lt;/p&gt;&lt;p style="margin-bottom: 0in;"&gt;Con una comprensión más clara de los conceptos, que de alguna forma, es muy posible ya estemos aplicando, estaremos en posibilidad de escribir código más desacoplado, flexible y sobre todo reutilizable.&lt;/p&gt; &lt;p&gt;&lt;/p&gt;  &lt;p style="margin-bottom: 0in;"&gt;&lt;/p&gt;&lt;p style="margin-bottom: 0in;"&gt;&lt;/p&gt;&lt;p style="margin-bottom: 0in;"&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2425636995525834170-632922192749693207?l=ihenrysmith.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ihenrysmith.blogspot.com/feeds/632922192749693207/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2425636995525834170&amp;postID=632922192749693207' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2425636995525834170/posts/default/632922192749693207'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2425636995525834170/posts/default/632922192749693207'/><link rel='alternate' type='text/html' href='http://ihenrysmith.blogspot.com/2010/03/inversion-de-control-e-inyeccion-de.html' title='Inversión de Control e Inyección de dependencias'/><author><name>Henry Smith</name><uri>http://www.blogger.com/profile/02246731323260602803</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_7QbB368NSo0/SMrdY7POsGI/AAAAAAAAFEg/F0bpFLjNqik/S220/SP_A0121.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2425636995525834170.post-7749303673541742472</id><published>2010-03-13T12:44:00.001-06:00</published><updated>2010-04-04T13:33:23.050-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='MVC'/><category scheme='http://www.blogger.com/atom/ns#' term='IoC'/><category scheme='http://www.blogger.com/atom/ns#' term='ASP.Net'/><category scheme='http://www.blogger.com/atom/ns#' term='Spring.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='Castle Windsor'/><title type='text'>Contenedor IoC</title><content type='html'>Cuando decidimos utilizar &lt;span style="font-style: italic;"&gt;&lt;a href="http://ihenrysmith.blogspot.com/2010/03/contenedor-ioc.html"&gt;IoC&lt;/a&gt; &lt;/span&gt;(&lt;span style="font-style: italic;"&gt;"Inversion of Control"&lt;/span&gt; - Inversión de Control) ocupamos un Contenedor o en otras palabras un software, en el cual podamos registrar nuestros objetos ya sea por medio de un archivo de configuración (usualmente XML) o desde el código mismo y que sea este quien se encargue de la inicialización de los objetos que estamos esperando.   La idea es que podamos tomar ya sea una clase abstracta o una Interfase y pedirle al contenedor que nos resuelva la instancia concreta deacuerdo con la definición esperada. &lt;a href="http://blog.stevensanderson.com/about/"&gt; &lt;span style="font-style: italic;"&gt;Steven Sanderson&lt;/span&gt;&lt;/a&gt; en su libro &lt;a href="http://www.amazon.com/gp/product/1430210079?ie=UTF8&amp;amp;tag=stesansblo-20&amp;amp;linkCode=as2&amp;amp;camp=1789&amp;amp;creative=9325&amp;amp;creativeASIN=1430210079"&gt;Pro ASP.NET MVCFramework&lt;/a&gt; (el cual les recomiendo) añade que un buen contenedor debe contar con tres características extra más allá de simplemente resolver la inicialización de la instancia.&lt;br /&gt;&lt;br /&gt;Esta tres características son:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;Resolución de dependencias en cadena&lt;/span&gt;: Lo que implica que si se esta resolviendo la dependencia de un objeto que requiere de otro, el contenedor debe ser capaz de proveer la dependencia requerida.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;Tiempo de vida de los objetos&lt;/span&gt;: Debe encargarse de mantener el estilo de vida de los objetos. Si una instancia es solicitada más de una vez, el contenedor deberá escoger entre varias opciones, por ejemplo mantener una única instancia para todas las solicitudes (&lt;span style="font-style: italic;"&gt;singleton&lt;/span&gt;), o crear una nueva por solicitud (&lt;span style="font-style: italic;"&gt;transient&lt;/span&gt;), entre otras. Esto es lo que se conoce como el "&lt;span style="font-style: italic;"&gt;lifestyle&lt;/span&gt;" del objeto, hay varias opciones predefinidas como &lt;span style="font-style: italic;"&gt;singleton (&lt;/span&gt;que es la default&lt;span style="font-style: italic;"&gt;)&lt;/span&gt;, &lt;span style="font-style: italic;"&gt;thread&lt;/span&gt;, &lt;span style="font-style: italic;"&gt;transient&lt;/span&gt;, &lt;span style="font-style: italic;"&gt;pooled&lt;/span&gt; y customizadas como &lt;span style="font-style: italic;"&gt;PerWebRequest&lt;/span&gt;.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;Valores de parámetros explícitos para los constructores&lt;/span&gt;: Esto quiere decir que si un constructor que debe inicializar el contenedor requiere de parámetros, deber existir un medio en la configuración que permita proveer los valores.  El ejemplo clásico es el  &lt;span style="font-style: italic;"&gt;ConnectionString &lt;/span&gt;para el acceso a datos o el servidor&lt;span style="font-style: italic;"&gt; SMTP &lt;/span&gt;&lt;span&gt;para enviar correos.&lt;br /&gt;&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Otra parte complicada es escoger cual de los contenedores disponibles actualmente vamos a usar.   Entre los más comunes se encuentran:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Castle Windsor (El que usamos actualmente)&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Spring.NET&lt;/li&gt;&lt;li&gt;StructureMap&lt;/li&gt;&lt;li&gt;Unity&lt;/li&gt;&lt;li&gt;Puzzle.NFactory &lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Después de una rápida vista por google, nos damos cuenta  lo difícil que es escoger alguno, a Spring por ejemplo se le achaca la poca documentación y el echo que sea portado de Java.  Muchos tienden a usar Castle Windsor por su documentación y se podría decir que es el más popular en este momento.&lt;br /&gt;&lt;br /&gt;Hay que recordar que utilizar un Contenedor puede provocar un poco de "&lt;span style="font-style: italic;"&gt;overhead&lt;/span&gt;"en la creación de los objetos,  pero esto es compensado con todas la facilidades que su uso implica.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2425636995525834170-7749303673541742472?l=ihenrysmith.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ihenrysmith.blogspot.com/feeds/7749303673541742472/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2425636995525834170&amp;postID=7749303673541742472' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2425636995525834170/posts/default/7749303673541742472'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2425636995525834170/posts/default/7749303673541742472'/><link rel='alternate' type='text/html' href='http://ihenrysmith.blogspot.com/2010/03/contenedor-ioc.html' title='Contenedor IoC'/><author><name>Henry Smith</name><uri>http://www.blogger.com/profile/02246731323260602803</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_7QbB368NSo0/SMrdY7POsGI/AAAAAAAAFEg/F0bpFLjNqik/S220/SP_A0121.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2425636995525834170.post-25523485609873749</id><published>2010-02-28T22:30:00.000-06:00</published><updated>2010-02-28T22:31:39.138-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Personal'/><title type='text'>Again??</title><content type='html'>Parece que de verdad olvide esto :p..... pero en el futuro prometo meter algunas otras entras ....:p&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2425636995525834170-25523485609873749?l=ihenrysmith.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ihenrysmith.blogspot.com/feeds/25523485609873749/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2425636995525834170&amp;postID=25523485609873749' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2425636995525834170/posts/default/25523485609873749'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2425636995525834170/posts/default/25523485609873749'/><link rel='alternate' type='text/html' href='http://ihenrysmith.blogspot.com/2010/02/again.html' title='Again??'/><author><name>Henry Smith</name><uri>http://www.blogger.com/profile/02246731323260602803</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_7QbB368NSo0/SMrdY7POsGI/AAAAAAAAFEg/F0bpFLjNqik/S220/SP_A0121.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2425636995525834170.post-522775601614751458</id><published>2008-09-12T15:25:00.000-06:00</published><updated>2010-03-14T13:30:38.337-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Personal'/><title type='text'>El Génesis..</title><content type='html'>Conforme tenga tiempo espero poder publicar cosas de interés sobre tecnologías de programación relacionadas a los proyectos en que trabajo y demás pasatiempos personales… Cosas como Java, Javascript, C#, C++, SQL server, Pascal, entre otros....&lt;br /&gt;&lt;br /&gt;Sin mas por el momento, me despido!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2425636995525834170-522775601614751458?l=ihenrysmith.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ihenrysmith.blogspot.com/feeds/522775601614751458/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2425636995525834170&amp;postID=522775601614751458' title='1 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2425636995525834170/posts/default/522775601614751458'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2425636995525834170/posts/default/522775601614751458'/><link rel='alternate' type='text/html' href='http://ihenrysmith.blogspot.com/2008/09/el-gnesis.html' title='El Génesis..'/><author><name>Henry Smith</name><uri>http://www.blogger.com/profile/02246731323260602803</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_7QbB368NSo0/SMrdY7POsGI/AAAAAAAAFEg/F0bpFLjNqik/S220/SP_A0121.jpg'/></author><thr:total>1</thr:total></entry></feed>
