<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://geeks.ms/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd"><channel><title>Lucas Ontivero</title><link>http://geeks.ms/blogs/lontivero/default.aspx</link><description>Sigo pensando todo de nuevo mil veces y todavia encuentro mejores maneras de hacer lo mismo.
Creo que ya tenemos todas las soluciones al igual que lo creia 8 años atras.</description><dc:language /><generator>CommunityServer 2008.5 SP1 (Build: 31106.3070)</generator><itunes:summary>Sigo pensando todo de nuevo mil veces y todavia encuentro mejores maneras de hacer lo mismo. Creo que ya tenemos todas las soluciones al igual que lo creia 8 años atras.</itunes:summary><itunes:explicit>no</itunes:explicit><language /><item><title>Bitcoin-hoy.com - Calcular el Precio del Bitcoin en argentina</title><link>http://geeks.ms/blogs/lontivero/archive/2013/05/13/bitcoin-hoy-com-calcular-el-precio-del-bitcoin-en-argentina.aspx</link><pubDate>Mon, 13 May 2013 03:23:00 GMT</pubDate><guid isPermaLink="false">2a2e7ade-7474-448b-9de5-1515d8bb7d1b:209459</guid><dc:creator>Lucas Ontivero</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://geeks.ms/blogs/lontivero/rsscomments.aspx?PostID=209459</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://geeks.ms/blogs/lontivero/commentapi.aspx?PostID=209459</wfw:comment><comments>http://geeks.ms/blogs/lontivero/archive/2013/05/13/bitcoin-hoy-com-calcular-el-precio-del-bitcoin-en-argentina.aspx#comments</comments><description>&lt;p&gt;Para todos aquellos que necesitan calcular constantemente para convertir Bitcoins –&amp;gt; Dolar Blue (y Oficial) –&amp;gt; Pesos Argentinos y viceversa, he puesto a disposición una calculadora online (está en alpha, o menos que eso… pero antes no hay nada…ummm). Espero que sea de utilidad, pronto estaré poniendo más servicios relacionados a esta cryptomoneda en el mismo dominio.   &lt;br /&gt;&lt;/p&gt;  &lt;p&gt;Visiten:   &lt;br /&gt;&lt;a href="http://bitcoin-hoy.com/"&gt;http://bitcoin-hoy.com/&lt;/a&gt;    &lt;br /&gt;&lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;    &lt;div id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:9cc32238-c417-4d33-a157-f8e5201e13d7" class="wlWriterEditableSmartContent" style="float:none;padding-bottom:0px;padding-top:0px;padding-left:0px;margin:0px;display:inline;padding-right:0px;"&gt;del.icio.us Tags: &lt;a href="http://del.icio.us/popular/bitcoin" rel="tag"&gt;bitcoin&lt;/a&gt;,&lt;a href="http://del.icio.us/popular/argentina" rel="tag"&gt;argentina&lt;/a&gt;,&lt;a href="http://del.icio.us/popular/dolar" rel="tag"&gt;dolar&lt;/a&gt;,&lt;a href="http://del.icio.us/popular/dolar+blue" rel="tag"&gt;dolar blue&lt;/a&gt;,&lt;a href="http://del.icio.us/popular/dolar+oficial" rel="tag"&gt;dolar oficial&lt;/a&gt;,&lt;a href="http://del.icio.us/popular/calculadora" rel="tag"&gt;calculadora&lt;/a&gt;,&lt;a href="http://del.icio.us/popular/bitcoin-hoy" rel="tag"&gt;bitcoin-hoy&lt;/a&gt;,&lt;a href="http://del.icio.us/popular/precio" rel="tag"&gt;precio&lt;/a&gt;&lt;/div&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://geeks.ms/aggbug.aspx?PostID=209459" width="1" height="1"&gt;</description><category domain="http://geeks.ms/blogs/lontivero/archive/tags/Misc/default.aspx">Misc</category></item><item><title>Deberían los testers arreglar bugs–Parte I</title><link>http://geeks.ms/blogs/lontivero/archive/2012/11/15/deber-237-an-los-testers-arreglar-bugs-parte-i.aspx</link><pubDate>Thu, 15 Nov 2012 03:23:00 GMT</pubDate><guid isPermaLink="false">2a2e7ade-7474-448b-9de5-1515d8bb7d1b:207429</guid><dc:creator>Lucas Ontivero</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://geeks.ms/blogs/lontivero/rsscomments.aspx?PostID=207429</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://geeks.ms/blogs/lontivero/commentapi.aspx?PostID=207429</wfw:comment><comments>http://geeks.ms/blogs/lontivero/archive/2012/11/15/deber-237-an-los-testers-arreglar-bugs-parte-i.aspx#comments</comments><description>&lt;p&gt;Esa es &lt;a href="http://sqa.stackexchange.com/questions/5194/should-tester-fix-bugs" target="_blank"&gt;la pregunta&lt;/a&gt; que lanzé en el sitio &lt;a href="http://sqa.stackexchange.com/" target="_blank"&gt;Software Quality Assurance and Testing&lt;/a&gt; de StackExchange.com en cuyas respuestas pude ver que existe cierto desacuerdo entre la comunidad de testers sobre ese tema y si bien yo tengo una idea clara al respecto, lo que en verdad quería conocer eran las argumentaciones de aquellos que piensan que sí deberían arreglar defectos (algunos defectos) y aquellos que piensan que no deberían para así hacer una síntesis. &lt;/p&gt;  &lt;p&gt;No obstante, al poco tiempo otro usuario inicia otro hilo en el que pregunta &lt;a href="http://sqa.stackexchange.com/questions/5097/what-are-the-main-role-and-responsibilities-of-a-tester" target="_blank"&gt;cuales son las principales responsabilidades de un tester&lt;/a&gt; en las que expone una pequeña lista de responsabilidades: &lt;/p&gt;  &lt;pre&gt;&lt;code&gt;1) Analyzing the Requirements from the client
2) Participating in preparing Test Plans
3) Preparing Test Scenarios,test cases
4) Defect Tracking
5) Preparing Suggestion Documents to improve the quality of the application
6) Communication with the Test Lead / Test Manager
7) Conducting Review Meetings within the Team&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Hay tantas cosas con las que no estoy de acuerdo con lo que leo en ese foro que voy a dejar plasmado aquí mi pensamiento. Para comenzar tengo que decir que para mi, la responsabilidad de todos los miembros de un equipo es exactamente la misma: contribuir tanto como sea posible al éxito del proyecto. Entonces, si bien las actividades, especialidades y orientaciones pueden ser distintas, la responsabilidad es la misma.&lt;/p&gt;

&lt;p&gt;Ahora bien, si aceptamos esto como válido deberíamos entonces definir qué es un proyecto exitoso y qué no lo es. Para todos aquellos medio entrado en años (de profesión) como yo de seguro les sonará el cuentito llamado OTOBOS que dice que un proyecto exitoso es un proyecto “on time, on budget, on scope” y la verdad es que en los tiempos del los modelos predictivos, en los que el SDLC era por lo general en cascada, mantener al proyecto a lo largo del tiempo on time, on budget y on scope era cosa de magos, se creía que la clave estaba en el *control*. Pues bien, puede que me equivoque pero voy a darles *mi* definición de lo que es un proyecto exitoso: &lt;/p&gt;

&lt;blockquote&gt;
  &lt;p align="center"&gt;&lt;em&gt;&lt;font color="#cccccc" size="4"&gt;“Un proyecto exitoso es aquel que nos otorga un alto retorno sobre la inversión a la vez que nos permite crear una relación de confianza con el cliente”&lt;/font&gt;&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p align="center"&gt;&lt;em&gt;&lt;font size="4"&gt;&lt;/font&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;La segunda parte de esta definición habla de la satisfacción del cliente, y puesto que lo que este recibe no es otra cosa que software, deberíamos aclarar qué es un software exitoso para el cliente. Veamos, nuestros clientes no nos encargan el desarrollo de una solución porque no se les ocurran mejores cosas en que despilfarrar el dinero, sino que lo invierten en una herramienta que les permita cumplir con sus metas de negocio. Ya sea optimizando o agilizando la gestión de la compañia, diferenciandose de la competencia, fidelizando clientes, brindando nuevos servicios online o alguna otra ventaja, las empresas *invierten* en software y esperan un retorno de esa inversión. Entonces:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p align="center"&gt;&lt;font color="#cccccc" size="4"&gt;&lt;em&gt;“Un software exitoso (para el cliente) es aquel que le permite cumplir con sus metas de negocios y por tal, le otorga el esperado retorno sobre la inversión” &lt;/em&gt;&lt;/font&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Y es que de eso se trata y siempre se ha tratado, de dinero. Por lo tanto, la responsabilidad de *todos los miembros del equipo* (sí, testers incluidos) es contribuir a este éxito. Y para esto hace falta mucho más que control y responsabilidades estrictas y predeterminadas.&lt;/p&gt;

&lt;p&gt;Continuará…&lt;/p&gt;

