<?xml version="1.0" encoding="utf-8"?><?xml-stylesheet type='text/xsl' href='http://lucasontivero.spaces.live.com/mmm2008-07-24_12.50/rsspretty.aspx?rssquery=en-US;http%3a%2f%2flucasontivero.spaces.live.com%2ffeed.rss' version='1.0'?><rss version="2.0" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:msn="http://schemas.microsoft.com/msn/spaces/2005/rss" xmlns:live="http://schemas.microsoft.com/live/spaces/2006/rss" xmlns:dcterms="http://purl.org/dc/terms/" xmlns:cf="http://www.microsoft.com/schemas/rss/core/2005" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Lucas Ontivero</title><description /><link>http://lucasontivero.spaces.live.com/</link><language>en-US</language><pubDate>Fri, 15 Aug 2008 15:15:42 GMT</pubDate><lastBuildDate>Fri, 15 Aug 2008 15:15:42 GMT</lastBuildDate><generator>Microsoft Spaces v1.1</generator><docs>http://www.rssboard.org/rss-specification</docs><ttl>60</ttl><live:identity><live:id>3988747590285877710</live:id><live:alias>lucasontivero</live:alias></live:identity><cf:listinfo><cf:group ns="http://schemas.microsoft.com/live/spaces/2006/rss" element="typelabel" label="Type" /><cf:group ns="http://schemas.microsoft.com/live/spaces/2006/rss" element="tag" label="Tag" /><cf:group element="category" label="Category" /><cf:sort element="pubDate" label="Date" data-type="date" default="true" /><cf:sort element="title" label="Title" data-type="string" /><cf:sort ns="http://purl.org/rss/1.0/modules/slash/" element="comments" label="Comments" data-type="number" /></cf:listinfo><item><title>Trata de Patron Factory Method 1</title><link>http://lucasontivero.spaces.live.com/Blog/cns!375AE0CCD1AF61CE!475.entry</link><description>&lt;p&gt; &lt;p&gt;Cita &lt;blockquote&gt;&lt;a href="http://video.msn.com/video.aspx?vid=2c151d4f-70a1-44b3-97ad-23c4f222dd98"&gt;Patron Factory Method 1&lt;/a&gt;&lt;br&gt;&lt;br&gt;&lt;span style="display:none"&gt; &lt;/span&gt;&lt;br&gt;&lt;a href="http://video.msn.com/video.aspx?vid=2c151d4f-70a1-44b3-97ad-23c4f222dd98" title="Patron Factory Method 1"&gt;Video: Patron Factory Method 1&lt;/a&gt;&lt;/blockquote&gt; &lt;br&gt;&lt;img src="http://c.services.spaces.live.com/CollectionWebService/c.gif?cid=3988747590285877710&amp;page=RSS%3a+Trata+de+Patron+Factory+Method+1&amp;referrer=" width="1px" height="1px" border="0" alt=""&gt;&lt;img style="position:absolute" alt="" width="0px" height="0px" src="http://c.live.com/c.gif?NC=31263&amp;amp;NA=1149&amp;amp;PI=73329&amp;amp;RF=&amp;amp;DI=3919&amp;amp;PS=85545&amp;amp;TP=lucasontivero.spaces.live.com&amp;amp;GT1=lucasontivero"&gt;</description><comments>http://lucasontivero.spaces.live.com/Blog/cns!375AE0CCD1AF61CE!475.entry#comment</comments><guid isPermaLink="true">http://lucasontivero.spaces.live.com/Blog/cns!375AE0CCD1AF61CE!475.entry</guid><pubDate>Wed, 30 Jul 2008 05:36:56 GMT</pubDate><slash:comments>0</slash:comments><msn:type>blogentry</msn:type><live:type>blogentry</live:type><live:typelabel>Blog entry</live:typelabel><wfw:commentRss>http://lucasontivero.spaces.live.com/blog/cns!375AE0CCD1AF61CE!475/comments/feed.rss</wfw:commentRss><wfw:comment>http://lucasontivero.spaces.live.com/Blog/cns!375AE0CCD1AF61CE!475.entry#comment</wfw:comment><dcterms:modified>2008-07-30T05:36:56Z</dcterms:modified></item><item><title>Lucas en Geeks.ms</title><link>http://lucasontivero.spaces.live.com/Blog/cns!375AE0CCD1AF61CE!464.entry</link><description>&lt;p&gt;&lt;a href="http://geeks.ms/blogs/rcorral/default.aspx" target="_blank"&gt;Rodrigo Corral&lt;/a&gt; me ha invitado a formar parte de &lt;a href="http://geeks.ms/" target="_blank"&gt;Geeks.ms&lt;/a&gt; y he aceptado con gusto su propuesta. Es por esto que no voy a escribir más en este espacio y los invito a que se subscriban a mi nuevo blog en &lt;a href="http://geeks.ms/blogs/lontivero"&gt;http://geeks.ms/blogs/lontivero&lt;/a&gt; .  &lt;p&gt;Saludos a todos. &lt;p&gt;&lt;strong&gt;Lucas Ontivero&lt;/strong&gt;&lt;img src="http://c.services.spaces.live.com/CollectionWebService/c.gif?cid=3988747590285877710&amp;page=RSS%3a+Lucas+en+Geeks.ms&amp;referrer=" width="1px" height="1px" border="0" alt=""&gt;&lt;img style="position:absolute" alt="" width="0px" height="0px" src="http://c.live.com/c.gif?NC=31263&amp;amp;NA=1149&amp;amp;PI=73329&amp;amp;RF=&amp;amp;DI=3919&amp;amp;PS=85545&amp;amp;TP=lucasontivero.spaces.live.com&amp;amp;GT1=lucasontivero"&gt;</description><comments>http://lucasontivero.spaces.live.com/Blog/cns!375AE0CCD1AF61CE!464.entry#comment</comments><guid isPermaLink="true">http://lucasontivero.spaces.live.com/Blog/cns!375AE0CCD1AF61CE!464.entry</guid><pubDate>Thu, 27 Sep 2007 21:03:07 GMT</pubDate><slash:comments>1</slash:comments><msn:type>blogentry</msn:type><live:type>blogentry</live:type><live:typelabel>Blog entry</live:typelabel><wfw:commentRss>http://lucasontivero.spaces.live.com/blog/cns!375AE0CCD1AF61CE!464/comments/feed.rss</wfw:commentRss><wfw:comment>http://lucasontivero.spaces.live.com/Blog/cns!375AE0CCD1AF61CE!464.entry#comment</wfw:comment><dcterms:modified>2007-09-27T21:03:07Z</dcterms:modified></item><item><title>[Anti-Patterns] Contenedor Mágico</title><link>http://lucasontivero.spaces.live.com/Blog/cns!375AE0CCD1AF61CE!458.entry</link><description>&lt;div&gt;El la facu siempre renegaba con mis compañero en cuanto a la calidad de código, ciertamente la inmensa mayoria escribia código extremadamente malo. Nunca pensé que luego, en empresas de software de gran nivel como en la que estoy ahora, iba a seguir renegando con lo mismo. La clase que estoy revisando ahora tiene 36.307 lineas! &lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;Así que acá va la descripción de este antipatrón de novatos.&lt;/div&gt;
&lt;div&gt;&lt;br&gt;Un contenedor mágico es un antipatrón de desarrollo que surge cuando, por inexperiencia, se crean métodos (o funciones) que sirven a una gran cantidad de propósitos afines. Este antipatrón se hace evidente cuando se advierten métodos que reciben una enorme cantidad de parámetros muchos de ellos opcionales, de tipos muy generales, arrays o listas y, muchas veces, retornan también mas de un valor mediante los parámetros pasados por referencia (punteros en C/C++, parámetros out en c#).&lt;/div&gt;
&lt;div&gt;
&lt;p&gt;La motivación de quien codifica este código radica en el afán de maximizar el reuso de una rutina mediante una generalización excesiva. Esto lo lleva a intentar la panacea de lograr la función que &amp;quot;sirve para todo&amp;quot;. 
&lt;p&gt;Un ejemplo común se ve con frecuencia en los cursos de programación universitarios en los que los alumnos crean sus funciones &amp;quot;LlenarGrilla(....)&amp;quot; las cuales les permiten completar grillas (controles visuales) de muchas formas diferentes, ordenadas según ciertas columnas, con filas coloreadas según algunas condiciones, con formatos por columnas, ancho por columnas, con bordes o sin ellos, editables o no, etc. Para lograr esto, una función &amp;quot;LlenarGrilla(....)&amp;quot; debe recibir un número significativo de parámetros, muchos opcional, muchos arrays de objetos, algunos booleanos, otros strings y así según las funcionalidades que los alumnos deseen. 
&lt;p&gt;El código final resulta en extremo complejo y dificil de mantener. Cuando surge un nuevo requerimiento, que la función no contempla, solo queda agregar más parámetros a su firma e intentar introducir la nueva característica. Este proceso se repite hasta que se vuelve inviable. 
&lt;p&gt;Lo puse &lt;a href="http://es.wikipedia.org/wiki/Contenedor_m%C3%A1gico" target="_blank"&gt;en wikipedia (Contenedor mágico)&lt;/a&gt; porque no estaba pero alguién en cualquier momento lo va a mejorar. 
&lt;p&gt;&lt;strong&gt;Lucas Ontivero&lt;/strong&gt;&lt;/div&gt;&lt;img src="http://c.services.spaces.live.com/CollectionWebService/c.gif?cid=3988747590285877710&amp;page=RSS%3a+%5bAnti-Patterns%5d+Contenedor+M%c3%a1gico&amp;referrer=" width="1px" height="1px" border="0" alt=""&gt;&lt;img style="position:absolute" alt="" width="0px" height="0px" src="http://c.live.com/c.gif?NC=31263&amp;amp;NA=1149&amp;amp;PI=73329&amp;amp;RF=&amp;amp;DI=3919&amp;amp;PS=85545&amp;amp;TP=lucasontivero.spaces.live.com&amp;amp;GT1=lucasontivero"&gt;</description><category>Anti-Patrones</category><comments>http://lucasontivero.spaces.live.com/Blog/cns!375AE0CCD1AF61CE!458.entry#comment</comments><guid isPermaLink="true">http://lucasontivero.spaces.live.com/Blog/cns!375AE0CCD1AF61CE!458.entry</guid><pubDate>Fri, 14 Sep 2007 19:31:30 GMT</pubDate><slash:comments>4</slash:comments><msn:type>blogentry</msn:type><live:type>blogentry</live:type><live:typelabel>Blog entry</live:typelabel><wfw:commentRss>http://lucasontivero.spaces.live.com/blog/cns!375AE0CCD1AF61CE!458/comments/feed.rss</wfw:commentRss><wfw:comment>http://lucasontivero.spaces.live.com/Blog/cns!375AE0CCD1AF61CE!458.entry#comment</wfw:comment><dcterms:modified>2007-09-14T19:32:26Z</dcterms:modified></item><item><title>[Patterns] UnitOfWork</title><link>http://lucasontivero.spaces.live.com/Blog/cns!375AE0CCD1AF61CE!456.entry</link><description>&lt;div align=justify&gt;&lt;a href="http://www.google.com/translate?u=http://lucasontivero.spaces.live.com/blog/cns!375AE0CCD1AF61CE!456.entry&amp;amp;langpair=es|en&amp;amp;hl=en&amp;amp;ie=UTF8" target="_blank"&gt;[Translate this post to english with google]&lt;/a&gt;&lt;/div&gt;
&lt;div align=justify&gt; &lt;/div&gt;
&lt;div align=justify&gt;Este es uno de los patrones más útiles (desde mi punto de vista) con que me he encontrado en el libro &amp;quot;&lt;a href="http://martinfowler.com/books.html#eaa"&gt;Patterns of Enterprise Application Architecture&lt;/a&gt;&amp;quot; (P of EAA) de Martin Fowler. Como dice Martin en su libro &lt;a href="http://martinfowler.com/eaaCatalog/unitOfWork.html"&gt;este patrón:&lt;/a&gt;&lt;/div&gt;
&lt;div align=center&gt;&amp;quot;Maintains a list of objects affected by a business transaction and coordinates the writing out of changes and the resolution of concurrency problems.&amp;quot;&lt;/div&gt;
&lt;div align=justify&gt;&lt;/div&gt;
&lt;div align=justify&gt;&lt;a href="http://martinfowler.com/eaaCatalog/unitOfWorkInterface.gif"&gt;&lt;img style="display:block;margin:0px auto 10px;width:160px;cursor:hand;text-align:center" alt="" src="http://martinfowler.com/eaaCatalog/unitOfWorkInterface.gif" border=0&gt;&lt;/a&gt; Este patrón se utiliza entonces para trabajar con un conjunto de objetos persistentes que deben tratarse como una &amp;quot;unidad&amp;quot; de trabajo, almacenandose en una base de datos de manera atómica. Este patrón es el encargado de trackear todos aquellos objetos que son nuevos, y que por lo tanto deben persistirse, todos los objetos que han sido modificados y que deben actualizarse en la DB y todos los que han sido borrados y deben quitarse de la base de datos.&lt;/div&gt;
&lt;div align=justify&gt;&lt;/div&gt;
&lt;div align=justify&gt;Mediante la implementación del patrón UnitOfWork, se logra una disminución de la cantidad de idas y vueltas hacia la base de datos ya que los cambios se realizan por lotes (o unidades de trabajo) redundando en una mejora de la performance del sistema porque muchas veces el cuello de botella de las aplicaciones se encuentra en la red de datos. Otro aspecto interesante es que posibilita el esquema de trabajo desconectado con bloqueos optimistas sobre la base de datos, es decir, no se mantienen bloqueados los registros por largos períodos de tiempo sino que se abre una conexión, se inicia una transacción, se hacen los cambios, se commitea y se libera la conexión todo esto en muy pero muy poco tiempo. &lt;/div&gt;
&lt;div align=justify&gt;&lt;/div&gt;
&lt;div align=justify&gt;De ser necesaria la incorporación de un control de concurrencia sobre los registros que serán afectados durante la transación, de modo de mantener la consistencia de los datos, este patrón nos brinda el ámbito adecuado en donde implementarlo. &lt;/div&gt;
&lt;div align=justify&gt;Veamos un caso concreto, el famoso ejemplo de la factura. Existe una factura que el usuario debe modificar, entonces traemos desde la base de datos la factura con sus items (de factura) cargados, luego, una vez que lo presentamos en pantalla, el usuario hace lo siguiente:&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;div align=justify&gt;Agrega dos items más a la lista de items,&lt;/div&gt;
&lt;li&gt;
&lt;div align=justify&gt;Modifica el importe y/o la cantidad de productos de uno de los items y finalmente,&lt;/div&gt;
&lt;li&gt;
&lt;div align=justify&gt;Elimina uno de los item.&lt;/div&gt;&lt;/ul&gt;
&lt;p align=justify&gt;En este caso, cuando deben persistirse los datos? apenas agrega, modifica o elimina un item? o debe tratarse a la factura como una unidad y persistir todo junto? Si algo falla,... debe guardarse el resto? que sucede si otro usuario (además del que estamos hablando) estaba trabajando con el mismo documento al mismo tiempo pero guardó primero? como sabemos que fue lo que modificó el usuario y que, por lo tanto, debemos guardar? guardamos primero la factura y luego los items o al revés? 
&lt;p align=justify&gt;Todas las respuestas a estas preguntas (que considero que las fuiste contestando) se resuelven mediante la implementación de este patrón. 
&lt;p align=justify&gt;Voy a explicarlo un poco. El Unit Of Work, como se observa en la figura de arriba, se implementa mediante una única clase la cual tendrá al menos tres listas, una lista para los objetos nuevos que deben guardarse en la db, otra lista para los objetos que han sido modificados y que por lo tanto deben modificarse en la db y, otra lista para los objetos que deben eliminarse. Opcionalmente, o mejor dicho, según la implementación lo requiera, puede contener una cuarta lista para almacenar clones de los objetos que se traen desde la base de datos, de manera que antes de persistir un objeto pueda corroborar, mediante estos clones de los objetos originales, que los registros correspondientes no han sido modificados por otro usuario. 
&lt;p align=justify&gt;Una razón para leer el libro y no solo conformarse con este artículo es que Fowler hace un análisi exaustivo de este patrón (y de todos sus patrones), sus formas de implementar, cuando implementarlos, pros y contras y sobre todo, lo que a mi más me gustó fueron los distintos intentos por hacer esta clase lo más transparente posible para el programador. Así, por ejemplo, analiza la posibilidad de que todas las clases persistibles hereden de una clase base que automáticamente las registre como nuevas en el contenedor, que cuando se invoque el setter methos de una propiedad, esta notifique al UnitOfWork correspondiente para que la registre como dirty, etc. Personalmente estube probando esto y otras ideas como AOP, que no me convenció para nada, y extensions methods con los cuales le agrega m'etodos de persistencia a los objetos que heredaban de esa clase base. 
&lt;p align=justify&gt;En cuanto a AOP, no me convención porque las opciones eran todas muy feas, o usaba el .Net Profiling API con C++ para capturar la ejecución del JIT y entonces inyectarle código MSIL a los setters, o las clases heredaban de ContextBoundObject para, mediante los proxies de remounting, poder interceptar las invocaciones a las propiedades (lento, sucio, que más?) o, usando un compilador de terceros (no MS) casi en todos los casos en beta 0.000001. Así que definitivamente por el momento no lo ví como una opción. 
&lt;p align=justify&gt;En resumen, creo que es mejor, aunque un poquito mas tedioso y propenso a errores, dejar que sea el programador quien registre los objetos en el Unit of Work. 
&lt;p align=justify&gt;Acá dejo una implementación sencillísima de UnitOfWork sin control de concurrencias y en colaboración con un DataMapper trivial. Más abajo les dejo un proyecto que implementa esta clase. 
&lt;div style="height:400px"&gt;&lt;pre style="border-right:#eee 1px solid;padding-right:5px;border-top:#eee 1px solid;padding-left:5px;border-bottom-width:1px;overflow:auto;border-left:#eee 1px solid;width:95%;padding-top:5px;height:100%"&gt;&lt;span style="color:blue"&gt;using&lt;/span&gt; System;

&lt;span style="color:blue"&gt;using&lt;/span&gt; System.Collections.Generic;
&lt;span style="color:blue"&gt;using&lt;/span&gt; System.Text;
&lt;span style="color:blue"&gt;using&lt;/span&gt; System.Transactions;
&lt;span style="color:blue"&gt;using&lt;/span&gt; System.Data.SqlClient;
&lt;span style="color:blue"&gt;using&lt;/span&gt; System.Configuration;
&lt;span style="color:blue"&gt;using&lt;/span&gt; System.Threading;
&lt;span style="color:blue"&gt;using&lt;/span&gt; System.Resources;

&lt;span style="color:blue"&gt;namespace&lt;/span&gt; Patterns
{
        &lt;span style="color:green"&gt;// Nuestra clase UnitOfWork (Martin Fowler)&lt;/span&gt;
        &lt;span style="color:blue"&gt;public&lt;/span&gt; &lt;span style="color:blue"&gt;class&lt;/span&gt; UnitOfWork
        {
                &lt;span style="color:green"&gt;// Aquí estan las tres listas de las que hablamos&lt;/span&gt;
                &lt;span style="color:green"&gt;// Ademas de estas puede existir una cuarta que almacene&lt;/span&gt;
                &lt;span style="color:green"&gt;// los objetos limpios (o que se leyeron de la db)&lt;/span&gt;
                List&amp;lt;IBusinessObject&amp;gt; newObjects;
                List&amp;lt;IBusinessObject&amp;gt; dirtyObjects;
                List&amp;lt;IBusinessObject&amp;gt; removedObjects;

                &lt;span style="color:green"&gt;// Creamos las listas en este constructor&lt;/span&gt;
                &lt;span style="color:blue"&gt;public&lt;/span&gt; UnitOfWork()
                {
                        newObjects = &lt;span style="color:blue"&gt;new&lt;/span&gt; List&amp;lt;IBusinessObject&amp;gt;();
                        dirtyObjects = &lt;span style="color:blue"&gt;new&lt;/span&gt; List&amp;lt;IBusinessObject&amp;gt;();
                        removedObjects = &lt;span style="color:blue"&gt;new&lt;/span&gt; List&amp;lt;IBusinessObject&amp;gt;();
                }

                &lt;span style="color:blue"&gt;public&lt;/span&gt; &lt;span style="color:blue"&gt;void&lt;/span&gt; New(IBusinessObject bo)
                {
                        Guard.NotNull(Resources.parameter_is_null, &amp;quot;&lt;span style="color:magenta"&gt;bo&lt;/span&gt;&amp;quot;, bo);
                        Guard.IsTrue (Resources.object_is_dirty, dirtyObjects.Contains(bo));
                        Guard.IsTrue (Resources.object_is_deleted, removedObjects.Contains(bo));
                        Guard.IsTrue(Resources.object_is_already_inserted, newObjects.Contains(bo));

                        newObjects.Add(bo);
                }

                &lt;span style="color:blue"&gt;public&lt;/span&gt; &lt;span style="color:blue"&gt;void&lt;/span&gt; Remove(IBusinessObject bo)
                {
                        Guard.NotNull(Resources.parameter_is_null, &amp;quot;&lt;span style="color:magenta"&gt;bo&lt;/span&gt;&amp;quot;, bo);
                        &lt;span style="color:blue"&gt;if&lt;/span&gt; (newObjects.Remove(bo)) &lt;span style="color:blue"&gt;return&lt;/span&gt;;
                        dirtyObjects.Remove(bo);

                        &lt;span style="color:blue"&gt;if&lt;/span&gt; (!removedObjects.Contains(bo))
                        removedObjects.Add(bo);
                }

                &lt;span style="color:blue"&gt;public&lt;/span&gt; &lt;span style="color:blue"&gt;void&lt;/span&gt; Update(IBusinessObject bo)
                {
                        Guard.NotNull(Resources.parameter_is_null, &amp;quot;&lt;span style="color:magenta"&gt;bo&lt;/span&gt;&amp;quot;, bo);
                        Guard.IsTrue(Resources.object_is_deleted, removedObjects.Contains(bo));

                        &lt;span style="color:blue"&gt;if&lt;/span&gt; (!newObjects.Contains(bo) &amp;amp;&amp;amp; !dirtyObjects.Contains(bo))
                        dirtyObjects.Add(bo);
                }

                &lt;span style="color:green"&gt;// El método Commit es el encargado de iniciar las transacciones,&lt;/span&gt;
                &lt;span style="color:green"&gt;// y realizar la invocación a la base de datos.&lt;/span&gt;
                &lt;span style="color:blue"&gt;public&lt;/span&gt; &lt;span style="color:blue"&gt;void&lt;/span&gt; Commit()
                {
                        &lt;span style="color:blue"&gt;string&lt;/span&gt; connectString = &lt;span style="color:blue"&gt;string&lt;/span&gt;.Empty;
                        &lt;span style="color:blue"&gt;using&lt;/span&gt; (TransactionScope transactionScope = &lt;span style="color:blue"&gt;new&lt;/span&gt; TransactionScope())
                        {
                                connectString = ConfigurationManager.ConnectionStrings[&amp;quot;&lt;span style="color:magenta"&gt;Patterns&lt;/span&gt;&amp;quot;].ConnectionString;

                                &lt;span style="color:blue"&gt;using&lt;/span&gt; (SqlConnection connection = &lt;span style="color:blue"&gt;new&lt;/span&gt; SqlConnection(connectString))
                                {
                                        &lt;span style="color:blue"&gt;try&lt;/span&gt;
                                        {
                                                &lt;span style="color:green"&gt;// Construimos las sentencias SQL para luego pasárselas a la DB&lt;/span&gt;
                                                &lt;span style="color:green"&gt;// mediante un command. Para esto, en .Net hay que hacerlo separando&lt;/span&gt;
                                                &lt;span style="color:green"&gt;// las sentencias con un punto y como (;)&lt;/span&gt;
                                                StringBuilder stringBuilder = &lt;span style="color:blue"&gt;new&lt;/span&gt; StringBuilder();

                                                &lt;span style="color:blue"&gt;foreach&lt;/span&gt; (IBusinessObject bo &lt;span style="color:blue"&gt;in&lt;/span&gt; newObjects)
                                                stringBuilder.Append(Mapper.Instance.Insert(bo) + &amp;quot;&lt;span style="color:magenta"&gt;;&lt;/span&gt;&amp;quot;);

                                                &lt;span style="color:blue"&gt;foreach&lt;/span&gt; (IBusinessObject bo &lt;span style="color:blue"&gt;in&lt;/span&gt; dirtyObjects)
                                                stringBuilder.Append(Mapper.Instance.Update(bo) + &amp;quot;&lt;span style="color:magenta"&gt;;&lt;/span&gt;&amp;quot;);

                                                &lt;span style="color:blue"&gt;foreach&lt;/span&gt; (IBusinessObject bo &lt;span style="color:blue"&gt;in&lt;/span&gt; removedObjects)
                                                stringBuilder.Append(Mapper.Instance.Delete(bo) + &amp;quot;&lt;span style="color:magenta"&gt;;&lt;/span&gt;&amp;quot;);

                                                &lt;span style="color:blue"&gt;string&lt;/span&gt; command = stringBuilder.ToString();

                                                &lt;span style="color:green"&gt;// Abre la conexió, crea el comando con las sentencias SQL&lt;/span&gt;
                                                &lt;span style="color:green"&gt;// e invoca al RDBMS.&lt;/span&gt;
                                                connection.Open();
                                                SqlCommand command1 = &lt;span style="color:blue"&gt;new&lt;/span&gt; SqlCommand(command, connection);
                                                command1.ExecuteNonQuery();

                                                &lt;span style="color:green"&gt;// Limpia las listas si todo estuvo bien.&lt;/span&gt;
                                                ClearAll();
                                        }
                                        &lt;span style="color:blue"&gt;catch&lt;/span&gt; (Exception ex)
                                        {
                                                System.Console.WriteLine(&amp;quot;&lt;span style="color:magenta"&gt;Exception Message: {0}&lt;/span&gt;&amp;quot;, ex.Message);
                                        }
                                }
                                transactionScope.Complete();
                        }
                }

                &lt;span style="color:blue"&gt;private&lt;/span&gt; &lt;span style="color:blue"&gt;void&lt;/span&gt; ClearAll()
                {
                        newObjects.Clear();
                        dirtyObjects.Clear();
                        removedObjects.Clear();
                }
        }
}

&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;El proyecto: &lt;a href="http://www.carloszanini.com.ar/shared/UnitOfWork.zip" target="_blank"&gt;http://www.carloszanini.com.ar/shared/UnitOfWork.zip&lt;/a&gt; No esperen gran cosa. Gracias a Carlos Zanini por el hosting. 
&lt;p&gt;&lt;strong&gt;Lucas Ontivero&lt;/strong&gt; 
&lt;p&gt;&lt;img src="http://c.services.spaces.live.com/CollectionWebService/c.gif?cid=3988747590285877710&amp;page=RSS%3a+%5bPatterns%5d+UnitOfWork&amp;referrer=" width="1px" height="1px" border="0" alt=""&gt;&lt;img style="position:absolute" alt="" width="0px" height="0px" src="http://c.live.com/c.gif?NC=31263&amp;amp;NA=1149&amp;amp;PI=73329&amp;amp;RF=&amp;amp;DI=3919&amp;amp;PS=85545&amp;amp;TP=lucasontivero.spaces.live.com&amp;amp;GT1=lucasontivero"&gt;</description><category>Patterns</category><comments>http://lucasontivero.spaces.live.com/Blog/cns!375AE0CCD1AF61CE!456.entry#comment</comments><guid isPermaLink="true">http://lucasontivero.spaces.live.com/Blog/cns!375AE0CCD1AF61CE!456.entry</guid><pubDate>Fri, 14 Sep 2007 18:42:33 GMT</pubDate><slash:comments>1</slash:comments><msn:type>blogentry</msn:type><live:type>blogentry</live:type><live:typelabel>Blog entry</live:typelabel><wfw:commentRss>http://lucasontivero.spaces.live.com/blog/cns!375AE0CCD1AF61CE!456/comments/feed.rss</wfw:commentRss><wfw:comment>http://lucasontivero.spaces.live.com/Blog/cns!375AE0CCD1AF61CE!456.entry#comment</wfw:comment><dcterms:modified>2007-09-14T18:48:20Z</dcterms:modified></item><item><title>Ajax and JSON</title><link>http://lucasontivero.spaces.live.com/Blog/cns!375AE0CCD1AF61CE!448.entry</link><description>&lt;div&gt;Estaba leyendo acerca de mappers y en particular sobre como resolver los problemas de impedancia entre los distintos componentes de los sistemas cuando encontré &lt;a href="http://blogs.msdn.com/dareobasanjo/archive/2004/02/20/77264.aspx" target="_blank"&gt;este artículo&lt;/a&gt; que analiza la impedancia entre el W3C XML y los objetos en tecnologias como .Net. &lt;/div&gt;
&lt;div&gt;Este problema se presenta, principalmente, en todas las aplicaciones que publican o consumen servicios web ya que XML y WS se relacionan de tal forma que se han vuelto casi sinónimos (perdón por la burrada). Pero existe gente detras de cada tecnología que se ocupa de ocultar o mitigar este y otros asuntos mediante proxies y sistemas de serialización/deserialización.&lt;/div&gt;
&lt;div&gt;ahora, en Ajax este es otro asunto. &lt;font size=2&gt;&lt;font face=Arial&gt;Asynchronous JavaScript technology and XML (AJAX) y JavaScript Object Notation &lt;/font&gt;(&lt;/font&gt;&lt;a href="http://json.org/json-es.html" target="_blank"&gt;&lt;font size=2&gt;JSON&lt;/font&gt;&lt;/a&gt;&lt;font size=2&gt;) es el tema de este artículo.&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font size=2&gt;&lt;/font&gt; &lt;/div&gt;
&lt;div&gt;&lt;font size=4&gt;Que es JSON?&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font size=2&gt;&lt;a href="http://json.org/json-es.html" target="_blank"&gt;JSON&lt;/a&gt;&lt;/font&gt; es un formato ligero de intercambio de datos&amp;quot;, así se define un su website. Esto es, un formato de intercambio que cumple una función similar al XML pero ... NO ES XML!.  La idea detras de &lt;a href="http://json.org/json-es.html" target="_blank"&gt;JSON&lt;/a&gt; es utilizar la misma notación de los objetos en javascript para intercambiar datos. Es decir, que si tenemos el siguiente fragmento de código en javascript,&lt;/div&gt;&lt;pre&gt;var contact = {
     &amp;quot;Name&amp;quot;: &amp;quot;John Doe&amp;quot;,
     &amp;quot;PermissionToCall&amp;quot;: true,
     &amp;quot;PhoneNumbers&amp;quot;: [ 
       {
           &amp;quot;Location&amp;quot;: &amp;quot;Home&amp;quot;,
           &amp;quot;Number&amp;quot;: &amp;quot;555-555-1234&amp;quot;
       },
       {
           &amp;quot;Location&amp;quot;: &amp;quot;Work&amp;quot;,
           &amp;quot;Number&amp;quot;: &amp;quot;555-555-9999 Ext. 123&amp;quot;
       }
     ]
};
&lt;/pre&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;la serialización de este objeto será exactamente idéntica al código fuente, osea:&lt;/div&gt;&lt;pre&gt;{&amp;quot;Name&amp;quot;: &amp;quot;John Doe&amp;quot;, &amp;quot;PermissionToCall&amp;quot;: true, &amp;quot;PhoneNumbers&amp;quot;: [{&amp;quot;Location&amp;quot;: &amp;quot;Home&amp;quot;, &amp;quot;Number&amp;quot;: &amp;quot;555-555-1234&amp;quot;}, {&amp;quot;Location&amp;quot;: &amp;quot;Work&amp;quot;, &amp;quot;Number&amp;quot;: &amp;quot;555-555-9999 Ext. 123&amp;quot;}]&lt;/pre&gt;
&lt;div&gt;&lt;font size=4&gt;Que ventajas tiene y como se relaciona con Ajax?&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;Bien, todavia recuerdo cuando trabajaba con ASP 3.0 y XmlHttpRequest, cuando necesitaba consultar algo al servidor, este me lo devolvía en un xml que yo debia cargar en un DOM y manejarlo con XPath y getElementxxx() entre otros métodos, es decir, o hacia esto o lo deserializaba (a pata) y llenaba objetos JavaScript en el cliente. Pero esto era un poco duro y realmente una desgracia. La ventaja de &lt;a href="http://json.org/json-es.html" target="_blank"&gt;JSON&lt;/a&gt; en este contexto particular es que la deserialización de los datos transmitidos se logra con solo hacer un eval() del mismo. Veamos este ejemplo:&lt;/div&gt;&lt;pre&gt;xmlhttp.open(&amp;quot;GET&amp;quot;,&amp;quot;/personnel/find?id=26481648&amp;quot;,true);
xmlhttp.onreadystatechange=function() {
    if (xmlhttp.readyState==4) {
        if (xmlhttp.status!=404) {
            var employee=new Function(&amp;quot;return &amp;quot;+xmlhttp.responseText)();
            alert(&amp;quot;DNI : &amp;quot; + employee[0].dni+' - Full Name : '+ employee[0].fullname);
        } else {
            alert(&amp;quot;Employee not found&amp;quot;);
        }
    }
}
&lt;/pre&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;Como vemos, no hay DOMs ni rutinas de parseo de XMLs, ni proxies por ningún lado!!!. Además contamos con el modelo de objetos del servidor en el código que ejecuta el browser. Así es mas sencillo que nuestro código en el browser consuma web services y se simplifican muchas tareas. Aunque aclaro: no es el único propósito de &lt;a href="http://json.org/json-es.html" target="_blank"&gt;JSON&lt;/a&gt;, &lt;a href="http://json.org/json-es.html" target="_blank"&gt;JSON&lt;/a&gt; es un standar abierto para el intercambio de datos así que su utilidad no se acota a Ajax solo que es en este campo donde la contribucón se hace más notoria. Algunas ventajas sobre XML (tiene como todo en la vida sus desventajas también) son su extremada sencillez, es más compacto que un xml, trabaja con tipos mientras que xml solo puede validar si el contenido respeta un cierto tipo mediante un esquema, no necesita al menos en JavaScript ningún parser ni DOM, una curva de aprendizaje mucho menor.&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;Ahora, si trabajamos en .Net nos estaremos preguntando: &lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;donde encaja &lt;a href="http://json.org/json-es.html" target="_blank"&gt;JSON&lt;/a&gt; en un WS si estos utilizan XML?, 
&lt;li&gt;Si quisiera utilizarlo, como serializo mis objetos? tengo que hacer mi propio serializador?&lt;/ul&gt;
&lt;p&gt;La verdad es que la serialización no es un problema, existen muchos Framework para trabajar con JSON en .Net (&lt;a href="http://jayrock.berlios.de/" target="_blank"&gt;Jayrock&lt;/a&gt; por ejemplo) los cuales son generalmente muy pequeños, fáciles y trabajan muy bien (por los comentarios en distintos sitios). También, para los que trabajan en ASP.NET está la implementación de AJAX &amp;quot;&lt;a href="http://asp.net/ajax/documentation/live/ClientReference/Sys.Serialization/JavascriptSerializerClass/JavascriptSerializerSerializeMethod.aspx" target="_blank"&gt;Serialization.JavaScriptSerializer&lt;/a&gt;&amp;quot;. 
&lt;p&gt;En cuanto a los WSs, la única restricción real es que debe transmitir texto dentro de un sobre SOAP y nada más. 
&lt;p&gt;Algunos link muy interesantes: 
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://json.org/json-es.html" target="_blank"&gt;JSON web site&lt;/a&gt; (en castellano) 
&lt;li&gt;&lt;a href="http://msdn2.microsoft.com/en-us/library/bb299886.aspx#intro_to_json_topic5" target="_blank"&gt;An Introduction to JavaScript Object Notation (JSON) in JavaScript and .NET&lt;/a&gt; (completísimo, muy bueno y por gente de MS) 
&lt;li&gt;&lt;a href="http://www.b-list.org/weblog/2006/dec/21/i-cant-believe-its-not-xml/" target="_blank"&gt;The B-List : I can't believe it's not XML!&lt;/a&gt; (muy buen artículo - explica muy bien el por qué JSON es una buena opción) 
&lt;li&gt;&lt;a href="http://blogs.msdn.com/mikechampion/archive/2006/12/21/the-json-vs-xml-debate-begins-in-earnest.aspx" target="_blank"&gt;The JSON vs XML debate begins in earnest &lt;/a&gt;(discusión y comparación entre JSON y XML pros y contras - de alto vuelo) 
&lt;li&gt;&lt;a href="http://msdn.microsoft.com/msdnmag/issues/07/01/ExtremeASPNET/" target="_blank"&gt;MSDN Magazine: Client-Side Web Service Calls with AJAX Extensions&lt;/a&gt; (Algo práctico con ASP.NET) 
&lt;li&gt;&lt;a href="http://developer.yahoo.com/common/json.html" target="_blank"&gt;Using JSON (JavaScript Object Notation) with Yahoo! Web Services &lt;/a&gt;(Otro ejemplo práctico - consumir WS de Yahoo - compara XML y JSON) 
&lt;li&gt;&lt;a href="http://weblogs.asp.net/mschwarz/archive/2007/06/01/silverlight-and-json-isolatedstorage-example.aspx" target="_blank"&gt;Silverlight and JSON&lt;/a&gt; (No lo leí pero dice &amp;quot;&lt;a href="http://www.silverlight.net/"&gt;&lt;u&gt;&lt;font color="#0000ff"&gt;Silverlight 1.1&lt;/font&gt;&lt;/u&gt;&lt;/a&gt; comes with an built-in JSON serializer which can...&amp;quot; )&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Lucas Ontivero&lt;/strong&gt;&lt;img src="http://c.services.spaces.live.com/CollectionWebService/c.gif?cid=3988747590285877710&amp;page=RSS%3a+Ajax+and+JSON&amp;referrer=" width="1px" height="1px" border="0" alt=""&gt;&lt;img style="position:absolute" alt="" width="0px" height="0px" src="http://c.live.com/c.gif?NC=31263&amp;amp;NA=1149&amp;amp;PI=73329&amp;amp;RF=&amp;amp;DI=3919&amp;amp;PS=85545&amp;amp;TP=lucasontivero.spaces.live.com&amp;amp;GT1=lucasontivero"&gt;</description><comments>http://lucasontivero.spaces.live.com/Blog/cns!375AE0CCD1AF61CE!448.entry#comment</comments><guid isPermaLink="true">http://lucasontivero.spaces.live.com/Blog/cns!375AE0CCD1AF61CE!448.entry</guid><pubDate>Wed, 12 Sep 2007 16:29:06 GMT</pubDate><slash:comments>2</slash:comments><msn:type>blogentry</msn:type><live:type>blogentry</live:type><live:typelabel>Blog entry</live:typelabel><wfw:commentRss>http://lucasontivero.spaces.live.com/blog/cns!375AE0CCD1AF61CE!448/comments/feed.rss</wfw:commentRss><wfw:comment>http://lucasontivero.spaces.live.com/Blog/cns!375AE0CCD1AF61CE!448.entry#comment</wfw:comment><dcterms:modified>2007-09-12T16:31:52Z</dcterms:modified></item><item><title>Software Factories Blog</title><link>http://lucasontivero.spaces.live.com/Blog/cns!375AE0CCD1AF61CE!446.entry</link><description>&lt;p&gt;&lt;a href="http://www.google.com.ar/translate?u=http://lucasontivero.spaces.live.com/blog/cns!375AE0CCD1AF61CE!446.entry&amp;amp;langpair=es|en&amp;amp;hl=en&amp;amp;ie=UTF8" target="_blank"&gt;[Tanslate this post to english with google]&lt;/a&gt; &lt;p&gt;He creado un nuevo blog dedicado a todo lo referido a software-factories, patrones, metodologías y todo lo que esté orientado a incrementar la calidad, la productividad y el tiempo de entrega de los productos de software. Seguramente también incluiré algunas ideas y/o traducciones de artículos interesante. Ya he pasado algunos post de este blogs al nuevo. Véanlo en &lt;a title="http://software-factories.blogspot.com/" href="http://software-factories.blogspot.com/"&gt;http://software-factories.blogspot.com/&lt;/a&gt;  &lt;p&gt;Saludos. &lt;p&gt;&lt;strong&gt;Lucas Ontivero&lt;/strong&gt;&lt;img src="http://c.services.spaces.live.com/CollectionWebService/c.gif?cid=3988747590285877710&amp;page=RSS%3a+Software+Factories+Blog&amp;referrer=" width="1px" height="1px" border="0" alt=""&gt;&lt;img style="position:absolute" alt="" width="0px" height="0px" src="http://c.live.com/c.gif?NC=31263&amp;amp;NA=1149&amp;amp;PI=73329&amp;amp;RF=&amp;amp;DI=3919&amp;amp;PS=85545&amp;amp;TP=lucasontivero.spaces.live.com&amp;amp;GT1=lucasontivero"&gt;</description><category>Software Factory</category><comments>http://lucasontivero.spaces.live.com/Blog/cns!375AE0CCD1AF61CE!446.entry#comment</comments><guid isPermaLink="true">http://lucasontivero.spaces.live.com/Blog/cns!375AE0CCD1AF61CE!446.entry</guid><pubDate>Sat, 08 Sep 2007 17:37:34 GMT</pubDate><slash:comments>1</slash:comments><msn:type>blogentry</msn:type><live:type>blogentry</live:type><live:typelabel>Blog entry</live:typelabel><wfw:commentRss>http://lucasontivero.spaces.live.com/blog/cns!375AE0CCD1AF61CE!446/comments/feed.rss</wfw:commentRss><wfw:comment>http://lucasontivero.spaces.live.com/Blog/cns!375AE0CCD1AF61CE!446.entry#comment</wfw:comment><dcterms:modified>2007-09-12T16:29:29Z</dcterms:modified></item><item><title>[Benchmark] Reflection Performance</title><link>http://lucasontivero.spaces.live.com/Blog/cns!375AE0CCD1AF61CE!440.entry</link><description>&lt;img style="margin:10px" src="http://byfiles.storage.live.com/y1pmVarknuftX1uaViMlHixhwkSm7gGR8t2P0_1FX3Df2w5B0Bxubcy3lF7AkshaNUVxKjpNJStEGA" align=left&gt; 
&lt;div&gt;&lt;font face=Arial color="#c00000" size=3&gt;&lt;a href="http://www.google.com/translate?u=http://lucasontivero.spaces.live.com/blog/cns!375AE0CCD1AF61CE!440.entry&amp;amp;langpair=es|en&amp;amp;hl=en&amp;amp;ie=UTF8"&gt;[Tanslate this post to english with google]&lt;/a&gt;&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;Escribiendo el próximo post sobre el patrón DataMapper mediante reflection (lo estoy cocinando) me puse a pensar en una lista de pros y contras como así también, algunos escenarios en donde yo lo implementaria y en donde no. Entre los argumentos en contra seguramente debía figurar el hecho de que reflection tiene un costo que hay que evaluar. Yo pensaba que este argumento bien podría ponerse en la balanza junto con todos los beneficios de este patrón y pensaba argumentar también que si bien, el uso de reflection es caro, tampoco es una locura.&lt;/div&gt;
&lt;div&gt;Pero después me saltó la duda, cuan lento puede ser el uso de reflecion en comparación con un acceso convencional? Así que primero tiré un número a la mancancha, &amp;quot;debe ser 6 o 7 veces mas lento...&amp;quot; pensé.  Y me puse a buscar en google, encontré &lt;a href="http://www.manuelabadia.com/blog/PermaLink,guid,772c7152-b00e-4334-b677-bfbdcd8e6b5d.aspx" target="_blank"&gt;este blog &lt;/a&gt;y &lt;a href="http://msdn.microsoft.com/msdnmag/issues/05/07/Reflection/default.aspx" target="_blank"&gt;este muy buen artículo&lt;/a&gt; y &lt;a href="http://west-wind.com/WebLog/posts/351.aspx" target="_blank"&gt;este otro blog&lt;/a&gt; que que aunque también hace la prueba parece que el benchmark está distorcionado porque lo hace con una aplicación winform en la que existen al menos dos threads compitiendo (UI y el que corre nuestro código). &lt;/div&gt;
&lt;div&gt;Pero después me acordé de un proyecto que abusaba tanto de esta técnica que tardaba 3 minutos en arrancar!! Así que tiré otro número, &amp;quot;nooo, debe ser como 100 veces más lento&amp;quot;. Así que hice mi propia prueba solo seteando un field, una property e invocando un método y los números me dieron la razón, en estos caso es mucho más lento. &lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;Los números:&lt;/div&gt;
&lt;div&gt; &lt;img src="http://byfiles.storage.live.com/y1pmVarknuftX1PZ1HwGq2ltCSL2Bl36E68uLiP1tmrsAtW3wgx2Fp2gKUeDcv97YLLmm_pckFIC3c"&gt; &lt;img src="http://byfiles.storage.live.com/y1pmVarknuftX39lGOdriSDCVNoN5CLddM2JMy9l9LtTavcub8O8YHjbXJf3vOGphBPTJCzUwswGBo"&gt; &lt;/div&gt;
&lt;p&gt;En un Pentium 4 de 2.8GHz y 1 GB de RAM / Windows XP PE SP2. 
&lt;p&gt;&lt;img src="http://byfiles.storage.live.com/y1pmVarknuftX0XnyvoE4e2hjm-mBNlJPmNLOg0W48vnHNfRYv03NsmJgAGc-xPCpNQ7BQ5OMreAUE"&gt; 
&lt;div&gt;El mismo test (con bucles más chicos para irme a dormir más temprano) pero en un ADM 2800 con 512 de RAM /W2003 Server PE dió el resultado de arriba.&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;Si se corre este test más de una vez se obtienen resultados similares aunque distintos por varias razones, en primer lugar este test compite con las otras aplicaciones por el tiempo de ejecución por lo que nunca sabemos en que parte del código el S.O. nos interrumpe, otra cosa que distorciona es el hecho de que las operaciones de acceso directo a los campos, propiedades y métodos son más rápidas por lo que tienen menos posibilidades de ser interrumpidas por el planificador del SO. Esto último hace que a veces se obtengan brechas mayores a las que se muestran.&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;En síntesis, reflection es, al menos en estas operaciones, unas cientos de veces más lento que un acceso &amp;quot;común&amp;quot;. También lo corrí poniendo el proceso con prioridad Hight y obtuve resultados similares.&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;Pueden impugnar este benchmark si ven algo que esté mal. Acá va el código:&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;&lt;pre style="border-right:#eee 1px solid;padding-right:5px;border-top:#eee 1px solid;padding-left:5px;font-size:12px;padding-bottom:20px;overflow:auto;border-left:#eee 1px solid;width:95%;padding-top:5px;border-bottom:#eee 1px solid;font-family:courier new;height:500px;background-color:#fff"&gt;&lt;font color=blue&gt;using&lt;/font&gt; System;
&lt;font color=blue&gt;using&lt;/font&gt; System.Text;
&lt;font color=blue&gt;using&lt;/font&gt; System.Reflection;

&lt;font color=blue&gt;namespace&lt;/font&gt; Temosoft.Benchmarks
{
        &lt;font color=blue&gt;class&lt;/font&gt; Program
        {
                &lt;font color=blue&gt;static&lt;/font&gt; &lt;font color=blue&gt;void&lt;/font&gt; Main(&lt;font color=blue&gt;string&lt;/font&gt;[] args)
                {
                        DateTime startDate;
                        TimeSpan ts;
                        &lt;font color=blue&gt;int&lt;/font&gt; max = 10000000; &lt;font color=green&gt;//int.MaxValue;&lt;/font&gt;

                        TestClass t = &lt;font color=blue&gt;new&lt;/font&gt; TestClass();

                        System.Console.WriteLine(&amp;quot;&lt;font color=magenta&gt;----- FIELDS ------&lt;/font&gt;&amp;quot;);
                        startDate = DateTime.Now;
                        &lt;font color=blue&gt;for&lt;/font&gt; (&lt;font color=blue&gt;int&lt;/font&gt; i = 0; i &amp;lt; max; i++)
                        {
                                t.field = i;
                        }
                        ts = DateTime.Now.Subtract(startDate);
                        System.Console.WriteLine(&amp;quot;&lt;font color=magenta&gt;{0, -42}: {1}&lt;/font&gt;&amp;quot;, &amp;quot;&lt;font color=magenta&gt;obj.field = i;&lt;/font&gt;&amp;quot;, ts.Ticks);


                        Type type = &lt;font color=blue&gt;typeof&lt;/font&gt;(TestClass);
                        FieldInfo fi = type.GetField(&amp;quot;&lt;font color=magenta&gt;field&lt;/font&gt;&amp;quot;);
                        startDate = DateTime.Now;
                        &lt;font color=blue&gt;for&lt;/font&gt; (&lt;font color=blue&gt;int&lt;/font&gt; i = 0; i &amp;lt; max; i++)
                        {
                                fi.SetValue(t, i);
                        }
                        ts = DateTime.Now.Subtract(startDate);
                        System.Console.WriteLine(&amp;quot;&lt;font color=magenta&gt;{0, -42}: {1}&lt;/font&gt;&amp;quot;, &amp;quot;&lt;font color=magenta&gt;fieldInfo.SetValue(t, i);&lt;/font&gt;&amp;quot;, ts.Ticks);


                        startDate = DateTime.Now;
                        &lt;font color=blue&gt;for&lt;/font&gt; (&lt;font color=blue&gt;int&lt;/font&gt; i = 0; i &amp;lt; max; i++)
                        {
                                &lt;font color=blue&gt;typeof&lt;/font&gt;(TestClass).GetField(&amp;quot;&lt;font color=magenta&gt;field&lt;/font&gt;&amp;quot;).SetValue(t, i);
                        }
                        ts = DateTime.Now.Subtract(startDate);
                        System.Console.WriteLine(&amp;quot;&lt;font color=magenta&gt;{0, -42}: {1}&lt;/font&gt;&amp;quot;, &amp;quot;&lt;font color=magenta&gt;typeof(TestClass).GetField(\&amp;quot;field\&amp;quot;).SetValue(t, i);&lt;/font&gt;&amp;quot;, ts.Ticks);


                        System.Console.WriteLine(&amp;quot;&lt;font color=magenta&gt;----- PROPERTIES --&lt;/font&gt;&amp;quot;);
                        startDate = DateTime.Now;
                        &lt;font color=blue&gt;for&lt;/font&gt; (&lt;font color=blue&gt;int&lt;/font&gt; i = 0; i &amp;lt; max; i++)
                        {
                                t.Field = i;
                        }
                        ts = DateTime.Now.Subtract(startDate);
                        System.Console.WriteLine(&amp;quot;&lt;font color=magenta&gt;{0, -42}: {1}&lt;/font&gt;&amp;quot;, &amp;quot;&lt;font color=magenta&gt;obj.Property = i;&lt;/font&gt;&amp;quot;, ts.Ticks);


                        PropertyInfo pi = type.GetProperty(&amp;quot;&lt;font color=magenta&gt;Field&lt;/font&gt;&amp;quot;);
                        startDate = DateTime.Now;
                        &lt;font color=blue&gt;for&lt;/font&gt; (&lt;font color=blue&gt;int&lt;/font&gt; i = 0; i &amp;lt; max; i++)
                        {
                                pi.SetValue(t, i, &lt;font color=blue&gt;null&lt;/font&gt;);
                        }
                        ts = DateTime.Now.Subtract(startDate);
                        System.Console.WriteLine(&amp;quot;&lt;font color=magenta&gt;{0, -42}: {1}&lt;/font&gt;&amp;quot;, &amp;quot;&lt;font color=magenta&gt;propertyInfo.SetValue(t, i);&lt;/font&gt;&amp;quot;, ts.Ticks);


                        startDate = DateTime.Now;
                        &lt;font color=blue&gt;for&lt;/font&gt; (&lt;font color=blue&gt;int&lt;/font&gt; i = 0; i &amp;lt; max; i++)
                        {
                                &lt;font color=blue&gt;typeof&lt;/font&gt;(TestClass).GetProperty(&amp;quot;&lt;font color=magenta&gt;Field&lt;/font&gt;&amp;quot;).SetValue(t, i, &lt;font color=blue&gt;null&lt;/font&gt;);
                        }
                        ts = DateTime.Now.Subtract(startDate);
                        System.Console.WriteLine(&amp;quot;&lt;font color=magenta&gt;{0, -42}: {1}&lt;/font&gt;&amp;quot;, &amp;quot;&lt;font color=magenta&gt;typeof(TestClass).GetProperty(\&amp;quot;Field\&amp;quot;).SetValue(t, i, null);&lt;/font&gt;&amp;quot;, ts.Ticks);


                        System.Console.WriteLine(&amp;quot;&lt;font color=magenta&gt;----- METHODS --&lt;/font&gt;&amp;quot;);
                        startDate = DateTime.Now;
                        &lt;font color=blue&gt;for&lt;/font&gt; (&lt;font color=blue&gt;int&lt;/font&gt; i = 0; i &amp;lt; max; i++)
                        {
                                t.Method1(i);
                        }
                        ts = DateTime.Now.Subtract(startDate);
                        System.Console.WriteLine(&amp;quot;&lt;font color=magenta&gt;{0, -42}: {1}&lt;/font&gt;&amp;quot;, &amp;quot;&lt;font color=magenta&gt;obj.Method(i);&lt;/font&gt;&amp;quot;, ts.Ticks);


                        MethodInfo mi = type.GetMethod(&amp;quot;&lt;font color=magenta&gt;Method1&lt;/font&gt;&amp;quot;);
                        startDate = DateTime.Now;
                        &lt;font color=blue&gt;for&lt;/font&gt; (&lt;font color=blue&gt;int&lt;/font&gt; i = 0; i &amp;lt; max; i++)
                        {
                                mi.Invoke(t, &lt;font color=blue&gt;new&lt;/font&gt; &lt;font color=blue&gt;object&lt;/font&gt;[]{i} );
                        }
                        ts = DateTime.Now.Subtract(startDate);
                        System.Console.WriteLine(&amp;quot;&lt;font color=magenta&gt;{0, -42}: {1}&lt;/font&gt;&amp;quot;, &amp;quot;&lt;font color=magenta&gt;methodInfo.Invoke(t, new object[]{i} );&lt;/font&gt;&amp;quot;, ts.Ticks);


                        mi = type.GetMethod(&amp;quot;&lt;font color=magenta&gt;Method2&lt;/font&gt;&amp;quot;);
                        startDate = DateTime.Now;
                        &lt;font color=blue&gt;for&lt;/font&gt; (&lt;font color=blue&gt;int&lt;/font&gt; i = 0; i &amp;lt; max; i++)
                        {
                                mi.Invoke(t, &lt;font color=blue&gt;new&lt;/font&gt; &lt;font color=blue&gt;object&lt;/font&gt;[] { i, i, i, i, i, i });
                        }
                        ts = DateTime.Now.Subtract(startDate);
                        System.Console.WriteLine(&amp;quot;&lt;font color=magenta&gt;{0, -42}: {1}&lt;/font&gt;&amp;quot;, &amp;quot;&lt;font color=magenta&gt;methodInfo.Invoke(t, new object[] { i, i, i, i, i, i });&lt;/font&gt;&amp;quot;, ts.Ticks);

                        System.Console.ReadLine();
                }
        }

        &lt;font color=blue&gt;class&lt;/font&gt; TestClass
        {
                &lt;font color=blue&gt;public&lt;/font&gt; &lt;font color=blue&gt;int&lt;/font&gt; field;
                &lt;font color=blue&gt;public&lt;/font&gt; &lt;font color=blue&gt;int&lt;/font&gt; Field
                {
                        set { field = value; }
                        get { &lt;font color=blue&gt;return&lt;/font&gt; field; }
                }

                &lt;font color=blue&gt;public&lt;/font&gt; &lt;font color=blue&gt;void&lt;/font&gt; Method1(&lt;font color=blue&gt;int&lt;/font&gt; i)
                {
                        field = i;
                }

                &lt;font color=blue&gt;public&lt;/font&gt; &lt;font color=blue&gt;void&lt;/font&gt; Method2(&lt;font color=blue&gt;int&lt;/font&gt; i, &lt;font color=blue&gt;int&lt;/font&gt; j, &lt;font color=blue&gt;int&lt;/font&gt; k, &lt;font color=blue&gt;int&lt;/font&gt; l, &lt;font color=blue&gt;int&lt;/font&gt; m, &lt;font color=blue&gt;int&lt;/font&gt; n)
                {
                        field = i;
                }

        }
}&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Lucas Ontivero&lt;/strong&gt;&lt;img src="http://c.services.spaces.live.com/CollectionWebService/c.gif?cid=3988747590285877710&amp;page=RSS%3a+%5bBenchmark%5d+Reflection+Performance&amp;referrer=" width="1px" height="1px" border="0" alt=""&gt;&lt;img style="position:absolute" alt="" width="0px" height="0px" src="http://c.live.com/c.gif?NC=31263&amp;amp;NA=1149&amp;amp;PI=73329&amp;amp;RF=&amp;amp;DI=3919&amp;amp;PS=85545&amp;amp;TP=lucasontivero.spaces.live.com&amp;amp;GT1=lucasontivero"&gt;</description><category>.NET</category><comments>http://lucasontivero.spaces.live.com/Blog/cns!375AE0CCD1AF61CE!440.entry#comment</comments><guid isPermaLink="true">http://lucasontivero.spaces.live.com/Blog/cns!375AE0CCD1AF61CE!440.entry</guid><pubDate>Thu, 06 Sep 2007 14:40:00 GMT</pubDate><slash:comments>0</slash:comments><msn:type>blogentry</msn:type><live:type>blogentry</live:type><live:typelabel>Blog entry</live:typelabel><wfw:commentRss>http://lucasontivero.spaces.live.com/blog/cns!375AE0CCD1AF61CE!440/comments/feed.rss</wfw:commentRss><wfw:comment>http://lucasontivero.spaces.live.com/Blog/cns!375AE0CCD1AF61CE!440.entry#comment</wfw:comment><dcterms:modified>2007-09-06T15:55:09Z</dcterms:modified></item><item><title>[Patterns] Lifetime Container Pattern</title><link>http://lucasontivero.spaces.live.com/Blog/cns!375AE0CCD1AF61CE!438.entry</link><description>&lt;div&gt;&lt;font size=2&gt;
&lt;p&gt;Muchas veces es necesario mantener el control del tiempo de vida de los objetos. En tecnologias de código administrado como .Net o Java, a diferencia de otros como C y C++, existe un mecanismo de recolección de basura que libera al programador de la tarea de destrucción de objetos y la liberación de la memoria. No obstante, existen ocaciones en las que tener el control de la destrucción de los objetos es muy conveniente. 
&lt;p&gt;Por ejemplo, cuando la creación de un objeto consume mucho tiempo y recursos del procesador, crear estos objetos y permitir que se destruyan cuando se pierden las referencia a él puede que no sea una buena idea, en este caso se opta por crear un pool de objetos que no se destruyan cuando ya no se usen sino que permanezan disponibles aún cuando no se los esté usando. Otra situación se da cuando se necesita liberar un conjunto de recursos (objetos) que ya no se van a utilizar más porque en su conjunto representan o sirven a una sola unidad de trabajo. Un caso concreto es cuando se utilizan objetos que administran gran cantidad de otros objetos también completos como los WorkItem del Composite UI Appication Block el cual mantiene colecciones de objetos Views, Controlers, Commands, EventTopics, Services, SmartParts, UIExtensionSites, WorkSpaces, otros WorkItems y algunas cosas más. En este caso, cuando se libera un workitem, se deben liberar todos los objetos que han colaborado con él. 
&lt;p&gt;El Lifetime container, como su nombre lo indica, es un contenedor (una colección) que mantiene vivas las referencias a todos los objetos que se registran en él. Vamos al código:&lt;/font&gt; &lt;/div&gt;&lt;pre style="border-right:#eee 1px solid;padding-right:5px;border-top:#eee 1px solid;padding-left:5px;font-size:12px;padding-bottom:20px;overflow:auto;border-left:#eee 1px solid;width:95%;padding-top:5px;border-bottom:#eee 1px solid;font-family:courier new;height:300px;background-color:#fff"&gt;&lt;font color=blue&gt;using&lt;/font&gt; System;
&lt;font color=blue&gt;using&lt;/font&gt; System.Collections;
&lt;font color=blue&gt;using&lt;/font&gt; System.Collections.Generic;

&lt;font color=blue&gt;namespace&lt;/font&gt; Temosoft.Containers
{
        &lt;font color=blue&gt;public&lt;/font&gt; &lt;font color=blue&gt;class&lt;/font&gt; LifetimeContainer : IEnumerable&amp;lt;&lt;font color=blue&gt;object&lt;/font&gt;&amp;gt;, IDisposable
        {
                &lt;font color=blue&gt;#region&lt;/font&gt; Private Fields
                &lt;font color=green&gt;// El contenedor interno que mantiene vivas las referencias.&lt;/font&gt;
                &lt;font color=blue&gt;private&lt;/font&gt; List&amp;lt;&lt;font color=blue&gt;object&lt;/font&gt;&amp;gt; items = &lt;font color=blue&gt;new&lt;/font&gt; List&amp;lt;&lt;font color=blue&gt;object&lt;/font&gt;&amp;gt;();
                &lt;font color=blue&gt;#endregion&lt;/font&gt;

                &lt;font color=blue&gt;#region&lt;/font&gt; Public Methods (Operations)
                &lt;font color=blue&gt;public&lt;/font&gt; &lt;font color=blue&gt;void&lt;/font&gt; Add(&lt;font color=blue&gt;object&lt;/font&gt; item)
                {
                        items.Add(item);
                }

                &lt;font color=blue&gt;public&lt;/font&gt; &lt;font color=blue&gt;void&lt;/font&gt; Remove(&lt;font color=blue&gt;object&lt;/font&gt; item)
                {
                        &lt;font color=blue&gt;if&lt;/font&gt; (!items.Contains(item))
                        &lt;font color=blue&gt;return&lt;/font&gt;;

                        items.Remove(item);
                }

                &lt;font color=blue&gt;public&lt;/font&gt; &lt;font color=blue&gt;bool&lt;/font&gt; Contains(&lt;font color=blue&gt;object&lt;/font&gt; item)
                {
                        &lt;font color=blue&gt;return&lt;/font&gt; items.Contains(item);
                }
                &lt;font color=blue&gt;#endregion&lt;/font&gt;

                &lt;font color=blue&gt;#region&lt;/font&gt; Public Properties (Read only)
                &lt;font color=blue&gt;public&lt;/font&gt; &lt;font color=blue&gt;int&lt;/font&gt; Count
                {
                        get { &lt;font color=blue&gt;return&lt;/font&gt; items.Count; }
                }
                &lt;font color=blue&gt;#endregion&lt;/font&gt;


                &lt;font color=blue&gt;#region&lt;/font&gt; IDisposable &lt;font color=blue&gt;interface&lt;/font&gt;
                &lt;font color=blue&gt;public&lt;/font&gt; &lt;font color=blue&gt;void&lt;/font&gt; Dispose()
                {
                        Dispose(&lt;font color=blue&gt;true&lt;/font&gt;);
                }

                &lt;font color=blue&gt;protected&lt;/font&gt; &lt;font color=blue&gt;void&lt;/font&gt; Dispose(&lt;font color=blue&gt;bool&lt;/font&gt; disposing)
                {
                        &lt;font color=blue&gt;if&lt;/font&gt; (disposing)
                        {
                                List&amp;lt;&lt;font color=blue&gt;object&lt;/font&gt;&amp;gt; itemsCopy = &lt;font color=blue&gt;new&lt;/font&gt; List&amp;lt;&lt;font color=blue&gt;object&lt;/font&gt;&amp;gt;(items);
                                itemsCopy.Reverse();

                                &lt;font color=blue&gt;foreach&lt;/font&gt; (&lt;font color=blue&gt;object&lt;/font&gt; o &lt;font color=blue&gt;in&lt;/font&gt; itemsCopy)
                                {
                                        IDisposable d = o &lt;font color=blue&gt;as&lt;/font&gt; IDisposable;

                                        &lt;font color=blue&gt;if&lt;/font&gt; (d != &lt;font color=blue&gt;null&lt;/font&gt;)
                                        d.Dispose();
                                }

                                items.Clear();
                        }
                }
                &lt;font color=blue&gt;#endregion&lt;/font&gt;


                &lt;font color=blue&gt;#region&lt;/font&gt; Enumerators
                &lt;font color=blue&gt;public&lt;/font&gt; IEnumerator&amp;lt;&lt;font color=blue&gt;object&lt;/font&gt;&amp;gt; GetEnumerator()
                {
                        &lt;font color=blue&gt;return&lt;/font&gt; items.GetEnumerator();
                }

                IEnumerator IEnumerable.GetEnumerator()
                {
                        &lt;font color=blue&gt;return&lt;/font&gt; GetEnumerator();
                }
                &lt;font color=blue&gt;#endregion&lt;/font&gt;
        }
}&lt;/pre&gt;
&lt;p&gt;&lt;em&gt;Como se puede ver, esta clase es muy parecida a una colección salvo porque implementa IDisposable para manejar la liberación de los objetos en orden inverso a su registración. No implementa ICollection porque en este caso no se debe posibilitar el método CopyTo() y porque en este caso, por razones de sencillez, no se hizo thread safe.&lt;/em&gt; 
&lt;p&gt;Como se ve, este es un contenedor sumamente sencillo y surge la pregunta &amp;quot;que hay de nuevo acá?&amp;quot;, bueno, la verdad es que lo nuevo lo encontramos en la manera o las formas de usarlo. Veamos, en la entrada de este blogs: &lt;a href="http://lucasontivero.spaces.live.com/blog/cns!375AE0CCD1AF61CE!430.entry" target="_blank"&gt;[Patterns] Distributed Applications using FactoryMethod and ServiceLocator Patterns&lt;/a&gt;, vimos como la clase ServiceLocator mantenia un diccionario de strings y objetos (después lo hicimos mediante object-object), este diccionario impide que los servicios que no se utilizan puedan ser eliminados! Como podemos manejar esto con un LifetimeContainer? la respuesta es NO mantener las referencias. Esto lo podemos hacer implementando el ServiceLocator mediante un weakRefDictionary&amp;lt;object, object&amp;gt; en lugar de un Dictionary&amp;lt;object, object&amp;gt;.&lt;pre style="border-right:#eee 1px solid;padding-right:5px;border-top:#eee 1px solid;overflow-y:hidden;padding-left:5px;font-size:12px;padding-bottom:20px;overflow:auto;border-left:#eee 1px solid;width:95%;padding-top:5px;border-bottom:#eee 1px solid;font-family:courier new;background-color:#fff"&gt;&lt;font color=blue&gt;public&lt;/font&gt; &lt;font color=blue&gt;class&lt;/font&gt; ServiceLocator
{
        &lt;font color=blue&gt;private&lt;/font&gt; WeakRefDictionary&amp;lt;&lt;font color=blue&gt;object&lt;/font&gt;, &lt;font color=blue&gt;object&lt;/font&gt;&amp;gt; services = &lt;font color=blue&gt;new&lt;/font&gt; WeakRefDictionary&amp;lt;&lt;font color=blue&gt;object&lt;/font&gt;, &lt;font color=blue&gt;object&lt;/font&gt;&amp;gt;();

        &lt;font color=blue&gt;public&lt;/font&gt; &lt;font color=blue&gt;void&lt;/font&gt; AddService(&lt;font color=blue&gt;object&lt;/font&gt; serviceKey, &lt;font color=blue&gt;object&lt;/font&gt; service)
&lt;/pre&gt;
&lt;p&gt;Que beneficios nos trae esto? Ahora, cada componente, plugin, unit of work, form, o lo que sea puede registrar sus servicios, de manera que estén disponibles para todas los demas componentes, mientras dure su vida y que dejen de estarlo cuando ellos son destruidos (a menos que alguien los esté usando). Por lo tanto, cada componente tiene su propio Lifetime container para manejar el ciclo de vida de SUS objetos.
&lt;p&gt;&lt;strong&gt;Lucas Ontivero&lt;/strong&gt;&lt;img src="http://c.services.spaces.live.com/CollectionWebService/c.gif?cid=3988747590285877710&amp;page=RSS%3a+%5bPatterns%5d+Lifetime+Container+Pattern&amp;referrer=" width="1px" height="1px" border="0" alt=""&gt;&lt;img style="position:absolute" alt="" width="0px" height="0px" src="http://c.live.com/c.gif?NC=31263&amp;amp;NA=1149&amp;amp;PI=73329&amp;amp;RF=&amp;amp;DI=3919&amp;amp;PS=85545&amp;amp;TP=lucasontivero.spaces.live.com&amp;amp;GT1=lucasontivero"&gt;</description><category>Patterns</category><comments>http://lucasontivero.spaces.live.com/Blog/cns!375AE0CCD1AF61CE!438.entry#comment</comments><guid isPermaLink="true">http://lucasontivero.spaces.live.com/Blog/cns!375AE0CCD1AF61CE!438.entry</guid><pubDate>Tue, 04 Sep 2007 15:52:20 GMT</pubDate><slash:comments>2</slash:comments><msn:type>blogentry</msn:type><live:type>blogentry</live:type><live:typelabel>Blog entry</live:typelabel><wfw:commentRss>http://lucasontivero.spaces.live.com/blog/cns!375AE0CCD1AF61CE!438/comments/feed.rss</wfw:commentRss><wfw:comment>http://lucasontivero.spaces.live.com/Blog/cns!375AE0CCD1AF61CE!438.entry#comment</wfw:comment><dcterms:modified>2007-09-04T15:52:20Z</dcterms:modified></item><item><title>[Patterns] Distributed Applications using Facade Pattern</title><link>http://lucasontivero.spaces.live.com/Blog/cns!375AE0CCD1AF61CE!431.entry</link><description>&lt;p&gt;Este patrón tan sencillo es seguramente uno de los más importantes en el desarrollo de aplicaciones que publican sus servicios mediante Web Services. El motivo de este post es ayudar a entender la forma correcta de implementar Web Services con .Net. 
&lt;h2&gt;El problema&lt;/h2&gt;
&lt;p&gt;Afortunadamente hoy contamos con muchas herramientas y facilidades para la creación y publicación de servicios web. En .Net, es increiblemente facil crear un servicio web a partir de una clase, solo hay que extender nuestra clase de la clase System.Web.Services.WeServices y adornar el o los metodos que queremos publicar con [WebMethod] y listo. Por ejemplo:&lt;pre style="border-right:#eee 1px solid;padding-right:5px;border-top:#eee 1px solid;overflow-y:hidden;padding-left:5px;font-size:12px;padding-bottom:20px;overflow:auto;border-left:#eee 1px solid;width:500px;padding-top:5px;border-bottom:#eee 1px solid;font-family:courier new;background-color:#fff"&gt;&lt;font color=blue&gt;using&lt;/font&gt; System;
&lt;font color=blue&gt;using&lt;/font&gt; System.Web.Services;

&lt;font color=blue&gt;public&lt;/font&gt; &lt;font color=blue&gt;class&lt;/font&gt; HelloWorld: WebService {
        [WebMethod(Description=&amp;quot;&lt;font color=magenta&gt;Returns Hello&lt;/font&gt;&amp;quot;, EnableSession=&lt;font color=blue&gt;false&lt;/font&gt;)]
        &lt;font color=blue&gt;public&lt;/font&gt; &lt;font color=blue&gt;string&lt;/font&gt; Say() {
                &lt;font color=blue&gt;return&lt;/font&gt; &amp;quot;&lt;font color=magenta&gt;Hello&lt;/font&gt;&amp;quot;;
        }
}&lt;/pre&gt;
&lt;p&gt;El problema con estas facilidades es que muchos desarrolladores entienden que el objetivo de esto es exponer en el cliente, proxies mediantes, los objetos de negocios que se encuentra en el servidor. Esta creencia promueven un mal estilo de programación de los servicios web. Es más, no son servicios ya que se parecen mas a llamadas RPC o RMI. Esto es un error. No deben exponerse los objetos de negocio mediante un WebService. 
&lt;p&gt;Un escenario real: En un desarrollo para una empresa de reservas de hoteles, teniamos las clases Hotel, Habitacion, Reserva, Pasajero, Temporada y otras más. Un amigo se encargaba del desarrollo del cliente y sus necesidades eran claras, &amp;quot;necesito una lista con las disponibilidades (con los dias disponibles) y precios de las habitaciones de los hoteles en esos dias y la descripción de las comodidades o servicios que incluyen en esa temporada&amp;quot;. Este y otros requerimientos no se corresponden con ningún objeto del negocio, es decir, sencillamente no se resuelven serializando y enviando ningún objeto del negocio.   
&lt;h2&gt;La solución&lt;/h2&gt;
&lt;p&gt;La solución consiste en crear un Facade cuyos métodos representen los servicios que puede brindar la aplicación como por ejemplo: obtener disponibilidades de tal fecha a tal fecha para tantas personas en determinado sitio turístico, obtener nuevas reservas para un hotel determinado, reservar, cancelar reserva, etc. 
&lt;p&gt;Ahora, por lo general los métodos del Facade no tendrán problemas en cuanto a los tipos de parámetros a recibir ya que serán (repito, por lo general) tipos simples como int, DateTime, String, Boolean, Double, etc. Pero sí requerirán retornar al cliente tipos especiales que, como dije antes, no se corresponden con los objetos de negocio. Entonces esto ya no es una simple clase &amp;quot;ReservationFacade&amp;quot; sino que se trata de un componente (o layer) con sus propios tipos como Availability, Recommend, etc. Si bien estos tipos pueden, por sus nombres, parecer que pertenecen a los tipos del dominio en realidad no lo son. Por ejemplo, Recommend puede contener un destino o zona turística recomendada junto con una lista de ofertas de tipos de habitaciones con sus precios en distintos hoteles y los periodos de validez de estas recomendaciones.  
&lt;p&gt;Ventajas de este patron: 
&lt;ul&gt;
&lt;li&gt;Facil de responder a los cambios. Si el Web Service debe modificarse para ajustarse a los nuevos requerimientos del negocio entonces solo es necesario modificar el Facade. 
&lt;li&gt;Facil de mantener. Es posible modificar la estructura interna (refactoring) de las clases de negocio sin alterar el contrato con los clientes de WS. Ya que no se crean dependencia entre las clases de negocio con las aplicaciones clientas. 
&lt;li&gt;Responde a la idea de servicios. Los servicios se consumen en operaciones atómicas. Es decir, el servicio de &amp;quot;Reservar habitación&amp;quot; se realiza mediante un solo mensaje con toda la información necesaria y es el Facade quien se encarga de realizar todas las operaciones (seguramente en una transacción). 
&lt;li&gt;Son mas veloces. Por la misma razón que expongo arriba se realizan muchas menos idas y vueltas desde el servidor al cliente y viceversa.&lt;/ul&gt;
&lt;p&gt;La ventaja quizás mas importante es independizar el WS del resto de la aplicación ahorrandonos de tener que regenerar el WS (salvo cuando tocamos el Facade) y por lo tanto evitamos tener que regenerar los proxies en todos los cliente de nuestro WS y recompilar todo, tanto nosotros como todos nuestros clientes que pueden estar utilizando nuestros servicios somos más felices. 
&lt;p&gt;Otra ventaje que se deriva del punto anterior es que el versionado de nuestro servicio se simplifica considerablemente. 
&lt;p&gt;&lt;strong&gt;Lucas Ontivero&lt;/strong&gt;&lt;img src="http://c.services.spaces.live.com/CollectionWebService/c.gif?cid=3988747590285877710&amp;page=RSS%3a+%5bPatterns%5d+Distributed+Applications+using+Facade+Pattern&amp;referrer=" width="1px" height="1px" border="0" alt=""&gt;&lt;img style="position:absolute" alt="" width="0px" height="0px" src="http://c.live.com/c.gif?NC=31263&amp;amp;NA=1149&amp;amp;PI=73329&amp;amp;RF=&amp;amp;DI=3919&amp;amp;PS=85545&amp;amp;TP=lucasontivero.spaces.live.com&amp;amp;GT1=lucasontivero"&gt;</description><category>Patterns</category><comments>http://lucasontivero.spaces.live.com/Blog/cns!375AE0CCD1AF61CE!431.entry#comment</comments><guid isPermaLink="true">http://lucasontivero.spaces.live.com/Blog/cns!375AE0CCD1AF61CE!431.entry</guid><pubDate>Fri, 31 Aug 2007 20:50:53 GMT</pubDate><slash:comments>0</slash:comments><msn:type>blogentry</msn:type><live:type>blogentry</live:type><live:typelabel>Blog entry</live:typelabel><wfw:commentRss>http://lucasontivero.spaces.live.com/blog/cns!375AE0CCD1AF61CE!431/comments/feed.rss</wfw:commentRss><wfw:comment>http://lucasontivero.spaces.live.com/Blog/cns!375AE0CCD1AF61CE!431.entry#comment</wfw:comment><dcterms:modified>2007-09-01T15:25:47Z</dcterms:modified></item><item><title>[Patterns] Distributed Applications using FactoryMethod and ServiceLocator Patterns</title><link>http://lucasontivero.spaces.live.com/Blog/cns!375AE0CCD1AF61CE!430.entry</link><description>&lt;div&gt;&lt;font size=2&gt;
&lt;p&gt;En esta entrada vamos a ver la utilidad del patrón Service Locator para construir aplicaciones distribuidas. Los componentes de estas aplicaciones deben estar totalmente desacoplados y por lo tanto la mejor manera de hacerlo es mediante el consumo de servicios que obviamente respeten ciertos contratos. 
&lt;p&gt;Ok, largamos con el patrón FactoryMethod como patrón inicial para ver como llegamos al ServiceLocator. Entonces, basicamente, todo método que tiene por objetivo crear diferentes tipos de objetos implementa implementa el patrón FactoryMethod. Veamos un ejemplo:&lt;/font&gt; &lt;/div&gt;&lt;pre style="border-right:#eee 1px solid;padding-right:5px;border-top:#eee 1px solid;padding-left:5px;font-size:12px;padding-bottom:20px;overflow:auto;border-left:#eee 1px solid;width:95%;padding-top:5px;border-bottom:#eee 1px solid;font-family:courier new;height:350px;background-color:#fff"&gt; 1 &lt;font color=blue&gt;using&lt;/font&gt; System.Windows.Forms;
 2 
 3 &lt;font color=blue&gt;namespace&lt;/font&gt; MyDocumentManager
 4 {
 5         &lt;font color=blue&gt;enum&lt;/font&gt; DocumentExtensionEnum {DOC, PDF, XML};
 6 
 7         &lt;font color=green&gt;/* La clase Abstracta */&lt;/font&gt;
 8         &lt;font color=blue&gt;public&lt;/font&gt; abstract &lt;font color=blue&gt;class&lt;/font&gt; Document
 9         {
10                 &lt;font color=blue&gt;public&lt;/font&gt; abstract &lt;font color=blue&gt;void&lt;/font&gt; Show(Form container);
11         }
12 
13         &lt;font color=green&gt;/* Las clases concretas */&lt;/font&gt;
14         &lt;font color=blue&gt;public&lt;/font&gt; &lt;font color=blue&gt;class&lt;/font&gt; WordDocument : Document
15         {
16                 &lt;font color=blue&gt;public&lt;/font&gt; &lt;font color=blue&gt;override&lt;/font&gt; &lt;font color=blue&gt;void&lt;/font&gt; Show(Form container){&lt;font color=green&gt;/*...*/&lt;/font&gt;}
17         }
18 
19         &lt;font color=blue&gt;public&lt;/font&gt; &lt;font color=blue&gt;class&lt;/font&gt; PDFDocument : Document
20         {
21                 &lt;font color=blue&gt;public&lt;/font&gt; &lt;font color=blue&gt;override&lt;/font&gt; &lt;font color=blue&gt;void&lt;/font&gt; Show(Form container){&lt;font color=green&gt;/*...*/&lt;/font&gt;}
22         }
23 
24         &lt;font color=blue&gt;public&lt;/font&gt; &lt;font color=blue&gt;class&lt;/font&gt; XMLDocument : Document
25         {
26                 &lt;font color=blue&gt;public&lt;/font&gt; &lt;font color=blue&gt;override&lt;/font&gt; &lt;font color=blue&gt;void&lt;/font&gt; Show(Form container){&lt;font color=green&gt;/*...*/&lt;/font&gt;}
27         }
28 
29         &lt;font color=green&gt;/* La clase creadora o consumidora de documentos */&lt;/font&gt;
30         &lt;font color=blue&gt;public&lt;/font&gt; &lt;font color=blue&gt;class&lt;/font&gt; DocumentManager
31         {
32                 DocumentManager(&lt;font color=blue&gt;string&lt;/font&gt; filename)
33                 {
34                         Document doc = FactoryMethod(filename);
35                         doc.Show(&lt;font color=blue&gt;new&lt;/font&gt; DocumentViewerForm());
36                 }
37 
38                 &lt;font color=green&gt;/* Este es el metodo */&lt;/font&gt;
39                 &lt;font color=blue&gt;private&lt;/font&gt; Document FactoryMethod(&lt;font color=blue&gt;string&lt;/font&gt; filename)
40                 {
41                         Document doc;
42                         DocumentExtensionEnum extension = GetExtension(filename);
43 
44                         &lt;font color=green&gt;/* crea el tipo de documento adecuado segun la extension del archivo */&lt;/font&gt;
45                         &lt;font color=blue&gt;switch&lt;/font&gt;(extension){
46                                 &lt;font color=blue&gt;case&lt;/font&gt; DocumentExtensionEnum.DOC:
47                                 doc = &lt;font color=blue&gt;new&lt;/font&gt; WordDocument();
48                                 &lt;font color=blue&gt;break&lt;/font&gt;;
49                                 &lt;font color=blue&gt;case&lt;/font&gt; DocumentExtensionEnum.PDF:
50                                 doc = &lt;font color=blue&gt;new&lt;/font&gt; PDFDocument();
51                                 &lt;font color=blue&gt;break&lt;/font&gt;;
52                                 &lt;font color=blue&gt;case&lt;/font&gt; DocumentExtensionEnum.XML:
53                                 doc = &lt;font color=blue&gt;new&lt;/font&gt; XMLDocument();
54                                 &lt;font color=blue&gt;break&lt;/font&gt;;
55                         }
56                         retrun doc;
57                 }
58         }
59 }
60 &lt;/pre&gt;&lt;font size=2&gt;
&lt;p&gt;Este es un ejemplo claro, según la extensión del archivo, nos devuelve el objeto adecuado. El tema es ahora que en este método tenemos un switch hardcodeado! Es decir, no podemos agregarle otros tipos de objetos a crear sin modificar el código :( 
&lt;p&gt;Y aquí entra el patrón que nos convoca, el Service Locator. Se trata de un patrón creational el cual permite registrar servicios o componentes y luego solicitar una instacia de alguno de ellos. Veamos un poco de código:&lt;/font&gt;  &lt;pre style="border-right:#eee 1px solid;padding-right:5px;border-top:#eee 1px solid;padding-left:5px;font-size:12px;padding-bottom:20px;overflow:auto;border-left:#eee 1px solid;width:95%;padding-top:5px;border-bottom:#eee 1px solid;font-family:courier new;height:300px;background-color:#fff"&gt;&lt;font color=blue&gt;public&lt;/font&gt; &lt;font color=blue&gt;class&lt;/font&gt; ServiceLocator
{
        &lt;font color=blue&gt;private&lt;/font&gt; Dictionary&amp;lt;&lt;font color=blue&gt;string&lt;/font&gt;, &lt;font color=blue&gt;object&lt;/font&gt;&amp;gt; services = &lt;font color=blue&gt;new&lt;/font&gt; Dictionary&amp;lt;&lt;font color=blue&gt;string&lt;/font&gt;, &lt;font color=blue&gt;object&lt;/font&gt;&amp;gt;();

        &lt;font color=blue&gt;public&lt;/font&gt; &lt;font color=blue&gt;void&lt;/font&gt; AddService(&lt;font color=blue&gt;string&lt;/font&gt; serviceName, &lt;font color=blue&gt;object&lt;/font&gt; service)
        {
                &lt;font color=blue&gt;if&lt;/font&gt; (&lt;font color=blue&gt;string&lt;/font&gt;.IsEmptyOrNull(serviceName))
                &lt;font color=blue&gt;throw&lt;/font&gt; &lt;font color=blue&gt;new&lt;/font&gt; ArgumentNullException(&amp;quot;&lt;font color=magenta&gt;serviceName&lt;/font&gt;&amp;quot;);
                &lt;font color=blue&gt;if&lt;/font&gt; (service == &lt;font color=blue&gt;null&lt;/font&gt;)
                &lt;font color=blue&gt;throw&lt;/font&gt; &lt;font color=blue&gt;new&lt;/font&gt; ArgumentNullException(&amp;quot;&lt;font color=magenta&gt;service&lt;/font&gt;&amp;quot;);

                services.Add(serviceName, service);
        }

        &lt;font color=blue&gt;public&lt;/font&gt; &lt;font color=blue&gt;object&lt;/font&gt; GetService(&lt;font color=blue&gt;string&lt;/font&gt; serviceName)
        {
                &lt;font color=blue&gt;if&lt;/font&gt; (&lt;font color=blue&gt;string&lt;/font&gt;.IsEmptyOrNull(serviceName))
                &lt;font color=blue&gt;throw&lt;/font&gt; &lt;font color=blue&gt;new&lt;/font&gt; ArgumentNullException(&amp;quot;&lt;font color=magenta&gt;serviceName&lt;/font&gt;&amp;quot;);

                &lt;font color=blue&gt;if&lt;/font&gt; (services.ContainsKey(serviceName))
                &lt;font color=blue&gt;return&lt;/font&gt; services[serviceName];

                &lt;font color=blue&gt;return&lt;/font&gt; &lt;font color=blue&gt;null&lt;/font&gt;;
        }
}
&lt;/pre&gt;
&lt;p&gt;Aquí lo he implementado con un diccionario string-object para hacerlo mas facil pero despues voy a mostrar una alternativa mejor. Otra cosa, por lo general, solo existe una instancia de esta clase as'i que se implementa mediante un Singleton. 
&lt;p&gt;La ventaja que tenemos ahora es que podemos hacer una clase &amp;quot;Services Loader&amp;quot; la cual lea un archivo de configuración (seguramente deserealizando un xml) y que de acuerdo a eso cargue los servicios que hagan falta dentro del Service Locator. Esto es especialmente útil cuando queremos hacer un sistema plug-able porque podemos poner un assembly en un directorio y modificar nuestro xml de configuración de modo que esta clase Service Loader cargue ahora los nuevos servicios de nuestro assembly haciendo que estos esten disponibles para la aplicación. 
&lt;p&gt;A ver si se entiende bien! puedo por ejemplo:&lt;pre style="border-right:#eee 1px solid;padding-right:5px;border-top:#eee 1px solid;padding-left:5px;font-size:12px;padding-bottom:20px;overflow:auto;border-left:#eee 1px solid;width:95%;padding-top:5px;border-bottom:#eee 1px solid;font-family:courier new;height:200px;background-color:#fff"&gt;IStorageManager sm = (IStorageManager)serviceLocator.GetService(&amp;quot;&lt;font color=magenta&gt;Storage Service&lt;/font&gt;&amp;quot;);

&lt;font color=blue&gt;if&lt;/font&gt;(sm != &lt;font color=blue&gt;null&lt;/font&gt;)
{
        sm.Save(myPersistentObject);
}
&lt;font color=blue&gt;else&lt;/font&gt;
{
        IEventLogger ev = (IEventLogger)serviceLocator.GetService(&amp;quot;&lt;font color=magenta&gt;Event Logger Service&lt;/font&gt;&amp;quot;);
        &lt;font color=blue&gt;if&lt;/font&gt;(ev != &lt;font color=blue&gt;null&lt;/font&gt;)
        ev.WriteWarning(
        String.Format(&amp;quot;&lt;font color=magenta&gt;{0} wasn't persisted&lt;/font&gt;&amp;quot;, myPersistentObject.ToString()
        );

}&lt;/pre&gt;
&lt;p&gt;Bien, alguno debe estar pensando &amp;quot;y como hace un cast así! habria que validar que respete esa interface antes de castearla tan burramente!!!&amp;quot;. Y sí, quien piesa así tiene razón, el tema es que lo hago así por sencilles y porque lo que quiero mostrar es que de esta manera lo que hacemos es: primero preguntamos si tenemos tal o cual servicio y de ser así lo usamos. Con este patrón (que todavia no tiene buena forma) podemos agregarle, sin tocar el código, un servicio de logueo cualquiera (que implemente la IEventLogger por supuesto). También podemos ponerle, sacarle o cambiarle el servicio de Storage registrando por ejemplo bajo el nombre de &amp;quot;Storage Service&amp;quot; a cualquier servicio que implemente la interface IStorageManage como por ejemplo, &amp;quot;SQL Storage Service&amp;quot;, &amp;quot;Amazon Storage Services&amp;quot;, &amp;quot;Web Blog Storage Service&amp;quot;, etc.    
&lt;p&gt;Tanto que hablamos del &amp;quot;Service Loader&amp;quot; veamos como puede ser:&lt;br&gt;&lt;font size=1&gt;&lt;em&gt;(Antes que nada, si ven algo que no anda es porque en la máquina en que estoy escribiendo esta entrada no tengo el .Net Framework 2.0)&lt;/em&gt;&lt;/font&gt; 
&lt;p&gt;  &lt;pre style="border-right:#eee 1px solid;padding-right:5px;border-top:#eee 1px solid;padding-left:5px;font-size:12px;padding-bottom:20px;overflow:auto;border-left:#eee 1px solid;width:95%;padding-top:5px;border-bottom:#eee 1px solid;font-family:courier new;height:200px;background-color:#fff"&gt;[XmlRootAttribute(&amp;quot;&lt;font color=magenta&gt;ServiceCatalog&lt;/font&gt;&amp;quot;, Namespace=&amp;quot;&lt;font color=magenta&gt;http://www.temosoft.com.ar/ServiceLoader&lt;/font&gt;&amp;quot;, IsNullable = &lt;font color=blue&gt;false&lt;/font&gt;)]
&lt;font color=blue&gt;public&lt;/font&gt; &lt;font color=blue&gt;class&lt;/font&gt; ServiceCatalog
{
        &lt;font color=blue&gt;private&lt;/font&gt; Service[] services;
        &lt;font color=blue&gt;public&lt;/font&gt; Service[] Services
        {
                get{ &lt;font color=blue&gt;return&lt;/font&gt; services; }
                set{ services=value;  }
        }
}

[Serializable]
&lt;font color=blue&gt;public&lt;/font&gt; &lt;font color=blue&gt;class&lt;/font&gt; Service
{
        &lt;font color=blue&gt;private&lt;/font&gt; &lt;font color=blue&gt;string&lt;/font&gt;   serviceName;
        &lt;font color=blue&gt;private&lt;/font&gt; &lt;font color=blue&gt;string&lt;/font&gt;   assemblyName;
        &lt;font color=blue&gt;private&lt;/font&gt; &lt;font color=blue&gt;string&lt;/font&gt;   typeName;
        &lt;font color=blue&gt;private&lt;/font&gt; Boolean  isAvailable;

        [XmlAttribute]
        &lt;font color=blue&gt;public&lt;/font&gt; &lt;font color=blue&gt;string&lt;/font&gt; ServiceName
        {
                get { &lt;font color=blue&gt;return&lt;/font&gt; serviceName; }
                set { serviceName= value; }
        }

        [XmlAttribute]
        &lt;font color=blue&gt;public&lt;/font&gt; &lt;font color=blue&gt;string&lt;/font&gt; AssemblyName
        {
                get { &lt;font color=blue&gt;return&lt;/font&gt; AssemblyName; }
                set { AssemblyName= value; }
        }

        [XmlAttribute]
        &lt;font color=blue&gt;public&lt;/font&gt; &lt;font color=blue&gt;string&lt;/font&gt; TypeName
        {
                get { &lt;font color=blue&gt;return&lt;/font&gt; typeName; }
                set { typeName= value; }
        }


        [XmlAttribute]
        &lt;font color=blue&gt;public&lt;/font&gt; Boolean IsAvailable
        {
                get { &lt;font color=blue&gt;return&lt;/font&gt; isAvailable; }
                set { isAvailable= value; }
        }
}


&lt;font color=blue&gt;public&lt;/font&gt; &lt;font color=blue&gt;class&lt;/font&gt; ServiceLoader
{
        &lt;font color=blue&gt;public&lt;/font&gt; &lt;font color=blue&gt;void&lt;/font&gt; Load()
        {
                XmlSerializer serializer = &lt;font color=blue&gt;new&lt;/font&gt; XmlSerializer(&lt;font color=blue&gt;typeof&lt;/font&gt;(ServiceCatalog));
                FileStream fs = &lt;font color=blue&gt;new&lt;/font&gt; FileStream(&amp;quot;&lt;font color=magenta&gt;ServiceCatalog.xml&lt;/font&gt;&amp;quot;, FileMode.Open);
                ServiceCatalog servicesCatalog = (ServiceCatalog)serializer.Deserialize(fs);

                &lt;font color=blue&gt;foreach&lt;/font&gt;(Service s &lt;font color=blue&gt;in&lt;/font&gt; servicesCatalog.Services)
                {
                        &lt;font color=blue&gt;try&lt;/font&gt;{
                                Assembly asm = Assembly.Load(s.AssemblyName);
                                Type serviceType asm.GetType(s.TypeName);

                                ServiceLocator.Instance.AddService( s.ServiceName, Activator.CreateInstance(serviceType));
                        }&lt;font color=blue&gt;catch&lt;/font&gt;(Exception e){
                        }
                }
        }
}
&lt;/pre&gt;
&lt;p&gt;En este caso asuminos que el ServiceLocator es un Singleton. Es posible también hacer que cada servicio pueda recibir parámetros en su constructor. Ahora, como hacemos para mejorar esto? &lt;pre style="border-right:#eee 1px solid;padding-right:5px;border-top:#eee 1px solid;padding-left:5px;font-size:12px;padding-bottom:20px;overflow:auto;border-left:#eee 1px solid;width:95%;padding-top:5px;border-bottom:#eee 1px solid;font-family:courier new;height:300px;background-color:#fff"&gt;&lt;font color=blue&gt;public&lt;/font&gt; &lt;font color=blue&gt;static&lt;/font&gt; &lt;font color=blue&gt;class&lt;/font&gt; ServiceLocator
{
        &lt;font color=blue&gt;private&lt;/font&gt; &lt;font color=blue&gt;static&lt;/font&gt; ServiceLocator instance;
        &lt;font color=blue&gt;private&lt;/font&gt; &lt;font color=blue&gt;static&lt;/font&gt; &lt;font color=blue&gt;object&lt;/font&gt; instanceLock = &lt;font color=blue&gt;new&lt;/font&gt; &lt;font color=blue&gt;object&lt;/font&gt;();
        &lt;font color=blue&gt;private&lt;/font&gt; Dictionary&amp;lt;&lt;font color=blue&gt;object&lt;/font&gt;, &lt;font color=blue&gt;object&lt;/font&gt;&amp;gt; services = &lt;font color=blue&gt;new&lt;/font&gt; Dictionary&amp;lt;&lt;font color=blue&gt;object&lt;/font&gt;, &lt;font color=blue&gt;object&lt;/font&gt;&amp;gt;();

        &lt;font color=blue&gt;public&lt;/font&gt; ServiceLocator Instance
        {
                get
                {
                        &lt;font color=blue&gt;if&lt;/font&gt; (instance == &lt;font color=blue&gt;null&lt;/font&gt;)
                        {
                                &lt;font color=blue&gt;lock&lt;/font&gt; (instanceLock)
                                {
                                        &lt;font color=blue&gt;if&lt;/font&gt; (instance == &lt;font color=blue&gt;null&lt;/font&gt;)
                                        {
                                                instance = &lt;font color=blue&gt;new&lt;/font&gt; ServiceLocator();
                                        }
                                }
                        }
                        &lt;font color=blue&gt;return&lt;/font&gt; instance;
                }
        }

        &lt;font color=blue&gt;public&lt;/font&gt; &lt;font color=blue&gt;void&lt;/font&gt; Add(&lt;font color=blue&gt;object&lt;/font&gt; serviceKeyObject, &lt;font color=blue&gt;object&lt;/font&gt; service)
        {
                &lt;font color=blue&gt;if&lt;/font&gt; (serviceKeyObject==&lt;font color=blue&gt;null&lt;/font&gt;)
                &lt;font color=blue&gt;throw&lt;/font&gt; &lt;font color=blue&gt;new&lt;/font&gt; ArgumentNullException(&amp;quot;&lt;font color=magenta&gt;serviceKeyObject&lt;/font&gt;&amp;quot;);
                &lt;font color=blue&gt;if&lt;/font&gt; (service == &lt;font color=blue&gt;null&lt;/font&gt;)
                &lt;font color=blue&gt;throw&lt;/font&gt; &lt;font color=blue&gt;new&lt;/font&gt; ArgumentNullException(&amp;quot;&lt;font color=magenta&gt;service&lt;/font&gt;&amp;quot;);

                &lt;font color=blue&gt;if&lt;/font&gt; (!services.ContainKey(serviceKeyObject))
                services.Add(serviceKeyObject, service);
        }

        &lt;font color=blue&gt;public&lt;/font&gt; &lt;font color=blue&gt;object&lt;/font&gt; Get(&lt;font color=blue&gt;object&lt;/font&gt; serviceKeyObject)
        {
                &lt;font color=blue&gt;if&lt;/font&gt; (serviceName==&lt;font color=blue&gt;null&lt;/font&gt;)
                &lt;font color=blue&gt;throw&lt;/font&gt; &lt;font color=blue&gt;new&lt;/font&gt; ArgumentNullException(&amp;quot;&lt;font color=magenta&gt;serviceKeyObject&lt;/font&gt;&amp;quot;);

                &lt;font color=blue&gt;if&lt;/font&gt; (services.ContainsKey(serviceName))
                &lt;font color=blue&gt;return&lt;/font&gt; services[serviceName];

                &lt;font color=blue&gt;return&lt;/font&gt; &lt;font color=blue&gt;null&lt;/font&gt;;
        }

        &lt;font color=blue&gt;public&lt;/font&gt; T Get&amp;lt;T&amp;gt; (&lt;font color=blue&gt;object&lt;/font&gt; serviceKeyObject)
        {
                &lt;font color=blue&gt;object&lt;/font&gt; obj = Get(serviceKeyObject);
                &lt;font color=blue&gt;if&lt;/font&gt; (obj != &lt;font color=blue&gt;null&lt;/font&gt; &amp;amp;&amp;amp; (obj &lt;font color=blue&gt;is&lt;/font&gt; T))
                &lt;font color=blue&gt;return&lt;/font&gt; (T)obj;

                &lt;font color=blue&gt;return&lt;/font&gt; &lt;font color=blue&gt;null&lt;/font&gt;;
        }
}&lt;/pre&gt;
&lt;p&gt;Si no te sirvió usa el ObjectBuilder :) ,que además de implementar este y otros muchos patrones muy grosos, implementa Inyección de Dependencias para un desacople muy bien pensado. 
&lt;p&gt;&lt;strong&gt;Lucas Ontivero.&lt;/strong&gt;&lt;img src="http://c.services.spaces.live.com/CollectionWebService/c.gif?cid=3988747590285877710&amp;page=RSS%3a+%5bPatterns%5d+Distributed+Applications+using+FactoryMethod+and+ServiceLocator+Patterns&amp;referrer=" width="1px" height="1px" border="0" alt=""&gt;&lt;img style="position:absolute" alt="" width="0px" height="0px" src="http://c.live.com/c.gif?NC=31263&amp;amp;NA=1149&amp;amp;PI=73329&amp;amp;RF=&amp;amp;DI=3919&amp;amp;PS=85545&amp;amp;TP=lucasontivero.spaces.live.com&amp;amp;GT1=lucasontivero"&gt;</description><category>Patterns</category><comments>http://lucasontivero.spaces.live.com/Blog/cns!375AE0CCD1AF61CE!430.entry#comment</comments><guid isPermaLink="true">http://lucasontivero.spaces.live.com/Blog/cns!375AE0CCD1AF61CE!430.entry</guid><pubDate>Thu, 30 Aug 2007 20:08:38 GMT</pubDate><slash:comments>3</slash:comments><msn:type>blogentry</msn:type><live:type>blogentry</live:type><live:typelabel>Blog entry</live:typelabel><wfw:commentRss>http://lucasontivero.spaces.live.com/blog/cns!375AE0CCD1AF61CE!430/comments/feed.rss</wfw:commentRss><wfw:comment>http://lucasontivero.spaces.live.com/Blog/cns!375AE0CCD1AF61CE!430.entry#comment</wfw:comment><dcterms:modified>2007-09-01T15:26:03Z</dcterms:modified></item><item><title>[Software Factories] Introducción (Parte 2)</title><link>http://lucasontivero.spaces.live.com/Blog/cns!375AE0CCD1AF61CE!424.entry</link><description>&lt;img style="margin:5px;height:30%" height=172 src="http://byfiles.storage.live.com/y1pykZ-TIQ2OCR0fgq5JSqonSG0J_olxohq30EgucWr-niuhateb2_BsR6nxLpyblCm0F8Dp7hvuO8ESQ4EuuxE3RQxnalwPqjx" width=240 align=left&gt;  &lt;p&gt;Ok. Esta es la parte dos de la introducción.  &lt;p&gt;Realmente no quería caer en el mismo ejemplo de libro pero lo voy a hacer. La manera en que hoy desarrollamos software es exactamente igual a como se hacian los automóviles antes de Mr. Ford. Como era esto? Bueno igual que lo que hacemos hoy, venia un cliente y decía: quiero una auto así, así y así con madera de pino de Groenlandia, cuero de jaguareté y pedales de tutú carreta, entonces se diseñaba el auto de cero, a alguno se le ocurria que lo mejor era un rodado de marfil y aluminio de 23,67 pulgadas, etc. Una vez listo el diseño se ponian con los cerruchos, martillos, un tornito y otras herramientas y en 6 o 7 meses estaba listo. Salian mas o menos bien y costaban caro. Hoy en cambio todos los autos comparten un gran número de componentes comunes entre otras cosas gracias a los estandares. Son estos lo que me permiten enchufar mi televisor en cualquier parte del pais y que siga funcionando o cambiar el cuerito de la grifería sin tener que averiguar medidas.  &lt;p&gt;Esta forma de trabajo se caracteriza por:  &lt;ul&gt; &lt;li&gt;Uso intensivo de la mano de obra,  &lt;li&gt;Uso de herramientas demasiado genéricas,  &lt;li&gt;Mínimo reuso y,   &lt;li&gt;Procesos genéricos &lt;/ul&gt; &lt;p&gt;De esta manera se producen demoras en los tiempos de entrega, defectos, agujeros de seguridad y retrabajos. Además de imposibilitar la introducción de calidad desde el primer momento en cuanto a aquellos detalles diferenciadores como seguridad, usabilidad, desempeño, mantenibilidad y escalabilidad de los productos (sin causar fatigas por falencias en la arquitectura) entre otros.  &lt;p&gt;Antes de continuar analizando los por qué del surgimiento de este paradigma vamos a definir algunos términos que son muy necesarios como por ejemplo el de Software Factory y luego voy a aclarar algunas cosas que me quedaron en el tintero del post anterior.  &lt;h2&gt;Definiciones&lt;/h2&gt; &lt;h3&gt;Software Factory&lt;/h3&gt; &lt;p&gt;Si se le hubiese llamado de otra manera nos habriamos visto forzados a realizar un esfuerzo mental para averiguar y tratar de entender de que se trata este concepto pero desgraciadamente esta palabrita &amp;quot;Factory&amp;quot; nos habilita a pensar cualquier cosa. Las analogías que encontramos por todos lados con fabricas de zapatos o electrodomésticos terminan de confirmar nuestras fantasias mal fundadas. No son pocos los que creen que se trata de hacer software como si de automoviles se tratara, simplemente ensamblando algunas partes hechas en una linea de montaje y automatizando, robots mediantes, los detalles como el color de la pintura y otros. Bueno, no es así. La figura que adorna este post también confunde pero está muy buena para reflejar el estado actual del arte :)  &lt;p&gt;Distingamos entre Software Factory como paradigma y como instancia. Como paradigma, es una alternativa a los métodos actuales de construcción que intenta resolver los 5 problemas planteados en el post anterior cuando las aplicaciones a construir comparten características comunes. Como instancia (SCSF por ejemplo), un Software Factory es un conjunto de herramientas, procesos tailorizados, frameworks, patrones y modelos (por lo general embebidos en los frameworks y/o herramientas integradas del IDE) y otros contenidos que usan para trabajar sobre una Linea de Productos. O mejor dicho, un SF es una linea de producto que utiliza un SF Template basado en un SF Schema.  &lt;h3&gt;Linea de Productos&lt;/h3&gt; &lt;p&gt;Una linea de productos se refiere a un tipo de aplicación que puede agruparse o identificarse como perteneciente a una familia de productos como por ejemplo sistemas de CRM, software de seguros, software para entidades bancarias, de control aereo y cualquier otro. Es decir, pueden agruparse de distintas maneras, por segmento de negocios, tipo de soluciones, plataforma, etc. Lo importante es poder identificar aquellas características comunes. Tres aspectos claves de una linea de productos son: los alcances, la variabilidad y la extensibilidad. Los &lt;b&gt;alcances&lt;/b&gt; determinan que tipo de soluciones pueden construirse a partir de la linea de productos y define por lo general la arcitectura base para la familia de aplicaciones, la &lt;b&gt;variabilidad&lt;/b&gt; hace referencia a las parte comunes definidas en los alcances y aquellas que son variables por medio de configuración de la linea y la &lt;b&gt;extensibilidad&lt;/b&gt; determina los puntos en los que es posible añadir funcionalidades.  &lt;h3&gt;Software Factory Schema&lt;/h3&gt; &lt;p&gt;Un Software Factory Schema es un modelo general que por lo general utiliza grillas, gráficos o cualquier otro artefacto para describir cuales son los productos de trabajo, los pasos a seguir para construirlos, las relaciones existentes entre ellos. Esta es una herramienta para entender y posiblemente automatizar el funcionamiento del SF. Por ejemplo, un SF Schema puede describir los paquetes que se utilizan, la distribución f'isica de los componentes y como los distintos miembros de los equipos se relacionan con cada uno de estos aspectos. Un SF Schema se compone de Viewpoints que no son otra cosa que la descripción de todos los &lt;a href="http://en.wikipedia.org/wiki/Asset"&gt;assets&lt;/a&gt; que intervienen en la generación de un aspecto del software que se desea desarrollar. Por ejemplo, un view point para la creación de un smart client podría ser la generación de la UI, en este caso el view point especificaría el conjunto de cosas necesarias para realizarlas, desde una clase base Form, diseñadores, DSL para especificar la navegabilidad entre formularios, herramientas de generación de algunos aspectos o plantillas, guias necesarias que intervienen es este punto, etc. Podría decirse que es la colección de todos los puntos de vista de un SF o el plano conceptual de este. Este plano tiene forma de arbol y cada rama trata un aspecto particular de la solución que a su vez se divide en otras ramas que los analizan desde otros puntos de vista. La definición de Viewpoint de la IEEE está en &lt;a href="http://ieeexplore.ieee.org/iel5/7040/18957/00875998.pdf"&gt;IEEE Recommended Practice for Architectural Description of Software-Intensive Systems&lt;/a&gt;.  &lt;h3&gt;Software Factory Template&lt;/h3&gt; &lt;p&gt;Una vez que tenemos los planos conceptuales del Software Factory que queremos construir debemos.... construirlo!! Es decir, ya sabemos que &lt;a href="http://en.wikipedia.org/wiki/Asset"&gt;assets&lt;/a&gt; necesitaremos, como serán, donde intervendrán, como se relacionarán, etc. Ok, ahora hay que hacerlos. Esto es, crear los frameworks, las guias, los asistentes, los DSLs, procesos y todos los demás asstes descritos en el esquema he integrarlos (en lo posible) al IDE. Cada vez que se construye un nuevo producto, cada desarrollador puede (y debería) contribuir con el SF añadiendo sus plantillas, snippets, instructivos, frameworksy cualquier otro &lt;a href="http://en.wikipedia.org/wiki/Asset"&gt;asset&lt;/a&gt;. Para más información acerca de estos últimos dos temas les recomiendo la edición número 9 de la revista &lt;a href="http://lucasontivero.spaces.live.com/mmm2007-07-26_17.23/www.architecturejournal.net"&gt;The Architecture Journal&lt;/a&gt; y en especial el artículo de Tom Fuller &amp;quot;Fundamentos para los pilares de las Fábricas de Software&amp;quot;.  &lt;h2&gt;Lo que me quedó en el tintero&lt;/h2&gt; &lt;p&gt;Algo que me quedó en el tintero es el tema de las metodologias cuyo problema resumia como &amp;quot;o (son) muy formales o (son) uy ágiles&amp;quot;. Greenfield  y Short  plantean (lo que a muchos nos parece obvio) que existen dos tendencias extremas con sus pros y contras. A diferencia de lo que uno podría esperar, Greenfield  y Short no creen que una metodología más formal sea más MADURA, por el contrario, entienden que son inmaduras por extremistas.  &lt;p&gt;&lt;strong&gt;En cuanto a los desarrolladores&lt;/strong&gt;  &lt;p&gt;Luego vamos a ver como distinguen entre &amp;quot;tipos&amp;quot; de desarrolladores (este &amp;quot;tipos&amp;quot; es mio, en realidad habla del valor de los desarrolladores y distingue entre ellos a aquellos que pueden construir los Software Factories y aquellos que los utilizan) y que importancia tienen estos dentro del proceso de desarrollo. Continuo planteando este tema porque cuantas veces hemos escuchado a gerentes de sistemas/Producers/Produc Manager/Team Leadres decir cosas como &amp;quot;Yo quiero/necesito poder sacar a uno (desarrollador) y poner a otro y que los proyectos continuen en marcha&amp;quot;?. La verdad creo que estas palabras (quiero/necesito) expresan un deseo. Sí, es una expresión de deseo! pero es un deseo genuino y entendible. Yo, en el lugar de esas personas querria exactamente lo mismo pero también entiendo que eso es un intento un poco necio de negar la realidad.  &lt;p&gt;Como por ahí nombro los libros o cito los autores y no quiero poner palabras mias en sus bocas les recomiendo que los lean. Aunque en este punto es coveniente citarlos de manera textual.  &lt;p&gt;&lt;em&gt;&amp;quot;Unfortunately, the industry has a tendency to become overly prescriptive, assuming that developers are naive and uninformed, and attempting to use formal processes to prevent them from making mistakes by telling them what to build, how to build, and what skills are required to perform certain tasks.&amp;quot;&lt;/em&gt;  &lt;p&gt;El problema mayor que describe esta frase no es sobre lo de &amp;quot;ingenuos&amp;quot; o &amp;quot;ignorantes&amp;quot; sino que producen una infrautilización de las capacidades de las personas. Esto a veces constrasta con lo que se busca en un aspirante para un puesto como desarrollor, que esté muy capacitado, que pueda demostrar logros, que pueda plantear soluciones innovativas, que sea proactivo, etc.  &lt;p&gt;Steve Jobs, fundador de Apple Computer, dice en una frase célebre:  &lt;p&gt;&lt;em&gt;&amp;quot;No tiene sentido contratar a personas inteligentes y después decirles lo que tienen que hacer. Nosotros contratamos a personas inteligentes para que nos digan qué tenemos que hacer.&amp;quot;&lt;/em&gt;  &lt;p&gt;Por otro lado, las metodologías ágiles no son la solución tampoco porque tienen sus problemas y no son aplicables a todas las realidades o mejor dicho, se aplican a un esquema muy particular de trabajo, gente, clientes, proyectos y demás.  &lt;p&gt;Que solución se plantea? Ahí viene:  &lt;p&gt;   &lt;h3&gt;Process Framework&lt;/h3&gt; &lt;p&gt;La solución planteada no sorprende a nadie. La clave es preservar la agilidad mientras se mantiene la posibilidad de escalar la complejidad introducida por el tamaño y la distribución geográfica de los proyectos. Lo verdaderamente importantes es como esta posibilidad va tomando forma real mediante la implementación del paradigma de Software Factories.  &lt;p&gt;Los autores siguen diciendo que el problema de las metodologias formales es que son demasiado abstractas en el sentido que para poder utilizarse deben ser tailorizadas a cada proyecto o necesidad particular. La idea detrás de esta crítica, que no lo es tal, es tailorizar los procesos a una familia de productos concreta.  &lt;p&gt;Es decir, enfocar los procesos hacia las tareas puntuales de todo el ciclo de vida de una familia de productos (o product line -este concepto es importantísimo y lo explicaré mas aelante). Así, por ejemplo, debería por cada actividad facilitarse los recursos necesarios como wikis, links a documentación importante (pero facilmente accesible y no en un archivo de Word o Excel que sabe dios donde está o que se tarda más en abrirse que en buscarlo por otros medios), información de contactos, guias específicas (instructivos) sobre como realizar tarea, checklists aplicables a la tarea, estilos de codificación, detalles de cual/es es/son el/los próximo/s paso/s en el desarrollo, herramientas, políticas, etc. Todo esto debería estar integrado al IDE y en lo posible automatizado.  &lt;p&gt;Como hecho un tanto anecdótico debo resaltar que Microsoft provée el MSF for CMMI Process Improvement Guidance el cual abarca las prácticas relacionadas a las areas claves cubiertas por CMMI nivel 3.  &lt;p&gt;Los Procces Frameworks se componen de dos conceptos: Constraint-Based Scheduling y Active Guidance.  &lt;p&gt;&lt;strong&gt;Constraint-Based Scheduling&lt;/strong&gt; se refiere a dividir (o abordar) un proceso en mini procesos para la construcción de artefactos o tangibles particulares. Cada uno de estos mini procesos define: los requerimientos para producir la salida, los recursos, los pasos a seguir y las decisiones claves que pueden requerirse en cada momento. Lo de Constraint hace referencia a que entre cada uno de los mini procesos existen precondiciones y postcondiciones que deben matchaer entre ellas y a las restricciones propias del scheduling del proyecto.  &lt;p&gt;&lt;strong&gt;Active Guidance&lt;/strong&gt; se refiere en parte a lo que ya mencioné arriba, que en cada paso de una actividad se brinde la información necesaria para realizarla. Esto debe ser estar facilmente accesible, facilmente entendible y en tiempo real, apoyado en asistentes, plantillas autodescriptivas y que asistan al desarrollador, recomendandole acciones, documentación y ejemplos a la vez que monitorizan el cumplimento de los constraints establecidos.&lt;img src="http://c.services.spaces.live.com/CollectionWebService/c.gif?cid=3988747590285877710&amp;page=RSS%3a+%5bSoftware+Factories%5d+Introducci%c3%b3n+(Parte+2)&amp;referrer=" width="1px" height="1px" border="0" alt=""&gt;&lt;img style="position:absolute" alt="" width="0px" height="0px" src="http://c.live.com/c.gif?NC=31263&amp;amp;NA=1149&amp;amp;PI=73329&amp;amp;RF=&amp;amp;DI=3919&amp;amp;PS=85545&amp;amp;TP=lucasontivero.spaces.live.com&amp;amp;GT1=lucasontivero"&gt;</description><category>Software Factory</category><comments>http://lucasontivero.spaces.live.com/Blog/cns!375AE0CCD1AF61CE!424.entry#comment</comments><guid isPermaLink="true">http://lucasontivero.spaces.live.com/Blog/cns!375AE0CCD1AF61CE!424.entry</guid><pubDate>Mon, 27 Aug 2007 23:31:52 GMT</pubDate><slash:comments>0</slash:comments><msn:type>blogentry</msn:type><live:type>blogentry</live:type><live:typelabel>Blog entry</live:typelabel><wfw:commentRss>http://lucasontivero.spaces.live.com/blog/cns!375AE0CCD1AF61CE!424/comments/feed.rss</wfw:commentRss><wfw:comment>http://lucasontivero.spaces.live.com/Blog/cns!375AE0CCD1AF61CE!424.entry#comment</wfw:comment><dcterms:modified>2007-09-05T01:57:12Z</dcterms:modified></item><item><title>Me nombraron Coordinador del Grupo de Sistemas Operativos de la IEEE!!!</title><link>http://lucasontivero.spaces.live.com/Blog/cns!375AE0CCD1AF61CE!416.entry</link><description>&lt;p&gt;Estoy muy contento con la noticia. Por fin soy coordinador de algo como la gente. Pero lo mejor de lo mejor es que nadie me avisó y me vengo a enterar gracias a mi irrefrenable narcisismo.  &lt;p&gt;Resulta que googleandome me encuentro en la página que la &lt;a href="http://www.organizaciones.frc.utn.edu.ar/ieee-acm/grupos/grupos.htm" target="_blank"&gt;IEEE tiene hosteada en la UTN de Córdoba&lt;/a&gt; en la que si bien he participado en algunas oportunidades y he dictado cursos de C++ organizado por ellos, nunca pero nunca me nombraron coordinador de nada. &lt;p&gt;Mañana mismo voy a cobrar el sueldo que me deben estar adeudando pero bueno, una referencia más para poner en el curriculum! jajaja. No sé que pensar o mejor dicho, si sé que pensar pero lo dejo ahí. &lt;p&gt;Espero que como buenos amigos me feliciten todos eh. &lt;p&gt;&lt;strong&gt;Lucas Ontivero&lt;/strong&gt;&lt;br&gt;&lt;em&gt;Operating System Group - Coordinator&lt;/em&gt;&lt;img src="http://c.services.spaces.live.com/CollectionWebService/c.gif?cid=3988747590285877710&amp;page=RSS%3a+Me+nombraron+Coordinador+del+Grupo+de+Sistemas+Operativos+de+la+IEEE!!!&amp;referrer=" width="1px" height="1px" border="0" alt=""&gt;&lt;img style="position:absolute" alt="" width="0px" height="0px" src="http://c.live.com/c.gif?NC=31263&amp;amp;NA=1149&amp;amp;PI=73329&amp;amp;RF=&amp;amp;DI=3919&amp;amp;PS=85545&amp;amp;TP=lucasontivero.spaces.live.com&amp;amp;GT1=lucasontivero"&gt;</description><comments>http://lucasontivero.spaces.live.com/Blog/cns!375AE0CCD1AF61CE!416.entry#comment</comments><guid isPermaLink="true">http://lucasontivero.spaces.live.com/Blog/cns!375AE0CCD1AF61CE!416.entry</guid><pubDate>Sun, 26 Aug 2007 04:16:36 GMT</pubDate><slash:comments>5</slash:comments><msn:type>blogentry</msn:type><live:type>blogentry</live:type><live:typelabel>Blog entry</live:typelabel><wfw:commentRss>http://lucasontivero.spaces.live.com/blog/cns!375AE0CCD1AF61CE!416/comments/feed.rss</wfw:commentRss><wfw:comment>http://lucasontivero.spaces.live.com/Blog/cns!375AE0CCD1AF61CE!416.entry#comment</wfw:comment><dcterms:modified>2007-08-26T05:05:35Z</dcterms:modified></item><item><title>[Software Factories] Introducción (Parte 1)</title><link>http://lucasontivero.spaces.live.com/Blog/cns!375AE0CCD1AF61CE!414.entry</link><description>&lt;img style="margin:5px;height:40%" src="http://www.ispysoft.net/BookCover.JPG" align=left&gt; 
&lt;div&gt;Hace un tiempo que estoy estudiando sobre Software Factories, mas precisamente, leyendo los libros: &amp;quot;Software Factories: Assembling Applications with Patterns, Models, Frameworks, and Tools&amp;quot; de Jack Greenfield y Keith Short y &amp;quot;Practical Software Factories in .NET: From Theory to Practice—A Primer, Reference, and Case Study&amp;quot; de Gunther Lenz y Christoph Wienands. Ademas de leer todo lo que diga &amp;quot;Software Factories&amp;quot; en google. &lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;Según sitan todas las fuentes, y en especial referencia al CHAOS Report, son muy pocos los proyectos de desarrollo de software que se consideran exitosos (alrededor del 30%) mientras que el 50% tuvo problemas de irse del presupuesto, tiempo de entrega y calidad. La porción restante fueron cancelados durante el ciclo de vida del desarrollo. El informe le asigna una minúscula importancia a los aspectos técnicos aislados como causal de los fracasos en la terminación e implementación exitosa de los proyectos aunque es evidente que ellos se deben a la manera en que se construye el software, y esta es una tarea eminentemente técnica. Es decir, si se simplificara dramáticamente la tarea de desarrollo seguramente la calidad, la productividad, los costos y tiempos de entrega se dispararían a niveles mas deseables que los actuales. Y esto es un problema de &amp;quot;como se hace&amp;quot; (Técnica).&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;Haciendo una comparación entre nuestra industria y otras de diciplinas ingenieriles mas maduras como la mecánica, electrónica y/o civil, Jack Greenfield y Keith Short dicen que fallamos al desarrollar software porque:&lt;/div&gt;
&lt;div&gt;&lt;strong&gt;Razón 1 - One-off development&lt;br&gt;&lt;/strong&gt;
&lt;div&gt;Cada proyecto se construye desde CERO e independientemente de otros sistemas similares. Los Assets (no encuentro una palabra mejor pero llamemosles componentes o mejor &amp;quot;tangibles&amp;quot;) de estos sistemas no se crearon con el prop'osito de ser reutilizables. Esto encuentra varias razones:&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;hacer algo reutilizable requiere una IDENTIFICACION y ANALISIS de aquellas características comunes que puedan servir en un futuro cercano. 
&lt;li&gt;hacer algo reutilizable requiere que se DISEÑE con ese propósito en mente, 
&lt;li&gt;que se CONSTRUYA, 
&lt;li&gt;que se VERSIONES y MANTENGA, 
&lt;li&gt;que se DOCUMENTE (si no se documenta no es reutilizable por más que se cumpla todo lo anterior)&lt;/ul&gt;
&lt;div&gt;En otras palabras, hacer un tangible reutilizable es una inversión que hay que analizar.&lt;/div&gt;
&lt;div&gt;Una de las formas de reutilización mas común en la actualidad es la dupla copy/paste, que desde mi punto de vista es la peor práctica de todas. Mejores resultados tenemos en la reutilización de componentes en binario o ILs como el Framework .NET, Componentes COM/Activex, los paquetes Java y las .lib en C sin perjuicio de crear nuestros propios binarios para reutilizarlos en esa forma.&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt; &lt;/div&gt;&lt;img style="margin:5px;height:40%" src="http://images.amazon.com/images/P/0471202843.01.LZZZZZZZ.jpg" align=right&gt; 
&lt;div&gt;Otro problema con la reutilización de fuentes es que el código es mas facil escribirlo que leerlo y eso hace que al leerlo, al no tener la documentación de este (casi nunca la tenemos), al no estar pensado para reutilizarlos facilmente y al no sernos &amp;quot;agradable&amp;quot; la &amp;quot;estética&amp;quot; del código, se nos cruce el pensamiento &amp;quot;Por dios! quien hizo esta porquería!?. Hay que hacerlo de nuevo&amp;quot;. Esto es reinventar la rueda. Más allá del hecho de si servía o no, el tema es que habrá dos fuentes con multitud de características similares que bien podrian haberse hecho de una manera mas inteligente.&lt;/div&gt;
&lt;div&gt;&lt;br&gt;&lt;strong&gt;Razón 2 - Monolithic systems and increasing systems complexity&lt;br&gt;&lt;/strong&gt;Los sistemas monolíticos son aquellos en los que sus componentes están fuertemente acoplados y no permiten tratarlos de manera sistemática porque un cambio en una parte produce la necesidad de hacer cambios en muchos de los componentes con los que se relaciona. El problema se observa con mayor claridad al tener que mantener, extender y adaptar el sistema a los cambios en los requerimientos post &lt;/div&gt;
&lt;div&gt;implementación. Como contrapartida de los sistemas monolíticos tenemos los sistemas pluggeables.&lt;/div&gt;
&lt;div&gt;&lt;br&gt;&lt;strong&gt;Razón 2 - Working at low levels of abstraction&lt;/strong&gt;&lt;br&gt;Este tema ya lo toqué en otros post sobre Domain Specific Language y NBusiness. Veamos como se desarrolla un software: Nos llegan los requerimientos de nuestro Program Manager/Team Leader y, despues de las reuniones de rutina, en que nos comentan hasta como se peina el cliente, empezamos con un pequeño brainstorn personal o con algún grosso amigo (hoy en dia esto lo hacemos casi desde CERO). &lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;Cuando tenemoslas ideas y los documentos y llega la hora de hecharle mano al código (en este caso ejemplifico con c# pero podría ser cualquier lenguaje: VB, Java, SQL, XSLT, etc) comenzamos así:&lt;/div&gt;
&lt;div&gt;  using System.IO;&lt;br&gt;    :&lt;br&gt;    :&lt;/div&gt;
&lt;div&gt;  public class Product&lt;br&gt;  {&lt;br&gt;    private string productName;&lt;br&gt;    public string Name&lt;br&gt;    { get {...} set {...} }&lt;br&gt;    &lt;/div&gt;
&lt;div&gt;La pregunta es: puede ser esta la manera más natural de especificar el comportamiento y las cualidades de un componente de catálogo de productos? No estaremos hilando demasiado fino? Es más, me atrevo a preguntar: no debería estar hecho ya por alguien más o es que acaso nadie nunca escribió un producto que trabajase con productos?. Está bien, acepto que para algo así falta mucho, que habria que estandarizar bloques de construcción y un montón de cosas más pero la pregunta inicial sigue en pie. Son los lenguajes de propósito general los adecuados para todos los casos particulares? Claro que no. Aquí es donde entran, entre otras cosas, los DSLs o Lenguajes específicos de un dominio.&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;Aclaro, como desarrollador siempre pienso en función de lenguajes de programación pero bien podrían ser lenguajes de empaquetado, de testings, de validación, de especificación de requerimientos o cualquier otro.&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;Como alternativa a este bajo nivel de abstracción se analizan una variedad inmensa de cosas, entre las que ya las DSL, como Model Driver development (MDD) y Model Driver Architectural (MDA). Todos con mayor o menor grado de relación con UML y su posibilidad, gracias a XML o mas precisamente XMI, de automatizar una gran cantidad de tareas de desarrollo como así también elevar el nivel de abstracción.&lt;/div&gt;
&lt;div&gt;Este es sin dudas el tema mas interesante si se lo estudia en forma aisladas y es el que mas material tiene escrito (tanto que te cansa).&lt;/div&gt;
&lt;div&gt;&lt;br&gt;&lt;strong&gt;Razón 3 - Process immaturity&lt;/strong&gt;&lt;br&gt;Alguién podrá pensar: &amp;quot;ah no!, ese problema nosotros no lo tenemos. Tenemos CMMI! jajaja&amp;quot;. Bueno, la verdad es que esto es para vos también y se resume así: o demasiado formal o demasiado agil.&lt;br&gt;&lt;/div&gt;
&lt;div&gt;Veamos por qué:&lt;/div&gt;
&lt;div&gt;   &lt;strong&gt;Los mas agiles&lt;/strong&gt;:&lt;br&gt;     &lt;em&gt;Ventajas&lt;/em&gt;:&lt;/div&gt;
&lt;ul&gt;
&lt;ul&gt;
&lt;ul&gt;
&lt;li&gt;responden bien ante los cambios 
&lt;li&gt;comunicación en lugar de documentación 
&lt;li&gt;desarrollo y corrida en iteraciones pequeñas 
&lt;li&gt;los requerimientos se validan continuamente gracias a una comunicación constante con el cliente 
&lt;li&gt;continuamente se hace refactorin de las aplicaciones&lt;/ul&gt;&lt;/ul&gt;&lt;/ul&gt;
&lt;p&gt;     &lt;em&gt;Fallan&lt;/em&gt;: 
&lt;ul&gt;
&lt;ul&gt;
&lt;ul&gt;
&lt;li&gt;imposible de escalar a grandes proyectos o muy complejos. 
&lt;li&gt;escaza documentación de la arquitectura crean problemas de soporte e integración 
&lt;li&gt;equipos distribuidos&lt;/ul&gt;&lt;/ul&gt;&lt;/ul&gt;
&lt;div&gt;   &lt;strong&gt;Los mas formales:&lt;br&gt;&lt;/strong&gt;        &lt;em&gt;ventajas&lt;/em&gt;:&lt;/div&gt;
&lt;ul&gt;
&lt;ul&gt;
&lt;ul&gt;
&lt;li&gt;tienen perfectamente establecidos los roles, artefactos y actividades activities 
&lt;li&gt;hacen énfasis en los requerimientos, análisis y diseño 
&lt;li&gt;la arquitectura se documenta con modelos&lt;/ul&gt;&lt;/ul&gt;&lt;/ul&gt;
&lt;p&gt;&lt;br&gt;         &lt;em&gt;Fallan&lt;/em&gt;: 
&lt;ul&gt;
&lt;ul&gt;
&lt;ul&gt;
&lt;li&gt;Responden lento a los cambios 
&lt;li&gt;perfectamente escalables a grandes proyectos o proyectos complejos&lt;/ul&gt;&lt;/ul&gt;&lt;/ul&gt;
&lt;div&gt;Existen muchas discuciones en torno a este tema. Cual es mejor?. La verdad es que en la práctica, esta elección muchas veces no es posible. Hay muchos aspectos a tener en cuenta además de los arriba mencionados que entran en juego y que condicionan una libre elección de la metodología. Por ejemplo: Si tengo grupos pequeños de gente muy capacitada (que no se me van a ir el mes que viene), expertos en temas puntuales, con experiencia, trabajando juntos, con clientes que confian en nosotros a los cuales podemos llamar o ver en cualquier momento, con proyectos relativamente pequeños; bueno, agil es la respuesta. Ahora, si tenemos clientes con distintos usos horarios, idiomas, o nuestro cliente es un gobierno extranjero, que no nos conoce, que quiere mas que una estimación un presupuesto ajustado, que puede hacernos una auditoría, si cotizamos en bolsa, si tenemos proyectos muy grandes, con mucha gente (que se nos va el mes que viene), o somos una pyme de una provincia del interior de un remoto pais que no conoce nadie llamado Argentina y queremos salir a vender nuestros productos por el mundo: bueno, no queda otra, entrá a &lt;a href="http://www.sei.cmu.edu/"&gt;http://www.sei.cmu.edu/&lt;/a&gt;.&lt;/div&gt;
&lt;div&gt;&lt;br&gt;&lt;strong&gt;Razón 4 - Rapidly growing demand for software systems&lt;/strong&gt;&lt;br&gt;No solo que se incrementó la demanda de software sino que además va creciendo el tamaño y la complejidad del mismo. Los clientes de hoy solicitan funcionalidades o características que hace 2 o 3 años atras ni se les hubiera cruzado por la cabeza. Así que no piensen solo estriban siguiendo la metodología HP (Horse Programming)&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;Bueno, esto ya está mas largo que un post de Diegum prometo seguir con este tema en próximos post.&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;Lucas Ontivero&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;&lt;/div&gt;&lt;img src="http://c.services.spaces.live.com/CollectionWebService/c.gif?cid=3988747590285877710&amp;page=RSS%3a+%5bSoftware+Factories%5d+Introducci%c3%b3n+(Parte+1)&amp;referrer=" width="1px" height="1px" border="0" alt=""&gt;&lt;img style="position:absolute" alt="" width="0px" height="0px" src="http://c.live.com/c.gif?NC=31263&amp;amp;NA=1149&amp;amp;PI=73329&amp;amp;RF=&amp;amp;DI=3919&amp;amp;PS=85545&amp;amp;TP=lucasontivero.spaces.live.com&amp;amp;GT1=lucasontivero"&gt;</description><category>Software Factory</category><comments>http://lucasontivero.spaces.live.com/Blog/cns!375AE0CCD1AF61CE!414.entry#comment</comments><guid isPermaLink="true">http://lucasontivero.spaces.live.com/Blog/cns!375AE0CCD1AF61CE!414.entry</guid><pubDate>Fri, 24 Aug 2007 20:12:01 GMT</pubDate><slash:comments>4</slash:comments><msn:type>blogentry</msn:type><live:type>blogentry</live:type><live:typelabel>Blog entry</live:typelabel><wfw:commentRss>http://lucasontivero.spaces.live.com/blog/cns!375AE0CCD1AF61CE!414/comments/feed.rss</wfw:commentRss><wfw:comment>http://lucasontivero.spaces.live.com/Blog/cns!375AE0CCD1AF61CE!414.entry#comment</wfw:comment><dcterms:modified>2007-08-27T23:49:28Z</dcterms:modified></item><item><title>Simpsonizate</title><link>http://lucasontivero.spaces.live.com/Blog/cns!375AE0CCD1AF61CE!409.entry</link><description>&lt;img src="http://byfiles.storage.live.com/y1pykZ-TIQ2OCRKQgp-dhjr4LiENU6w91u2lpO5vg9tG-5_nzDf2GSqI0GiPG0jT5qhJaObzivTwR4UjZywqj-Dpg" align=left&gt; 
&lt;p&gt;Hoy leí una &lt;a href="http://misopiniones.spaces.live.com/Blog/cns!2737DC89A4AAB26B!990.entry" target="_blank"&gt;entrada del blog de Gustavo Bonansea&lt;/a&gt; en el que él se simpsoniza así que acá voy yo. 
&lt;p&gt;La verdad es que estoy bastante parecido o al menos eso creo, jajaja. La página para convertirte en un personaje más es &lt;a href="http://simpsonizeme.com/"&gt;&lt;strong&gt;http://simpsonizeme.com/&lt;/strong&gt;&lt;/a&gt;, eso sí, mejor si tenes alguien al lado que te diga &amp;quot;nooo, vos sos mas pelado&amp;quot; o &amp;quot;tenés los ojos un poo mas chiquitos&amp;quot;. 
&lt;p&gt;Saludos.&lt;img src="http://c.services.spaces.live.com/CollectionWebService/c.gif?cid=3988747590285877710&amp;page=RSS%3a+Simpsonizate&amp;referrer=" width="1px" height="1px" border="0" alt=""&gt;&lt;img style="position:absolute" alt="" width="0px" height="0px" src="http://c.live.com/c.gif?NC=31263&amp;amp;NA=1149&amp;amp;PI=73329&amp;amp;RF=&amp;amp;DI=3919&amp;amp;PS=85545&amp;amp;TP=lucasontivero.spaces.live.com&amp;amp;GT1=lucasontivero"&gt;</description><comments>http://lucasontivero.spaces.live.com/Blog/cns!375AE0CCD1AF61CE!409.entry#comment</comments><guid isPermaLink="true">http://lucasontivero.spaces.live.com/Blog/cns!375AE0CCD1AF61CE!409.entry</guid><pubDate>Tue, 07 Aug 2007 03:27:37 GMT</pubDate><slash:comments>1</slash:comments><msn:type>blogentry</msn:type><live:type>blogentry</live:type><live:typelabel>Blog entry</live:typelabel><wfw:commentRss>http://lucasontivero.spaces.live.com/blog/cns!375AE0CCD1AF61CE!409/comments/feed.rss</wfw:commentRss><wfw:comment>http://lucasontivero.spaces.live.com/Blog/cns!375AE0CCD1AF61CE!409.entry#comment</wfw:comment><dcterms:modified>2007-08-27T18:10:04Z</dcterms:modified></item><item><title>"Vení que te queremos mucho" y el flujo del personal</title><link>http://lucasontivero.spaces.live.com/Blog/cns!375AE0CCD1AF61CE!373.entry</link><description>&lt;img src="http://byfiles.storage.msn.com/y1pxChyvkZ21WtRDa3eRes4VC177eFMyEZCzgr63mYmBHLRbpPFOYIFL1kHCgbfY2qN" align=left&gt; 
&lt;div&gt;Es curioso, a diario observo como va rotando el personal mas calificado de las empresas de una manera que a veces parece un algoritmo de &lt;a href="http://en.wikipedia.org/wiki/Leaky_bucket" target="_blank"&gt;cubeta con goteo&lt;/a&gt; (se  van llendo de a poquito) y otras veces me recuerda al de &lt;a href="http://en.wikipedia.org/wiki/Token_bucket" target="_blank"&gt;cubeta con ficha&lt;/a&gt; (se van en lotes :) ) generando una implosión de la nómina de una empresa. Este último caso ocurre por alguna situación especial que rebalsa el vaso. 
&lt;p&gt;Leyendo sobre filosofía de la calidad en una monografia sobre los 14 puntos de Deming leo lo siguiente: 
&lt;blockquote&gt;&lt;em&gt;&amp;quot;Hay zonas en donde los empleados viven rotando entre las diferentes empresas , inclusive escuchamos un caso, que cuando cambia una persona, sus amigos se van con ésta. Es tan poco atractivo permanecer en una empresa, hay tan poco estímulo. Realmente muchos ven a sus colaboradores como &amp;quot;enemigos pagados&amp;quot;, desaprovechando el potencial que tienen para lograr la transformación que las empresas necesitan. Frecuentemente escuchamos casi como súplica, &amp;quot;ya sabe, si conoce de algo para mi, me avisa&amp;quot;. Todos están dispuestos a cambiar de empresa. No se escuchan las sugerencias, no se les involucra en la solución de problemas.&amp;quot;&lt;/em&gt;&lt;/blockquote&gt;
&lt;p&gt;Otro síntoma de esto es que cuando algún compañero avisa que se va porque ha conseguido otro trabajo todo el mundo lo felicita. Sin dudas, el artículo facilitado por &lt;a href="http://www.carloszanini.com.ar/" target="_blank"&gt;Carlos Zanini&lt;/a&gt;, &amp;quot;&lt;a href="http://www.diarioti.com/gate/n.php?id=14310" target="_blank"&gt;Las empresas no están preparadas para el mercado laboral del futuro&lt;/a&gt;&amp;quot;, dice un par de grandes verdades y sugiere a las empresas &amp;quot;procurar un marco más libre para sus empleados&amp;quot; que como decia Job Steven (Apple): 
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;&amp;quot;Contrato gente inteligente para que me diga qué y cómo tengo que hacer, no para decírselos a ellos&amp;quot;&lt;/em&gt;&lt;/blockquote&gt;
&lt;p&gt;Y es sentido común no? 
&lt;p&gt;Aunque los principales factores, a mi entender, son la falta de ilusión, expectativas y mala administración que genera la inmensa mayoria de males, existen también otros factores de entre los cuales rescato al &amp;quot;contrato individual&amp;quot;. La clásica &amp;quot;¿cuales son tus pretenciones económicas?&amp;quot; o &amp;quot;la empresa tiene una oferta para hacerte..&amp;quot;. Si bien esto logra bajar el costo inicial del empleado, es como empezar con el pie izquierdo porque genera un montón de problemas. Es una especie de causa de todos los males que propicia la aparición de envidias, la existencia de vivos y tontos, injusticia por cuanto no se respeta el principio de igual paga a igual trabajo, malestar por el hecho de quien entra último entra mejor y hasta broncas al tener que capacitar a gente inexperta que ingresa con mejor salario que tu que llevas años en esa empresa. Esto también genera incomodidad a la hora de reclamar un aumento por lo que muchos prefieren escuchar otras ofertas.&lt;a&gt;&lt;/a&gt; 
&lt;p&gt;Este y otros asuntos como los premios, bonos, incentivos, presentismos y otras yerbas son producto de la conjunción de varios aspectos: 
&lt;ul&gt;
&lt;li&gt;Una concepción clasista de los puestos de trabajos aun en organizaciones colegiadas, 
&lt;li&gt;Un estilo de administración centrado exclusivamente en el costo evidente e inmediato de personal, 
&lt;li&gt;La falta de conocimientos de administración científica (basada en número de costos finales) con respecto a la rotación del personal, ¿cuanto cuesta? 
&lt;li&gt;Falta de experiencia, estudios, estilos de administración y demás conocimientos necesarios para la creación y administración de organizaciones basadas en las personas como ejes generadores de innovación y valor.&lt;/ul&gt;
&lt;p&gt;Todas los tipos de poder, poder coercitivo, de información, de premios, de relación (o amistad) y cualquier otro tipo dentro de las empresas deben dejar lugar al poder de experto y normativo. Incentivar la innovación pero de verdad, la autonomia, el trabajo en grupo pero de la boca para adentro también, la igualdad, las relaciones sin barreras horizontales ni verticales, igualmente la comunicación en todos los sentidos, en resumen seria algo así como crear un grupo sin escollos en donde la sinergia surje de manera natural y en donde la gente quiera trabajar, permanecer y sentirse orgullosa de pertenecer y de hacer para ella. 
&lt;p&gt;Lean algo de Deming por Dios!! 
&lt;p&gt;Saludos&lt;/div&gt;&lt;div&gt;&lt;table cellspacing="0" border="0"&gt;&lt;tr height="8"&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td valign="top"&gt;&lt;p&gt;&lt;a href="http://byfiles.storage.live.com&amp;#47;y1pMgMf6ioz70q1e_W6GuPsMzobesSGMRurA0Jwy8I2qvdAtYGP_XLT4A"&gt;&lt;img src="http://storage.live.com&amp;#47;items&amp;#47;375AE0CCD1AF61CE&amp;#33;374&amp;#58;thumbnail" border="0"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/td&gt;&lt;td width="15"&gt;&lt;/td&gt;&lt;td valign="top"&gt;&lt;p&gt;&lt;a href="http://byfiles.storage.live.com&amp;#47;y1pEUuDP5zYAJibLua9xg6KWZUL9VZqodkMemxzN0PTJRqTz_KtmNiJtA"&gt;&lt;img src="http://storage.live.com&amp;#47;items&amp;#47;375AE0CCD1AF61CE&amp;#33;375&amp;#58;thumbnail" border="0"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/td&gt;&lt;td width="15"&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;img src="http://c.services.spaces.live.com/CollectionWebService/c.gif?cid=3988747590285877710&amp;page=RSS%3a+%22Ven%c3%ad+que+te+queremos+mucho%22+y+el+flujo+del+personal&amp;referrer=" width="1px" height="1px" border="0" alt=""&gt;&lt;img style="position:absolute" alt="" width="0px" height="0px" src="http://c.live.com/c.gif?NC=31263&amp;amp;NA=1149&amp;amp;PI=73329&amp;amp;RF=&amp;amp;DI=3919&amp;amp;PS=85545&amp;amp;TP=lucasontivero.spaces.live.com&amp;amp;GT1=lucasontivero"&gt;</description><comments>http://lucasontivero.spaces.live.com/Blog/cns!375AE0CCD1AF61CE!373.entry#comment</comments><guid isPermaLink="true">http://lucasontivero.spaces.live.com/Blog/cns!375AE0CCD1AF61CE!373.entry</guid><pubDate>Thu, 31 May 2007 20:13:59 GMT</pubDate><slash:comments>1</slash:comments><msn:type>blogentry</msn:type><live:type>blogentry</live:type><live:typelabel>Blog entry</live:typelabel><wfw:commentRss>http://lucasontivero.spaces.live.com/blog/cns!375AE0CCD1AF61CE!373/comments/feed.rss</wfw:commentRss><wfw:comment>http://lucasontivero.spaces.live.com/Blog/cns!375AE0CCD1AF61CE!373.entry#comment</wfw:comment><dcterms:modified>2007-05-31T20:36:16Z</dcterms:modified></item><item><title>Los informáticos también somos blancos de prejuicios (parte I)</title><link>http://lucasontivero.spaces.live.com/Blog/cns!375AE0CCD1AF61CE!363.entry</link><description>&lt;p&gt;&lt;a href="http://byfiles.storage.msn.com/y1pxChyvkZ21WvFvxKBLyluhKUApOZ4bsuBoa3qLS3jTBS7mnPoaNqSxBlF71OQU7lX"&gt;&lt;img style="border-right:0px;border-top:0px;border-left:0px;border-bottom:0px" height=120 src="http://byfiles.storage.msn.com/y1pxChyvkZ21WvAY-nGY0aSLnb2GIl2BPHzBkQq2FwwH8Sjx8oezFG6wc_jJcO3hVUn" width=110 align=left border=0&gt;&lt;/a&gt; Hace algunos meses cenaba en casa con un geólogo, su mujer e hijo, mi novia y una pareja de amigos de ella, en un momento comenzamos a hablar de mi profesión por algunas preguntas y comentarios que se estaban haciendo y así que despues de explicar mas o menos los pasos gene