&lt;div style="padding-bottom:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;float:none;padding-top:0px;" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:a842d013-bfb5-4c47-bb5b-12f95046a2ac" class="wlWriterEditableSmartContent"&gt;del.icio.us Tags: &lt;a href="http://del.icio.us/popular/software+testing" rel="tag"&gt;software testing&lt;/a&gt;,&lt;a href="http://del.icio.us/popular/bug+fixing" rel="tag"&gt;bug fixing&lt;/a&gt;,&lt;a href="http://del.icio.us/popular/testers+roles" rel="tag"&gt;testers roles&lt;/a&gt;&lt;/div&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://geeks.ms/aggbug.aspx?PostID=207429" width="1" height="1"&gt;</description><category domain="http://geeks.ms/blogs/lontivero/archive/tags/Project+Management/default.aspx">Project Management</category><category domain="http://geeks.ms/blogs/lontivero/archive/tags/Gesti_26002300_243_3B00_n+de+proyectos/default.aspx">Gesti&amp;#243;n de proyectos</category><category domain="http://geeks.ms/blogs/lontivero/archive/tags/Desarrollo/default.aspx">Desarrollo</category><category domain="http://geeks.ms/blogs/lontivero/archive/tags/Conceptos/default.aspx">Conceptos</category><category domain="http://geeks.ms/blogs/lontivero/archive/tags/Productividad/default.aspx">Productividad</category><category domain="http://geeks.ms/blogs/lontivero/archive/tags/Testing/default.aspx">Testing</category></item><item><title>Lo que espero de un buen desarrollador</title><link>http://geeks.ms/blogs/lontivero/archive/2012/11/13/lo-que-espero-de-un-buen-desarrollador.aspx</link><pubDate>Tue, 13 Nov 2012 04:15:00 GMT</pubDate><guid isPermaLink="false">2a2e7ade-7474-448b-9de5-1515d8bb7d1b:207397</guid><dc:creator>Lucas Ontivero</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://geeks.ms/blogs/lontivero/rsscomments.aspx?PostID=207397</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://geeks.ms/blogs/lontivero/commentapi.aspx?PostID=207397</wfw:comment><comments>http://geeks.ms/blogs/lontivero/archive/2012/11/13/lo-que-espero-de-un-buen-desarrollador.aspx#comments</comments><description>&lt;p&gt;El buen desarrollador, además de poseer conocimientos y experiencia superiores debe estar infectado por una pasión altamente contagiosa, de esa manera, tarde o temprano el equipo completo se verá contagiado en mayor o menor medida. Esto no es tan inusual, muchas veces nos encontramos con personas que se convierten en referentes no solo de sus equipos sino que también de otros equipos de la misma empresa y todos se benefician de sus conocimientos y su dedicación, especialmente la de enseñar, compartir conocimientos y experiencias… esas cosas que no se encuentran en los libros.&lt;/p&gt;  &lt;p&gt;La mayor contribución de estos desarrolladores no suele plasmarse tanto en su código sino en la capacidad de hacer de otros, mejores desarrolladores. Y es que como la experiencia no se adquiere de los libros sino de los errores (no solo propios), es este tipo de desarrolladores el que puede salvar a los menos experimentados de cometerlos. Por último, y para ampliar el punto anterior, otra cualidad necesaria para lograr esto es el conocimiento profundo de la história del software, sus personalidades, sus aportes, sus pensamientos, sus aciertos y errores.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://geeks.ms/aggbug.aspx?PostID=207397" width="1" height="1"&gt;</description><category domain="http://geeks.ms/blogs/lontivero/archive/tags/Misc/default.aspx">Misc</category><category domain="http://geeks.ms/blogs/lontivero/archive/tags/Desarrollo/default.aspx">Desarrollo</category></item><item><title>Cómo fallar en el desarrollo – distinguiendo lo importante de lo accesorio</title><link>http://geeks.ms/blogs/lontivero/archive/2012/11/04/c-243-mo-fallar-en-el-desarrollo-distinguiendo-lo-importante-de-lo-accesorio.aspx</link><pubDate>Sun, 04 Nov 2012 03:38:00 GMT</pubDate><guid isPermaLink="false">2a2e7ade-7474-448b-9de5-1515d8bb7d1b:207314</guid><dc:creator>Lucas Ontivero</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://geeks.ms/blogs/lontivero/rsscomments.aspx?PostID=207314</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://geeks.ms/blogs/lontivero/commentapi.aspx?PostID=207314</wfw:comment><comments>http://geeks.ms/blogs/lontivero/archive/2012/11/04/c-243-mo-fallar-en-el-desarrollo-distinguiendo-lo-importante-de-lo-accesorio.aspx#comments</comments><description> &lt;a href="http://martinfowler.com" target="_blank"&gt;Martin Fowler&lt;/a&gt;&lt;/a&gt; escribió un interesante artículo llamado &lt;a href="http://martinfowler.com/bliki/TransMediaApplication.html" target="_blank"&gt;TransMediaApplication&lt;/a&gt; en el cual explica un problema común que se presenta a la hora de desarrollar aplicaciones para distintos dispositivo. Creo que esta frase resume todo el artículo: &lt;i&gt;A common mistake is to think of different apps for different delivery devices.&lt;/i&gt;    &lt;p&gt;En mi experiencia este escenario no se presenta solo cuando se trata de aplicaciones que corren en distintos dispositivos sino que se presenta con mucha mayor frecuencia de lo que se cree. El caso es que lo que &lt;a href="http://martinfowler.com" target="_blank"&gt;Martin Fowler&lt;/a&gt; describe es un caso muy particular de un problema mayor: no comprender de que se trata en parte la arquitectura.&lt;/p&gt;  &lt;p&gt;Lo voy a explicar con un ejemplo. Imaginemos que una empresa de transporte de carga nos pide desarrollar un sistema de seguimiento de sus vehículos. Estos vehículos tienen rutas específicas por las que deben transitar y tienen además una velocidad máxima autorizada. Nuestro cliente quiere conocer la ubicación de cada uno de sus camiones y sus velocidades (entre otras miles de cosas) prácticamente en tiempo real o con una demora no mayor a 1 minuto. &lt;/p&gt;  &lt;p&gt;Para esto, cada vehículo tiene incorporado algún tipo de dispositivo móvil con GPS (o alguna variante). Nuestro cliente quiere visualizar la posición de sus vehículos en un mapa (en principio, mapas de google) y quiere poder hacerlo desde su dispositivo móvil.&lt;/p&gt;  &lt;p&gt;Ahora bien, si quien lee esto fuese el responsable del desarrollo de este sistema… ¿por donde comenzaría?. Muchas personas comienzan por interiorizarse sobre los distintos modelos de dispositivos móviles incorporados a los vehículos, comienzan a interiorizarse por los diferentes sistemas de coordenadas que manejan, por los distintos mecanismos de despacho de esas coordenadas, esto es, si tienen conexión a internet continua, si soportan mensajes SMS, si http, tcp o udp, por los servicios que soportan en cada uno de sus puertos, etc. Luego, continúan por estudiar las apis de google maps, los lenguajes en los que esas apis están disponibles y demás consideraciones sobre cómo trabajar con esos mapas. Por último posiblemente, querrán conocer desde que tipo de dispositivo móvil es que el cliente quiere poder consultar la información. &lt;/p&gt;  &lt;p&gt;Todo lo anterior está mal! No quiero decir que no deba hacerse ya que tarde o temprano conocer estas cosas será muy necesario, pero está mal porque denota una falta de análisis reflexivo sobre qué es lo que se debe desarrollar y sobre qué es lo que el cliente (negocio) necesita. Veamos, en la descripción del problema existen varios elementos que debemos notar y sobre los que tenemos que reflexionar, estos son: seguimiento, rutas, posición, velocidad, vehículo, dispositivo móvil, GPS y mapa. Existen otros elementos mencionados directa o indirectamente, pero quiero focalizarme solo estos. &lt;/p&gt;  &lt;p&gt;A estos elementos debemos agruparlos en dos categorías: esenciales y accidentales. Así, posición, ruta, velocidad y seguimiento son esenciales mientras que dispositivo móvil, GPS y mapa son accidentales. Vehículo, por su parte, es un sinsentido. Si bien por alguna razón, las descripciones de los problemas que nos proveen los clientes suelen abundar en elementos accidentales, es nuestra responsabilidad el identificarlos y catalogarlos como tales en primera instancia. &lt;/p&gt;  &lt;p&gt;El sistema a desarrollar debe, en principio, ser totalmente independiente de consideraciones superfluas como el protocolo de comunicación por medio del cual recibirá la posición de los vehículos. Si lo hace mediante TCP, UDP, por mensajes SMS o por correo twitter no es relevante en principio. Tampoco lo es la manera en que la información será presentada, ni si los clientes corren en dispositivos móviles o en PCs de escritorio, sobre un web browser o una aplicación nativa. Todas estas cosas deberán abordarse en su momento pero es importante comprender que se debe esperar a que llegue ese momento.&lt;/p&gt;  &lt;p&gt;¿Y mientras tanto qué? Bueno, mientras no llegue el momento de encarar los detalles debemos centrarnos en resolver el problema esencial: desarrollar el sistema de seguimiento. Esto es lo primero! &lt;/p&gt;  &lt;p&gt;En el software como en la vida, no distinguir lo importante de lo accesorio es el camino seguro al fracaso.&lt;/p&gt;  &lt;div style="padding-bottom:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;float:none;padding-top:0px;" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:42e71fa7-62f5-445e-a1dc-832222a9323d" class="wlWriterEditableSmartContent"&gt;del.icio.us Tags: &lt;a href="http://del.icio.us/popular/software" rel="tag"&gt;software&lt;/a&gt;,&lt;a href="http://del.icio.us/popular/arquitectura" rel="tag"&gt;arquitectura&lt;/a&gt;,&lt;a href="http://del.icio.us/popular/desarrollo" rel="tag"&gt;desarrollo&lt;/a&gt;,&lt;a href="http://del.icio.us/popular/dise%c3%b1o" rel="tag"&gt;dise&amp;#241;o&lt;/a&gt;&lt;/div&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://geeks.ms/aggbug.aspx?PostID=207314" width="1" height="1"&gt;</description><category domain="http://geeks.ms/blogs/lontivero/archive/tags/Arquitectura/default.aspx">Arquitectura</category><category domain="http://geeks.ms/blogs/lontivero/archive/tags/Dise_26002300_241_3B00_o/default.aspx">Dise&amp;#241;o</category><category domain="http://geeks.ms/blogs/lontivero/archive/tags/Desarrollo/default.aspx">Desarrollo</category><category domain="http://geeks.ms/blogs/lontivero/archive/tags/Conceptos/default.aspx">Conceptos</category></item><item><title>Design patterns in the test of time: VISITOR</title><link>http://geeks.ms/blogs/lontivero/archive/2012/10/30/design-patterns-in-the-test-of-time-visitor.aspx</link><pubDate>Tue, 30 Oct 2012 04:46:00 GMT</pubDate><guid isPermaLink="false">2a2e7ade-7474-448b-9de5-1515d8bb7d1b:207265</guid><dc:creator>Lucas Ontivero</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://geeks.ms/blogs/lontivero/rsscomments.aspx?PostID=207265</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://geeks.ms/blogs/lontivero/commentapi.aspx?PostID=207265</wfw:comment><comments>http://geeks.ms/blogs/lontivero/archive/2012/10/30/design-patterns-in-the-test-of-time-visitor.aspx#comments</comments><description>&lt;p&gt;&lt;a href="http://ayende.com/blog/" target="_blank"&gt;@Ayende&lt;/a&gt; ha comenzado una &lt;a href="http://ayende.com/blog/tags/design-patterns-test-of-time" target="_blank"&gt;serie de post en lo que revisa algunos patrones de diseño&lt;/a&gt; (Go4) luego de transcurridos más de 18 años desde su formalización en el libro &lt;a href="http://www.amazon.com/Design-Patterns-Elements-Reusable-Object-Oriented/dp/0201633612" target="_blank"&gt;Design Patterns: Elements of Reusable Object-Oriented Software&lt;/a&gt;.&amp;#160; Inspirado por esa serie, y por el hecho de que en mi última entrevista laboral me preguntaron sobre esto,&amp;#160; voy a presentar una revisión sobre el patrón visitor.&lt;/p&gt;  &lt;h1&gt;&amp;#160;&lt;/h1&gt;  &lt;h1&gt;Visitor en su forma clásica&lt;/h1&gt;  &lt;p&gt;La motivación detrás de este patrón es poder añadir funcionalidad a una estructura de datos sin necesidad de modificar las clases que conforman esa estructura. En otras palabras: separar las estructuras de datos de aquellos algoritmos que operan sobre ellas. Si vamos a la Wikipedia vamos a ver este diagrama:&lt;/p&gt;  &lt;p&gt;&lt;img src="http://upload.wikimedia.org/wikipedia/commons/5/59/VisitorPatternUML.png" width="640" height="366" alt="" /&gt;    &lt;div style="padding-bottom:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;float:none;padding-top:0px;" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:cffd77cf-ec12-4d23-9593-d382195dca33" class="wlWriterEditableSmartContent"&gt;Technorati Tags: &lt;a href="http://technorati.com/tags/Design" rel="tag"&gt;Design&lt;/a&gt;,&lt;a href="http://technorati.com/tags/Pattern" rel="tag"&gt;Pattern&lt;/a&gt;,&lt;a href="http://technorati.com/tags/Visitor" rel="tag"&gt;Visitor&lt;/a&gt;&lt;/div&gt; &lt;/p&gt;  &lt;p&gt;Como se ve, tiene referencias cíclicas, es decir, todos los CarElements deben implementar un método accept que recibe una referencia a un CarElementVisitor y todo CarElementVisitor matiene referencias a todos los tipos que implementan la interface CarElement. Esto es porque C# (el diagrama usa java) no posibilida doble dispatch y así, mediante estas referencias cíclicas es cómo se logra simularla.&lt;/p&gt;  &lt;p&gt;Aparte del fuertísimo acoplamiento al que nos fuerza, tiene el inconveniente de ser un patrón que agrega bastante complejidad y que es poco legible debido a su “extraña” sintaxis. Así, si tuviésemos un AST y quisiésemos volverlo código mediante un visitor, nuestro código se vería así:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lontivero/image_5F00_1506DE1F.png"&gt;&lt;img style="background-image:none;border-right-width:0px;padding-left:0px;padding-right:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;padding-top:0px;" title="image" border="0" alt="image" src="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lontivero/image_5F00_thumb_5F00_10CCE08D.png" width="401" height="31" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Pero si tratamos de seguir este código, y vamos directamente a la implementación de este método ‘Accept’ nos encontraremos con esto:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lontivero/image_5F00_16A78426.png"&gt;&lt;img style="background-image:none;border-right-width:0px;padding-left:0px;padding-right:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;padding-top:0px;" title="image" border="0" alt="image" src="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lontivero/image_5F00_thumb_5F00_7B8EB517.png" width="401" height="74" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Y por último, si nos salteamos la abstracción IVisitor y vamos directamente a la implementación del método Visit del PrinterVisitor, nos encontramos con esto otro:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lontivero/image_5F00_0573A683.png"&gt;&lt;img style="background-image:none;border-right-width:0px;padding-left:0px;padding-right:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;padding-top:0px;" title="image" border="0" alt="image" src="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lontivero/image_5F00_thumb_5F00_2AFD23E4.png" width="401" height="104" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Si no conoces el patrón, posiblemente no comprendas este código (y tengamos en cuenta que nos hemos salteado las abstracciones!). Pero el motivo más frecuente por el que no se entiende, si es ese el caso, es porque es complejo.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h1&gt;Visitor alternativo&lt;/h1&gt;  &lt;p&gt;La propuesta que dejo no es mia, ni es nueva. Esta es una implementación muy popular en lenguajes dinámicos.&lt;/p&gt;  &lt;p&gt;Partamos del mismo supuesto: tenemos un AST al que queremos transformar en un string. Lo primero que podemos cambiar es la sintaxis confuza del visitor clásico mediante el uso de un Extension Method, como sigue:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lontivero/image_5F00_4F420866.png"&gt;&lt;img style="background-image:none;border-right-width:0px;padding-left:0px;padding-right:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;padding-top:0px;" title="image" border="0" alt="image" src="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lontivero/image_5F00_thumb_5F00_161B0597.png" width="401" height="194" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Ahora veamos cómo se ven los nodos de este árbol:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lontivero/image_5F00_451D416E.png"&gt;&lt;img style="background-image:none;border-right-width:0px;padding-left:0px;padding-right:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;padding-top:0px;" title="image" border="0" alt="image" src="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lontivero/image_5F00_thumb_5F00_5755E263.png" width="401" height="278" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Si bien aquí tenemos una interface INode la cual no luce muy bien, la simplicidad de los nodos es evidente ya que no estamos forzando a implementar ningún método extraño, me refiero al método ‘Accept’. Peo vamos a ver la implementación:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lontivero/image_5F00_680D6744.png"&gt;&lt;img style="background-image:none;border-right-width:0px;padding-left:0px;padding-right:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;padding-top:0px;" title="image" border="0" alt="image" src="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lontivero/image_5F00_thumb_5F00_75AFFD7F.png" width="583" height="532" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Esta implementación es mucho menos compleja y legible, además de reducir notablemente el acoplamiento (los nodos no necesitan conocer al IVisitor ni implementar ningún método extra) lo que posibilita eliminar las referencias cíclicas. &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Lucas Ontivero&lt;/strong&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://geeks.ms/aggbug.aspx?PostID=207265" width="1" height="1"&gt;</description><category domain="http://geeks.ms/blogs/lontivero/archive/tags/Patterns/default.aspx">Patterns</category><category domain="http://geeks.ms/blogs/lontivero/archive/tags/Arquitectura/default.aspx">Arquitectura</category><category domain="http://geeks.ms/blogs/lontivero/archive/tags/Dise_26002300_241_3B00_o/default.aspx">Dise&amp;#241;o</category><category domain="http://geeks.ms/blogs/lontivero/archive/tags/.Net/default.aspx">.Net</category><category domain="http://geeks.ms/blogs/lontivero/archive/tags/Languages/default.aspx">Languages</category><category domain="http://geeks.ms/blogs/lontivero/archive/tags/Patrones/default.aspx">Patrones</category><category domain="http://geeks.ms/blogs/lontivero/archive/tags/Desarrollo/default.aspx">Desarrollo</category><category domain="http://geeks.ms/blogs/lontivero/archive/tags/Conceptos/default.aspx">Conceptos</category><category domain="http://geeks.ms/blogs/lontivero/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://geeks.ms/blogs/lontivero/archive/tags/Clean+Code/default.aspx">Clean Code</category></item><item><title>Creando la Matrix</title><link>http://geeks.ms/blogs/lontivero/archive/2012/06/01/creando-la-matrix.aspx</link><pubDate>Fri, 01 Jun 2012 16:35:55 GMT</pubDate><guid isPermaLink="false">2a2e7ade-7474-448b-9de5-1515d8bb7d1b:205354</guid><dc:creator>Lucas Ontivero</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://geeks.ms/blogs/lontivero/rsscomments.aspx?PostID=205354</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://geeks.ms/blogs/lontivero/commentapi.aspx?PostID=205354</wfw:comment><comments>http://geeks.ms/blogs/lontivero/archive/2012/06/01/creando-la-matrix.aspx#comments</comments><description>&lt;p&gt;Tengo que bloguear esto porque es muy gracioso! Es una conversación con el cliente que estoy teniendo en este momento.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lontivero/image_5F00_7EA71C64.png"&gt;&lt;img style="background-image:none;border-bottom:0px;border-left:0px;padding-left:0px;padding-right:0px;display:inline;border-top:0px;border-right:0px;padding-top:0px;" title="image" border="0" alt="image" src="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lontivero/image_5F00_thumb_5F00_5D4776C8.png" width="594" height="109" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Será que el agente Smith realmente nos está infectando el sistema?&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://geeks.ms/aggbug.aspx?PostID=205354" width="1" height="1"&gt;</description><category domain="http://geeks.ms/blogs/lontivero/archive/tags/Misc/default.aspx">Misc</category><category domain="http://geeks.ms/blogs/lontivero/archive/tags/Humor/default.aspx">Humor</category></item><item><title>C# Closures y tipos anónimos a la Javascript</title><link>http://geeks.ms/blogs/lontivero/archive/2012/05/24/c-closures-y-tipos-an-243-nimos-a-la-javascript.aspx</link><pubDate>Thu, 24 May 2012 05:13:28 GMT</pubDate><guid isPermaLink="false">2a2e7ade-7474-448b-9de5-1515d8bb7d1b:205199</guid><dc:creator>Lucas Ontivero</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://geeks.ms/blogs/lontivero/rsscomments.aspx?PostID=205199</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://geeks.ms/blogs/lontivero/commentapi.aspx?PostID=205199</wfw:comment><comments>http://geeks.ms/blogs/lontivero/archive/2012/05/24/c-closures-y-tipos-an-243-nimos-a-la-javascript.aspx#comments</comments><description>&lt;p&gt;Es C# realmente dinámico? Si hace Cuac es un pato, si hace lo mismo que un lenguaje dinámico es dinámico. Qué te dice este código:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lontivero/image_5F00_605E376E.png"&gt;&lt;img style="background-image:none;border-bottom:0px;border-left:0px;padding-left:0px;padding-right:0px;display:inline;border-top:0px;border-right:0px;padding-top:0px;" title="image" border="0" alt="image" src="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lontivero/image_5F00_thumb_5F00_57418620.png" width="586" height="590" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://geeks.ms/aggbug.aspx?PostID=205199" width="1" height="1"&gt;</description><category domain="http://geeks.ms/blogs/lontivero/archive/tags/Patterns/default.aspx">Patterns</category><category domain="http://geeks.ms/blogs/lontivero/archive/tags/Dise_26002300_241_3B00_o/default.aspx">Dise&amp;#241;o</category><category domain="http://geeks.ms/blogs/lontivero/archive/tags/Languages/default.aspx">Languages</category><category domain="http://geeks.ms/blogs/lontivero/archive/tags/Patrones/default.aspx">Patrones</category><category domain="http://geeks.ms/blogs/lontivero/archive/tags/Desarrollo/default.aspx">Desarrollo</category><category domain="http://geeks.ms/blogs/lontivero/archive/tags/Conceptos/default.aspx">Conceptos</category><category domain="http://geeks.ms/blogs/lontivero/archive/tags/C_2300_/default.aspx">C#</category></item><item><title>Nivelando para abajo</title><link>http://geeks.ms/blogs/lontivero/archive/2012/05/24/nivelando-para-abajo.aspx</link><pubDate>Thu, 24 May 2012 03:44:00 GMT</pubDate><guid isPermaLink="false">2a2e7ade-7474-448b-9de5-1515d8bb7d1b:205197</guid><dc:creator>Lucas Ontivero</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://geeks.ms/blogs/lontivero/rsscomments.aspx?PostID=205197</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://geeks.ms/blogs/lontivero/commentapi.aspx?PostID=205197</wfw:comment><comments>http://geeks.ms/blogs/lontivero/archive/2012/05/24/nivelando-para-abajo.aspx#comments</comments><description>&lt;p&gt;Leía &lt;a href="http://geeks.ms/blogs/lruiz/archive/2012/05/22/pregunta-191-cu-225-l-es-la-salida-de-este-programa.aspx"&gt;este post de Luis Ruiz Pavon&lt;/a&gt; acerca del comportamiento de los closures en el que Luis anima a responder cual es la salida de un bloque de código en el que se devuelve un array de expresiones lambdas que referencian a la variable utilizada para iterar dicho array (closures) y entonces veo este comentario de &lt;a href="http://geeks.ms/user/Profile.aspx?UserID=5172"&gt;Eduard Tomàs i Avellana&lt;/a&gt;:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lontivero/image_5F00_31F5FFF4.png"&gt;&lt;img style="background-image:none;border-right-width:0px;padding-left:0px;padding-right:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;padding-top:0px;" title="image" border="0" alt="image" src="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lontivero/image_5F00_thumb_5F00_5E5EE440.png" width="640" height="123" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;El link al que referencia Eduard pertenece al blog de Eric Lippert: &lt;a href="http://blogs.msdn.com/b/ericlippert/archive/2009/11/12/closing-over-the-loop-variable-considered-harmful.aspx"&gt;Closing over the loop variable considered harmful&lt;/a&gt;, una vieja entrada que había leído en su oportunidad pero que desestimé porque nunca pensé que llegara a tomarse la decisión de introducir un breaking change en el lenguaje para solucionar algo que &lt;strong&gt;NO ESTÁ ROTO&lt;/strong&gt;, repito,&lt;strong&gt; NO ESTÁ ROTO&lt;/strong&gt;.&lt;/p&gt;  &lt;p&gt;Está claro que introducir este tipo de cambios no le gusta a nadie, y que por lo tanto debe de haberse meditado, y mucho. Pero ¿qué es lo que anima semejante cosa? Es decir, si vamos a romperle el código a muchos programadores es porque pensamos que es lo mejor para todos, ¿o no?&lt;/p&gt;  &lt;p&gt;Veamos, ¿quiénes pueden verse afectados? de seguro todos aquellos que entiendan lo que son los closures y comprendan el scope de las variables y, ¿quienes pueden verse beneficiados? pues todos aquellos que no entienden esto. Y es por eso que estoy en desacuerdo, porque lo que se intenta una vez más es hacer que el lenguaje sea el guardián de la correctitud del software y no el desarrollado.&lt;/p&gt;  &lt;p&gt;En mi experiencia, &lt;strong&gt;es absolutamente imposible defenderse de un desarrollador que no sabe lo que hace&lt;/strong&gt;. &lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://geeks.ms/aggbug.aspx?PostID=205197" width="1" height="1"&gt;</description><category domain="http://geeks.ms/blogs/lontivero/archive/tags/Desarrollo/default.aspx">Desarrollo</category><category domain="http://geeks.ms/blogs/lontivero/archive/tags/Conceptos/default.aspx">Conceptos</category><category domain="http://geeks.ms/blogs/lontivero/archive/tags/C_2300_/default.aspx">C#</category></item><item><title>ECMA Harmony y la conquista del mundo</title><link>http://geeks.ms/blogs/lontivero/archive/2012/05/12/ecma-harmony-y-la-conquista-del-mundo.aspx</link><pubDate>Sun, 13 May 2012 00:13:45 GMT</pubDate><guid isPermaLink="false">2a2e7ade-7474-448b-9de5-1515d8bb7d1b:204991</guid><dc:creator>Lucas Ontivero</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://geeks.ms/blogs/lontivero/rsscomments.aspx?PostID=204991</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://geeks.ms/blogs/lontivero/commentapi.aspx?PostID=204991</wfw:comment><comments>http://geeks.ms/blogs/lontivero/archive/2012/05/12/ecma-harmony-y-la-conquista-del-mundo.aspx#comments</comments><description>&lt;p&gt;Dicen que existe un plan para que javascript domine el mundo en los próximos años, y a decir verdad, y viendo las propuestas que se plasman en el draf del ECMA-262 sexta edición, creo que el plan aunque algo silencioso sigue a marcha firme.&lt;/p&gt;  &lt;p&gt;Quiero mostrar aquellas propuestas que a mi me resultan más interesantes:&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Strings&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Lo bueno: se agregan métodos startsWith(), endsWith(), contains(), repeat(), toArray()&lt;/p&gt;  &lt;p&gt;Lo malo: la interpolación de strings no forma parte del draft actual, esta feature permitiría crear string de manera más natural, como por ejemplo:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lontivero/image_5F00_0CEAA143.png"&gt;&lt;img style="background-image:none;border-bottom:0px;border-left:0px;padding-left:0px;padding-right:0px;display:inline;border-top:0px;border-right:0px;padding-top:0px;" title="image" border="0" alt="image" src="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lontivero/image_5F00_thumb_5F00_41C780B3.png" width="540" height="66" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;en lugar de usar las formas actuales:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lontivero/image_5F00_6B5B4BE6.png"&gt;&lt;img style="background-image:none;border-bottom:0px;border-left:0px;padding-left:0px;padding-right:0px;display:inline;border-top:0px;border-right:0px;padding-top:0px;" title="image" border="0" alt="image" src="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lontivero/image_5F00_thumb_5F00_3ED21C00.png" width="640" height="38" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Destructuring&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Esta es una de mis preferidas y permitiría entre otras cosas que una función retorne más de un resultado:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lontivero/image_5F00_4F6A16EE.png"&gt;&lt;img style="background-image:none;border-bottom:0px;border-left:0px;padding-left:0px;padding-right:0px;display:inline;border-top:0px;border-right:0px;padding-top:0px;" title="image" border="0" alt="image" src="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lontivero/image_5F00_thumb_5F00_74F3944F.png" width="559" height="52" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Iterar las propiedades de los objetos de manera más natural:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lontivero/image_5F00_0181416C.png"&gt;&lt;img style="background-image:none;border-bottom:0px;border-left:0px;padding-left:0px;padding-right:0px;display:inline;border-top:0px;border-right:0px;padding-top:0px;" title="image" border="0" alt="image" src="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lontivero/image_5F00_thumb_5F00_1FEB8255.png" width="443" height="36" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;y quien sabe cuantas cosas más!&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Iterators&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;for-of para iterar sobre los valores de las propiedades en lugar de hacerlo sobre las propiedades es sí mismas.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lontivero/image_5F00_40AF453C.png"&gt;&lt;img style="background-image:none;border-bottom:0px;border-left:0px;padding-left:0px;padding-right:0px;display:inline;border-top:0px;border-right:0px;padding-top:0px;" title="image" border="0" alt="image" src="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lontivero/image_5F00_thumb_5F00_13B9E261.png" width="433" height="119" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Generators&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Esto nos tienen que resultar familiar a todos, solo hace falta ver el yield para darse cuenta de cómo funciona. Exactamente como se hace en .Net. Ahora podríamos por agregarle al prototype una función where, por ejemplo, para evaluar un predicado contra cada uno de los elementos del iterador y listo, tendremos linq en ECMAScript. (pero mejor ver Array comprehension)&lt;/p&gt;  &lt;p&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lontivero/image_5F00_0436D092.png"&gt;&lt;img style="background-image:none;border-bottom:0px;border-left:0px;padding-left:0px;padding-right:0px;display:inline;border-top:0px;border-right:0px;padding-top:0px;" title="image" border="0" alt="image" src="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lontivero/image_5F00_thumb_5F00_5BB7EE7D.png" width="272" height="176" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Lo mismo pero quizás más claro y conveniete puede realizarse con un Generator comprehension:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lontivero/image_5F00_071C0F78.png"&gt;&lt;img style="background-image:none;border-bottom:0px;border-left:0px;padding-left:0px;padding-right:0px;display:inline;border-top:0px;border-right:0px;padding-top:0px;" title="image" border="0" alt="image" src="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lontivero/image_5F00_thumb_5F00_690DDBB6.png" width="479" height="144" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Lambdas&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Aunque actualmente no forma parte del draft de la versión 6, la discusión está vida. No hay que explicar nada.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lontivero/image_5F00_4D88D9B3.png"&gt;&lt;img style="background-image:none;border-bottom:0px;border-left:0px;padding-left:0px;padding-right:0px;display:inline;border-top:0px;border-right:0px;padding-top:0px;" title="image" border="0" alt="image" src="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lontivero/image_5F00_thumb_5F00_17A3E499.png" width="228" height="22" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Array comprehension&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lontivero/image_5F00_6B86E7A7.png"&gt;&lt;img style="background-image:none;border-bottom:0px;border-left:0px;padding-left:0px;padding-right:0px;display:inline;border-top:0px;border-right:0px;padding-top:0px;" title="image" border="0" alt="image" src="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lontivero/image_5F00_thumb_5F00_1586E5D0.png" width="446" height="23" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;¿Quien no entiende esto? es un generator que retorna los cuadrados de los números pares de numbers.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Let&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Si bien la idea detrás de la sintaxis de javascript era parecerse a java, pocos lenguajes se parecen tan poco. El scope de las variables en javascript es la función y no el code block como en java. Let es justamente para limitar el scope al code block.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lontivero/image_5F00_5478666B.png"&gt;&lt;img style="background-image:none;border-bottom:0px;border-left:0px;padding-left:0px;padding-right:0px;display:inline;border-top:0px;border-right:0px;padding-top:0px;" title="image" border="0" alt="image" src="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lontivero/image_5F00_thumb_5F00_66E0B720.png" width="326" height="156" /&gt;&lt;/a&gt;&amp;#160;&lt;/p&gt;                          &lt;p&gt;Estas son solo unas pocas de las propuestas que se discuten actualmente y que me han gustado más. Otras más importantes quizás sean las de modularidad del lenguaje, pragmas y API, pero a mi me gustan las que tratan sobre la expresividad del lenguaje y la verdad es que con estas y otras propuestas tomadas de ruby y python, ECMAScript va a dar un lindo paso en su plan de conquista del mundo.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://geeks.ms/aggbug.aspx?PostID=204991" width="1" height="1"&gt;</description><category domain="http://geeks.ms/blogs/lontivero/archive/tags/Dise_26002300_241_3B00_o/default.aspx">Dise&amp;#241;o</category><category domain="http://geeks.ms/blogs/lontivero/archive/tags/Languages/default.aspx">Languages</category><category domain="http://geeks.ms/blogs/lontivero/archive/tags/Investigaciones/default.aspx">Investigaciones</category><category domain="http://geeks.ms/blogs/lontivero/archive/tags/Desarrollo/default.aspx">Desarrollo</category><category domain="http://geeks.ms/blogs/lontivero/archive/tags/Clean+Code/default.aspx">Clean Code</category><category domain="http://geeks.ms/blogs/lontivero/archive/tags/javascript/default.aspx">javascript</category><category domain="http://geeks.ms/blogs/lontivero/archive/tags/ECMAScript/default.aspx">ECMAScript</category></item><item><title>Infraestructura</title><link>http://geeks.ms/blogs/lontivero/archive/2012/04/17/infraestructura.aspx</link><pubDate>Tue, 17 Apr 2012 19:52:05 GMT</pubDate><guid isPermaLink="false">2a2e7ade-7474-448b-9de5-1515d8bb7d1b:204516</guid><dc:creator>Lucas Ontivero</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://geeks.ms/blogs/lontivero/rsscomments.aspx?PostID=204516</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://geeks.ms/blogs/lontivero/commentapi.aspx?PostID=204516</wfw:comment><comments>http://geeks.ms/blogs/lontivero/archive/2012/04/17/infraestructura.aspx#comments</comments><description>&lt;p&gt;Por qué es necesario empujar tantos conceptos a la infaestructura como sea posible.&lt;/p&gt;  &lt;p&gt;&lt;object style="height:390px;width:640px;"&gt;&lt;param name="movie" value="http://www.youtube.com/v/9oSh2IZ88mU?version=3&amp;amp;feature=player_detailpage"&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;param name="allowScriptAccess" value="always"&gt;&lt;embed src="http://www.youtube.com/v/9oSh2IZ88mU?version=3&amp;amp;feature=player_detailpage" type="application/x-shockwave-flash" allowscriptaccess="always" width="640" height="360"&gt;&lt;/object&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://geeks.ms/aggbug.aspx?PostID=204516" width="1" height="1"&gt;</description><category domain="http://geeks.ms/blogs/lontivero/archive/tags/Patterns/default.aspx">Patterns</category><category domain="http://geeks.ms/blogs/lontivero/archive/tags/Arquitectura/default.aspx">Arquitectura</category><category domain="http://geeks.ms/blogs/lontivero/archive/tags/Dise_26002300_241_3B00_o/default.aspx">Dise&amp;#241;o</category><category domain="http://geeks.ms/blogs/lontivero/archive/tags/Patrones/default.aspx">Patrones</category><category domain="http://geeks.ms/blogs/lontivero/archive/tags/Desarrollo/default.aspx">Desarrollo</category><category domain="http://geeks.ms/blogs/lontivero/archive/tags/Conceptos/default.aspx">Conceptos</category><category domain="http://geeks.ms/blogs/lontivero/archive/tags/Refactoring/default.aspx">Refactoring</category><category domain="http://geeks.ms/blogs/lontivero/archive/tags/Exceptions/default.aspx">Exceptions</category><category domain="http://geeks.ms/blogs/lontivero/archive/tags/Clean+Code/default.aspx">Clean Code</category></item><item><title>Cómo crear un Compact Framework (I)</title><link>http://geeks.ms/blogs/lontivero/archive/2012/02/10/crear-un-compact-framework-i.aspx</link><pubDate>Fri, 10 Feb 2012 21:17:46 GMT</pubDate><guid isPermaLink="false">2a2e7ade-7474-448b-9de5-1515d8bb7d1b:203297</guid><dc:creator>Lucas Ontivero</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://geeks.ms/blogs/lontivero/rsscomments.aspx?PostID=203297</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://geeks.ms/blogs/lontivero/commentapi.aspx?PostID=203297</wfw:comment><comments>http://geeks.ms/blogs/lontivero/archive/2012/02/10/crear-un-compact-framework-i.aspx#comments</comments><description>&lt;p&gt;Imaginemos los siguientes escenarios:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;tenemos un gran framework super completo del cual queremos obtener una versión más pequeña para correr en dispositivos móviles, y tenemos que quitar ciertas características que el dispositivo no soporta. Además la idea del concepto de “Compact” Framework también hace referencia al tamaño, por lo que queremos eliminar todo el código del las características no soportadas. &lt;/li&gt;    &lt;li&gt;queremos lanzar varias versiones de nuestra aplicación como Free Edition, Profesional Edition, Enterprise Edition, y no deseamos que en cada una de las ediciones solo vaya el código necesario para esa edición (y no todo). &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;¿Cómo lo hacemos?&lt;/p&gt;  &lt;p&gt;La idea que propongo, si bien no es original ya que tengo entendido que .Net Compact Framework se ha realizado con una técnica similar, es simplemente identificar en los assemblies todos aquellos fragmentos de código (IL) que se utilizan para implementar las características deseadas y una vez conocido esto, eliminar el resto. Es decir, eliminar todos los métodos, propiedades, campos, eventos, tipos y demás elementos que no tomen parte en la realización de las características que queremos.&lt;/p&gt;  &lt;p&gt;Por ejemplo:&lt;/p&gt;  &lt;p&gt;En un procesador de texto tenemos 2 features: Save y Print. Y la interacción como se ve abajo.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lontivero/image_5F00_33E2B149.png"&gt;&lt;img style="background-image:none;border-right-width:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;padding-top:0px;" title="image" border="0" alt="image" src="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lontivero/image_5F00_thumb_5F00_51D09970.png" width="688" height="298" /&gt;&lt;/a&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Del diagrama queda claro que no todas las funcionalidades hacen uso de todos los tipos ni de todos los métodos ni de todas las propiedades, etc. Entonces, si solo quisiésemos permitir guardar un documento, sería seguro eliminar los tipos DocumentReader y Printer, verdad?&lt;/p&gt;  &lt;p&gt;Esto es posible hacerlo reescribiendo los ensamblados con Mono.Cecil, solo hay que conocer algo de IL para hacer cosas sencillas aunque para hacerlo realmente bien hay que conocer IL a la perfección.&lt;/p&gt;  &lt;p&gt;Veamos el código del ejemplo del cual queremos eliminar la feature que permite imprimir es documento.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lontivero/image_5F00_716F4D6B.png"&gt;&lt;img style="background-image:none;border-right-width:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;padding-top:0px;" title="image" border="0" alt="image" src="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lontivero/image_5F00_thumb_5F00_00C2AF7B.png" width="370" height="325" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Ahora bien, antes de continuar quiero mostrar el resultado de como queda el assembly antes y después de ser procesado:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lontivero/image_5F00_59E4736D.png"&gt;&lt;img style="background-image:none;border-right-width:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;padding-top:0px;" title="image" border="0" alt="image" src="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lontivero/image_5F00_thumb_5F00_2346A25C.png" width="586" height="674" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Lo que se eliminó es la posibilidad de imprimir y por eso, en el assembly procesado no existe el método TargetClass.Print(), ni los field _reader y printer ya que estos solo eran usados por el método TargetClass.Print(). Los tipos Printer y DocumentReader también han sido eliminados ya que no eran usados por otro método más que el TargetClass.Print(). &lt;/p&gt;  &lt;p&gt;Por otra parte, todos los tipos, campos, propiedades y eventos que son utilizados por otras características, aún cuando sean utilizados además por el TargetClass.Print(), permanecen intactos. Para esto solo hace falta comprobar que la clase Document aún sigue allí (aunque modificada ya que la propiedad Title se ha quitado porque solo era relevante al imprimir).&lt;/p&gt;  &lt;p&gt;Bien, la idea entonces es que una vez que conocemos cuales son los métodos que implementan las features que deseamos mantener, la técnica consiste en seguir todas y cada una de las llamadas que ese método realiza. Luego, hacer lo mismo con cada uno de estos de manera recursiva hasta tener la lista de todos los métodos que participan en la realización de la características deseada. Abajo puede verse el mecanismo:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lontivero/image_5F00_75B55CCB.png"&gt;&lt;img style="background-image:none;border-right-width:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;padding-top:0px;" title="image" border="0" alt="image" src="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lontivero/image_5F00_thumb_5F00_0B4F9569.png" width="539" height="259" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Y con esto ya tenemos el listado de todos los métodos usados, ahora lo que hacemos es eliminar todos aquellos métodos que no se encuentren en la lista:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lontivero/image_5F00_611FE780.png"&gt;&lt;img style="background-image:none;border-right-width:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;padding-top:0px;" title="image" border="0" alt="image" src="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lontivero/image_5F00_thumb_5F00_17AD92C5.png" width="294" height="146" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Esto elimina todos los métodos no usados incluyendo getters, setters, los add y remove de los eventos. Por esta razón es que de seguro nos quedan propiedades sin gettes ni setters y que por lo tanto tenemos que eliminar para que el ensamblado nos quede funcional.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lontivero/image_5F00_6E09A1C4.png"&gt;&lt;img style="background-image:none;border-right-width:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;padding-top:0px;" title="image" border="0" alt="image" src="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lontivero/image_5F00_thumb_5F00_30993D3D.png" width="448" height="131" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Por último, si existen clases sin métodos, ni campos, ni propiedades ni eventos… la eliminamos también.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lontivero/image_5F00_43018DF2.png"&gt;&lt;img style="background-image:none;border-right-width:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;padding-top:0px;" title="image" border="0" alt="image" src="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lontivero/image_5F00_thumb_5F00_486FFE96.png" width="522" height="120" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Como esto es solo una prueba de concepto, quizás cambie muchas cosas en el código, voy a continuar con la explicación en la siguiente entrada.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://geeks.ms/aggbug.aspx?PostID=203297" width="1" height="1"&gt;</description><category domain="http://geeks.ms/blogs/lontivero/archive/tags/Arquitectura/default.aspx">Arquitectura</category><category domain="http://geeks.ms/blogs/lontivero/archive/tags/.Net/default.aspx">.Net</category><category domain="http://geeks.ms/blogs/lontivero/archive/tags/Desarrollo/default.aspx">Desarrollo</category><category domain="http://geeks.ms/blogs/lontivero/archive/tags/Conceptos/default.aspx">Conceptos</category><category domain="http://geeks.ms/blogs/lontivero/archive/tags/Herramientas/default.aspx">Herramientas</category><category domain="http://geeks.ms/blogs/lontivero/archive/tags/Mono.Cecil/default.aspx">Mono.Cecil</category></item><item><title>Patrón repetido en MVC. Mi propuesta</title><link>http://geeks.ms/blogs/lontivero/archive/2012/02/08/patr-243-n-repetido-en-mvc-mi-propuesta.aspx</link><pubDate>Wed, 08 Feb 2012 06:20:43 GMT</pubDate><guid isPermaLink="false">2a2e7ade-7474-448b-9de5-1515d8bb7d1b:203251</guid><dc:creator>Lucas Ontivero</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://geeks.ms/blogs/lontivero/rsscomments.aspx?PostID=203251</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://geeks.ms/blogs/lontivero/commentapi.aspx?PostID=203251</wfw:comment><comments>http://geeks.ms/blogs/lontivero/archive/2012/02/08/patr-243-n-repetido-en-mvc-mi-propuesta.aspx#comments</comments><description>&lt;p&gt;Cuando usamos ASP.MVC uno de los patrones que debemos respetar es el de “Un modelo entra, un modelo sale” y otro muy común es el de validar el modelo y si este no es válido devolverle la misma vista al usuario para que corrija los datos de entrada. Por esto es común ver el siguiente patrón:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lontivero/image_5F00_6921C6C4.png"&gt;&lt;img style="background-image:none;border-bottom:0px;border-left:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;border-top:0px;border-right:0px;padding-top:0px;" title="image" border="0" alt="image" src="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lontivero/image_5F00_thumb_5F00_6A36AFE3.png" width="489" height="179" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;¿Qué está mal aquí? ¿Lo ves?&lt;/p&gt;  &lt;p&gt;Lo que está mal es que este patrón se repite en cada una de las acciones de cada uno de los controladores de cada una de las aplicaciones que hacemos con MVC Framework y eso huele muy pero muy mal (DRY).&lt;/p&gt;  &lt;p&gt;Este es el tipo de casos en los que puede ayudarnos AOP, y MVC framework hace un trabajo espectacular al posibilitarnos implementar AOP mediante filtros. Entonces mi idea es que esto debería hacerse así:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lontivero/image_5F00_47263E73.png"&gt;&lt;img style="background-image:none;border-bottom:0px;border-left:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;border-top:0px;border-right:0px;padding-top:0px;" title="image" border="0" alt="image" src="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lontivero/image_5F00_thumb_5F00_22D13424.png" width="462" height="115" /&gt;&lt;/a&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Ahora sí el método hace lo que tiene que hacer, ni más ni menos. Para esto (y solo para demostrar mi punto) he creado el atributo ModelValidationAttribute (necesita un mejor nombre!) como sigue:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lontivero/image_5F00_463DB2BC.png"&gt;&lt;img style="background-image:none;border-bottom:0px;border-left:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;border-top:0px;border-right:0px;padding-top:0px;" title="image" border="0" alt="image" src="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lontivero/image_5F00_thumb_5F00_1797840D.png" width="544" height="288" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Y esto funciona a la perfección! Ojo, no recomiendo usarlo sin antes hacer una buena implementación ya que le faltan cosas al ViewResult como TempData entre otras (y el OnActionExecuted vacio tiene un olorcito medio feo – pero no es culpa mia! ¿por qué el creador de la interface IActionFilter me obliga a incumplir el contrato? ¿No serán 2 interfaces distintas [LSP]?)&lt;/p&gt;  &lt;p&gt;Bueno, esto como les dije funciona a la perfección. La prueba:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lontivero/image_5F00_71257AF4.png"&gt;&lt;img style="background-image:none;border-bottom:0px;border-left:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;border-top:0px;border-right:0px;padding-top:0px;" title="image" border="0" alt="image" src="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lontivero/image_5F00_thumb_5F00_125570D1.png" width="440" height="80" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Saludos.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://geeks.ms/aggbug.aspx?PostID=203251" width="1" height="1"&gt;</description><category domain="http://geeks.ms/blogs/lontivero/archive/tags/Patterns/default.aspx">Patterns</category><category domain="http://geeks.ms/blogs/lontivero/archive/tags/Dise_26002300_241_3B00_o/default.aspx">Dise&amp;#241;o</category><category domain="http://geeks.ms/blogs/lontivero/archive/tags/.Net/default.aspx">.Net</category><category domain="http://geeks.ms/blogs/lontivero/archive/tags/Patrones/default.aspx">Patrones</category><category domain="http://geeks.ms/blogs/lontivero/archive/tags/Desarrollo/default.aspx">Desarrollo</category><category domain="http://geeks.ms/blogs/lontivero/archive/tags/Conceptos/default.aspx">Conceptos</category><category domain="http://geeks.ms/blogs/lontivero/archive/tags/Refactoring/default.aspx">Refactoring</category><category domain="http://geeks.ms/blogs/lontivero/archive/tags/Clean+Code/default.aspx">Clean Code</category><category domain="http://geeks.ms/blogs/lontivero/archive/tags/ASP.MVC/default.aspx">ASP.MVC</category></item><item><title>Viendo la web como en 2006</title><link>http://geeks.ms/blogs/lontivero/archive/2012/02/05/viendo-la-web-como-en-2006.aspx</link><pubDate>Sun, 05 Feb 2012 19:26:40 GMT</pubDate><guid isPermaLink="false">2a2e7ade-7474-448b-9de5-1515d8bb7d1b:203192</guid><dc:creator>Lucas Ontivero</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://geeks.ms/blogs/lontivero/rsscomments.aspx?PostID=203192</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://geeks.ms/blogs/lontivero/commentapi.aspx?PostID=203192</wfw:comment><comments>http://geeks.ms/blogs/lontivero/archive/2012/02/05/viendo-la-web-como-en-2006.aspx#comments</comments><description>&lt;p&gt;Muchas veces uno tuvo un sitio que dejó en el olvido y quisiera verlo nuevamente o quizás recordar cómo se veía Geeks.ms en el 2006. Bueno, para los segundos les muestro cómo se veía esto en 206. Que lindos tiempos! las fechas de los artículos en inglés, nada de publicidad, un artículo de Carlos Fouz sobre la batalla que Microsoft la daría a Google y las 18 visitas que tuvo, algo que hoy tenemos en 15 minutos.&amp;#160; &lt;/p&gt;  &lt;p&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lontivero/image_5F00_414E0F16.png"&gt;&lt;img style="background-image:none;border-bottom:0px;border-left:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;border-top:0px;border-right:0px;padding-top:0px;" title="image" border="0" alt="image" src="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lontivero/image_5F00_thumb_5F00_65531E0B.png" width="1000" height="694" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Bueno, la verdad es que esta entrada es solo para mostrar algo que probablemente ya muchos conocen pero que para aquellos que no, les resultará interesante. Se trata de &lt;a href="http://web.archive.org"&gt;http://web.archive.org&lt;/a&gt; donde podemos ver el contenido de la web en las fechas que queramos.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://geeks.ms/aggbug.aspx?PostID=203192" width="1" height="1"&gt;</description><category domain="http://geeks.ms/blogs/lontivero/archive/tags/Investigaciones/default.aspx">Investigaciones</category><category domain="http://geeks.ms/blogs/lontivero/archive/tags/Herramientas/default.aspx">Herramientas</category></item><item><title>10 consejos para que no te crackeen tan fácil</title><link>http://geeks.ms/blogs/lontivero/archive/2012/02/05/10-consejos-para-que-no-te-crackeen-tan-f-225-cil.aspx</link><pubDate>Sun, 05 Feb 2012 18:10:33 GMT</pubDate><guid isPermaLink="false">2a2e7ade-7474-448b-9de5-1515d8bb7d1b:203191</guid><dc:creator>Lucas Ontivero</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://geeks.ms/blogs/lontivero/rsscomments.aspx?PostID=203191</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://geeks.ms/blogs/lontivero/commentapi.aspx?PostID=203191</wfw:comment><comments>http://geeks.ms/blogs/lontivero/archive/2012/02/05/10-consejos-para-que-no-te-crackeen-tan-f-225-cil.aspx#comments</comments><description>&lt;p&gt;Crackear una aplicación tiene algo de arte y de ingenio pero crackear una aplicación .Net es demasiado sencillo para mi gusto, y representa un problema para la empresa o desarrollador que la comercializa y vive de mantener y mejorar el producto. Ya no vale eso de “total quien se va a dar cuenta”, eso no es válido para ninguna aplicación pero esto es aún peor cuando se trata de herramientas de desarrollo de software las cuales serán utilizadas por profesionales que conocen como pueden saltearse los sistemas de licencias.&lt;/p&gt;  &lt;p&gt;Hoy, con todas las herramientas de que disponemos en .Net (ILSpy y sus addins de debugging, Cecil, RegSpy, entre otros) saltearse estas validaciones es demasiado sencillo. Por eso quiero hacer algunas pocas recomendaciones que si bien no pueden por si solas detener a quien se lo proponga, por lo menos le dificultará un poco la tarea. Esto es importante desde mi punto de vista ya que si debo invertir una semana para crackear una aplicación quizás me convenga comprarla.&lt;/p&gt;  &lt;p&gt;Aquí van:&lt;/p&gt;  &lt;p&gt;&lt;font size="2"&gt;&lt;strong&gt;1. Firma los ensamblados&lt;/strong&gt;&lt;/font&gt;. Esto hará que no puedan reemplazarlo por otro o reescribirlo; caso contrario lo único que debe hacer alguien para saltearse las validaciones es reescribir algún método y listo. Para ilustrar esto veamos un ejemplo, imaginemos que tenemos una clase encargada de verificar la licencia del usuario llamada &lt;em&gt;&lt;strong&gt;LicenseChecker&lt;/strong&gt;&lt;/em&gt; la cual tiene un método &lt;strong&gt;&lt;em&gt;CheckLicense&lt;/em&gt;&lt;/strong&gt; que retorna TRUE si la licencia es válida y FALSE en caso contrario. En este caso, solo bastaría con reescribir el método insertándole un &lt;strong&gt;&lt;em&gt;return true. (ldc.i4.1 ret) &lt;/em&gt;&lt;/strong&gt;Abajo puede verse lo ridículamente sencillo que es lograr esto con Cecil.&lt;strong&gt;&lt;em&gt;&amp;#160;&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lontivero/image_5F00_288F7750.png"&gt;&lt;img style="background-image:none;border-bottom:0px;border-left:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;border-top:0px;border-right:0px;padding-top:0px;" title="image" border="0" alt="image" src="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lontivero/image_5F00_thumb_5F00_2F9E8DFB.png" width="528" height="255" /&gt;&lt;/a&gt;    &lt;br /&gt;    &lt;br /&gt;Del mismo modo, no guardes información valiosa en constantes publicas ya que de la misma manera, se puede modificar sus valores. Por ejemplo, imagina que en una clase &lt;strong&gt;&lt;em&gt;LicenseConstants&lt;/em&gt;&lt;/strong&gt; tenemos un field llamado TrialDays con un valor de 30 que se asigna en el constructor estático en la instrucción nro. 10. en este caso, lo más sencillo será sobrescribir el assembly para asignarle un valor mayor y así extender el período de prueba tanto como queramos. El código sería así:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lontivero/image_5F00_71E18071.png"&gt;&lt;img style="background-image:none;border-bottom:0px;border-left:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;border-top:0px;border-right:0px;padding-top:0px;" title="image" border="0" alt="image" src="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lontivero/image_5F00_thumb_5F00_26522CED.png" width="509" height="226" /&gt;&lt;/a&gt;&lt;/p&gt;      &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;font size="2"&gt;&lt;strong&gt;2. Nombres de identificadores&lt;/strong&gt;&lt;/font&gt;. Nada va a salvarte de ti mismo, si la clase que verifica la licencia se llama LicenseChecker, LicenseValidator o de alguna otra forma altamente sugestiva, cualquiera con medio dedo de frente comenzará por ahí. Simplemente buscará con Reflector o ILSpy la pablabra “License” y listo!    &lt;br /&gt;Recuerda que los ofuscadores no pueden cambiar los nombres de los identificadores que forman parte de la superficie pública porque de lo contrario el assembly quedaría inutilizable. Sabiendo esto, te darás cuenta que todo lo que suene altamente sugestivo no puede formar parte de la superficie pública.&lt;/p&gt;  &lt;p&gt;&lt;font size="2"&gt;&lt;strong&gt;3. Ofusca&lt;/strong&gt;&lt;/font&gt; los ensamblados como parte del proceso de Build. Si bien esto tiene pros y contras, con esto no solo dificultas un poco la tarea de examinar el código mediante Reflector, ILSpy u otros sino que además proteges un poco el código de copias ya que la mayoría de estas herramientas permiten extraer el código fuente en proyectos compilables. &lt;/p&gt;  &lt;p&gt;&lt;font size="2"&gt;&lt;strong&gt;4. Strings&lt;/strong&gt;&lt;/font&gt;. Los strings con mensajes que se muestran en la UI referidos a temas de licencias deben estar encriptados de alguna manera. Por ejemplo, si alguien quisiera romper con el componente de validación de licencias y ve que en la UI dice “Enter License Number:”, lo primero que hará será buscar ese string en los assemblies y una vez que lo encuentre se fijará en donde se usa, y desde allí llegará a donde quiera.&lt;/p&gt;  &lt;p&gt;&lt;font size="2"&gt;&lt;strong&gt;5. Encriptación&lt;/strong&gt;&lt;/font&gt;. Encriptar datos no detendrá a nadie aunque sí hará más lento el proceso de cracking y quizás llegue a frustrar a la persona que intenta saltearse la licencia. Lo que hay que tener en cuenta es que no debe ser la clave pública fácil de encontrar. Otro punto aún más importante es que los métodos que encriptan y desencriptan no deben nunca estar en assemblies separados de donde se usan porque de lo contrario estos tendrán que ser públicos y con esto ya arruinamos todo. Es decir, nunca poner estos métodos en un assembly “Utils” con nombres tales como Encript y Decrypt y hacerlos públicos, de lo contrario, cualquiera creará un proyecto de consola, referenciará a ese assembly y buscará las en el registro aquellas claves creadas por la aplicación que se ven claramente como encriptadas. Es decir, aquellas que se ven como sigue “9L3a1IQLzZFOmlU/3GkYu5Dm1ijRA+”, todo el mundo sabe que ésta es una cadena que ha sido encriptada.&lt;/p&gt;  &lt;p&gt;&lt;font size="2"&gt;&lt;strong&gt;6. Registro de windows&lt;/strong&gt;&lt;/font&gt;. Ya sea que el código esté o no ofuscado, los strings con las claves del registro no deben reconocerse fácilmente. Si en alguna parte tenemos un string que comienza con “HKCU\Software\”, ya está! Si además ponemos públicos los algoritmos de desencriptación ni siquiera será necesario buscar la clave de desencriptación, solo será necesario hacer algo así:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lontivero/image_5F00_09F4C500.png"&gt;&lt;img style="background-image:none;border-bottom:0px;border-left:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;border-top:0px;border-right:0px;padding-top:0px;" title="image" border="0" alt="image" src="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lontivero/image_5F00_thumb_5F00_6175E2EB.png" width="442" height="71" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Luego modificamos el valor que obtuvimos por consola y lo encriptamos nuevamente (gracias a los métodos que nos brinda el mismo producto) y lo escribimos en el registro.&lt;/p&gt;  &lt;p&gt;&lt;font size="2"&gt;&lt;strong&gt;7. Períodos de prueba&lt;/strong&gt;&lt;/font&gt;. La mayoría de los productos permiten ser usados por un período de prueba, este es uno de los puntos más débiles de casi todos los productos que conozco ya que para lograrlo, por lo general deben guardar la información de activación, días de prueba o fecha de finalización en alguna parte de nuestros equipos (por lo general, en el registro de windows). Suele ser muy sencillo manipular las claves del registro para que ese período de evaluación se extienda ad infinitum. Recuerda que quien intenta saltearse la licencia, tiene el código a su disposición por lo que encontrará la manera de burlar el mecanismo.&lt;/p&gt;  &lt;p&gt;Ten en cuenta que puede espiarse la actividad que el sistema realiza en el registro al momento de aceptar la licencia de evaluación con lo que encontrar qué es lo que hay que modificar no es el problema sino el cómo hay que modificarla. Ahí es donde debe ponerse toda la inteligencia.&amp;#160; &lt;/p&gt;  &lt;p&gt;&lt;font size="2"&gt;&lt;strong&gt;8. Datetime.Now&lt;/strong&gt;&lt;/font&gt;. Restringe al máximo el uso de Datetime.Now para checkear las diferencias de días que le quedan antes de que expire el período de evaluación, ya que este devuelve la fecha del sistema y esta es modificable por el usuario. Es decir, le damos al usuario una variable que él puede modificar a su antojo.&amp;#160; Por lo tanto verifica todos los casos posibles, piensa que el usuario puede cambiar la fecha del sistema al momento de la instalación, piensa en lo valores límites, piensa si la diferencia (DateTime.Now – InstallationDate) es positiva y si es negativa, piensa que lo más fácil para el que menos sabe será jugar con la fecha del sistema.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font size="2"&gt;9. Prueba&lt;/font&gt;&lt;/strong&gt;. Muchas empresas desarrollan sus sistemas de licencias y realizan pruebas funcionales sobre estas para comprobar su correcto funcionamiento. Esto es necesario pero es solo una prueba de caja negra; sobre estos sistemas deben realizarse pruebas de caja blanca y dedicar al menos un día de, al menos, uno de los mejores desarrolladores a probar si puede vulnerar el sistema.&lt;/p&gt;  &lt;p&gt;10. Dedicarle el esfuerzo y la inteligencia necesaria. Si no querés que las instrucciones de cómo vulnerar tu sistema se encuentren al otro día de realizado el release&amp;#160; accesibles en toda la internet, si no querés que los seriales estén por todos lados, si no querés perder ventas, entonces dedicale el tiempo, esfuerzo, inteligencia y recursos necesarios. Quizás te convenga contratar a un experto en el tema.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://geeks.ms/aggbug.aspx?PostID=203191" width="1" height="1"&gt;</description><category domain="http://geeks.ms/blogs/lontivero/archive/tags/.Net/default.aspx">.Net</category><category domain="http://geeks.ms/blogs/lontivero/archive/tags/Investigaciones/default.aspx">Investigaciones</category><category domain="http://geeks.ms/blogs/lontivero/archive/tags/Desarrollo/default.aspx">Desarrollo</category><category domain="http://geeks.ms/blogs/lontivero/archive/tags/Conceptos/default.aspx">Conceptos</category></item><item><title>Código libre de NULLs</title><link>http://geeks.ms/blogs/lontivero/archive/2012/02/02/c-243-digo-libre-de-nulls.aspx</link><pubDate>Thu, 02 Feb 2012 20:02:23 GMT</pubDate><guid isPermaLink="false">2a2e7ade-7474-448b-9de5-1515d8bb7d1b:203159</guid><dc:creator>Lucas Ontivero</dc:creator><slash:comments>16</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://geeks.ms/blogs/lontivero/rsscomments.aspx?PostID=203159</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://geeks.ms/blogs/lontivero/commentapi.aspx?PostID=203159</wfw:comment><comments>http://geeks.ms/blogs/lontivero/archive/2012/02/02/c-243-digo-libre-de-nulls.aspx#comments</comments><description>&lt;p&gt;En este video explico los problemas que causan las referencias nulas en nuestro código y planteo cómo debemos crear un código libre de NULLs.&lt;/p&gt; &lt;object style="height:390px;width:640px;"&gt;&lt;param name="movie" value="http://www.youtube.com/v/vnO5whrfx9M?version=3&amp;amp;feature=player_detailpage"&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;param name="allowScriptAccess" value="always"&gt;&lt;embed src="http://www.youtube.com/v/vnO5whrfx9M?version=3&amp;amp;feature=player_detailpage" type="application/x-shockwave-flash" allowscriptaccess="always" width="640" height="360"&gt;&lt;/object&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://geeks.ms/aggbug.aspx?PostID=203159" width="1" height="1"&gt;</description><category domain="http://geeks.ms/blogs/lontivero/archive/tags/Dise_26002300_241_3B00_o/default.aspx">Dise&amp;#241;o</category><category domain="http://geeks.ms/blogs/lontivero/archive/tags/Series/default.aspx">Series</category><category domain="http://geeks.ms/blogs/lontivero/archive/tags/.Net/default.aspx">.Net</category><category domain="http://geeks.ms/blogs/lontivero/archive/tags/Languages/default.aspx">Languages</category><category domain="http://geeks.ms/blogs/lontivero/archive/tags/Desarrollo/default.aspx">Desarrollo</category><category domain="http://geeks.ms/blogs/lontivero/archive/tags/Conceptos/default.aspx">Conceptos</category><category domain="http://geeks.ms/blogs/lontivero/archive/tags/Refactoring/default.aspx">Refactoring</category></item><item><title>Refactoring – Move switch to Table</title><link>http://geeks.ms/blogs/lontivero/archive/2012/01/30/refactoring-move-switch-to-table.aspx</link><pubDate>Mon, 30 Jan 2012 16:57:00 GMT</pubDate><guid isPermaLink="false">2a2e7ade-7474-448b-9de5-1515d8bb7d1b:203062</guid><dc:creator>Lucas Ontivero</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://geeks.ms/blogs/lontivero/rsscomments.aspx?PostID=203062</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://geeks.ms/blogs/lontivero/commentapi.aspx?PostID=203062</wfw:comment><comments>http://geeks.ms/blogs/lontivero/archive/2012/01/30/refactoring-move-switch-to-table.aspx#comments</comments><description>&lt;p&gt;Esta es quiz&amp;aacute;s una de las t&amp;eacute;cnicas m&amp;aacute;s antiguas de programaci&amp;oacute;n pero como no lo he visto en el &lt;a target="_blank" href="http://martinfowler.com/refactoring/catalog/index.html"&gt;catalogo de refactoring&lt;/a&gt; me he decidido a ponerlo aqu&amp;iacute;. Esta t&amp;eacute;cnica es llamada Table Driven Method en el libro de &lt;a target="_blank" href="http://www.stevemcconnell.com/"&gt;Steve McConnell&lt;/a&gt; (&lt;a target="_blank" href="http://www.stevemcconnell.com/cc.htm"&gt;Code Complete&lt;/a&gt;) pero como ya dije, la t&amp;eacute;cnica es mucho m&amp;aacute;s antigua que el libro.&lt;/p&gt;
&lt;p&gt;La idea es reemplazar c&amp;oacute;digo como este:&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lontivero/image_5F00_7D07EB64.png"&gt;&lt;img height="415" width="337" src="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lontivero/image_5F00_thumb_5F00_0114C9E8.png" alt="image" border="0" title="image" style="border-bottom:0px;border-left:0px;display:inline;border-top:0px;border-right:0px;" /&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;Por algo como lo que sigue:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lontivero/image_5F00_726CAEB3.png"&gt;&lt;img height="247" width="358" src="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lontivero/image_5F00_thumb_5F00_48F86D73.png" alt="image" border="0" title="image" style="border-bottom:0px;border-left:0px;display:inline;border-top:0px;border-right:0px;" /&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;Nota: es cierto que el comportamiento de ambos m&amp;eacute;todos es distinto pero es solo para mostrar la idea.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://geeks.ms/aggbug.aspx?PostID=203062" width="1" height="1"&gt;</description><category domain="http://geeks.ms/blogs/lontivero/archive/tags/Refactoring/default.aspx">Refactoring</category></item><item><title>¿Por qué tanto miedo al movimiento software craftsmanship? Mi visión.</title><link>http://geeks.ms/blogs/lontivero/archive/2012/01/28/191-por-qu-233-tanto-miedo-al-movimiento-software-craftsmanship-mi-visi-243-n.aspx</link><pubDate>Sat, 28 Jan 2012 05:05:21 GMT</pubDate><guid isPermaLink="false">2a2e7ade-7474-448b-9de5-1515d8bb7d1b:203041</guid><dc:creator>Lucas Ontivero</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://geeks.ms/blogs/lontivero/rsscomments.aspx?PostID=203041</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://geeks.ms/blogs/lontivero/commentapi.aspx?PostID=203041</wfw:comment><comments>http://geeks.ms/blogs/lontivero/archive/2012/01/28/191-por-qu-233-tanto-miedo-al-movimiento-software-craftsmanship-mi-visi-243-n.aspx#comments</comments><description>&lt;p&gt;Hace ya más de 10 años se redactó el “&lt;a href="http://agilemanifesto.org/" target="_blank"&gt;Manifesto for Agile Software Development&lt;/a&gt;” con sus 4 valores y 12 principios, un hito importantísimo dentro de la historia de nuestra profesión pero de ningún modo el comienzo del movimiento ágil porque para cuando los próceres se reunieron ya existía cierto consenso, al menos entre ellos, sobre la manera en que se debía desarrollar software. Como miembros respetados de la comunidad y la industria, todo el mundo técnico se sintió representado por los 17, sobre todo porque no eran un grupo de MBAs ni de auditores de calidad ni miembros de algún que otro instituto de normalización o estándares sino personas reconocidas por, entre otras cosas, sus conocimientos técnicos. Y sí, mis “ídolos” Martin Fowler, Kent Beck y&amp;#160; Uncle Bob están allí y son tipos técnicamente fuertes.&lt;/p&gt;  &lt;p&gt;El Manifesto no podía esperar más, los procesos de desarrollos eran pesadísimos y todos lo sabíamos y por esto, salvo aquellos que vivían de la ineficiencia (auditores, certificadores, documentadores, analistas de causas, consultores CMMI y recolectores de métricas entre otros), odiábamos el sinsentido. Lo que era evidente que no funcionaba parecía solo ser evidente por los técnicos que despotricábamos todo el tiempo por el estado de las cosas porque la inmensa mayoría de los gerentes de proyecto, y de ahí para arriba, estaban fascinados con la visión “Ingenieril”, pensaban que si lo hacían lo suficientemente bien podrían al fin deshacerse del problema de los desarrolladores y en su lugar reclutar a ejércitos de amas de casa deprimidas por el sobrepeso y obtener los mismo resultados.&lt;/p&gt;  &lt;p&gt;Aunque el Manifesto dio un gran empuje, la revolución no iba a esperar por él, si no lo hacían estos 17, lo hubieran hecho otros porque XP ya estaba en boca de todos cambiando las mentes desde abajo de la pirámide. Y es que aunque muchos piensan que esto debemos agradecerlo a los 17, y a las primeras empresas importantes que lo comenzaron a intentar, la verdad es que en toda empresa que yo haya conocido existía al menos uno, y bien respetado técnico, que machacaba, transmitía (“evangelizaba”),&amp;#160; discutía y peleaba por que las cosas cambiaran. Desde las bases, como una guerra de guerrillas. Y al fin, uno por uno, hasta el más escéptico, terminó recitando los principios&amp;#160; del Manifesto mientras se daban golpes en el pecho. (Si hasta el SEI se camufló de ágil, algo similar a ponerle el traje de Spiderman a una anciana de 200 kilos) &lt;/p&gt;  &lt;p&gt;Eso es lo que queríamos, cambiar para mejorar. Ese es y ha sido siempre el pensamiento de quienes hacemos de esto nuestras vidas, cambiar para mejorar! Y la cosa mejoró sin dudas, ahora ya tenemos iteraciones, ya aceptamos mejor los cambios, ya nos concentramos más en aquello que da valor pero… ¿qué hay del software?&amp;#160; ¿qué hay de eso de la “excelencia técnica”?. Si si si, hoy estamos mejor pero también es cierto que los técnicos seguimos viendo lo evidente: tenemos un problema muy grave con “la excelencia técnica” que impide que todo esto funcione como debería, como sabemos que debe funcionar. Mientras que hoy la capa de management, mayoritariamente Scrum, está ampliamente difundida, las prácticas de ingeniería por su parte, mucho más antiguas que el mismo scrum, no se implementan (quizás si estás leyendo esto es porque formás parte del 5% de desarrolladores que leen blogs y que implementa alguna de ellas), pair programming casi no existe, TDD muy pero muy poco (muchos se llenan la boca pero el porcentaje de software escrito con TDD es ínfimo), Integración contínua aún cuando es una de las más sencillas todavía está lejos de ser la norma, refactoring hoy se le llama a cualquier cambio suicida (sin tests, sin metodología) y así podemos seguir. Ni hablemos de la formación de los desarrolladores.&lt;/p&gt;  &lt;p&gt;El código sigue apestando, esto significa que los diseños apestan, que la calidad sigue lejos de lo que debería ser, esto mismo también significa que los costos siguen altos y que quien invierte en esto puede hacerse de la ventaja competitiva. Pero de todo el movimiento ágil parece que lo que se ha llevado todo es Scrum (y ahora Lean). Pero entre tanta gestión nos estamos olvidando de algo importante: el software y como este se diseña, se programa y se prueba. ¿O acaso está por volver la idea de los monos programadores? ¿Será posible formar equipos de alto rendimiento con maestras jardineras reconvertidas a programadoras?&lt;/p&gt;  &lt;p&gt;La verdad es que hoy como ayer, quienes pensamos en cambiar para mejorar, estamos dando una nueva batalla, la de profesionalizar la profesión, la de reforzar las prácticas, la de recrear la carrera técnica (porque el “paraíso” del management (y sus salarios) sigue llevándose a los mejores de entre nosotros), la de formar realmente a los aspirantes para que puedan hacer frente a la complejidad de los desarrollos actuales y futuros, en fin… la batalla sigue siendo por lo mismo: por mejorar la manera en que desarrollamos software. ¿Alguien ve algo malo en esto?&lt;/p&gt;  &lt;p&gt;Increiblemente, aunque no veo cómo esto pueda perjudicar a la industria, a la profesión, a los clientes o a la sociedad, hay gente preocupada por el movimiento, personas importantes como Martin Fowler &lt;a href="http://martinfowler.com/bliki/CraftmanshipAndTheCrevasse.html" target="_blank"&gt;aquí&lt;/a&gt;. ¿En qué modo puede un intento por mejorar la profesión, de mejorar y difundir aún más las practicas de ingeniería ser peligroso? El miedo es que se le preste “demasiada” atención a la disciplina y se deje de lado al cliente, el miedo es a que nos perdamos en discusiones ñoñas sobre arquitectura, frameworks, patrones y sesiones de refactoring. Este miedo se basa en la creencia de que podemos volvernos aún mucho más idiotas!. Martin Fowler, quien ha escrito los libros más técnicos que yo haya leído en mi vida parece tener cierto grado de preocupación.&lt;/p&gt;  &lt;p&gt;Y sí, yo sé que existe un pequeño grupo de fanáticos que de alguna forma se han sentido traicionados por el rumbo que tomó el movimiento ágil, gente que acompañó al movimiento y que pensó que el camino iba a ser diferente. Después de todo yo también me sentí algo defraudado, pero eso no significa que no aprecie lo que hemos logrado de la mano del movimiento ágil. No obstante, tenemos un problema entre manos, un problema que muchos creyeron que iba a ser resuelto por el movimiento ágil pero que aún persiste y se sigue cargando costos y sigue perjudicando a los clientes. &lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://geeks.ms/aggbug.aspx?PostID=203041" width="1" height="1"&gt;</description><category domain="http://geeks.ms/blogs/lontivero/archive/tags/Conceptos/default.aspx">Conceptos</category></item><item><title>Autodisciplina al hacer check in</title><link>http://geeks.ms/blogs/lontivero/archive/2012/01/27/autodisciplina-al-hacer-check-in.aspx</link><pubDate>Fri, 27 Jan 2012 16:22:23 GMT</pubDate><guid isPermaLink="false">2a2e7ade-7474-448b-9de5-1515d8bb7d1b:203035</guid><dc:creator>Lucas Ontivero</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://geeks.ms/blogs/lontivero/rsscomments.aspx?PostID=203035</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://geeks.ms/blogs/lontivero/commentapi.aspx?PostID=203035</wfw:comment><comments>http://geeks.ms/blogs/lontivero/archive/2012/01/27/autodisciplina-al-hacer-check-in.aspx#comments</comments><description>&lt;p&gt;Cuando el build se rompe con demasiada frecuencia o permanece en ese estado por mucho tiempo, el equipo se ve impedido de avanzar cómodamente. Pero la razón principal por la que se rompen es sin dudas el descuido: no compilar antes de subir, no correr las pruebas antes de subir y no prestar la suficiente atención al mergear entre otras cosas. Esto es porque existe un exceso de confianza en los miembros del equipo.&lt;/p&gt;  &lt;p&gt;Para ayudar a mitigar esto, en mi equipo anterior creé este premio semanal con el que nos hemos divertido mucho y la verdad es que me ha dado un resultado enorme hasta el punto que debí quitarlo cuando lo empecé a ganar yo!&lt;/p&gt;  &lt;p&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lontivero/image_5F00_4D45DF4B.png"&gt;&lt;img style="border-bottom:0px;border-left:0px;display:inline;border-top:0px;border-right:0px;" title="image" border="0" alt="image" src="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lontivero/image_5F00_thumb_5F00_45535E4B.png" width="604" height="484" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Nota: usábamos CC.Net y SVN por lo que más que descansar en la herramienta, lo que logramos fue autodisciplica.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://geeks.ms/aggbug.aspx?PostID=203035" width="1" height="1"&gt;</description><category domain="http://geeks.ms/blogs/lontivero/archive/tags/Desarrollo/default.aspx">Desarrollo</category><category domain="http://geeks.ms/blogs/lontivero/archive/tags/Conceptos/default.aspx">Conceptos</category><category domain="http://geeks.ms/blogs/lontivero/archive/tags/Herramientas/default.aspx">Herramientas</category><category domain="http://geeks.ms/blogs/lontivero/archive/tags/Productividad/default.aspx">Productividad</category><category domain="http://geeks.ms/blogs/lontivero/archive/tags/Continuous+Integration/default.aspx">Continuous Integration</category></item><item><title>Arquitectos e intelectuales</title><link>http://geeks.ms/blogs/lontivero/archive/2012/01/27/arquitectos-e-intelectuales.aspx</link><pubDate>Fri, 27 Jan 2012 06:19:50 GMT</pubDate><guid isPermaLink="false">2a2e7ade-7474-448b-9de5-1515d8bb7d1b:203026</guid><dc:creator>Lucas Ontivero</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://geeks.ms/blogs/lontivero/rsscomments.aspx?PostID=203026</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://geeks.ms/blogs/lontivero/commentapi.aspx?PostID=203026</wfw:comment><comments>http://geeks.ms/blogs/lontivero/archive/2012/01/27/arquitectos-e-intelectuales.aspx#comments</comments><description>&lt;p&gt;Ser llamado arquitecto es similar a ser llamado “un intelectual”, es un título que un grupo te otorga debido a tu actividad en la comunidad o en la industria pero que entiendo que nunca debería autoasignarse. Del mismo modo en que es de mal gusto que una persona se presente a si mismo como “un intelectual”, lo mismo sucede con aquellos desarrolladores que se presentan como “arquitectos”. No obstante, aunque nunca he escuchado a nadie presentarse como “un intelectual” (quizás porque queda algo ridículo decir: “Hola, me llamo Pedro y soy un intelectual”), sí lo veo a diario en desarrolladores que se presentan a si mismos como arquitectos.&lt;/p&gt;  &lt;p&gt;Hoy por hoy, arquitecto es muchas veces una “categoría” que muchas empresas utilizan a la hora de categorizar (valga la redundancia) a sus desarrolladores más capaces y en ese contexto puede que presentarse ante los demás como arquitecto de tal o cual compañía sea correcto. &lt;/p&gt;  &lt;p&gt;Por otro lado, conozco a algunos desarrolladores de esos que son invisibles a Google, que no mantienen un blog, que no dan charlas, que no participan en los foros y que no twitean pero que son auténticos cracks, tipos a los que aún cuando todos en su entorno los reconocen como arquitectos, no se sienten cómodos con el título, al igual que le sucede a muchos auténticos intelectuales. &lt;/p&gt;  &lt;p&gt;Así que por favor, no te autodenomines arquitecto! Si eres uno, tus compañeros, la empresa en la que trabajas, la comunidad y quizás el mundo entero te reconocerá como tal aún cuando no te guste o creas que el título te queda grande. No depende de tí.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://geeks.ms/aggbug.aspx?PostID=203026" width="1" height="1"&gt;</description><category domain="http://geeks.ms/blogs/lontivero/archive/tags/Misc/default.aspx">Misc</category></item><item><title>Difícil demostrar con números las ventajas de Pair Programming</title><link>http://geeks.ms/blogs/lontivero/archive/2012/01/27/dif-237-cil-demostrar-con-n-250-meros-las-ventajas-de-pair-programming.aspx</link><pubDate>Fri, 27 Jan 2012 05:29:31 GMT</pubDate><guid isPermaLink="false">2a2e7ade-7474-448b-9de5-1515d8bb7d1b:203023</guid><dc:creator>Lucas Ontivero</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://geeks.ms/blogs/lontivero/rsscomments.aspx?PostID=203023</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://geeks.ms/blogs/lontivero/commentapi.aspx?PostID=203023</wfw:comment><comments>http://geeks.ms/blogs/lontivero/archive/2012/01/27/dif-237-cil-demostrar-con-n-250-meros-las-ventajas-de-pair-programming.aspx#comments</comments><description>&lt;p&gt;&lt;a href="http://elbruno.com/" target="_blank"&gt;ElBruno&lt;/a&gt; ha escrito un interesante artículo en su blog titulado “&lt;a href="http://geeks.ms/blogs/elbruno/archive/2012/01/26/alm-demostrando-con-n-250-meros-porqu-233-es-conveniente-realizar-pair-programming.aspx" target="_blank"&gt;[#ALM] DEMOSTRANDO CON NÚMEROS PORQUÉ ES CONVENIENTE REALIZAR PAIR PROGRAMMING&lt;/a&gt;” en el que, mediante lo que considero un ejercicio de razonamiento, intenta demostrar el incremento que esta práctica puede generar en la productividad de un equipo con una configuración ficticia, aunque bastante común, de 2 Devs. Srs. y 4 Devs. Jrs.&amp;#160; Recomiendo su lectura (y además, es condición necesaria para entender de que se habla en esta entrada).&lt;/p&gt;  &lt;p&gt;En primer lugar debo aclarar que todo intento por ayudar a difundir, y animar a implementar, esta y otras prácticas es de agradecer e imitar. Además, y solo para dejar explícita mi posición acerca de esta práctica (Pair Programming), debo decir que estoy absolutamente de acuerdo con ella, incrementa la calidad, los diseños, la comunicación y el conocimiento del equipo como pocas prácticas lo hacen. Y además es más sociable y divertido mientras que eleva el compromiso. &lt;/p&gt;  &lt;p&gt;Ahora, una vez aclarado esto, debo decir que a mi humilde entender &lt;a href="http://elbruno.com/" target="_blank"&gt;ElBruno&lt;/a&gt; no ha acertado en su enfoque. ¿Por qué? Veamos, para demostrar la hipótesis, utiliza el siguiente ejemplo: &lt;/p&gt;  &lt;p&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lontivero/image_5F00_166C3BF5.png"&gt;&lt;img style="background-image:none;border-bottom:0px;border-left:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;border-top:0px;border-right:0px;padding-top:0px;" title="image" border="0" alt="image" src="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lontivero/image_5F00_thumb_5F00_420CE024.png" width="462" height="507" /&gt;&lt;/a&gt;&lt;/p&gt;      &lt;p&gt;El problema con la argumentación es que todo el modelo cierra cuando existe una cantidad de desarrolladores juniors los cuales no pueden completar su trabajo sin quitarles tiempo a los desarrolladores seniors, de esta forma y en este contexto parece que la propuesta es una buena idea para maximizar la productividad. Lo curioso es que según el ejemplo, la mejor solución sería eliminar esos 4 factores de &lt;strong&gt;anti-capacity&lt;/strong&gt; llamados juniors y así, con solo una fracción del costo, los 2 desarrolladores seniors podrían completar sus 2 unidades de trabajo diarias con lo que a la semana tendríamos 20 unidades de trabajo completas. Entonces, es la existencia de esos juniors la condición necesaria para que esto cierre.&lt;/p&gt;  &lt;p&gt;No obstante creo que aquí se cumple una gran verdad: poner más desarrolladores, poco experimentados, no incrementa la velocidad del equipo; y como este modelo concuerda con las experiencias de la vida misma, podemos pensar que no está muy lejos de ser correcto.&lt;/p&gt;  &lt;p&gt;Ahora, este mismo razonamiento no arroja los mismos resultados si el equipo tuviese otra configuración como por ejemplo si fuesen solamente 6 Devs. Srs. En este caso, si aplicamos el mismo razonamiento utilizado en el ejemplo, el resultado será que como nadie requiere ayuda de otro para terminar (o al menos idealmente), entonces tener a 2 Devs. Srs. en una misma máquina resultaría en una pérdida de la productividad.&lt;/p&gt;  &lt;p&gt;Como Pair Programming es exactamente para, entre otras muchas cosas, incrementar la calidad y con esto reducir los costos, creo que esta argumentación podría habilitar a aquellos quienes desconocen la práctica, detractores por ignorancia, a jugar con modelos similares concentrándose en la economía evidente (para ver “si les conviene” o “no les conviene”) ignorando la disminución del costo a largo plazo que esta logra. Quizás, como todo el ejemplo cierra gracias a estos 4 devs. juniors alguien podría argumentar que su equipo no necesita de esta práctica ya que el mismo se compone solo de devs. seniors. Así las cosas, este argumento es de doble filo!&lt;/p&gt;  &lt;p&gt;Otro motivo por el que este ejemplo no me parece el mejor es porque, en mi experiencia, Pair Programming funciona mucho mejor cuando ambos desarrolladores tienen conocimientos “equivalentes” y no tan bien cuando la diferencia de conocimientos es grande como entre un junior y un senior. En este último caso, el juniors casi siempre se limita a mirar (y en el mejor de los casos a aprender, que no es poco) pero difícilmente pueda darse la dinámica de cambiar con cierta frecuencia el teclado y los roles. &lt;/p&gt;  &lt;p&gt;Por desgracia esta práctica es quizás la menos utilizada y esto se debe entre otras cosas a que es difícil de demostrar de manera “teórica” lo que la hace no muy evidente. Otro problema es que en varios papers de señores científicos que publican en la IEEE y la ACM se menciona que esta incrementa el time to market en entre un 15-20% y por eso es también que se hace mucho más difícil de justificar. En el tiempo de los resultados rápidos pocos quieren invertir a largo plazo.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://geeks.ms/aggbug.aspx?PostID=203023" width="1" height="1"&gt;</description><category domain="http://geeks.ms/blogs/lontivero/archive/tags/Gesti_26002300_243_3B00_n+de+proyectos/default.aspx">Gesti&amp;#243;n de proyectos</category><category domain="http://geeks.ms/blogs/lontivero/archive/tags/Desarrollo/default.aspx">Desarrollo</category><category domain="http://geeks.ms/blogs/lontivero/archive/tags/Conceptos/default.aspx">Conceptos</category><category domain="http://geeks.ms/blogs/lontivero/archive/tags/Productividad/default.aspx">Productividad</category><category domain="http://geeks.ms/blogs/lontivero/archive/tags/Pair+Programming/default.aspx">Pair Programming</category></item></channel></rss>