<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:georss="http://www.georss.org/georss" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0"><channel><atom:id>tag:blogger.com,1999:blog-3732630541286744699</atom:id><lastBuildDate>Fri, 30 Jul 2010 15:06:13 +0000</lastBuildDate><title>Ideas 3p</title><description>El blog técnico de &lt;strong&gt;Tercer Planeta&lt;/strong&gt;</description><link>http://blog.tercerplaneta.com/</link><managingEditor>noreply@blogger.com (Benjamin Eidelman)</managingEditor><generator>Blogger</generator><openSearch:totalResults>45</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/Ideas3p" /><feedburner:info uri="ideas3p" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3732630541286744699.post-3875739004973980894</guid><pubDate>Mon, 26 Jul 2010 15:36:00 +0000</pubDate><atom:updated>2010-07-26T12:42:52.879-03:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">dynamic</category><category domain="http://www.blogger.com/atom/ns#">.Net 4.0</category><category domain="http://www.blogger.com/atom/ns#">ViewModel</category><category domain="http://www.blogger.com/atom/ns#">MVC</category><title>Model View ViewModel</title><description>&lt;span style="color: black;"&gt;En un mail reciente de MSDN apareció &lt;a href="http://msdn.microsoft.com/es-ar/magazine/ff798279(en-us).aspx"&gt;un artículo&lt;/a&gt; que toca un tema de diseño interesante.&lt;br /&gt;
Y es el patrón Model-ViewModel-Model, en el artículo se hace referencia a su implementación en WPF/Silverlight, sin embargo es un tema con el que seguramente muchos se topen al incursionar en &lt;a href="http://www.asp.net/mvc"&gt;Asp.Net Mvc&lt;/a&gt;, y en realidad es imposible de esquivar en cualquier implementación de MVC, ya sea en Asp.Net, WinForms, Ruby o Haskell.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;ViewModels&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Cuando trabajamos con un modelo MVC, especialmente si elegimos algún mecanismo de DataBinding entre M y V (y en un sentido amplio de la palabra consideremos los templates (como las vistas de Asp.Net Mvc) como un caso particular de DataBinding), resulta inmediato que cualquier aplicación que escape de lo elemental necesita algun tipo de transformación entre un Modelo y su Vista, ahi es donde llegan al rescate los ViewModels.&lt;br /&gt;
&lt;br /&gt;
Para hacerlo menos abstracto, pongamos un ejemplo, imaginemos que&amp;nbsp;nuestros amigos de Facebook® quieren construir la pagina de perfil de un usuario:&lt;br /&gt;
&lt;/span&gt;&lt;br /&gt;
&lt;span style="color: black;"&gt;&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_GcXPWR_goXk/TE2UZytZIEI/AAAAAAAAAts/LmfCqsM267k/s1600/SampleProfile.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" height="419" src="http://4.bp.blogspot.com/_GcXPWR_goXk/TE2UZytZIEI/AAAAAAAAAts/LmfCqsM267k/s640/SampleProfile.JPG" width="640" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;Perfil de Usuario&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;&lt;/span&gt;&lt;span style="color: black;"&gt;&amp;nbsp;supongamos también que utilizan MVC y construyen su "Model" de la siguiente forma:&lt;br /&gt;
&lt;/span&gt;&lt;br /&gt;
&lt;span style="color: black;"&gt;&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_GcXPWR_goXk/TE2VnbESUbI/AAAAAAAAAt0/eMYa1I2wELE/s1600/UserProfileModel.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" height="205" src="http://3.bp.blogspot.com/_GcXPWR_goXk/TE2VnbESUbI/AAAAAAAAAt0/eMYa1I2wELE/s400/UserProfileModel.jpg" width="400" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;Nota: el modelo real de Facebook® podría ser más complejo&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;La duda es como obtener los datos resaltados en &lt;span class="Apple-style-span" style="background-color: yellow;"&gt;amarillo &lt;/span&gt;en la captura de ejemplo&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;Antigüedad del mensaje de estado ("lunes pasado").&lt;/li&gt;
&lt;li&gt;Ubicación ("Villa Devoto" en lugar de el GUID correspondiente)&lt;/li&gt;
&lt;li&gt;Amigos en común (con el usuario logueado actualmente)&lt;/li&gt;
&lt;/ul&gt;Para esto podemos "envolver" estas entidades del modelo con otras más emparentadas a la vista que queremos construir:&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_GcXPWR_goXk/TE2XLkjFcTI/AAAAAAAAAt8/Qu63qVhCrpk/s1600/UserProfileViewModel.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="190" src="http://3.bp.blogspot.com/_GcXPWR_goXk/TE2XLkjFcTI/AAAAAAAAAt8/Qu63qVhCrpk/s400/UserProfileViewModel.jpg" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;Estas clases extienden a las anteriores con campos calculados, listas filtradas, consolidaciones, u otro tipo de transformaciones sobre el modelo original.&lt;br /&gt;
Para ilustrar ésta sería una versión (muy naive) de la nueva propiedad "CommonFriends" en UserVM:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; IList&amp;lt;UserVM&amp;gt; CommonFriends
        {
            get
            {
                &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;this&lt;/span&gt;.Friends
                    .Where(f =&amp;gt; f.Friends
                      .Any(ff =&amp;gt; ff.UserID == User.CurrentUserID))
                    .ToList();
            }
        }&lt;/pre&gt;&lt;br /&gt;
Si usted ya estuvo agregando este tipo de campos calculados y transformaciones, y se sentía culpable por haber violado la prístina pureza de su modelo MVC&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://gryphonscry.files.wordpress.com/2009/06/guilty-puppy1.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="192" src="http://gryphonscry.files.wordpress.com/2009/06/guilty-puppy1.jpg" width="200" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
&amp;nbsp;siéntase liberado de la culpa!, esto ya tiene nombre y se llama &lt;a href="http://en.wikipedia.org/wiki/Model_View_ViewModel"&gt;ViewModel&lt;/a&gt;!&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Separación Model-ViewModel-Model&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Por supuesto en esto podemos imaginar un gradiente de creciente complejidad:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;Propiedades agregadas directamente a las entidades de nuestro modelo&lt;/li&gt;
&lt;li&gt;Algunas clases nuevas y propiedades agregadas a entidades que descienden de las de nuestro modelo&lt;/li&gt;
&lt;li&gt;Una capa de ViewModels que se interpone y separa completamente View de Model.&lt;/li&gt;
&lt;/ul&gt;Volviendo un poco al principio, el &lt;a href="http://msdn.microsoft.com/es-ar/magazine/ff798279(en-us).aspx"&gt;artículo de MSDN&lt;/a&gt;&amp;nbsp;trata sobre la última opción, implementada como assemblies separados para View, Model y ViewModel, en el que no existen referencias entre View y Model.&lt;br /&gt;
&lt;br /&gt;
Véase este gráfico explicativo que tomé prestado de &lt;a href="http://blogs.msdn.com/b/dphill/archive/2009/01/31/the-viewmodel-pattern.aspx"&gt;un artículo que resume muy bien el tema&lt;/a&gt;&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://blogs.msdn.com/blogfiles/dphill/WindowsLiveWriter/CollectionsAndViewModels_EE56/ViewModel_2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://blogs.msdn.com/blogfiles/dphill/WindowsLiveWriter/CollectionsAndViewModels_EE56/ViewModel_2.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
Rápidamente puede verse el problema burocrático en que nos pone este enfoque, ya que implica tener para casi todas las clases del modelo, una equivalente en ViewModel, con wrappers para todas las propiedades visibles. Imagínense la flagrante violación al principio &lt;a href="http://en.wikipedia.org/wiki/Don't_repeat_yourself"&gt;DRY&lt;/a&gt;&amp;nbsp;que supone crear páginas y páginas de código como este:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; Fullname
        {
            get
            {
                &lt;span class="kwrd"&gt;return&lt;/span&gt; InnerEntity.Fullname;
            }
            set
            {
                InnerEntity.Fullname = &lt;span class="kwrd"&gt;value&lt;/span&gt;;
            }
        }&lt;/pre&gt;&lt;br /&gt;
Tiene que haber algo mejor!&lt;br /&gt;
&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;/div&gt;&lt;b&gt;Dynamic Proxies&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Como dice la máxima "El mejor código es aquel que no se escribe", y&amp;nbsp;el &lt;a href="http://msdn.microsoft.com/es-ar/magazine/ff798279(en-us).aspx"&gt;artículo al que hice referencia&lt;/a&gt; propone generar estos ViewModels como proxies dinámicos, implementar esos "gets" y "sets" automáticamente con el nuevo tipo &lt;a href="http://msdn.microsoft.com/en-us/library/dd264736.aspx"&gt;dynamic &lt;/a&gt;en .Net 4.0, un poco de Reflection y unos atributos muy elegantes para declarar dependencias entre propiedades (ej: Edad &amp;lt;-depende de-&amp;gt; FechaDeNacimiento).&lt;br /&gt;
&lt;br /&gt;
Existen también librerías muy famosas para la creación de proxies dinámicos (que funcionan con .Net 2.0), como por ejemplo las que son usadas en &lt;a href="http://es.wikipedia.org/wiki/NHibernate"&gt;NHibernate &lt;/a&gt;(para crear proxies que soporten lazy loading):&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;&lt;a href="http://code.google.com/p/linfu/"&gt;LinFu&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.castleproject.org/dynamicproxy/index.html"&gt;Castle Project&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/span&gt;&lt;span style="color: black;"&gt;que hacen fácil agregarle a estos proxies interceptores en getters y setters (u otros métodos) que implementen notificación de cambios, logging, autorización y otras cosas por el estilo.&lt;br /&gt;
&lt;br /&gt;
Y finalmente...&lt;a href="http://en.wikipedia.org/wiki/KISS_principle"&gt;&lt;b&gt;KISS&lt;/b&gt;&lt;/a&gt;! es importante recordar que puede resultar más que suficiente con mantener las clases en el modelo accesibles a las vistas, y las clases "ViewModel" mezcladas con el "Model", o separadas simplemente por namespace.&lt;br /&gt;
&lt;br /&gt;
&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3732630541286744699-3875739004973980894?l=blog.tercerplaneta.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Ideas3p/~4/eeBB8FRExS8" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/Ideas3p/~3/eeBB8FRExS8/model-view-viewmodel.html</link><author>noreply@blogger.com (Benjamin Eidelman)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/_GcXPWR_goXk/TE2UZytZIEI/AAAAAAAAAts/LmfCqsM267k/s72-c/SampleProfile.JPG" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://blog.tercerplaneta.com/2010/07/model-view-viewmodel.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3732630541286744699.post-8946578167382058314</guid><pubDate>Wed, 07 Jul 2010 18:03:00 +0000</pubDate><atom:updated>2010-07-26T13:10:38.258-03:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">CMS</category><category domain="http://www.blogger.com/atom/ns#">Sitecore</category><title>Sitecore, otra opción que ofrecer</title><description>Algunas semanas atrás, uno de nuestros clientes más importantes, nos invitó a participar junto con otros proveedores de un curso intensivo de una semana sobre &lt;a href="http://www.sitecore.net/"&gt;Sitecore&lt;/a&gt;.&lt;br /&gt;Sitecore es un CMS que proporciona software de gestión de contenidos web y portales a organizaciones que requieran funciones empresariales, integración y escalabilidad a la hora de administrar sitios web.&lt;br /&gt;&lt;br /&gt;Sitecore fue desarrollado en Dinamarca, y tiene su mayor mercado actualmente en Estados Unidos y Europa. Nuestro cliente vio interesante, la posibilidad de que sus proveedores de mayor confianza, se puedan instruir en esta herramienta para que en el futuro los acompañen en la integración de Sitecore con otras aplicaciones, puedan agregar nuevas funcionalidades o colaboren en la implementación de la herramienta.&lt;br /&gt;&lt;br /&gt;Como en &lt;a href="http://www.tercerplaneta.com/"&gt;Tercer Planeta&lt;/a&gt; estamos acostumbrados a realizar nuestros propios desarrollos, la primera reacción a la invitación fue “y no sé, ¿te parece que tengamos que aprender Sitecore?”, pero rápidamente comprendimos que la mejor respuesta a esa pregunta con un , “claro que sí”, y hoy en día vemos los beneficios de haber participado en ese encuentro.&lt;br /&gt;&lt;br /&gt;Más allá que nuestro fuerte esté en los desarrollos a medida, siempre es enriquecedor poder conocer cómo otros pueden encarar una determinada solución. En este caso puntual, Sitecore nos pareció un producto muy completo, que tiene cubiertas muchísimas funcionalidades, muchas de las cuales todavía no pudimos explorar, pero en las que sí pudimos indagar descubrimos que están resueltas de manera muy diferente al enfoque que le hubiéramos dado nosotros, simplemente porque fue pensado por otras personas, en otro contexto, con otra experiencia y otras costumbres.&lt;br /&gt;&lt;br /&gt;Con lo cual la posibilidad de poder salir, tomar distancia de nuestros tareas diarias, y ver cómo piensan otros, nos resultó más que interesante.&lt;br /&gt;&lt;br /&gt;El curso fue dictado por &lt;a href="http://www.linkedin.com/in/theinsidecorner"&gt;Craig Nelson&lt;/a&gt;, un instructor técnico especializado en Sitecore, que viajo especialmente desde Estados Unidos. Cada día estaba orientado a diferentes perfiles (Usuarios Finales, Diseñadores, Desarrolladores, etc.), constaba de partes teóricas y prácticas, las cuales resolvíamos en grupos, esta interacción con otros colegas fue también una experiencia que valió la pena.&lt;br /&gt;&lt;br /&gt;Este curso nos sirvió para conocer una nueva herramienta, y fundamentalmente para ver otra forma de hacer las cosas, e independientemente del uso que la vayamos a dar en el futuro, hoy en día, sentimos que tenemos&lt;strong&gt; una posibilidad más&lt;/strong&gt;, &lt;strong&gt;otra opción que ofrecer&lt;/strong&gt;, o tener en cuenta, y eso creo que es lo más importante, para nosotros y para nuestros clientes.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3732630541286744699-8946578167382058314?l=blog.tercerplaneta.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Ideas3p/~4/23EEdmC7joc" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/Ideas3p/~3/23EEdmC7joc/sitecore-otra-opcion-que-ofrecer.html</link><author>noreply@blogger.com (Ricardo D. de Guzmán)</author><thr:total>0</thr:total><feedburner:origLink>http://blog.tercerplaneta.com/2010/07/sitecore-otra-opcion-que-ofrecer.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3732630541286744699.post-8848141161492440923</guid><pubDate>Mon, 05 Jul 2010 18:00:00 +0000</pubDate><atom:updated>2010-07-05T16:56:20.148-03:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">desarrollo personal</category><category domain="http://www.blogger.com/atom/ns#">Coaching ontológico</category><title>Cómo entendemos el crecimiento</title><description>Cuando en diciembre del 2009 nos reunimos con Jose a definir los objetivos del 2010 decidimos que teníamos que poner el foco en &lt;strong&gt;madurar&lt;/strong&gt;.&lt;br /&gt;&lt;br /&gt;Pero, qué significaba en ese momento “madurar” para nosotros ? Para el tamaño de organización que tenemos y por los lineamientos que seguimos, lo que buscábamos era lograr un crecimiento de la empresa pero no medido en este caso en cantidad de integrantes o en monto de facturación, sino &lt;em&gt;&lt;span style="color:#ff9900;"&gt;en base al crecimiento profesional y desarrollo personal de todos los integrantes del equipo&lt;/span&gt;&lt;/em&gt; de Tercer Planeta.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Help, I need somebody!&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Para quienes no somos especialistas en coaching y tenemos un perfil más técnico, el objetivo se presentaba como un gran desafío y sabíamos también que nos embarcábamos en un trabajo de largo plazo que implicaba grandes cambios individuales y en el grupo.&lt;br /&gt;&lt;br /&gt;Estaba claro que para poder llevar a cabo esta tarea necesitábamos contactar a especialistas en el tema y fue así que acudimos a &lt;a href="http://ar.linkedin.com/in/pfondevila" target="_blank"&gt;Pablo Fondevila&lt;/a&gt; y su empresa “Nuevas Miradas en Organizaciones”, quien junto con &lt;a href="http://ar.linkedin.com/in/carolaherrscher" target="_blank"&gt;Carola Herrscher&lt;/a&gt; y &lt;a href="http://ar.linkedin.com/in/marisaberges" target="_blank"&gt;Marisa Bergés&lt;/a&gt;  se dedican al &lt;a href="http://flapco.org/" target="_blank"&gt;Coaching Ontológico&lt;/a&gt; . Con ellos empezamos a transitar este camino desde hace 6 meses.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Algunos caminos a seguir&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Uno de los aspectos que comenzamos a abordar es tratar de lograr una convergencia entre la vida personal y la laboral ¿cómo pensar que con la cantidad de horas que compartimos en la oficina ambos entornos marchan cada uno por un “carril exclusivo” sin tocarse en ningún momento?&lt;br /&gt;Es lógico entender que estas dos “vidas” se cruzan en varios puntos pero no nos resultaba tan lógico hacer visible y poner un esfuerzo claro y público en juntarlas y complementarlas.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Y para qué querríamos hacer esto? Una de las respuestas que encontramos a esta pregunta es que creemos que la realización de las personas debe ser algo integral, el desarrollo personal y profesional implica poder mostrar los logros, tomar nuevos compromisos, cerrar etapas, explorar nuevos caminos, descubrir y explotar nuestras habilidades.&lt;br /&gt;&lt;br /&gt;Por otro lado, aceptar la influencia que las emociones tienen en nuestras vidas es fundamental para entender algunos comportamientos: por ejemplo, aclarar que estamos viviendo un momento difícil o que tenemos algo importante que resolver puede evitarnos conflictos de comunicación si encontramos un ámbito donde nos sintamos cómodos para declararlo y los demás entiendan el por qué de ciertas actitudes.&lt;br /&gt;&lt;br /&gt;Entender cuán valioso es el esfuerzo de alguien por terminar una carrera o por emprender nuevos retos, por ejemplo, nos anima a fomentar ese tipo de logros, que sin duda, redundarán en valor para los objetivos de la empresa.&lt;br /&gt;&lt;br /&gt;Cómo hacer entonces para acercar estos dos mundos y lograr que se retroalimenten ? O que el trabajo sea un medio más a través del cual alcanzar objetivos personales ?&lt;br /&gt;Cómo hacer que la "vida de la oficina" no genere trabas en la vida privada ? O que la vida privada (logros, alegrías, tristezas) puedan ser, de alguna manera, compartidos, apoyados y comprendidos por la empresa?&lt;br /&gt;&lt;br /&gt;Estas fueron algunas de las dudas que empezaron a surgir. Dudas que, gracias a las herramientas que nos van dando quienes nos acompañan (talleres, entrevistas individuales periódicas, consejos para la organización de eventos internos y externos, etc.), empezaron a disiparse.&lt;br /&gt;&lt;br /&gt;Puede asombrarnos pensar que con pequeños cambios o con la creación de ámbitos de discusión de cosas simples y concretas, es absolutamente posible y realizable encarar el tema.&lt;br /&gt;&lt;br /&gt;De la misma manera las &lt;em&gt;&lt;span style="color:#ff9900;"&gt;charlas individuales para desarrollo personal&lt;/span&gt;&lt;/em&gt; nos están abriendo los ojos a nuevas posibilidades de solución de conflictos, de aprovechamiento de las capacidades de cada uno, de alineamiento con los objetivos y visión de la empresa, de comunicación, de roles, etc.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Esfuerzo vs. Beneficios&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Según mi opinión, el mayor desafío en este emprendimiento está en &lt;span style="color:#ff9900;"&gt;&lt;em&gt;saber incorporar y mantener estos valores&lt;/em&gt;&lt;/span&gt;. Lo cual implica un trabajo de replanteo individual, de delegación de tareas, de acompañamiento, de promoción de la creatividad, de generación de espacios de intercambio, entre otras cosas.&lt;br /&gt;&lt;br /&gt;Creo que el entender que estos procesos implican pensar a largo plazo, esfuerzo y modificaciones en la mentalidad, en las costumbres, en las estructuras y en la mirada con que enfocamos las cosas, es una de las &lt;span style="color:#ff9900;"&gt;&lt;em&gt;principales claves&lt;/em&gt;&lt;/span&gt; para obtener buenos resultados.&lt;br /&gt;&lt;br /&gt;Ahora, sin dejar de lado un enfoque más “empresario”, qué beneficios veo en estos cambios en relación con la organización y la productividad ?&lt;br /&gt;&lt;br /&gt;• Mayor compromiso de todos&lt;br /&gt;• Mayor motivación&lt;br /&gt;• Mejoramiento del ambiente laboral&lt;br /&gt;• Mayor confianza entre los miembros del equipo&lt;br /&gt;• Mejoras en la comunicación&lt;br /&gt;• Hacer que los objetivos y la visión de la empresa sean sostenibles en el tiempo&lt;br /&gt;&lt;br /&gt;Me animo a decir también que todo este “movimiento” &lt;em&gt;&lt;span style="color:#ff9900;"&gt;trasciende los límites de la empresa y repercute en la relación con nuestros clientes&lt;/span&gt;&lt;/em&gt;, quienes, en definitiva, se benefician con los resultados que un equipo de trabajo motivado y “en sintonía” es capaz de producir.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Vale la pena?&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Considero que para empresas como la nuestra, donde el &lt;strong&gt;capital humano&lt;/strong&gt; es considerado uno de los puntos más importantes, &lt;em&gt;&lt;span style="color:#ff9900;"&gt;la inversión en este tipo de emprendimientos está más que justificada&lt;/span&gt;&lt;/em&gt; y muestra sus frutos en muchas áreas.&lt;br /&gt;&lt;br /&gt;Finalmente, creo que para “poner a rodar la maquinaria” en todo esto, el principal motor es &lt;strong&gt;ver y reconocer&lt;/strong&gt; la importancia que tienen estas cuestiones en nuestra vida cotidiana, cualquiera sea el carril por el que marche.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3732630541286744699-8848141161492440923?l=blog.tercerplaneta.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Ideas3p/~4/7lay0J0UTaE" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/Ideas3p/~3/7lay0J0UTaE/como-entendemos-el-crecimiento.html</link><author>noreply@blogger.com (Andrea Morales)</author><thr:total>0</thr:total><feedburner:origLink>http://blog.tercerplaneta.com/2010/07/como-entendemos-el-crecimiento.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3732630541286744699.post-8826237730653893111</guid><pubDate>Tue, 29 Jun 2010 19:33:00 +0000</pubDate><atom:updated>2010-07-30T12:06:13.052-03:00</atom:updated><title>¡Qué comience la sesión!</title><description>Resulta común que durante el almuerzo o en esos 5' que lleva batir el café o preparar el mate surjan temas o ideas interesantes que son para "&lt;span style="font-style: italic;"&gt;discutir entre todos&lt;/span&gt;", o al menos entre muchos; y, por lo general, se hace difícil buscar y encontrar el tiempo necesario para hacerlo, por lo que esas ideas quedan sin transmitir ni impulsar.&lt;br /&gt;Esto nos sucedió a nosotros, hemos de reconocerlo. Pero encontramos la solución y, como era lógico, la misma surgió en esos momentos de "recreo laboral".&lt;br /&gt;La propuesta fue tener reuniones cortas para charlar y debatir acerca de diferentes temas. Así surgió nuestro "&lt;span style="font-style: italic;"&gt;&lt;span style="font-weight: bold;"&gt;Cabildo Abierto&lt;/span&gt;&lt;/span&gt;", pensado como un espacio en el que se pudieran plantear problemas o inquietudes, discutir soluciones, propuestas o acciones a tomar y llegar a alguna conclusión con una solución rápidamente aplicable.&lt;br /&gt;&lt;br /&gt;El nombre elegido no fue al azar, ya que combina el nombre de la Avenida en la cual está nuestra oficina con el llamado a debate mediante la participación activa y sin límites de cualquier integrante de Tercer Planeta (3P) que quiera hacerlo.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;&lt;span style="font-weight: bold;"&gt;¿En qué consiste?&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;El término Cabildo Abierto no es nuevo, surge en la época del Virreinato del Río de La Plata en la cual algunos pobladores se reunían para tratar diversos temas.&lt;br /&gt;&lt;br /&gt;Nuestro &lt;span style="font-style: italic;"&gt;Cabildo Abierto&lt;/span&gt; consiste en hacer sesiones para debatir temas propuestos por los integrantes de 3P. Cada uno, al tener un tema a tratar, anota un título representativo en una Wiki. Fue designada la figura de &lt;span style="font-style: italic;"&gt;moderador&lt;/span&gt; quién es el encargado de seleccionar 2 o 3 temas propuestos para debatir en la siguiente sesión, estos temas pueden estar conectados o no; la particularidad de ellos es que el debate no debería llevar mas de 1 hora.&lt;br /&gt;&lt;br /&gt;Una vez seleccionados los temas, se proponen días y horarios (es deseable mas de 2 opciones para elegir) y cada interesado en participar se anota según su conveniencia. Aquel día-horario que tenga mas participantes será el día elegido para sesionar. Es fundamental que aquella persona que propuso el tema asista a la sesión ya que es la encargada de presentar el tema, impulsar el debate y anotar las conclusiones.&lt;br /&gt;&lt;br /&gt;Al comenzar la sesión, se expone cada tema, se lo discute y, al dar cierre al debate, se anotan las conclusiones propuestas en la Wiki. En caso de requerir un seguimiento, la persona que propuso el tema tendrá la responsabilidad de hacerlo.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;&lt;span style="font-weight: bold;"&gt;Anotando temas&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;Los temas a proponer pueden ser muy variados, ellos surgen de la motivación personal de mejorar algo que vemos y sentimos puede ser mejorado o revisado. Por supuesto dado que cada persona tiene al respecto una visión distinta, un enfoque distinto, esto es lo que enriquecerá la gama de tipos de temas propuestos.&lt;br /&gt;&lt;br /&gt;Se pueden proponer temas que traten asuntos relacionados con la metodología de trabajo o con cuestiones técnicas del desarrollo. También pueden sumarse aquellas cuestiones que tienen que ver con la convivencia o el espacio físico en el que nos encontramos. En definitiva, vale anotar cualquier tema que cada uno quiera tratar en una sesión de Cabildo Abierto.&lt;br /&gt;&lt;br /&gt;Nosotros, en particular, hemos presentado diversos temas. Algunos de ellos fueron:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Cómo manejamos el Collate en SQLServer?&lt;/li&gt;&lt;li&gt;Timeboxing (como afecta la calidad, como tenerlo en cuenta en la planificación, como prever y manejar imprevistos, etc)&lt;/li&gt;&lt;li&gt;Equipar lo necesario para poder hacer reuniones remotas&lt;/li&gt;&lt;li&gt;Cómo mejorar nuestra relación con el cliente?&lt;/li&gt;&lt;li&gt;Cambiar las cortinas&lt;/li&gt;&lt;/ul&gt;por citar algunos títulos.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;&lt;span style="font-weight: bold;"&gt;Conclusiones&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;Es importante saber que existe un epacio en el que se puede proponer y accionar esas propuestas. El Cabildo Abierto intenta ser eso precisamente: un espacio en el cual se planteen y canalicen las inquietudes de todos y se busquen las respuestas y soluciones en forma conjunta.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3732630541286744699-8826237730653893111?l=blog.tercerplaneta.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Ideas3p/~4/eV6LFaURTGo" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/Ideas3p/~3/eV6LFaURTGo/que-comience-la-sesion_29.html</link><author>noreply@blogger.com (Nora Martinez)</author><thr:total>0</thr:total><feedburner:origLink>http://blog.tercerplaneta.com/2010/06/que-comience-la-sesion_29.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3732630541286744699.post-5067336697248028538</guid><pubDate>Thu, 18 Mar 2010 16:16:00 +0000</pubDate><atom:updated>2010-07-22T12:07:34.239-03:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Html5</category><category domain="http://www.blogger.com/atom/ns#">Internet Explorer</category><category domain="http://www.blogger.com/atom/ns#">ASP.NET</category><category domain="http://www.blogger.com/atom/ns#">Silverlight</category><title>HTML5, un paso más cerca</title><description>&lt;h3&gt;Html5: Html para aplicaciones web&lt;/h3&gt;&lt;p&gt;Desde hace mucho tiempo, oímos culpar de los problemas intrínsicos de las aplicaciones web, a la naturaleza “document-oriented” de la web. La web fue pensada originalmente como una red para compartir documentos “hipervinculados”, y no como plataforma de aplicaciones distribuídas. De hecho fue éste el &lt;a href="http://www.google.com/googlebooks/chrome/" target="_blank"&gt;argumento expuesto por Google en forma de historieta&lt;/a&gt; para lanzar &lt;a href="http://www.google.com/chrome" target="_blank"&gt;Chrome&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Para subsanar esta brecha surgieron una gran variedad de tecnologías, como javascript, Java Applets, Ajax, Flash, y más recientemente &lt;a href="http://gears.google.com/" target="_blank"&gt;Google Gears&lt;/a&gt;, &lt;a href="http://java.sun.com/javafx/" target="_blank"&gt;Java FX&lt;/a&gt; y &lt;a href="http://www.microsoft.com/silverlight/" target="_blank"&gt;Silverlight&lt;/a&gt; con la intención de crear en los browsers lo que se conoce como Rich Clients, clientes que permitan una experiencia de usuario similar a la de una aplicación de escritorio, con todas la ventajas de la web.&lt;/p&gt;&lt;p&gt;Sin embargo en todo este tiempo,  el “poder legislativo” de la web, la &lt;a href="http://www.w3.org/" target="_blank"&gt;W3C&lt;/a&gt;, no se quedó de brazos cruzados, y como es de esperar, respondieron con un estándar, tomándose su tiempo. La respuesta de la W3C fue: &lt;a href="http://dev.w3.org/html5/spec/Overview.html" target="_blank"&gt;HTML5&lt;/a&gt;&lt;/p&gt;&lt;p&gt;HTML5 traerá muchas novedades, pero lo importante, la idea que está detrás de la mayoría de ellas, es la creación de aplicaciones web “ricas” en nuestros browsers. Para muestra basta un botón:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="color:#000000;"&gt;Graficos vectoriales, animaciones y efectos visuales más avanzados&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="color:#000000;"&gt;Almacenamiento local en el browser, no sólo como diccionarios, también en forma de bases de datos SQL, y otras facilidades para aplicaciones “offline/online”&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="color:#000000;"&gt;WebWorkers, tareas asincrónicas, y un sistema de mensajería entre ellas. &lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="color:#000000;"&gt;Navegación Ajax&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="color:#000000;"&gt;Streaming de audio y video&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="color:#000000;"&gt;DOM Events, los elementos de un documento html, expondrán una serie eventos (ej: div.resize)&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="color:#000000;"&gt;Drag &amp;amp; Drop&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="color:#000000;"&gt;Tags semánticos asociados a aplicaciones como: &amp;lt;progress&amp;gt;, &amp;lt;meter&amp;gt;, &amp;lt;command&amp;gt;, &amp;lt;datalist&amp;gt;, &amp;lt;output&amp;gt;, y nuevos tipos de campos para formularios (&amp;lt;input&amp;gt;) como “datetime”, “range”, “search”, etc.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="color:#000000;"&gt;varios etc.&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt; &lt;/p&gt;&lt;p&gt;A esta altura, resulta evidente que tener soporte para todo esto, de forma nativa en HTML, se ve como una amenaza para todos los que proveen estos features actualmente mediante plugins, como Flash, Java FX, Silverlight y otros. &lt;/p&gt;&lt;p&gt;&lt;span style="color:#000000;"&gt;HTML5 todavía está en pañales, y se acerca lentamente, sin embargo &lt;a href="http://en.wikipedia.org/wiki/Comparison_of_layout_engines_(HTML_5)" target="_blank"&gt;la mayoría de los browsers ya soportan varios features de HTML5&lt;/a&gt;.&lt;/span&gt;&lt;/p&gt;&lt;p&gt; &lt;/p&gt;&lt;h3&gt;&lt;span style="color:#000000;"&gt;IE9, Podría Microsoft estar suicidando Silverlight?&lt;/span&gt;&lt;/h3&gt;&lt;p&gt;Con la salida de IE8, Microsoft empezó a soportar algunos features de HTML5, sin embargo este era muy limitado, y con la ausencia del elemento &amp;lt;canvas&amp;gt; que permite la inclusión de gráficos vectoriales, se especuló sobre una estratégica defensa de Silverlight.&lt;/p&gt;&lt;p&gt;Sin embargo, con la llegada de IE9 están anunciando un soporte para HTML5 mucho más completo, tanto que publicaron &lt;a href="http://ie.microsoft.com/testdrive/" target="_blank"&gt;una pagina para probar entre otras cosas el soporte HTML5 de IE9&lt;/a&gt; (incluyendo animaciones y gráficos vectoriales con aceleración por hardware).&lt;/p&gt;&lt;p&gt;Y a esto se suma un nuevo engine Javascript, que pretende ponerse a tiro con el resto con &lt;a href="http://ie.microsoft.com/testdrive/benchmarks/SunSpider/Default.html" target="_blank"&gt;benchmarkings prometedores&lt;/a&gt;. Esto me recuerda un comentario sobre &lt;a href="http://blog.salias.com.ar/2008/09/javascript-la-programacin-del-futuro.html" target="_blank"&gt;el futuro de Javascript&lt;/a&gt; de Martín Salías.&lt;/p&gt;&lt;p&gt;Para los que trabajamos con .Net surgen ahora dudas existenciales sobre como afectará esto el futuro de Silverlight.&lt;/p&gt;&lt;p&gt;&lt;img style="DISPLAY: block; FLOAT: none; MARGIN-LEFT: auto; MARGIN-RIGHT: auto" src="http://www.extendiendoelreino.com/img/desanimo.JPG" /&gt; &lt;/p&gt;&lt;p&gt;&lt;span style="color:#000000;"&gt;Sin duda la familiaridad del framework .Net, C#, y la integración con VisualStudio son la panacea para los desarrolladores que ya trabajamos con .Net, &lt;/span&gt;&lt;span style="color:#000000;"&gt;sin embargo, ¿Qué features realmente distintivos tendrá Silverlight para los usuarios?&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.microsoft.com/silverlight/features/" target="_blank"&gt;Gráficos 3D, Out-of-browser y Smooth Streaming&lt;/a&gt;?&lt;/p&gt;&lt;p&gt;Quizás todavía sea solo futurología, pero la llegada de IE9 nos acerca bastante a la pregunta: &lt;/p&gt;&lt;p&gt;¿Cuál será el lugar que ocupará Silverlight (y otras RIU) con la llegada de HTML5?.&lt;/p&gt;&lt;p&gt; &lt;/p&gt;&lt;h3&gt;&lt;span style="color:#000000;"&gt;Profecía autocumplida: Google + Apple + Microsoft&lt;/span&gt;&lt;/h3&gt;&lt;p&gt;Ya no hace falta decirlo, a esta altura, HTML5 será un caso evidente de profecía autocumplida, no sólo por tratarse de un estándar de la W3C, sino por contar con el apoyo de Google (además de incluir soporte en Chrome, decidió abandonar Google Gears, por considerarlo un subset de lo que HTML5 proveerá y creo una versión HTML5 de YouTube), Apple (soporte en Safari, que incluirá IPhones que actualmente no soportan Flash), y finalmente Microsoft con la llegada IE9.&lt;/p&gt;&lt;p&gt;Falta aún saber cuanto falta para que sea soportado completamente por los browsers más populares, y para que nuestras IDEs nos permitan aprovecharlo.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3732630541286744699-5067336697248028538?l=blog.tercerplaneta.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Ideas3p/~4/w7l1ylBQKc4" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/Ideas3p/~3/w7l1ylBQKc4/html5-un-paso-mas-cerca.html</link><author>noreply@blogger.com (Benjamin Eidelman)</author><thr:total>0</thr:total><feedburner:origLink>http://blog.tercerplaneta.com/2010/03/html5-un-paso-mas-cerca.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3732630541286744699.post-7662955392339753754</guid><pubDate>Mon, 30 Nov 2009 16:18:00 +0000</pubDate><atom:updated>2010-07-22T12:08:23.499-03:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Metodologias</category><category domain="http://www.blogger.com/atom/ns#">Agile</category><category domain="http://www.blogger.com/atom/ns#">Timeboxing</category><category domain="http://www.blogger.com/atom/ns#">Time Management</category><title>¿Y si jugamos a que hacemos software?</title><description>&lt;p&gt;Desde hace un tiempo, estoy dando una mirada de vez en cuando a una revista online sobre metodologías ágiles en portugués. &lt;a href="http://www.visaoagil.com/" target="_blank"&gt;Visão Ágil&lt;/a&gt;, como tarea hogareña del curso portugués que estoy haciendo, y con la intención de leer un poco sobre este tema (como dice la poco ecológica metáfora: matar dos pájaros de un tiro).&lt;/p&gt;&lt;p&gt; &lt;/p&gt;&lt;h4&gt;La técnica del Tomate&lt;/h4&gt;&lt;p&gt;En el blog de esta revista encontré recientemente un &lt;a href="http://visaoagil.wordpress.com/2009/11/20/pensamentos-sobre-a-tecnica-pomodoro/" target="_blank"&gt;artículo sobre la “Técnica Pomodoro”&lt;/a&gt; de Manoel Pimentel. La Técnica Pomodoro se utiliza para la administración personal del tiempo, y está inspirada en ideas de las metodologías ágiles, como TimeBoxing y el uso de herramientas de “baja tecnología”, puntualmente: papel, lápiz y un timer de cocina. &lt;/p&gt;&lt;p&gt; &lt;/p&gt;&lt;p&gt; &lt;/p&gt;&lt;p align="center"&gt;&lt;img style="BORDER-BOTTOM: 0px; BORDER-LEFT: 0px; DISPLAY: inline; BORDER-TOP: 0px; BORDER-RIGHT: 0px" title="tomato_timer1" border="0" alt="tomato_timer1" src="http://lh4.ggpht.com/_GcXPWR_goXk/SxPxE0DlenI/AAAAAAAAAhA/jLy5n_3K6SY/tomato_timer1%5B5%5D.jpg?imgmax=800" width="163" height="163" /&gt; &lt;img style="BORDER-BOTTOM: 0px; BORDER-LEFT: 0px; DISPLAY: inline; BORDER-TOP: 0px; BORDER-RIGHT: 0px" title="paper-pencil" border="0" alt="paper-pencil" src="http://lh3.ggpht.com/_GcXPWR_goXk/SxPxFMR_bqI/AAAAAAAAAhE/jFeXA-rV6AA/paper-pencil%5B5%5D.jpg?imgmax=800" width="167" height="166" /&gt; &lt;/p&gt;&lt;p&gt;&lt;em&gt;Estos timers con forma de tomate (pomodoro en italiano) son los que dan nombre a la técnica&lt;/em&gt;&lt;/p&gt;&lt;p&gt; &lt;/p&gt;&lt;p&gt;Si bien ese artículo tiene un &lt;a href="http://en.wikipedia.org/wiki/Mind_map" target="_blank"&gt;mindmap&lt;/a&gt; que resume muy bien los puntos clave, lo que más destacaría es la simplicidad, el énfasis en mantener el foco, y la asignación rígida de tiempos (véase TimeBoxing) tanto a las tareas como a los intervalos de descanso entre éstas.&lt;/p&gt;&lt;p&gt; &lt;/p&gt;&lt;p&gt;Con respecto a este último punto, el libro oficial que puede descargarse de &lt;a href="http://www.pomodorotechnique.com/"&gt;http://www.pomodorotechnique.com&lt;/a&gt; destaca la importancia de estos intervalos para “asimilar lo aprendido y hacer algo bueno por tu salud”, como caminar, ejercicios de respiración o contar un chiste. Interrumpir este período de descanso con cualquier tarea que implique un esfuerzo mental, “bloqueara el constructivo proceso mental de integración necesario para estar alerta y listo para el proximo ciclo”. Una especie de build de integración que se ejecuta periódicamente en background en nuestro cerebro.&lt;/p&gt;&lt;p&gt; &lt;/p&gt;&lt;h4&gt;El último que se escondió arma el release!&lt;/h4&gt;&lt;p&gt;Sin embargo lo que quería mencionar en este artículo (y por eso el título), es algo que me parece muy valioso y puede pasar desapercibido a primera vista. Es el espíritu &lt;strong&gt;lúdico&lt;/strong&gt; que hay detrás de esta técnica (vi este punto escrito en el mindmap del artículo de Pimentel).&lt;/p&gt;&lt;p&gt;Una idea que tambien está implícita en varias técnicas utilizadas en metodologías ágiles.&lt;/p&gt;&lt;p&gt; &lt;/p&gt;&lt;p&gt;Creo que en esta manera de encarar el trabajo (y cualquier otra cosa) hay mucho más jugo de lo que se cree habitualmente. Especialmente en ambientes que promueven la productividad y la creatividad.&lt;/p&gt;&lt;p&gt;No hay que confundirlo con una forma de hacer apología de la competencia (que casi nunca es sana), o de esquivar el bulto a las tareas tediosas. Se trata más bien de evitar que nuestro trabajo sea una letárgica marcha atrás de la recompensa monetaria de fin de mes (Dispositivo del burro y la zanahoria),&lt;/p&gt;&lt;p&gt; &lt;/p&gt;&lt;p&gt;&lt;img style="BORDER-BOTTOM: 0px; BORDER-LEFT: 0px; DISPLAY: block; FLOAT: none; MARGIN-LEFT: auto; BORDER-TOP: 0px; MARGIN-RIGHT: auto; BORDER-RIGHT: 0px" title="burro_zanahoria" border="0" alt="burro_zanahoria" src="http://lh5.ggpht.com/_GcXPWR_goXk/SxPxFg3jAkI/AAAAAAAAAhI/bX8AVt6Hq8Q/burro_zanahoria%5B4%5D.gif?imgmax=800" width="200" height="205" /&gt; &lt;/p&gt;&lt;p&gt; &lt;/p&gt;&lt;p&gt;para empezar a disfrutar del día a día, transformándolo en un juego constructivo, hasta casi “sentir que no trabajamos”.&lt;/p&gt;&lt;p&gt;&lt;a href="http://lh6.ggpht.com/_GcXPWR_goXk/SxPxGIByFXI/AAAAAAAAAhM/qon5xs9cqS0/s1600-h/burrojugando%5B3%5D.jpg"&gt;&lt;img style="BORDER-BOTTOM: 0px; BORDER-LEFT: 0px; DISPLAY: block; FLOAT: none; MARGIN-LEFT: auto; BORDER-TOP: 0px; MARGIN-RIGHT: auto; BORDER-RIGHT: 0px" title="burrojugando" border="0" alt="burrojugando" src="http://lh5.ggpht.com/_GcXPWR_goXk/SxPxGk7P1tI/AAAAAAAAAhQ/P5ueqC_UeX4/burrojugando_thumb%5B1%5D.jpg?imgmax=800" width="240" height="180" /&gt;&lt;/a&gt; &lt;/p&gt;&lt;p&gt;Sin duda el tema, da para mucho más que este artículo (y para autores más calificados!) pero la intención era traer a colación el tema, y tratar de poner en evidencia, o preguntar, ¿Cuántas cosas hacemos (o podemos hacer) en este sentido? &lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3732630541286744699-7662955392339753754?l=blog.tercerplaneta.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Ideas3p/~4/Q7BZiUw3j9k" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/Ideas3p/~3/Q7BZiUw3j9k/y-si-jugamos-que-hacemos-software.html</link><author>noreply@blogger.com (Benjamin Eidelman)</author><thr:total>1</thr:total><feedburner:origLink>http://blog.tercerplaneta.com/2009/11/y-si-jugamos-que-hacemos-software.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3732630541286744699.post-3939478359948820844</guid><pubDate>Fri, 13 Nov 2009 20:19:00 +0000</pubDate><atom:updated>2009-11-13T17:25:19.167-03:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Metodologias</category><category domain="http://www.blogger.com/atom/ns#">Scrum</category><category domain="http://www.blogger.com/atom/ns#">Agile</category><title>"La columna del medio"</title><description>&lt;h4&gt;Aportando dinámica a la pizarra&lt;/h4&gt;  &lt;p&gt;En nuestro equipo de trabajo contamos con los ambientes de desarrollo (pruebas de unidad) y de QA (pruebas de integración).&lt;/p&gt;  &lt;p&gt;Desde hace tiempo venimos aplicando prácticas de SCRUM. Con el uso de la pizarra notamos la necesidad de diferenciar las tareas cuyo desarrollo se encontraba en progreso de aquellas terminadas y a la espera de un pasaje al ambiente de QA.&lt;/p&gt;  &lt;p&gt;Esto era debido a que cada vez que terminábamos una tarea la pasábamos a la columna de “Test”, ocasionando muchas veces confusiones ya que no teníamos manera de saber si las tareas que se encontraban en esta columna estaban contempladas dentro del último build.&lt;/p&gt;  &lt;p&gt;Durante un tiempo intentamos hacer el pasaje de papelitos solamente cuando hacíamos el build al ambiente QA, pero para eso contábamos con nuestra memoria para saber que tareas estaban completas, lo que no siempre resultaba con éxito por que… seamos sinceros… esta no siempre nos era fiel =)&lt;/p&gt;  &lt;p&gt;Entonces un día, durante la retrospectiva de uno de nuestros proyectos tuvimos la siguiente maravillosa idea para arribar a una solución: &lt;/p&gt;  &lt;p&gt;Agregar una columna intermedia entre DESA (In progress) y QA (Test) que nos permitiera saber, de forma inmediata, cuáles eran las tareas que estaban listas pero que todavía no estaban disponibles para ser probadas en QA…&lt;/p&gt;  &lt;h4&gt;¿Como funciona?&lt;/h4&gt;  &lt;p&gt;Cada vez que el desarrollador termina alguna tarea, mueve el papelito correspondiente de “In Progress” a la columna “DESA/TEST”(la columna del medio) indicando de esta manera que el desarrollo ha finalizado y estará disponible en el próximo build para su prueba.&lt;/p&gt;  &lt;p&gt;Si bien debo reconocer que en un principio tuve mis dudas acerca de si la nueva columna iba a servir de algo, el uso de la misma nos demostró gran efectividad.&lt;/p&gt;  &lt;p&gt;Su implementación acarreó las siguientes mejoras:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Nos permitió tener una noción más precisa del avance del sprint, rompiendo con la sensación de un “avance estático” generado por la acumulación de tareas en la columna de desarrollo. &lt;/li&gt;    &lt;li&gt;Da una idea más clara al desarrollador de qué tareas le falta completar y cuáles completó. &lt;/li&gt;    &lt;li&gt;Brinda al tester la certeza de saber qué estará para probar. &lt;/li&gt;    &lt;li&gt;Es mucho más fácil decidir en qué momento hacer un pasaje de ambiente. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;&lt;font color="#555555"&gt;&lt;/font&gt;&lt;/p&gt;  &lt;h4&gt;Resultado final&lt;/h4&gt;  &lt;p&gt;&lt;font color="#555555"&gt;&lt;a href="http://lh4.ggpht.com/_F67APmX9ii0/Sv2_ZgsYKmI/AAAAAAAAABY/3vnrsQ2Kv7k/s1600-h/DSC01508%5B2%5D.jpg"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="La pizarra" border="0" alt="La pizarra" src="http://lh3.ggpht.com/_F67APmX9ii0/Sv2_aFWlxnI/AAAAAAAAABc/V8-XeQ8EjcQ/DSC01508_thumb.jpg?imgmax=800" width="244" height="184" /&gt;&lt;/a&gt;&amp;#160;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#555555"&gt;&lt;/font&gt;&lt;/p&gt;  &lt;h4&gt;Conclusiones&lt;/h4&gt;  &lt;p&gt;Por nuestra experiencia, la incorporación de esta nueva columna trae grandes beneficios a la dinámica del equipo, agilizando la comunicación. Los invitamos a probar esta alternativa y que compartan con nosotros sus experiencias.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3732630541286744699-3939478359948820844?l=blog.tercerplaneta.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Ideas3p/~4/c3RsqJUNZWA" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/Ideas3p/~3/c3RsqJUNZWA/columna-del-medio-aportando-dinamica-la.html</link><author>noreply@blogger.com (Matías Timossi)</author><thr:total>0</thr:total><feedburner:origLink>http://blog.tercerplaneta.com/2009/11/columna-del-medio-aportando-dinamica-la.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3732630541286744699.post-3679111601919045866</guid><pubDate>Wed, 08 Jul 2009 11:54:00 +0000</pubDate><atom:updated>2009-07-08T08:57:38.263-03:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Metodologias</category><category domain="http://www.blogger.com/atom/ns#">Agile</category><category domain="http://www.blogger.com/atom/ns#">Timeboxing</category><category domain="http://www.blogger.com/atom/ns#">Planificacion</category><title>Sobre Ratas, Elefantes y TimeBoxing</title><description>&lt;p&gt; &lt;/p&gt;  &lt;p&gt;La semana pasada nos dispusimos a realizar un cronograma de entregas para las próximas semanas de uno de nuestros proyectos, así que me reuní con el resto del  grupo involucrado, y empezamos una planificación, haciendo una revisión rápida de las historias de usuario prioritarias en nuestro backlog.&lt;/p&gt;  &lt;p&gt;Acto seguido, ubicaríamos estas historias de usuario según sus “tamaños” , prioridades y dependencias, en hipotéticos sprints, manteniendo presente el concepto de &lt;a href="http://www.proyectosagiles.org/timebox"&gt;TimeBoxing&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt; &lt;/p&gt;  &lt;h4&gt;La bolsa de Gatos&lt;/h4&gt;  &lt;p&gt;La lista resultó ser bastante extensa, y estimar el esfuerzo requerido por cada ítem, se volvía un poco confuso. Eran demasiado heterogéneas (lo que comúnmente llamamos bolsa de gatos).&lt;/p&gt;  &lt;p&gt;Era necesario dividir un poco las aguas y separar cosas como “cambiar el color de fondo del campo X” de “diseñar un generador de fusión en frío”.&lt;/p&gt;  &lt;p&gt;Creo que lo más peligroso de esto es que camufladas en medio de la estampida de historias de usuario más pequeñas, podían pasar desapercibidas las más pesadas o de más difícil estimación.&lt;/p&gt;  &lt;p&gt; &lt;/p&gt;  &lt;h4&gt;Una metodología de planificación para toda la familia&lt;/h4&gt;  &lt;p&gt;Normalmente utilizamos para estimar el esfuerzo requerido de cada historia de usuario, cartas de &lt;a href="http://en.wikipedia.org/wiki/Planning_poker"&gt;Planning Poker&lt;/a&gt; (gracias a &lt;a href="http://www.planningpoker.com/"&gt;Mountain Goat&lt;/a&gt;) al comienzo de cada sprint, sin embargo esta planificación prolongada requería de una primera clasificación grosera.&lt;/p&gt;  &lt;p&gt;Fue así que con el ánimo de innovar un poco y de hacer la reunión un poco más divertida inventamos (y ofrecemos sin patente alguna) un método de planificación que podría llamarse “El Arca de Noé”.&lt;/p&gt;  &lt;p&gt;Es importante que participen todos los miembros del equipo (funcionales, desarrolladores, líder de proyecto, etc. con sus diferentes visiones) y consiste básicamente en 2 etapas:&lt;/p&gt;  &lt;p&gt; &lt;/p&gt;  &lt;h4&gt;1. Clasificación&lt;/h4&gt;  &lt;p&gt;En esta etapa se toma cada una de las historias de usuario, y luego de una breve descripción, y discusión sobre sus implicancias (aquí típicamente es el momento de que un desarrollador advierta sobre dificultades posibles, o calle para siempre :)). se procede a su clasificación.&lt;/p&gt;  &lt;p&gt;Las tareas se ubicarán en 3 grandes categorías de acuerdo al esfuerzo que representa la tarea, para hacerlo más entretenido decidimos identificar estas categorías con especies animales:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;&lt;strong&gt;Rata&lt;/strong&gt;: Con este nombre identificamos historias de usuario más rápidas de resolver y que no requieren casi ningún análisis sobre la forma de implementarlas. Típicamente cambios estéticos, cambios de configuración,  pseudo-duplicar un componente ya existente, etc. &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Perro&lt;/strong&gt;: En esta categoría van tareas que implican un cierto análisis y/o un trabajo más cuidadoso o extenso que las anteriores. &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Elefante&lt;/strong&gt;: Finalmente elefantes son las historias de usuario más pesadas, generalmente requieren un esfuerzo de diseño, o hay muchas dudas sobre la forma implementarlo, o implica un riesgo díficil de estimar. &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;&lt;span style="color:#555555;"&gt;&lt;a href="http://lh6.ggpht.com/_GcXPWR_goXk/SlSI0siPTbI/AAAAAAAAAXc/-kXlKgDIsIU/s1600-h/MouseElephant2.jpg"&gt;&lt;img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="MouseElephant" border="0" alt="MouseElephant" src="http://lh5.ggpht.com/_GcXPWR_goXk/SlSI1OpcDsI/AAAAAAAAAXg/7-CEutfscpk/MouseElephant_thumb.jpg?imgmax=800" width="244" height="184" /&gt;&lt;/a&gt; &lt;/span&gt;&lt;/p&gt;  &lt;p&gt;&lt;span style="color:#555555;"&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;&lt;span class="Apple-style-span"  style="color:#555555;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="color:#555555;"&gt;Finalmente es importante entender que tanto el número de categorías (3), como los criterios para ubicar un historia de usuario en cada categoría, son parámetros que deben ajustarse con el tiempo a las particularidades de cada equipo.&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;&lt;span style="color:#555555;"&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p&gt; &lt;/p&gt;  &lt;h4&gt;2. Planificación&lt;/h4&gt;  &lt;p&gt;En esta etapa al igual que Noé con su Arca, es dónde tenemos que acomodar estos animales (o historias de usuario) en compartimientos finitos (o sprints). &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Advertencia&lt;/strong&gt;: Si la cantidad de sprints es limitada, es posible que algunas historias de usuario se pierdan en el diluvio universal.&lt;/p&gt;  &lt;p&gt;Para esto tenemos que sopesar diferentes criterios:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;span style="color:#000000;"&gt;Historias prioritarias para el cliente&lt;/span&gt; &lt;/li&gt;    &lt;li&gt;&lt;span style="color:#000000;"&gt;Dependencias entre éstas&lt;/span&gt; &lt;/li&gt;    &lt;li&gt;&lt;span style="color:#000000;"&gt;Recursos disponibles&lt;/span&gt; &lt;/li&gt;    &lt;li&gt;&lt;span style="color:#000000;"&gt;Imprevisibilidad o riesgo de una tarea (generalmente es preferible comenzar estas tareas lo antes posible para en caso de necesidad ajustar el rumbo a tiempo)&lt;/span&gt; &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;y otros que puedan ser particulares del proyecto.&lt;/p&gt;  &lt;p&gt;Aquí es dónde se aplican todas las metodologías de planificación que normalmente utilizamos.&lt;/p&gt;  &lt;p&gt;Por supuesto que la medida de cuántos “elefantes” entran en cada sprint, además de depender de los recursos disponibles en ese sprint, es algo que los miembros del equipo irán refinando con el paso del tiempo.&lt;/p&gt;  &lt;p&gt; &lt;/p&gt;  &lt;p&gt;El Resultado:&lt;/p&gt;  &lt;p&gt;&lt;img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="DSC01439_rr" border="0" alt="DSC01439_rr" src="http://lh5.ggpht.com/_GcXPWR_goXk/SlSI15D1fNI/AAAAAAAAAXk/5DFooaXRNp4/DSC01439_rr_thumb.jpg?imgmax=800" width="224" height="244" /&gt;&lt;/p&gt;  &lt;h5&gt; &lt;/h5&gt;  &lt;h4&gt;Conclusiones&lt;/h4&gt;  &lt;p&gt;Antes de empezar a dibujar Gantts, Cronogramas o un Análisis de Riesgo, se hace necesario hacer una primera pasada que identifique las historias de usuario clave. Esta variante simple resulta bastante divertida, lo cual en una larga planificación nunca está demás.&lt;/p&gt;  &lt;p&gt;Eso sí, una consecuencia inmediata y un poco vergonzosa, son expresiones del tipo; “Yo 2 elefantes en esta semana no me puedo comer, mejor empiezo agarro un elefante y voy intercalando con algunas ratitas” o “Me parece que nos estás vendiendo perro por rata”&lt;/p&gt;  &lt;p&gt; &lt;/p&gt;  &lt;p&gt;Quién se anima a compartir otras variantes de este tipo?&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3732630541286744699-3679111601919045866?l=blog.tercerplaneta.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Ideas3p/~4/Z0whgcajREE" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/Ideas3p/~3/Z0whgcajREE/sobre-ratas-elefantes-y-timeboxing.html</link><author>noreply@blogger.com (Benjamin Eidelman)</author><thr:total>2</thr:total><feedburner:origLink>http://blog.tercerplaneta.com/2009/07/sobre-ratas-elefantes-y-timeboxing.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3732630541286744699.post-187738207977977667</guid><pubDate>Mon, 16 Feb 2009 12:36:00 +0000</pubDate><atom:updated>2009-02-16T14:35:28.868-02:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">web.config</category><category domain="http://www.blogger.com/atom/ns#">Team Fundation Server</category><category domain="http://www.blogger.com/atom/ns#">TFS</category><category domain="http://www.blogger.com/atom/ns#">Source Control</category><title>Como excluir archivos de configuración de Source Control</title><description>&lt;span style="color:#000000;"&gt;Una pregunta que alguien se podría hacer al leer este artículo, es ¿porque voy a querer quitar los archivos de configuración del repositorio de código fuente?&lt;br /&gt;&lt;br /&gt;El objetivo de los Repositorios de Código es justamente ese, resguardar el código, los archivos de configuración son necesarios al ejecutar la aplicación, y muchas veces al compilarla, tal es el caso del &lt;em&gt;web.config&lt;/em&gt;, por este motivo necesitamos que sean parte del proyecto, pero tenerlos en el repositorio de código fuente nos puede traer algunos problemas.&lt;br /&gt;&lt;br /&gt;Uno de los inconvenientes ocurre en los procesos de Deployment, ya que los archivos de configuración, ente otras cosas, almacenan información referida al ambiente donde corre la aplicación:&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="color:#000000;"&gt;Desarrollo&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="color:#000000;"&gt;Qa&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="color:#000000;"&gt;Producción&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="color:#000000;"&gt;etc&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;span style="color:#000000;"&gt;y el repositorio almacena versiones del código, independientemente de los ambientes en donde se instale.&lt;br /&gt;&lt;br /&gt;En este sentido excluirlos, nos obliga a hacer un manejo especial con ellos en los diferentes pasajes de ambiente, que nos puede evitar errores. Por otro lado mientras estamos desarrollando, es bastante común hacer pruebas modificando los archivos de configuración, pruebas que nunca vamos a querer subir al repositorio de código (Ej.: apuntar la configuración a una Base de Datos local), si tenemos los archivos en el repositorio, es necesario hacer CECK OUT, para luego hacer UNDO PENDING CHANGES al finalizar la prueba. Esto, mas allá de ser una tarea tediosa para el desarrollador, es problemática si son muchos los que están trabajando al mismo tiempo.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Veamos cómo hacerlo&lt;/h3&gt;En este caso vamos a hacer un ejemplo utilizando como Repositorio de Código Fuente a &lt;strong&gt;Team Fundation Server&lt;/strong&gt;.&lt;br /&gt;&lt;br /&gt;En este ejemplo, voy a abrir la solución correspondiente al Sitio corporativo de Tercer Planeta &lt;a href="http://www.tercerplaneta.com/"&gt;http://www.tercerplaneta.com/&lt;/a&gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;, para excluir al &lt;em&gt;web.config&lt;/em&gt;, cabe aclarar que esto se puede aplicar también, en una aplicación WinForms, excluyendo el &lt;em&gt;app.config&lt;/em&gt;.&lt;br /&gt;&lt;br /&gt;Al abrir la solución vemos la siguiente estructura de carpetas y archivos desde Solution Explorer de &lt;strong&gt;Visual Studio 2008&lt;/strong&gt;.&lt;br /&gt;&lt;br /&gt;&lt;img id="BLOGGER_PHOTO_ID_5303376490676414306" style="DISPLAY: block; MARGIN: 0px auto 10px; WIDTH: 250px; CURSOR: hand; HEIGHT: 320px; TEXT-ALIGN: center" alt="" src="http://1.bp.blogspot.com/_gPVbIsAFkYs/SZlg0dzs52I/AAAAAAAAAHI/KSQX1IpQ-9s/s320/Untitled.jpg" border="0" /&gt;El primer paso consta de hacer una copia del&lt;em&gt; web.config,&lt;/em&gt; para luego renombrarlo como &lt;strong&gt;&lt;em&gt;web.config.template&lt;/em&gt;&lt;/strong&gt;. Este témplate nos sirve para almacenar la configuración que requiere la aplicación, en el también podríamos identificar de alguna manera, que cosas vamos a tener que modificar, cada vez que la aplicación se encuentre en un ambiente diferente.&lt;br /&gt;&lt;br /&gt;Para esto nos paramos sobre el archivo &lt;em&gt;web.config&lt;/em&gt; en el Solution Explorer, hacemos una copia del mismo y lo renombramos como lo dijimos anteriormente.&lt;br /&gt;&lt;br /&gt;&lt;img id="BLOGGER_PHOTO_ID_5303392503497990034" style="DISPLAY: block; MARGIN: 0px auto 10px; WIDTH: 266px; CURSOR: hand; HEIGHT: 320px; TEXT-ALIGN: center" alt="" src="http://1.bp.blogspot.com/_gPVbIsAFkYs/SZlvYiN3n5I/AAAAAAAAAHQ/wD_m0Qlkug0/s320/Untitled.jpg" border="0" /&gt;&lt;br /&gt;&lt;/span&gt;&lt;p&gt;&lt;span style="color:#000000;"&gt;Luego de subir los cambios, pasamos a excluir el &lt;em&gt;web.config&lt;/em&gt; de Source Control.&lt;br /&gt;&lt;br /&gt;Para ello, seleccionando el &lt;em&gt;web.config&lt;/em&gt; desde el Solution Explorer, debemos ir al punto de menú File / Source Control /&lt;strong&gt;Exclude web.config from Source Control&lt;/strong&gt; como se ve a continuación.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="color:#000000;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="color:#000000;"&gt;&lt;img id="BLOGGER_PHOTO_ID_5303393336756519394" style="DISPLAY: block; MARGIN: 0px auto 10px; WIDTH: 320px; CURSOR: hand; HEIGHT: 274px; TEXT-ALIGN: center" alt="" src="http://3.bp.blogspot.com/_gPVbIsAFkYs/SZlwJCWLweI/AAAAAAAAAHg/JM4N4CtBzMU/s320/Untitled.jpg" border="0" /&gt;Este último paso hace CHECK OUT del proyecto para marcar al &lt;em&gt;web.config&lt;/em&gt; como archivo excluido.&lt;br /&gt;&lt;br /&gt;Luego de guardar los cambios debemos eliminar definitivamente al &lt;em&gt;web.config&lt;/em&gt; de Source Control, para esto en la solapa Source Control Explorer de &lt;strong&gt;Visual Studio 2008&lt;/strong&gt;, debemos pararnos sobre el archivo &lt;em&gt;web.config&lt;/em&gt; y hacer Click Derecho / Delete.&lt;br /&gt;&lt;br /&gt;Si en este punto miramos la columna Pending Change, de la solapa Source Control Explorer vamos a ver que marca el archivo &lt;em&gt;web.config&lt;/em&gt; como Delete y además hace cambios sobre los archivos del proyecto.&lt;br /&gt;&lt;br /&gt;Como solo queremos quitarlo de Source Control y no del proyecto, lo que tenemos que hacer es desde el Source Control Explorer, deshacer los cambios sobre los archivos del proyecto.&lt;br /&gt;&lt;br /&gt;Para eso los seleccionamos y hacemos UNDO PENDING CHANGES como se muestra a continuación. &lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="color:#000000;"&gt;&lt;img id="BLOGGER_PHOTO_ID_5303394011395741346" style="DISPLAY: block; MARGIN: 0px auto 10px; WIDTH: 320px; CURSOR: hand; HEIGHT: 222px; TEXT-ALIGN: center" alt="" src="http://2.bp.blogspot.com/_gPVbIsAFkYs/SZlwwTktVqI/AAAAAAAAAHo/FKDHQyKtI2w/s320/Untitled.jpg" border="0" /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="color:#000000;"&gt;Luego hacemos CHECK IN sobre el &lt;em&gt;web.config&lt;/em&gt; , para podes borrarlo definitivamente.&lt;br /&gt;&lt;br /&gt;Estos últimos dos pasos, hacen que el &lt;em&gt;web.config&lt;/em&gt; desaparezca del árbol de Source Control, pero no lo excluye del proyecto web.&lt;br /&gt;&lt;br /&gt;Si ahora observamos nuevamente el Solution Explorer vamos a ver que el&lt;em&gt; web.config&lt;/em&gt; sigue apareciendo en la lista de archivos, pero ahora con dos iconos.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="color:#000000;"&gt;&lt;img id="BLOGGER_PHOTO_ID_5303394585592065970" style="DISPLAY: block; MARGIN: 0px auto 10px; WIDTH: 285px; CURSOR: hand; HEIGHT: 197px; TEXT-ALIGN: center" alt="" src="http://3.bp.blogspot.com/_gPVbIsAFkYs/SZlxRunx77I/AAAAAAAAAHw/8ddTjGmZ6c4/s320/Untitled.jpg" border="0" /&gt;El icono rojo indica que el archivo está excluido de Source Control, mientras que el icono amarillo nos dice que no lo tenemos actualmente en el disco local.&lt;br /&gt;&lt;br /&gt;El último paso consta de ir a nuestro disco local, hacer una copia del témplate que generamos en los pasos anteriores, y renombrarla como &lt;em&gt;web.config&lt;/em&gt;, de esta manera en el Solution Explorer solo veríamos el icono rojo.&lt;br /&gt;&lt;br /&gt;A partir de este momento el &lt;em&gt;web.config&lt;/em&gt;, está localmente y nunca se va a pisar cuando hagamos Get Latest Version. Es importante aplicar los cambios al Témplate cuando se necesite hacer un cambio en el &lt;em&gt;web.config&lt;/em&gt;, y avisar de esto al resto del equipo, para que lo actualice localmente.&lt;br /&gt;&lt;br /&gt;De esta manera, cada puesto de trabajo pasa a tener su copia del &lt;em&gt;web.config&lt;/em&gt;, que el desarrollador puede modificar cuando quiera, evitando hacer CHECK-OUT cada vez. Por otro lado, cada ambiente donde se instale la aplicación va a tener que tener su propio &lt;em&gt;web.config&lt;/em&gt;, la forma de obtenerlo en este caso dependerá del mecanismo que utilicemos como publicación. &lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="color:#000000;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3732630541286744699-187738207977977667?l=blog.tercerplaneta.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Ideas3p/~4/1v_lM14uuhA" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/Ideas3p/~3/1v_lM14uuhA/como-excluir-archivos-de-configuracion.html</link><author>noreply@blogger.com (Ricardo D. de Guzmán)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/_gPVbIsAFkYs/SZlg0dzs52I/AAAAAAAAAHI/KSQX1IpQ-9s/s72-c/Untitled.jpg" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://blog.tercerplaneta.com/2009/02/como-excluir-archivos-de-configuracion.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3732630541286744699.post-8892822083038595854</guid><pubDate>Fri, 05 Sep 2008 20:09:00 +0000</pubDate><atom:updated>2008-09-05T17:09:20.571-03:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">WinForms</category><category domain="http://www.blogger.com/atom/ns#">DataGridView</category><category domain="http://www.blogger.com/atom/ns#">DragAndDrop</category><title>Drag and Drop en WinForms</title><description>&lt;p&gt;Hace unos d&amp;#237;as durante un curso de capacitaci&amp;#243;n un cliente nos coment&amp;#243; que necesitaban implementar una grilla cuyas filas fueran reordenables mediante &amp;quot;drag and drop&amp;quot; (es decir arrastrando y soltando) y vergonzosamente tuvimos que reconocer que apenas ten&amp;#237;amos una (muy vaga) idea te&amp;#243;rica de como implementarlo.&lt;/p&gt;  &lt;p&gt;A la semana siguiente con la intenci&amp;#243;n de dar un respuesta un poco m&amp;#225;s s&amp;#243;lida, dediqu&amp;#233; unos minutos a leer un poco y dado que resultaba f&amp;#225;cil, arm&amp;#233; una peque&amp;#241;a demo para probar el uso de Drag and Drop en WinForms.&lt;/p&gt;  &lt;h5&gt;Demo&lt;/h5&gt;  &lt;p&gt;El c&amp;#243;digo puede descargarse de &lt;a href="http://cid-2e532b202f3287ba.skydrive.live.com/self.aspx/P%c3%bablico/DragNDropDemo/DragDropDemo1Sln.zip" target="_blank"&gt;aqu&amp;#237;&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;En el ejemplo hay un simple DataGridView al cual se puede arrastrar un archivo Xml, cuyo formato sea &amp;quot;convertible&amp;quot; a DataSet, con lo cual la tabla (la primera si hay m&amp;#225;s de una) se muestra en la grilla (en el ejemplo inclu&amp;#237; un Items.xml que sirve a tal fin).&lt;/p&gt;  &lt;p&gt;Una vez que tengo filas en la grilla, puedo arrastrar filas con el mouse para modificando el orden.&lt;/p&gt;  &lt;p&gt;Esto muestra como realizar Drag n Drop, desde una aplicaci&amp;#243;n externa (Explorador de Windows por ejemplo) hacia un control WinForms propio, y como hacerlo desde y hacia la misma aplicaci&amp;#243;n.&lt;/p&gt;  &lt;h5&gt;Paso a Paso&lt;/h5&gt;  &lt;ul&gt;   &lt;li&gt;Lo primero que necesitamos es iniciar el &amp;quot;arrastre&amp;quot;, y una forma posible es en el evento MouseMove del control de origen, para esto agregue en el c&amp;#243;digo de este evento una llamada al m&amp;#233;todo &amp;quot;DoDragDrop&amp;quot; (cuando el bot&amp;#243;n izquierdo est&amp;#225; presionado, etc.), al cual se le debe pasar como argumentos el objeto a arrastrar (en mi caso el DataGridViewRow que se esta arrastrando), que simplemente sirve como informaci&amp;#243;n para el control de destino, y la acci&amp;#243;n deseada, por ej. &amp;quot;Move&amp;quot;.&lt;/li&gt;    &lt;li&gt;Con esto ya podemos tomar una fila y llevarla por toda la pantalla, sin embargo todav&amp;#237;a nadie acepta nuestro &amp;quot;DataGridViewRow&amp;quot;, con la cual el cursor muestra el conocido s&amp;#237;mbolo de prohibido.&lt;/li&gt;    &lt;li&gt;Lo que necesitamos ahora es que nuestra grilla diga &amp;quot;Vienes con un DataGridViewRow? Puedes soltarlo aqu&amp;#237;!&amp;quot;, lo que hace que el cursor se transforme en uno m&amp;#225;s amigable indicando la acci&amp;#243;n permitida.&lt;/li&gt;    &lt;li&gt;Para esto hay que agregar c&amp;#243;digo en el evento &amp;quot;DragOver&amp;quot;, en este una vez que me aseguro que el objeto arrastrado es una DataGridViewRow, perteneciente a mi misma grilla, informo mediante un argumento del evento &amp;quot;DragOver&amp;quot; que la acci&amp;#243;n permitida es (como fue solicitado) &amp;quot;Move&amp;quot;.&lt;/li&gt;    &lt;li&gt;Finalmente tengo que hacerlo cuando el objeto es soltado, esto ocurre en el evento &amp;quot;DragDrop&amp;quot;, en el cual verifico nuevamente que estoy recibiendo una DataGridViewRow de mi propia grilla, y realizo finalmente el movimiento de filas (lo cual depender&amp;#225; de la fuente de datos de la grilla (DataTable, DataView, List, etc.).&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;De forma similar en DragOver y DragDrop espero un objeto con formato &amp;quot;FileName&amp;quot; (el cual nos env&amp;#237;a el Windows Explorer) para aceptar archivos .xml sobre la grilla. Lo cual muestra que el origen y destino pueden estar en aplicaciones separadas, y tecnolog&amp;#237;as diferentes, ya que Drag and Drop es una funcionalidad propia del Sistema Operativo.&lt;/p&gt;  &lt;p&gt;Esto por supuesto no abarca todas las posibilidades como por ejemplo &lt;a href="http://blog.paranoidferret.com/index.php/2008/01/30/csharp-tutorial-how-to-use-custom-cursors/" target="_blank"&gt;mostrar un icono personalizado durante el arrastre&lt;/a&gt;, arrastrar informaci&amp;#243;n en diferentes formatos, etc. Pero es un buen ejemplito introductorio.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3732630541286744699-8892822083038595854?l=blog.tercerplaneta.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Ideas3p/~4/Yj5Qhh7vQto" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/Ideas3p/~3/Yj5Qhh7vQto/drag-and-drop-en-winforms.html</link><author>noreply@blogger.com (Benjamin Eidelman)</author><thr:total>2</thr:total><feedburner:origLink>http://blog.tercerplaneta.com/2008/09/drag-and-drop-en-winforms.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3732630541286744699.post-5978436299433849383</guid><pubDate>Wed, 04 Jun 2008 04:13:00 +0000</pubDate><atom:updated>2008-12-01T17:50:36.942-02:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Implicit and Explicit operators</category><category domain="http://www.blogger.com/atom/ns#">C#</category><category domain="http://www.blogger.com/atom/ns#">.NET 2.0</category><title>Operadores de conversión (Implícitos y Explícitos)</title><description>Es muy habitual realizar conversiones entre tipos de datos diferentes, por defecto muchos tipos de datos permiten la conversión implícita, esto se da en los casos en los cuales el tipo de dato de origen puede expresarse en su totalidad, como el Tipo de dato de destino, acá podemos ver un ejemplo:&lt;br /&gt;&lt;pre style="color: rgb(0, 0, 0); background-color: rgb(232, 232, 232);"&gt;byte valByte = 123;&lt;br /&gt;int valInt = valByte;&lt;br /&gt;double valDouble = valInt;&lt;/pre&gt;Como se ve en este caso no es necesario hacer ningún CAST, en cambio para el siguiente caso:&lt;br /&gt;&lt;pre style="color: rgb(0, 0, 0); background-color: rgb(232, 232, 232);"&gt;int valInt = 0;&lt;br /&gt;byte valByte = valInt;&lt;/pre&gt;Tendriamos un error de compilación &lt;b&gt;“Cannot implicitly convert type 'int' to 'byte'. An explicit conversion exists (are you missing a cast?)”&lt;/b&gt;, que nos indica que podemos hacer una conversión explícita, quedando resuelto de esta forma:&lt;br /&gt;&lt;pre style="color: rgb(0, 0, 0); background-color: rgb(232, 232, 232);"&gt;int valInt = 0;&lt;br /&gt;byte valByte = (byte)valInt;&lt;/pre&gt;&lt;i&gt;"Claro está que de esta manera, el Desarrollador está asumiendo los riesgos de obtener en la variable destino “valByte” información no esperada, si el valor origen “valInt” es superior al soportado por el tipo de dato Byte."&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Conversión para clases definidas por el usuario&lt;/h3&gt;Desde la versión del .NET 2.0 podemos definir operadores de conversión para los tipos definidos por el usuario, como se puede ver en el siguiente ejemplo:&lt;br /&gt;&lt;pre style="color: rgb(0, 0, 0); background-color: rgb(232, 232, 232);"&gt;public class MyClase&lt;br /&gt;{&lt;br /&gt;public double valor;&lt;br /&gt;&lt;br /&gt;/// &amp;lt;summary&amp;gt;&lt;br /&gt;/// Permite la conversion implicita&lt;br /&gt;/// desde Double hacia MyClase&lt;br /&gt;/// &amp;lt;/summary&amp;gt;&lt;br /&gt;/// &amp;lt;param name="arg"&amp;gt;Desde&lt;br /&gt;/// &amp;lt;returns&amp;gt;Hacia&amp;lt;/returns&amp;gt;&lt;br /&gt;public static implicit operator MyClase(double arg)&lt;br /&gt;{&lt;br /&gt;MyClase res = new MyClase();&lt;br /&gt;res.valor = arg;&lt;br /&gt;return res;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;/// &amp;lt;summary&amp;gt;&lt;br /&gt;/// Permite la conversion implicita&lt;br /&gt;/// desde MyClase hacia Double&lt;br /&gt;/// &amp;lt;/summary&amp;gt;&lt;br /&gt;/// &amp;lt;param name="arg"&amp;gt;Desde&lt;br /&gt;/// &amp;lt;returns&amp;gt;Hacia&amp;lt;/returns&amp;gt;&lt;br /&gt;public static implicit operator double(MyClase arg)&lt;br /&gt;{&lt;br /&gt;return arg.valor;&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public class MyClase2&lt;br /&gt;{&lt;br /&gt;public double valor;&lt;br /&gt;&lt;br /&gt;/// &amp;lt;summary&amp;gt;&lt;br /&gt;/// Permite la conversion explicita&lt;br /&gt;/// desde Double hacia MyClase&lt;br /&gt;/// &amp;lt;/summary&amp;gt;&lt;br /&gt;/// &amp;lt;param name="arg"&amp;gt;Desde&lt;br /&gt;/// &amp;lt;returns&amp;gt;Hacia&amp;lt;/returns&amp;gt;&lt;br /&gt;public static explicit operator MyClase2(double arg)&lt;br /&gt;{&lt;br /&gt;MyClase2 res = new MyClase2();&lt;br /&gt;res.valor = arg;&lt;br /&gt;return res;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;/// &amp;lt;summary&amp;gt;&lt;br /&gt;/// Permite la conversion explicita&lt;br /&gt;/// desde MyClase hacia Double&lt;br /&gt;/// &amp;lt;/summary&amp;gt;&lt;br /&gt;/// &amp;lt;param name="arg"&amp;gt;Desde&lt;br /&gt;/// &amp;lt;returns&amp;gt;Hacia&amp;lt;/returns&amp;gt;&lt;br /&gt;public static explicit operator double(MyClase2 arg)&lt;br /&gt;{&lt;br /&gt;return arg.valor;&lt;br /&gt;}&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;En este caso la clase MyClase permite la conversión implícita con double, mientras que en la clase MyClase2 la conversión es explícita, la utilización de estas clases podría ser la siguiente:&lt;br /&gt;&lt;br /&gt;&lt;pre style="color: rgb(0, 0, 0); background-color: rgb(232, 232, 232);"&gt;double valDouble = 22;&lt;br /&gt;&lt;br /&gt;MyClase myClase = new MyClase();&lt;br /&gt;// Conversión implicita en ambos casos&lt;br /&gt;valDouble = myClase;&lt;br /&gt;myClase = valDouble;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;MyClase2 myClase2 = new MyClase2();&lt;br /&gt;// En este caso se requiere del CAST&lt;br /&gt;valDouble = (double)myClase2;&lt;br /&gt;myClase2 = (MyClase2)valDouble;&lt;/pre&gt;&lt;br /&gt;&lt;h3&gt;En resumen&lt;/h3&gt;Vimos un modo sencillo de implementar mecanismos de conversión entre tipos definidos por nosotros, generalmente entre tipos numéricos.&lt;br /&gt;Otro modo de hacerlo es implementar System.IConvertible para utilizar la conversión a través de System.Convert, lo cual nos permite especificar la conversión por cultura.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3732630541286744699-5978436299433849383?l=blog.tercerplaneta.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Ideas3p/~4/krv-MpgZPAc" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/Ideas3p/~3/krv-MpgZPAc/operadores-de-conversin-implcitos-y.html</link><author>noreply@blogger.com (Ricardo D. de Guzmán)</author><thr:total>1</thr:total><feedburner:origLink>http://blog.tercerplaneta.com/2008/06/operadores-de-conversin-implcitos-y.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3732630541286744699.post-2163960801919048929</guid><pubDate>Mon, 19 May 2008 19:30:00 +0000</pubDate><atom:updated>2009-02-19T10:19:50.075-02:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Windows Vista</category><category domain="http://www.blogger.com/atom/ns#">IIS 7</category><category domain="http://www.blogger.com/atom/ns#">Windows Server 2008</category><title>Conferencia online - IIS 7 para desarrolladores</title><description>&lt;p&gt;En esta presentación online de MSDN (20/mayo/08) que realizamos con &lt;a href="http://msmvps.com/blogs/cwalzer"&gt;Carlos Walzer&lt;/a&gt;, destacamos algunos de los aspectos de la nueva plataforma de hosting en Windows Server 2008 y Windows Vista, enfocados desde la óptica de los desarrolladores.&lt;/p&gt;&lt;p&gt;Puede descargar aquí la &lt;a href="http://www.tercerplaneta.com/Data/Conf/0805IIS7Dev/0805MSDN-IIS7.pptx"&gt;presentación&lt;/a&gt; (.PPTX) y el ejemplo de código &lt;a href="http://www.tercerplaneta.com/Data/Conf/0805IIS7Dev/Code.zip"&gt;DemoWebsite&lt;/a&gt; con la extensión de consola para el administrador de IIS7. Los ejemplos están desarrollados con Visual Studio 2008.&lt;/p&gt;&lt;p&gt;NOTA: al abrir en Visual Studio la solucion de la consola administrativa, puede pedir una contraseña para el archivo de claves encriptadas. La misma es 123456&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3732630541286744699-2163960801919048929?l=blog.tercerplaneta.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Ideas3p/~4/7fVMp0Kaox0" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/Ideas3p/~3/7fVMp0Kaox0/conferencia-online-iis-7-para.html</link><author>noreply@blogger.com (Jose Marcenaro)</author><thr:total>4</thr:total><feedburner:origLink>http://blog.tercerplaneta.com/2008/05/conferencia-online-iis-7-para.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3732630541286744699.post-1339289421745468551</guid><pubDate>Wed, 14 May 2008 18:36:00 +0000</pubDate><atom:updated>2008-05-14T15:57:41.153-03:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Pampa Notes</category><category domain="http://www.blogger.com/atom/ns#">Microsoft SQL Server</category><category domain="http://www.blogger.com/atom/ns#">.NET 3.5</category><category domain="http://www.blogger.com/atom/ns#">SQL</category><category domain="http://www.blogger.com/atom/ns#">LINQ para SQL</category><title>Linq to SQL y Stored Procedures</title><description>&lt;p&gt;Continuando con el &lt;a href="http://blog.tercerplaneta.com/2008/03/linq-para-sql-reemplaza-por-completo-la.html"&gt;art&amp;#237;culo anterior&lt;/a&gt; sobre Linq to SQL en la Dal, donde explica el rol que siguen cumpliendo los Stored Procedures. Raz&amp;#243;n por la cual esta entrada se llama &amp;quot;Linq to SQL y Stored Procedures&amp;quot; y no &amp;quot;Linq to SQL vs. Stored Procedures&amp;quot;).&lt;/p&gt;  &lt;p&gt;Las razones m&amp;#225;s importantes son:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Las consultas Linq to SQL se traducen en queries SQL, no son procedimientos: con Linq to SQL no podemos aprovechar tablas temporales, estructuras de control (if-else, loops, cursores), devolver m&amp;#250;ltiples resultsets, operaciones por lotes (UPDATE, DELETE), etc. &lt;/li&gt;    &lt;li&gt;Performance, desde hace varias generaciones SQL Server sabe como optimizar c&amp;#243;digo Transact-SQL en Stored Procedures. M&amp;#225;s a&amp;#250;n, la traducci&amp;#243;n de Linq a SQL, aunque evolucione con el .Net Framework, no siempre genera los mejores resultados, existir&amp;#225;n los casos en que necesitemos escribir nuestro propio Transact-SQL.      &lt;table cellspacing="0" cellpadding="2" width="400" border="1"&gt;&lt;tbody&gt;         &lt;tr&gt;           &lt;td valign="top" width="400"&gt;&lt;em&gt;Como ejemplo de esto el &lt;/em&gt;&lt;a href="http://blogs.msdn.com/adonet/archive/2008/05/12/what-s-new-in-the-sp1-beta.aspx"&gt;&lt;em&gt;.Net Framework 3.5 SP 1 Beta&lt;/em&gt;&lt;/a&gt;&lt;em&gt; reducir&amp;#225; la cantidad de tablas usadas en ciertos joins.&lt;/em&gt;&lt;/td&gt;         &lt;/tr&gt;       &lt;/tbody&gt;&lt;/table&gt;   &lt;/li&gt; &lt;/ul&gt;  &lt;ul&gt;   &lt;li&gt;Seguridad, son limitados los escenarios en que nuestra aplicaci&amp;#243;n tiene acceso total a las tablas de la base de datos. Es habitual que nuestro DBA, por razones de seguridad y desacoplamiento entre modelos de datos, limite el acceso al SQL Server a la ejecuci&amp;#243;n de Stored Procedures. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Llegamos a la conclusi&amp;#243;n de que, en general, no podemos prescindir de los SP, la buena noticia es: &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Linq to SQL incorpora un manejo simple de SP que permite realizar cualquier tipo de operaciones sobre los datos v&amp;#237;a SP.&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Pero la mala noticia es:&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;El O/R Designer con el cual editamos gr&amp;#225;ficamente nuestros Dbml, no soporta completamente el uso de SP.&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Mientras esperamos que la mala noticia se solucione con actualizaciones del VS2008, en algunos puntos tendremos que tocar algo de c&amp;#243;digo manualmente.&lt;/p&gt;  &lt;h4&gt;Generaci&amp;#243;n de wrappers&lt;/h4&gt;  &lt;p&gt;Primero vamos a incorporar los SP que queremos invocar a nuestro dbml, para esto basta con arrastrarlos a la zona de m&amp;#233;todos (a la derecha en el O/R Designer), esto generar&amp;#225; en nuestro DataContext un m&amp;#233;todo para cada SP, con el mismo nombre y lista de par&amp;#225;metros.&lt;/p&gt;  &lt;p&gt;Ahora podemos invocar estos SP con intellisense, comprobaci&amp;#243;n de tipos, y control sobre cada invocaci&amp;#243;n (detecci&amp;#243;n temprana de errores, mayor mantenibilidad y desacoplamiento).&lt;/p&gt;  &lt;p&gt;Esto genera tambi&amp;#233;n para cada SP una clase que representa el tipo de resultado detectado, una clase con propiedades p&amp;#250;blicas an&amp;#225;logas a las columnas del resultado devuelto, esto le permite a Linq to SQL devolver de la invocaci&amp;#243;n de estos m&amp;#233;todos wrappers una colecci&amp;#243;n de estos objetos.&lt;/p&gt;  &lt;p&gt;El nombre que tienen estas clases por defecto ser&amp;#225; &amp;quot;NombreDelStoredProcedureResult&amp;quot;, y esto es invisible desde el O/R Designer, por lo tanto si queremos cambiar el nombre de la clase de resultados (por ej: ListarClientesPorZonaResult a Cliente), ser&amp;#225; necesario meterse en el Designer.cs asociado al dbml, cortar esta clase, pegarla en otro archivo (por ejemplo junto con el resto del modelo de datos), y aqu&amp;#237; cambiarle el nombre (el c&amp;#243;digo autogenerado se pisa cada vez que tocamos el dbml).&lt;/p&gt;  &lt;p&gt;Ahora resta actualizar el wrapper del SP con el nombre del tipo devuelto, desafortunadamente el O/R Designer solo nos permite especificar como tipo devuelto una entidad que se encuentre visible en el mapa dbml, lo cual no siempre es posible si queremos compartir estas entidades entre otros dbml, o mover las entidades a un assembly separado. Inclusive tampoco es posible con el O/R Designer especificar m&amp;#250;ltiples resultados (t&amp;#237;picamente utilizado para devolver entidades cabecera-detalle).&lt;/p&gt;  &lt;p&gt;Si podemos hacer esto &amp;quot;tocando&amp;quot; los wrappers auto-generados, para lo cual tenemos 2 opciones:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Una vez generados, mover los wrappers a una partial class del DataContext, y modificando manualmente los atributos que decoran los wrappers, especificar tipos devueltos, inclusive m&amp;#250;ltiples resultsets. Ejemplo: &lt;/li&gt; &lt;/ul&gt; &lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;  &lt;pre class="csharpcode"&gt;        [Function(Name = &lt;span class="str"&gt;&amp;quot;dbo.LeerClienteConPedidos&amp;quot;&lt;/span&gt;)] &lt;br /&gt;        [ResultType(&lt;span class="kwrd"&gt;typeof&lt;/span&gt;(Cliente))] &lt;br /&gt;        [ResultType(&lt;span class="kwrd"&gt;typeof&lt;/span&gt;(Pedidos))] &lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; IMultipleResults LeerClienteConPedidos([Parameter(Name = &lt;span class="str"&gt;&amp;quot;IdCliente&amp;quot;&lt;/span&gt;, DbType = &lt;span class="str"&gt;&amp;quot;Int&amp;quot;&lt;/span&gt;)] System.Nullable&amp;lt;&lt;span class="kwrd"&gt;int&lt;/span&gt;&amp;gt; idCliente) &lt;br /&gt;        { &lt;br /&gt;            IExecuteResult result = &lt;span class="kwrd"&gt;this&lt;/span&gt;.ExecuteMethodCall(&lt;span class="kwrd"&gt;this&lt;/span&gt;, ((MethodInfo)(MethodInfo.GetCurrentMethod())), idCliente); &lt;br /&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; (IMultipleResults)result.ReturnValue; &lt;br /&gt;        }&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;esto indica que el SP devuelve 2 resultsets, el primero con Clientes, y el segundo con Pedidos.&lt;/p&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Reemplazar el generador de c&amp;#243;digo por defecto MSLinqToSQLGenerator, por uno que genere los wrappers &amp;quot;a gusto&amp;quot;, lo cual afortunadamente resulta m&amp;#225;s simple de lo que parece. Nuestro generador de c&amp;#243;digo &lt;a href="http://www.codeplex.com/ULinqGen"&gt;ULinqGen&lt;/a&gt; podr&amp;#237;a extenderse para realizar esto. &lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;h4&gt;Aplicar cambios&lt;/h4&gt;&lt;br /&gt;&lt;p&gt;Una vez obtenidas colecciones de entidades existentes en la base de datos, por defecto, Linq to SQL activa para todas ellas un control de cambios (cuando estos objetos notifican sus modificaciones mediante eventos). Cuando se detectan modificaciones, se mantiene en el DataContext un &amp;quot;change set&amp;quot;, que permite luego aplicar todos esos cambios en la base de datos.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Cuando se llama al m&amp;#233;todo SubmitChanges() del DataContext, Linq to SQL genera y ejecuta una serie de comandos UPDATE, INSERT y DELETE necesarios para reflejar los cambios en la base de datos.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Sin embargo es com&amp;#250;n que necesitemos realizar alg&amp;#250;n tipo de verificaci&amp;#243;n o auditor&amp;#237;a al momento de realizar estas operaciones. Es por esto que desde el O/R Designer es posible configurar el &amp;quot;Behavior&amp;quot; de una entidad, defiendo el m&amp;#233;todo a invocar para realizar un UPDATE, un DELETE o un INSERT de esta entidad, en lugar del SQL auto-generado.&lt;/p&gt;&lt;br /&gt;&lt;h4&gt;Carga de entidades asociadas&lt;/h4&gt;&lt;br /&gt;&lt;p&gt;Por &amp;#250;ltimo, existe un uso de estos wrappers de SP un poco m&amp;#225;s desconocido, revelado por &lt;a href="http://blogs.msdn.com/dinesh.kulkarni/"&gt;Dinesh Kulkarni&lt;/a&gt;, en su blog.&lt;/p&gt;&lt;p&gt;Cuando existen foreign keys entre 2 tablas del SQL, en el dbml se generan asociaciones, que se ven como colecciones de detalle (EntitySet) dentro las entidades maestro. Ej:&lt;/p&gt;&lt;br /&gt;&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;Cliente c = ...&lt;br /&gt;&lt;span class="kwrd"&gt;for&lt;/span&gt; each (Pedido p &lt;span class="kwrd"&gt;in&lt;/span&gt; c.Pedidos) &lt;br /&gt;{&lt;br /&gt;...&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;La forma en que se obtienen los Pedidos para un Cliente, es por defecto mediante un query Linq generado a partir de la foreign key, sin embargo es posible definir esto mediante un m&amp;#233;todo propio, definido en una partial class del DataContext.&lt;/p&gt;&lt;p&gt;Ejemplo:&lt;/p&gt;&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;partial&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; VentasDataContext {&lt;br /&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; IEnumerable&amp;lt;Pedido&amp;gt; LoadPedidos(Cliente c) {&lt;br /&gt;        &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;this&lt;/span&gt;.LeerPedidosPorCliente(c.IdCliente);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; Cliente LoadCliente(Pedido p) {&lt;br /&gt;        &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;this&lt;/span&gt;.LeerCliente(p.IdCliente);&lt;br /&gt;    }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;El m&amp;#233;todo LoadPedidos es llamado al cargar la propiedad Pedidos en un Cliente, y el segundo al cargar la propiedad Cliente en un pedido.&lt;/p&gt;&lt;p&gt;Esto funciona tanto para carga deferida (deferred loading) como para carga inmediata (utilizando el m&amp;#233;todo LoadWith&amp;lt;T&amp;gt;()).&lt;/p&gt;&lt;br /&gt;&lt;h4&gt;Conclusiones&lt;/h4&gt;&lt;br /&gt;&lt;p&gt;Teniendo estos features podemos decir que el uso Linq to SQL para invocar Stored Procedures, nos atrae por estas ventajas:&lt;/p&gt;&lt;ul&gt;&lt;br /&gt;  &lt;li&gt;Integraci&amp;#243;n con Linq to SQL (a trav&amp;#233;s de compartir un mismo modelo de datos). &lt;/li&gt;&lt;li&gt;Wrappers para invocaci&amp;#243;n de SP, con las ventajas de tener comprobaci&amp;#243;n de tipos en los par&amp;#225;metros, intellisense, y control sobre las invocaciones. &lt;/li&gt;&lt;li&gt;Materializaci&amp;#243;n de objetos (POCO) para los resultados (en lugar de s&amp;#243;lo DataSets). &lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;p&gt;y preocupan estas desventajas:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Una invocaci&amp;#243;n a Stored Procedures un poco oscura, que no permite demasiada personalizaci&amp;#243;n. Por ejemplo no es posible interceptar errores, tocar la lista de par&amp;#225;metros, o forzar reintentos, etc. de forma global. &lt;/li&gt;&lt;li&gt;Solo funciona (en la versi&amp;#243;n actual) con MS SQL Server. &lt;/li&gt;&lt;/ul&gt;&lt;p&gt;En el &lt;a href="http://blog.tercerplaneta.com/2008/03/linq-para-sql-reemplaza-por-completo-la.html"&gt;art&amp;#237;culo anterior&lt;/a&gt;, Jos&amp;#233; explica con m&amp;#225;s detalle razones que justifican mantener un mecanismo separado para las invocaciones a procedimientos almacenados. &lt;/p&gt;&lt;p&gt;Por lo tanto, exploramos la posibilidad de tener las ventajas mencionadas, sin las desventajas mencionadas.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Para esto trabajamos en el desarrollo de estas herramientas:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Un generador de wrappers, esto nos permitir&amp;#237;a solucionar el problema de los tipos de retorno custom y/o m&amp;#250;ltiples, y la posibilidad elegir el mecanismo de invocaci&amp;#243;n.&lt;/li&gt;&lt;li&gt;Un materializador de objetos que proyecte colecciones de objetos POCO de cualquier DataReader, permiti&amp;#233;ndonos invocar SP con ADO.Net puro, EnterpriseLibraries, etc. En nuestro blog en ingl&amp;#233;s escrib&amp;#237; un articulo con algunos &lt;a href="http://pampanotes.tercerplaneta.com/2008/04/object-materialization.html"&gt;prototipos de materializaci&amp;#243;n de objetos&lt;/a&gt; &lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;p&gt;Hasta pronto,&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3732630541286744699-1339289421745468551?l=blog.tercerplaneta.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Ideas3p/~4/YuPa-OM4r18" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/Ideas3p/~3/YuPa-OM4r18/linq-to-sql-y-stored-procedures.html</link><author>noreply@blogger.com (Benjamin Eidelman)</author><thr:total>0</thr:total><feedburner:origLink>http://blog.tercerplaneta.com/2008/05/linq-to-sql-y-stored-procedures.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3732630541286744699.post-2307069620779656353</guid><pubDate>Mon, 03 Mar 2008 11:21:00 +0000</pubDate><atom:updated>2008-03-03T09:21:20.317-02:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">.NET 3.5</category><category domain="http://www.blogger.com/atom/ns#">LINQ</category><category domain="http://www.blogger.com/atom/ns#">Buenas Prácticas</category><category domain="http://www.blogger.com/atom/ns#">LINQ para SQL</category><title>LINQ para SQL, ¿reemplaza por completo a la DAL?</title><description>&lt;p&gt;O dicho de otra forma: Si usamos LINQ, &amp;#191;podemos olvidarnos de nuestros componentes propios o gen&amp;#233;ricos de acceso a datos? (por ej. Data Access Block de Enterprise Library). Para dar una respuesta simple: NO, de ninguna manera.&lt;/p&gt;  &lt;p&gt;Al menos si consideramos cualquier aplicacion basada en SQL Server que no sea trivial (en cuanto a su modelo de datos o la concurrencia de usuarios), no hay mucha duda de que &lt;strong&gt;los procedimientos almacenados siguen teniendo un rol clave &lt;/strong&gt;en el acceso a los datos. &lt;/p&gt;  &lt;p&gt;Su funcionalidad ahora puede ser complementada con consultas o actualizaciones directas via LINQ, en una mezcla cuya proporcion depender&amp;#225; del contexto de la aplicaci&amp;#243;n: desde &amp;quot;s&amp;#243;lo procedimientos almacenados&amp;quot; en algunos entornos corporativos, hasta escenarios con una buena proporci&amp;#243;n de consultas LINQ en otros entornos. En cualquier caso, las consultas complejas y actualizaciones cr&amp;#237;ticas requerir&amp;#225;n ser implementadas como procedimientos almacenados.&lt;/p&gt;  &lt;p&gt;Una vez establecido esto, volvemos a la pregunta inicial: &amp;#191;es necesario &amp;quot;duplicar&amp;quot; el c&amp;#243;digo de acceso a datos, teniendo en cuenta que LINQ para SQL ya implementa la conexi&amp;#243;n con la base de datos y tiene un mecanismo para la invocaci&amp;#243;n de procedimientos almacenados?&lt;/p&gt;  &lt;p&gt;Se me ocurren varias razones que justifican mantener un mecanismo separado para las invocaciones a procedimientos almacenados:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Posibilidad de control: t&amp;#237;picamente hay una serie de tareas y controles que se aplican antes y despues de las invocaciones, en el c&amp;#243;digo gen&amp;#233;rico de invocacion de SP: revisar y completar par&amp;#225;metros (ej. Id del usuario autenticado), manejar excepciones, ajustar timeout de la conexion, etc.&lt;/li&gt;    &lt;li&gt;Capacidad de retornar distintos tipos de resultado: ej. valores escalares, Data Readers, XML Readers&lt;/li&gt;    &lt;li&gt;Posibilidad de retornar datasets en forma sencilla. Si, por supuesto. &amp;#191;o acaso la aparici&amp;#243;n de LINQ significa la extinci&amp;#243;n de los datasets? En muchas situaciones, un dataset sigue siendo una forma muy simple y eficiente de trasladar datos tabulares entre capas de la aplicaci&amp;#243;n.&lt;/li&gt;    &lt;li&gt;Capacidad de retornar tambien colecciones de objetos (o instancias simples) como resultado de la invocaci&amp;#243;n a un procedimiento almacenado. Esto puede realizarse mediante c&amp;#243;digo propio (examinando atributos de las entidades o utilizando Reflection sobre los miembros) o utilizando el m&amp;#233;todo Translate del mismo DataContext de LINQ to SQL. Esto &amp;#250;ltimo requiere atributos LINQ en la definicion de las clases, pero estos atributos son creados autom&amp;#225;ticamente por nuestro &lt;a href="http://www.codeplex.com/ULinqGen"&gt;generador de c&amp;#243;digo&lt;/a&gt; asociado a un modelo DBML que se edita con el mismo dise&amp;#241;ador O/R de Visual Studio 2008.&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Como criterio de aplicaci&amp;#243;n, nosotros en general utilizamos la siguiente regla:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Todas las invocaciones a procedimientos almacenados las realizamos a traves de la DAL (Data Access Layer) propia, a&amp;#250;n las que retornan colecciones o instancias de entidades.&lt;/li&gt;    &lt;li&gt;Para las consultas y actualizaciones de LINQ sobre SQL utilizamos el mecanismo de acceso a datos incluido en el Data Context.&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Esta combinaci&amp;#243;n le da, a nuestro &amp;quot;framework&amp;quot; de construcci&amp;#243;n de aplicaciones, la m&amp;#225;xima flexibilidad para adaptarse a distintos escenarios y a&amp;#250;n a distintos casos de uso dentro de la misma empresa (ej. un sistema de reserva de salas no requiere la misma complejidad de soluci&amp;#243;n que un sistema de gesti&amp;#243;n de inventarios).&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3732630541286744699-2307069620779656353?l=blog.tercerplaneta.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Ideas3p/~4/XOXDTR-xdYc" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/Ideas3p/~3/XOXDTR-xdYc/linq-para-sql-reemplaza-por-completo-la.html</link><author>noreply@blogger.com (Jose Marcenaro)</author><thr:total>2</thr:total><feedburner:origLink>http://blog.tercerplaneta.com/2008/03/linq-para-sql-reemplaza-por-completo-la.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3732630541286744699.post-2773259026909206445</guid><pubDate>Fri, 29 Feb 2008 18:08:00 +0000</pubDate><atom:updated>2008-03-03T17:14:32.385-02:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Pampa Notes</category><category domain="http://www.blogger.com/atom/ns#">Tercer Planeta</category><category domain="http://www.blogger.com/atom/ns#">LINQ para SQL</category><category domain="http://www.blogger.com/atom/ns#">Blog</category><title>Nuevo blog: Pampa Notes on Software Trends</title><description>&lt;p&gt;Finalmente después de preparar algunos artículos iniciales decidimos lanzar un nuevo blog, al cual decidimos telúricamente llamar: &lt;a href="http://pampanotes.tercerplaneta.com/" target="_blank"&gt;&lt;strong&gt;Pampa Notes on Software Trends&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Contenidos&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;Este nuevo blog no viene a reemplazar el actual, sino que tiene como objetivo volcar puntos de vista, notas, conclusiones que irán surgiendo al incursionar en nuevas tecnologías.&lt;/p&gt;&lt;p&gt;De ninguna forma esto implica convertirnos en "evangelizadores" de los más recientes productos Microsoft, sin embargo tenemos la obligación de ensuciarnos un poco en las tecnologías pujantes para poder tener criterios justificados sobre su adopción en los escenarios que se nos presenten.&lt;/p&gt;&lt;p&gt;Consecuencia natural de esta actividad será el contenido de este nuevo blog.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Linq to SQL&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;Actualmente existen en Pampa Notes &lt;a href="http://pampanotes.tercerplaneta.com/search/label/LINQ%20to%20SQL" target="_blank"&gt;una serie de entradas sobre Linq to SQL&lt;/a&gt;, particularmente sobre como incorporar Linq to SQL en una arquitectura N capas.&lt;/p&gt;&lt;p&gt;Desde su lanzamiento ha habido muchas discusiones sobre modos de lograr esto. Y en estos artículos comentamos algunos puntos, como la necesidad de un control de cambios desconectado en las entidades (después de todo en su momento éste es uno de los principales features que los DataSets nos trajeron, véase RowState, HasChanges, etc.), dado que en Linq to SQL los cambios son detectados y registrados por un objeto DataContext encargado de materializar las entidades, se "engancha" a estos para poder luego aplicar todos los cambios realizados.&lt;/p&gt;&lt;p&gt;Sin embargo en una aplicación N capas queremos que nuestras entidades viajen a través de la red, o en Asp.Net queremos que persistan entre postbacks: Queremos entidades desconectadas de su DataContext. Si bien esto no está disponible en Linq-to-SQL "Out-of-the-box" está contemplado y soportado si se reemplazan algunas piezas, y agregan otras.&lt;/p&gt;&lt;p&gt;Como parte de las piezas a reemplazar para este "control de cambios desconectado", subimos a CodePlex una custom tool  que nos permite auto-generar nuestro propio código para las entidades Linq, manteniendo la GUI del O/R Designer, más detalles en el sitio del proyecto: &lt;a href="http://www.codeplex.com/ULinqGen"&gt;http://www.codeplex.com/ULinqGen&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Un blog en inglés?&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://pampanotes.tercerplaneta.com/" target="_blank"&gt;Pampa Notes&lt;/a&gt; estará escrito en ingles, con lo cual haremos eventualmente en este blog referencias a lo que ocurra en el otro. Para consolar nuestro espíritu nacional!, el nombre &lt;a href="http://es.wikipedia.org/wiki/Pampa_%28Sudam%C3%A9rica%29" target="_blank"&gt;Pampa&lt;/a&gt; hace alusión a la llanura de &lt;a href="http://es.wikipedia.org/wiki/Argentina" target="_blank"&gt;Argentina&lt;/a&gt; donde se encuentra &lt;a href="http://es.wikipedia.org/wiki/Buenos_Aires" target="_blank"&gt;Buenos Aires&lt;/a&gt;, sede de &lt;a title="Tercer Planeta" href="http://www.tercerplaneta.com/" target="_blank"&gt;Tercer Planeta&lt;/a&gt;.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3732630541286744699-2773259026909206445?l=blog.tercerplaneta.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Ideas3p/~4/uUxuM0M7I78" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/Ideas3p/~3/uUxuM0M7I78/nuevo-blog-pampa-notes-on-software.html</link><author>noreply@blogger.com (Benjamin Eidelman)</author><thr:total>0</thr:total><feedburner:origLink>http://blog.tercerplaneta.com/2008/02/nuevo-blog-pampa-notes-on-software.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3732630541286744699.post-2089414165620681689</guid><pubDate>Tue, 26 Feb 2008 20:36:00 +0000</pubDate><atom:updated>2008-02-27T10:02:50.244-02:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">C#</category><category domain="http://www.blogger.com/atom/ns#">.NET 2.0</category><title>El fin del ArrayList</title><description>&lt;p&gt;Desde la versión del Framework 2.0 llego el concepto de Generics, este nos da la posibilidad de definir clases genéricas, donde el cliente de la misma, es el encargado de definir que tipo desea utilizar. &lt;/p&gt;&lt;p&gt;Las ventajas más importantes son las siguientes&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Nos evitamos el cast innecesario de objetos y en algunos casos el Boxing y Unboxing &lt;/li&gt;&lt;li&gt;Tenemos la posibilidad de hacer chequeo de tipos en tiempo de compilación &lt;/li&gt;&lt;li&gt;Ganamos claridad en el código &lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Uno de los lugares donde es utilizado, es en las colecciones de objetos, de ahí la aparición de un nuevo espacio de nombre &lt;em&gt;System.Collections.Generics&lt;/em&gt; donde encontramos un grupo de clases muy útiles, referidas al manejo de colecciones con tipos genéricos.&lt;/p&gt;&lt;p&gt;Antes de Generics, la manera mas fácil de tener una colección en memoria, que nos permita&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Recorrer sus elementos &lt;/li&gt;&lt;li&gt;Buscar un elemento por índice &lt;/li&gt;&lt;li&gt;Agregar y quitar elementos despues de haber definida la colección &lt;/li&gt;&lt;/ul&gt;&lt;p&gt;es utilizar la clase ArrayList, que incluso nos deja definir una colección con elementos de tipos diferente, con el problema de no poder hacer ningún tipo de chequeo, además de los problemas de performance referidos a los Cast innecesarios.&lt;/p&gt;&lt;p&gt;Con la llegada de Generics, tenemos una nueva clase llamada List&amp;lt;T&amp;gt;, que viene a cumplir en gran medida con lo que la mayoría de los usuarios de ArrayList esperábamos.&lt;/p&gt;&lt;p&gt;La posibilidad de tener Colecciones de objetos realmente genéricas, donde al momento de utilizarlas uno pueda definir con que tipo quiere trabajar, aprovechando así el chequeo de tipos, Intellisense, sin Cast innecesarios, sin Boxing y Unboxing para tipos por valor, y hasta logrando un código mas legible.&lt;/p&gt;&lt;p&gt;Veamos algunos ejemplos utilizando clases cutom genéricas, para familiarizarnos con la sintaxis, y luego como utilizar estas nuevas listas.&lt;/p&gt;&lt;p&gt;Supongamos un ejemplo ilustrativo, donde queremos tener una propiedad Edad que pueda ser String o Int según la implementación.&lt;/p&gt;&lt;h3&gt;Clases cutom sin utilizar Generics&lt;/h3&gt;&lt;p&gt;La única manera de tener un tipo Genérico era definirlo como Object&lt;/p&gt;&lt;pre style="COLOR: #000000; BACKGROUND-COLOR: #e8e8e8"&gt;public class Persona&lt;br /&gt;{&lt;br /&gt;private object edad;&lt;br /&gt;public object Edad&lt;br /&gt;{&lt;br /&gt;  get { return edad;}&lt;br /&gt;  set { edad = value;}&lt;br /&gt;}&lt;br /&gt;}&lt;/pre&gt;&lt;h3&gt;Caso 1, con un tipo por referencia &lt;/h3&gt;&lt;pre style="COLOR: #000000; BACKGROUND-COLOR: #e8e8e8"&gt;Persona per = new Persona();&lt;br /&gt;per.Edad = "25";&lt;br /&gt;// En este caso da un error de compilación&lt;br /&gt;// int edad = (int)per.Edad;&lt;br /&gt;// Aca funicona, pero tuvimos que hacer un CAST&lt;br /&gt;string edad = (string)per.Edad;&lt;/pre&gt;&lt;h3&gt;Caso 2, con un tipo por valor&lt;/h3&gt;&lt;pre style="COLOR: #000000; BACKGROUND-COLOR: #e8e8e8"&gt;Persona per = new Persona();&lt;br /&gt;// Boxing innecesario&lt;br /&gt;per.Edad = 25;&lt;br /&gt;// Aca funicona, pero tuvimos que hacer un CAST&lt;br /&gt;int edad = (int)per.Edad;&lt;br /&gt;// Esto falla por no ser un String&lt;br /&gt;// string edad = (string)per.Edad;&lt;/pre&gt;&lt;h3&gt;Clases cutom con Generics&lt;/h3&gt;&lt;pre style="COLOR: #000000; BACKGROUND-COLOR: #e8e8e8"&gt;public class Persona&amp;lt;T&amp;gt;&lt;br /&gt;{&lt;br /&gt;private T edad;&lt;br /&gt;public T Edad&lt;br /&gt;{&lt;br /&gt;  get { return edad; }&lt;br /&gt;  set { edad = value; }&lt;br /&gt;}&lt;br /&gt;}&lt;/pre&gt;&lt;h3&gt;Caso 1, con un tipo por referencia &lt;/h3&gt;&lt;pre style="COLOR: #000000; BACKGROUND-COLOR: #e8e8e8"&gt;Persona&amp;lt;string&amp;gt; per = new Persona&amp;lt;string&amp;gt;();&lt;br /&gt;per.Edad = "25";&lt;br /&gt;// Esto funciona sin necesidad de CAST&lt;br /&gt;string edad = per.Edad;&lt;br /&gt;// Esto código no compila, evitando problemas posteriores&lt;br /&gt;// int edad = per.Edad;&lt;/pre&gt;&lt;h3&gt;Caso 2, con un tipo por valor&lt;/h3&gt;&lt;pre style="COLOR: #000000; BACKGROUND-COLOR: #e8e8e8"&gt;Persona&amp;lt;int&amp;gt; per = new Persona&amp;lt;int&amp;gt;();&lt;br /&gt;per.Edad = 25;&lt;br /&gt;// Esto código no compila, evitando problemas posteriores&lt;br /&gt;// string edad = per.Edad;&lt;br /&gt;// Esto funciona sin necesidad de CAST&lt;br /&gt;int edad = per.Edad;&lt;/pre&gt;&lt;h3&gt;Listas genéricas&lt;/h3&gt;&lt;p&gt;Ahora apliquemos esto a las Listas genéricas, veamos un ejemplo muy común donde uno necesita definir una lista de un tipo de dato en particular, en este caso con un tipo entero.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre style="COLOR: #000000; BACKGROUND-COLOR: #e8e8e8"&gt;int suma = 0;&lt;br /&gt;ArrayList numeros = new ArrayList();&lt;br /&gt;numeros.Add(1); // Boxing innecesario&lt;br /&gt;numeros.Add(2); // Boxing innecesario&lt;br /&gt;numeros.Add(3); // Boxing innecesario&lt;br /&gt;numeros.Add(4); // Boxing innecesario&lt;br /&gt;//numeros.Add("cadorna"); Esta linea es valida pero falla en tiempo de ejecucion&lt;br /&gt;foreach (int num in numeros) // Unboxing innecesario&lt;br /&gt;{&lt;br /&gt;suma += num;&lt;br /&gt;}&lt;br /&gt;int valor = (int)numeros[0]; // CAST innecesario al recuperar un valor&lt;/pre&gt;&lt;br /&gt;En cambio utilizando la nueva clase List&amp;lt;T&amp;gt; este código se veria así&lt;br /&gt;&lt;br /&gt;&lt;pre style="COLOR: #000000; BACKGROUND-COLOR: #e8e8e8"&gt;List&amp;lt;int&amp;gt; numeros = new List&amp;lt;int&amp;gt;(); // Se define el tipo a utilizar&lt;br /&gt;numeros.Add(1);&lt;br /&gt;numeros.Add(2);&lt;br /&gt;numeros.Add(3);&lt;br /&gt;numeros.Add(4);&lt;br /&gt;numeros.Add("cadorna"); // Error en tiempo de compilación&lt;br /&gt;foreach (int num in numeros) // Valida en tiempo de compilación&lt;br /&gt;{&lt;br /&gt;suma += num;&lt;br /&gt;}&lt;br /&gt;int valor = numeros[0]; // No necesita CAST&lt;br /&gt;Este segundo caso como se ve es mucho más eficiente.&lt;/pre&gt;&lt;h3&gt;Algunas conclusiones finales&lt;/h3&gt;&lt;p&gt;Como se ve a la hora de necesitar una colección fácil de manipular, de agregar y quitar ítems es mejor utilizar la clase List&amp;lt;T&amp;gt; y dejar de lado ArrayList que solo seria utilizable si queremos mezclar tipos de datos dentro de la misma colección, algo que no es muy recomendable y que seria lo mismo que definir una lista de objetos List&amp;lt;object&amp;gt;.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3732630541286744699-2089414165620681689?l=blog.tercerplaneta.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Ideas3p/~4/q_n8Bh4nTx8" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/Ideas3p/~3/q_n8Bh4nTx8/el-fin-del-arraylist.html</link><author>noreply@blogger.com (Ricardo D. de Guzmán)</author><thr:total>0</thr:total><feedburner:origLink>http://blog.tercerplaneta.com/2008/02/el-fin-del-arraylist.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3732630541286744699.post-5152741580934280672</guid><pubDate>Tue, 05 Feb 2008 18:55:00 +0000</pubDate><atom:updated>2008-02-05T16:55:02.103-02:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">C#</category><category domain="http://www.blogger.com/atom/ns#">.NET 3.5</category><category domain="http://www.blogger.com/atom/ns#">LINQ</category><category domain="http://www.blogger.com/atom/ns#">LINQ para SQL</category><title>Linq: Asomándose detrás de escena</title><description>&lt;p&gt;Para entender un poco mejor lo que ocurre al utilizar LINQ to SQL (DLINQ), voy a mostrar con ejemplos pr&amp;#225;cticos un poco de lo que ocurre cada vez que ejecutamos un query LINQ sobre SQL&lt;/p&gt;  &lt;p&gt;Utilizando SqlMetal o el O/R Designer, podemos crear para cada tabla existente en el servidor SQL una colecci&amp;#243;n equivalente, contenida en un DataContext, que representa una vista de nuestra base de datos.&lt;/p&gt;  &lt;p&gt;Adem&amp;#225;s, estas tablas son IQueryables, lo que significan que son colecciones de elementos sobre los cuales pueden escribirse queries LINQ, Por Ejemplo:&lt;/p&gt; &lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;  &lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;var&lt;/span&gt; query = &lt;span class="kwrd"&gt;from&lt;/span&gt; p &lt;span class="kwrd"&gt;in&lt;/span&gt; VideoClubDataContext.Peliculas &lt;span class="kwrd"&gt;where&lt;/span&gt; p.Genero == &lt;span class="str"&gt;&amp;quot;Terror&amp;quot;&lt;/span&gt; &lt;span class="kwrd"&gt;select&lt;/span&gt; p.ClienteConCopia&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;&amp;#160; &lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;strong&gt;Enumerando resultados&lt;/strong&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Peliculas es un IQueryable, por lo tanto tambi&amp;#233;n es un IEnumerable. Pero a diferencia de una lista o array en memoria, al enumerar sobre &amp;#233;ste, el trabajo de construir el enumerador, es delegado a un &amp;quot;Provider&amp;quot;, que en el caso de LINQ to SQL, traduce la expresi&amp;#243;n C# (o VB.Net) a SQL, y enumera los resultados con un SqlCommand creado por el DataContext (quien conoce el ConnectionString necesario).&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Si prestaron atenci&amp;#243;n a las presentaciones de LINQ sabr&amp;#225;n que hasta este punto, al construir mi objeto query, todav&amp;#237;a ninguna conexi&amp;#243;n se abri&amp;#243; con el SQL, solo se construy&amp;#243; en memoria la estructura de la consulta (esto es un ExpressionTree que mencionar&amp;#233; m&amp;#225;s adelante).&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Reci&amp;#233;n al enumerar este objeto query, se construye la sintaxis SQL, y se env&amp;#237;a al SQL Server, trayendo los resultados para ser enumerados.&lt;/p&gt;&lt;br /&gt;&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;foreach&lt;/span&gt; (&lt;span class="str"&gt;Cliente&lt;/span&gt; cliente &lt;span class="kwrd"&gt;in&lt;/span&gt; query)&lt;br /&gt;    EnviarMailRecordatorio(cliente.Email);&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Una de las primeras dudas que tuvimos es: Qu&amp;#233; ocurre si vuelvo a enumerar el objeto query? Existe alg&amp;#250;n tipo de cach&amp;#233; de los resultados?&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;La respuesta es... no. Simplemente porque enumerar nuestro objeto query, es &lt;u&gt;enumerar la consulta&lt;/u&gt;, con lo cual se construye nuevamente la sentencia SQL, se abre (o reutiliza) una conexi&amp;#243;n con el SQL, y se devuelven los nuevos resultados en la enumeraci&amp;#243;n.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Si queremos &lt;u&gt;enumerar los resultados&lt;/u&gt; anteriores nuevamente, podemos hacerlo de esta forma&lt;/p&gt;&lt;br /&gt;&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;Cliente[] clientes = query.ToArray();&lt;br /&gt;&lt;span class="kwrd"&gt;foreach&lt;/span&gt; (Cliente cliente &lt;span class="kwrd"&gt;in&lt;/span&gt; clientes)&lt;br /&gt;    EnviarMailRecordatorio(cliente.Email);&lt;br /&gt;&lt;span class="kwrd"&gt;foreach&lt;/span&gt; (Cliente cliente &lt;span class="kwrd"&gt;in&lt;/span&gt; clientes)&lt;br /&gt;    LlamarPidiendoDevolucionDeCopias(cliente.Nombre, cliente.Telefono);&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;y evitamos as&amp;#237; viajar 2 veces al SQL.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&amp;#160;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;strong&gt;El &amp;#193;rbol de Las Expresiones&lt;/strong&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Yendo un poco m&amp;#225;s lejos nos preguntamos que ocurre cuando los par&amp;#225;metros de un query se modifican luego de haberlo construido, y enumerado, dicho de otra forma, que ocurre si ejecuto el siguiente c&amp;#243;digo:&lt;/p&gt;&lt;br /&gt;&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;txtDirector.Text = &lt;span class="str"&gt;&amp;quot;Kubrik&amp;quot;&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt;&lt;span class="rem"&gt;// solo por comodidad, utilizo en este query dot-notation&lt;/span&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;var&lt;/span&gt; query = VideoClubDataContext.Peliculas.Where(p =&amp;gt; p.Director.StartsWith(txtDirector.Text)).Select(p =&amp;gt; p.Titulo);&lt;br /&gt;&lt;br /&gt;MessageBox.Show(query.ToArray()[0]);&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;span class="rem"&gt;// modifico una variable que sirve como par&amp;#225;metro en query&lt;/span&gt;&lt;br /&gt;txtDirector.Text = &lt;span class="str"&gt;&amp;quot;de la Iglesia&amp;quot;&lt;/span&gt;;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;&lt;span class="rem"&gt;// enumero nuevamente, con el m&amp;#233;todo ToArray() &lt;/span&gt;&lt;br /&gt;MessageBox.Show(query.ToArray()[0]);&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&amp;#160;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;El primer mensaje ser&amp;#225; &amp;quot;2001: Una Odisea del Espacio&amp;quot; (de Kubrik, claro).&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;La gran pregunta ahora es... que mostrar&amp;#225; el segundo mensaje? Si apuestan a que el mensaje es el mismo, perdieron!&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;El segundo mensaje ser&amp;#225; &amp;quot;300 Balas&amp;quot; (de Alex de la Iglesia, claro)&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Como se entera nuestro objeto query de que el texto de nuestro TextBox cambi&amp;#243;? La respuesta es el &lt;strong&gt;Expression Tree&lt;/strong&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Un Expression Tree es un estructura en memoria que representa de forma jer&amp;#225;rquica una expresi&amp;#243;n C# (o VB.Net), no es c&amp;#243;digo compilado, de manera que permite recorrer la expresi&amp;#243;n del query, convirti&amp;#233;ndola a sintaxis SQL.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Expression Trees es un tema que requiere otros posts, con lo cual sin entrar en m&amp;#225;s detalles, voy a mostrar algo similar a una parte del &amp;#225;rbol que se construye en memoria con nuestro query de m&amp;#225;s arriba:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;  &lt;li&gt;LlamadaAFuncion &lt;br /&gt;    &lt;ul&gt;&lt;br /&gt;      &lt;li&gt;nombre = StartsWith &lt;/li&gt;&lt;br /&gt;&lt;br /&gt;      &lt;li&gt;objeto = Atributo &lt;br /&gt;        &lt;ul&gt;&lt;br /&gt;          &lt;li&gt;nombre = &amp;quot;Director&amp;quot; &lt;/li&gt;&lt;br /&gt;&lt;br /&gt;          &lt;li&gt;objeto = p (Elemento de la coleccion) &lt;/li&gt;&lt;br /&gt;        &lt;/ul&gt;&lt;br /&gt;      &lt;/li&gt;&lt;br /&gt;&lt;br /&gt;      &lt;li&gt;parametro1 = Atributo &lt;br /&gt;        &lt;ul&gt;&lt;br /&gt;          &lt;li&gt;nombre = &amp;quot;Text&amp;quot; &lt;/li&gt;&lt;br /&gt;&lt;br /&gt;          &lt;li&gt;objeto = &amp;quot;txtDirector&amp;quot; &lt;/li&gt;&lt;br /&gt;        &lt;/ul&gt;&lt;br /&gt;      &lt;/li&gt;&lt;br /&gt;    &lt;/ul&gt;&lt;br /&gt;  &lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Es decir que el objeto query sabe que debe utilizar como par&amp;#225;metro el valor de la propiedad Text del objeto txtDirector, reci&amp;#233;n al enumerar el objeto query, esto se traducir&amp;#225; a algo como:&lt;/p&gt;&lt;br /&gt;&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;WHERE&lt;/span&gt; [t0].[Director] &lt;span class="kwrd"&gt;LIKE&lt;/span&gt; @p0&lt;/pre&gt;&lt;br /&gt;donde: &lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;@p0 = &lt;span class="str"&gt;'Kubrik%'&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Esto tambi&amp;#233;n nos permite comenzar a entender como sintaxis LINQ se traduce en c&amp;#243;digo SQL, y lo que es muy importante, cuando.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Debe pensarse bien en que momento enumerarlos, y cuando utilizar ToArray(), ToList(), etc., para cachear los resultados.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3732630541286744699-5152741580934280672?l=blog.tercerplaneta.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Ideas3p/~4/VXH0UNwKXM8" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/Ideas3p/~3/VXH0UNwKXM8/linq-asomndose-detrs-de-escena.html</link><author>noreply@blogger.com (Benjamin Eidelman)</author><thr:total>0</thr:total><feedburner:origLink>http://blog.tercerplaneta.com/2008/01/linq-asomndose-detrs-de-escena.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3732630541286744699.post-5163503622585049198</guid><pubDate>Fri, 01 Feb 2008 20:14:00 +0000</pubDate><atom:updated>2008-02-01T18:26:22.357-02:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">.NET 3.5</category><category domain="http://www.blogger.com/atom/ns#">LINQ</category><category domain="http://www.blogger.com/atom/ns#">LINQ para SQL</category><title>LINQ y LINQ para SQL</title><description>&lt;p&gt;Un par de meses después de la liberación pública del Microsoft .NET Framework 3.5 (y su plataforma de desarrollo preferida, Visual Studio 2008), es buen momento para presentar algunas de nuestras impresiones sobre lo que probamos para el uso de estas tecnologías en aplicaciones reales.&lt;/p&gt;&lt;h4&gt;LINQ y sus providers&lt;/h4&gt;&lt;p&gt;El Language INtegrated Query (consultas integradas al lenguaje) consiste en un conjunto de &lt;strong&gt;extensiones &lt;/strong&gt;introducidas en el runtime de .NET y sus lenguajes principales (C# y VB) que permiten implementar una &lt;strong&gt;sintaxis flexible de consulta, &lt;/strong&gt;y de paso varias cosas más.&lt;/p&gt;&lt;p&gt;La aplicación de LINQ a diversas fuentes de datos, tales como colecciones en memoria, bases de datos relacionales, documentos de estructura jerárquica (XML) y otras, depende de la disponibilidad de los "providers" específicos para ese tipo de origen de datos.&lt;/p&gt;&lt;p&gt;Por eso, al analizar las capacidades de LINQ hay que distinguir entre la tecnología (o sintaxis) LINQ genérica, y los distintos proveedores específicos (LINQ to SQL, LINQ to XML, LINQ to DataSet, etc.) que pueden encontrarse en distinto grado de evolución. Vamos a analizarlos por separado:&lt;/p&gt;&lt;h4&gt;LINQ&lt;/h4&gt;&lt;p&gt;Una de las ventajas que inmediatamente resaltan al empezar a usar sintaxis LINQ en las aplicaciones, es la enorme simplificación que significa usar una sola sintaxis (una sola API) para operar sobre colecciones absolutamente heterogéneas. Hace unos meses yo conocía perfectamente el método Sort -específico de la clase Array- que permite ordenarlos; una propiedad Sort -en los DataView- que con otra sintaxis logra el mismo efecto sobre las vistas de un datatable. Y recurria a la ayuda en línea cuando necesitaba ordenar un conjunto de nodos XML o cualquier otra cosa. Lo mismo para filtrar, etc.&lt;/p&gt;&lt;p&gt;Felizmente ya me estoy olvidando de todo eso, porque ahora sólo uso expresiones como estas, independientemente de cuál es la coleccion sobre la que opero:&lt;/p&gt;&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;var&lt;/span&gt; pedidos = &lt;span class="kwrd"&gt;from&lt;/span&gt; a &lt;span class="kwrd"&gt;in&lt;/span&gt; archivos&lt;br /&gt;    &lt;span class="kwrd"&gt;where&lt;/span&gt; a.Extension == &lt;span class="str"&gt;".xml"&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;order by&lt;/span&gt; a.Name&lt;br /&gt;    &lt;span class="kwrd"&gt;select&lt;/span&gt; a;&lt;/pre&gt;&lt;p&gt;O su equivalente, no tan natural para leer pero más revelador de lo que ocurre tras la escena:&lt;/p&gt;&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;var&lt;/span&gt; pedidos = archivos&lt;br /&gt;    .Where(a =&amp;gt; a.Extension == ".xml")&lt;br /&gt;    .OrderBy(a =&amp;gt; a.Name)&lt;br /&gt;    .Select(a =&amp;gt; a);"&lt;/pre&gt;&lt;p&gt;Por supuesto, en ambos casos dejo que el Intellisense haga la mayor parte del trabajo. &lt;/p&gt;&lt;p&gt;Las extensiones que permiten esta sintaxis, como la declaracion anónima de tipos (new { Edad = m.edad, Nombre = ... }) y los métodos de extensión (ej. .Where(), .Select(), etc) tambien hacen que &lt;strong&gt;todo el manejo de colecciones&lt;/strong&gt; propias y &lt;strong&gt;de clases de negocio representadas como objetos "custom"&lt;/strong&gt; sea muchísmo mas fácil y abreviado.&lt;/p&gt;&lt;p&gt;Hasta acá, no hay ninguna duda. &lt;strong&gt;Esto es para usarlo, cuanto antes&lt;/strong&gt;, y no hay retorno.&lt;/p&gt;&lt;p&gt;NOTA: El segundo ejemplo trae reminiscencias de los paradigmas de programación funcional, y eso es exactamente lo que se ha incorporado al runtime .NET, mediante las &lt;strong&gt;expresiones lambda&lt;/strong&gt; (otra de las extensiones incluidas en la nueva versión).&lt;/p&gt;&lt;h4&gt;LINQ para SQL&lt;/h4&gt;&lt;p&gt;Acá el paisaje es muy atractivo, pero hay que estar atento al camino que empieza a volverse espinoso. &lt;/p&gt;&lt;p&gt;Lo primero que uno nota es que LINQ para SQL está integrado por distintos componentes, algunos de los cuales son más deseables (o están más maduros en su evolución) que otros.&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Existe un O/R designer (diseñador Objeto / Relacional), integrado en la IDE de Visual Studio, que permite mapear visualmente las tablas, procedimientos almacenados, etc. de un SQL Server y genera un archivo .DBML (XML) con su estructura. &lt;/li&gt;&lt;br /&gt;&lt;li&gt;Hay una herramienta de generación de código ("custom tool") tambien integrada en la IDE, que a partir de ese "mapa" DBML genera código de clases, decoradas con atributos de LINQ, que permiten el posterior armado de consultas LINQ &lt;/li&gt;&lt;br /&gt;&lt;li&gt;Las clases generadas se integran con un "Data Context" y otras clases del nuevo namespace System.Data.Linq, que incluyen la lógica de acceso a datos (sin necesidad de utilizar explícitamente las clases de ADO.NET) para traer los objetos de la BD y para persistir los cambios, en una modalidad "conectada" que no siempre resulta la más apropiada. &lt;/li&gt;&lt;br /&gt;&lt;li&gt;Finalmente, existe un "provider" de LINQ para SQL que, en base a los atributos de las clases, convierte la consulta LINQ en una sentencia Transact-SQL para enviar al servidor &lt;/li&gt;&lt;br /&gt;&lt;li&gt;Para los primeros dos componentes enumerados en esta lista(que se integran en la IDE) existe una alternativa como comando de línea (SqlMetal.exe) que tiene una funcionalidad similar pero no idéntica. &lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;p&gt;En proximos artículos del blog avanzaremos más sobre las características y escenarios de uso de LINQ para SQL. Por ahora, es importante entender la distincion entre la tecnología LINQ en general -de indudable aplicación- y su actual implementación para SQL, que tiene claros y oscuros.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3732630541286744699-5163503622585049198?l=blog.tercerplaneta.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Ideas3p/~4/Rp3vWdEKbiY" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/Ideas3p/~3/Rp3vWdEKbiY/linq-y-linq-para-sql.html</link><author>noreply@blogger.com (Jose Marcenaro)</author><thr:total>0</thr:total><feedburner:origLink>http://blog.tercerplaneta.com/2008/02/linq-y-linq-para-sql.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3732630541286744699.post-8425170195208849410</guid><pubDate>Thu, 06 Dec 2007 11:57:00 +0000</pubDate><atom:updated>2007-12-17T12:46:27.378-03:00</atom:updated><title>Jornadas 3P</title><description>En esta oportunidad queremos contarles acerca de nuestra experiencia en lo que denominamos "Jornadas 3P", orientadas a la comunicación e integración de un equipo de trabajo pequeño y al gerenciamiento de los distintos proyectos.&lt;br /&gt;&lt;br /&gt;La idea de una Jornada es reunirse en un lugar "neutral", siempre fuera de la oficina, para discutir acerca de diferentes temas que hacen a la empresa y al grupo.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;El objetivo principal de estas reuniones es crear un ambiente laboral cómodo y ameno, donde:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;cada integrante se sienta parte del grupo, una parte importante,&lt;/li&gt;&lt;li&gt;cada uno pueda expresar sus ideas libremente y&lt;/li&gt;&lt;li&gt;se colabore con el crecimiento tanto de la empresa, como del grupo, y por supuesto, esto tiene una influencia en el crecimiento laboral y personal de cada integrante.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;&lt;strong&gt;De qué consta específicamente una jornada...&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;Una jornada es en definitiva una lista de ítems a tratar. Entre estos items se incluyen temas laborales, charlas, recreación o juegos.&lt;/p&gt;&lt;p&gt;&lt;em&gt;Por que incluir juegos…&lt;/em&gt; Porque nos parece importante que las jornadas cuenten con espacios para la recreación en conjunto, por lo cual nos gusta incluir juegos y charlas que nos permitan distendernos mientras desayunamos o almorzamos. Esto ayuda a "romper el hielo", así cada uno puede relajarse y sentirse a gusto, sin ninguna presión, y ayuda también a la integración y comunicación del grupo.&lt;/p&gt;&lt;p&gt;Unos días previos a la Jornada se define un &lt;em&gt;cronograma&lt;/em&gt; con los ítems a desarrollar, por cada uno se indica: fecha, hora, item y duración, y de ser necesario también se indica un responsable de dirigirlo. Este cronograma se le entrega a cada integrante, con lo cual, al llegar el día de la reunión todos los participantes conocen los temas y el horario de cada uno.&lt;/p&gt;&lt;p&gt;También dentro del cronograma se incluye el horario de cada comida (desayuno, almuerzo, cena).&lt;/p&gt;&lt;p&gt;A Jornadas las podriamos dividir en dos grandes grupos, de acuerdo a la periodicidad con que se realizan:&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:130%;"&gt;&lt;strong&gt;Jornada trimestral&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;Se elige algún lugar cerca de la oficina. El mismo tiene que ser cómodo y confortable para que podamos estar reunidos todos juntos o divididos en grupos de 2 o 3 personas, diseminados por el lugar.&lt;/p&gt;&lt;p&gt;En algunos casos elegimos lugares que parecen poco convencionales para una reunión laboral, como por ejemplo el zoológico. Lo importante es elegir el lugar adecuado para crear el ambiente apropiado y así poder tratar los diversos temas con la soltura que necesitamos.&lt;/p&gt;&lt;p&gt;Comienzan a las 9am, con un desayuno y una charla amena, no necesariamente laboral, que permita la participación de todos. Y finalizan con el almuerzo.&lt;/p&gt;&lt;p&gt;Se realizan cada 3 o 4 meses.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:130%;"&gt;&lt;strong&gt;Jornada anual&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;Las jornadas anuales pueden ser de 1 o 2 días completos.&lt;/p&gt;&lt;p&gt;En estas Jornadas se utilizará un pizarrón, se desayunará y almorzará, se realizará algún juego… con lo cual el lugar elegido tiene que tener las condiciones necesarias para que resulte cómodo en el desarrollo de todas las actividades. Una buena ubicación podría ser una quinta.&lt;/p&gt;&lt;p&gt;Las Jornadas de 1 día completo se realizan una vez por año, alrededor de Mayo o Junio.&lt;/p&gt;&lt;p&gt;Comienzan a las 9am y finalizan a las 18hs. &lt;/p&gt;&lt;p&gt;En las jornadas que lleven mas de un día, se elige un lugar "alejado de la civilización", nosotros optamos por la Costa Atlántica (Pinamar o Cariló, como fue este año), y por lo general las realizamos a mediados de Noviembre. También se elige un lugar que nos resulte cómodo tanto para desarrollar las diversas actividades como para hospedarnos.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;&lt;strong&gt;Que temas se tratan?&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;Tanto para las Jornadas trimestrales como las anuales, los socios de la empresa son los encargados de decidir cuáles son los principales temas a tratar, y el momento de tratarlos durante la Jornada (ellos realizan el cronograma de items).&lt;/p&gt;&lt;p&gt;Estos temas resultan de inquietudes propias o de los integrantes del equipo, las cuales se exponen al grupo para su posterior evaluación. Por ejemplo, se escriben ideas de temas en un Sharepoint, o se comentan en alguna reunión.&lt;/p&gt;&lt;p&gt;En las Jornadas trimestrales se plantean los posibles temas a tratar en las Jornadas anuales. También se hace una conclusión de cómo resultó lo que se trató en las Jornadas anuales.&lt;/p&gt;&lt;p&gt;En las Jornadas anuales los temas que se tratan estan mas orientados a lo que pasó en el año y lo que esperamos del año próximo.&lt;/p&gt;&lt;p&gt;Cada uno de los temas seleccionado esta dirigido por un integrante del equipo, el cual es responsable del mismo: da una breve introducción, induce al debate entre los integrantes, y en caso de ser un tema a continuar en el tiempo, se lo propone como responsable del seguimiento y cumplimiento de lo acordado.&lt;/p&gt;&lt;p&gt;Los posibles temas a tratar en las Jornadas serian:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;cómo se siente cada integrante del equipo, con respecto a las tareas que realiza y al entorno de trabajo&lt;/li&gt;&lt;li&gt;cuales son sus inquietudes y objetivos, tanto laborales, como personales (si quieren comentar, claro)&lt;/li&gt;&lt;li&gt;determinar un plan de trabajo para el año en curso y el siguiente (Jornadas anuales)&lt;/li&gt;&lt;li&gt;para los proyectos finalizados, se analiza qué nos dejó: errores y aciertos, para aplicar el aprendizaje en el futuro&lt;/li&gt;&lt;li&gt;cada integrante expresa su opinión acerca de la empresa: lo que es, lo que espera que sea y el lugar que espera ocupar (Jornadas anuales)&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="font-size:130%;"&gt;&lt;strong&gt;Pinamar - Cariló 2007&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;Nuestra mas reciente Jornada fue en Noviembre, la cual duró 2 días. El lugar elegido fue un complejo de cabañas sito en Cariló (se encuentra en la Costa Atlántica).&lt;/p&gt;&lt;p&gt;Se trataron diferentes temas, entre los principales podemos destacar:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;como ve cada uno a Tercer Planeta: cual es la imagen que tenemos y que queremos lograr, y que hay que hacer para alcanzarlo&lt;/li&gt;&lt;li&gt;expectativas y/o proyectos personales&lt;/li&gt;&lt;li&gt;expectativas con respecto a la Jornada&lt;/li&gt;&lt;li&gt;qué anduvo bien y qué anduvo mal en el año&lt;/li&gt;&lt;li&gt;charlas individuales de los socios con cada integrante&lt;/li&gt;&lt;li&gt;objetivos 2008&lt;/li&gt;&lt;li&gt;comunicación interna (¿Nos comunicamos bien? ¿Qué podemos hacer para mejorar? ¿Hay quejas?)&lt;/li&gt;&lt;li&gt;capacitaciones&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="font-size:130%;"&gt;&lt;strong&gt;Conclusiones&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;El objetivo principal de realizar una Jornada es facilitar la comunicación e integración del grupo. Mediante charlas, debates, exposición de ideas e inquietudes o juegos se logra poder conocer un poco mas a la persona con la que trabajamos y convivimos todos los días, y logramos poder hablar libremente.&lt;/p&gt;&lt;p&gt;Otro objetivo importante es poder definir los lineamientos de la empresa, tener la capacidad de ver los aciertos y errores, para potenciar y corregir lo necesario y establecer un plan de trabajo tanto de la empresa como de los integrantes.&lt;/p&gt;&lt;p&gt;&lt;em&gt;Cuando los objetivos son claros y conocidos, es sencillo alcanzarlos...&lt;/em&gt;&lt;/p&gt;&lt;p&gt;&lt;em&gt;Cuando el grupo esta integrado y motivado, ¡el trabajo resulta menos denso y el ambiente laboral resulta agradable!&lt;/em&gt;&lt;/p&gt;&lt;p&gt;Por lo cual les recomendamos ampliamente la práctica de una Jornada, de acuerdo a las necesidades y estructura organizacional.&lt;/p&gt;&lt;p&gt;&lt;em&gt;¡Animense! ¡No es imposible!&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3732630541286744699-8425170195208849410?l=blog.tercerplaneta.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Ideas3p/~4/g6MgPJ_eVM8" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/Ideas3p/~3/g6MgPJ_eVM8/jornadas-3p.html</link><author>noreply@blogger.com (Nora Martinez)</author><thr:total>0</thr:total><feedburner:origLink>http://blog.tercerplaneta.com/2007/12/jornadas-3p.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3732630541286744699.post-7808697038943280988</guid><pubDate>Thu, 06 Dec 2007 10:35:00 +0000</pubDate><atom:updated>2007-12-06T07:44:30.193-03:00</atom:updated><title>Uso de Team Foundation Server Source Control en VB6: proveedor MSSCCI para TFS</title><description>Para quienes hemos adoptado Visual Studio 2005 Team Foundation Server como administrador de código fuente, una necesidad frecuente es la de integrar en el mismo repositorio el trabajo desde otras herramientas anteriores a VS 2005, por ejemplo Visual Basic 6.0, Visual FoxPro 9, Visual Studio .NET 2003, etc.&lt;br /&gt;&lt;br /&gt;Para estos casos Microsoft ha liberado en diciembre 2006 el proveedor MSSCCI correspondiente a Team Foundation Server, haciendo posible la integracion de código fuente con TFS en cualquier herramienta compatible con el estandard MSSCCI. El software puede descargarse aquí: &lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyId=87E1FFBD-A484-4C3A-8776-D560AB1E6198&amp;amp;displaylang=en"&gt;http://www.microsoft.com/downloads/details.aspx?FamilyId=87E1FFBD-A484-4C3A-8776-D560AB1E6198&amp;amp;displaylang=en&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Debe tenerse en cuenta que este proveedor MSSCCI es sólo el conector entre las herramientas cliente y el TFS, y no incluye un "explorador" del arbol de código similar al Team Explorer (TFS) o el Source Safe Explorer (VSS). Para esas tareas de exploración debe utilizarse (y de hecho es un prerequisito de la instalación) el Team Explorer, que es una extensión a la IDE de Visual Studio 2005&lt;br /&gt;&lt;br /&gt;Lo que el conector sí realiza, en herramientas que tienen integración con un Source Control Provider, es permitir que dentro de la IDE respectiva (p.ej. en VB6, o VFP 9, VS.NET 2003) se acceda en forma transparente al repositorio de código montado en Team Foundation&lt;br /&gt;Server.&lt;br /&gt;&lt;p&gt;Veamos por ejemplo los pasos para integrar en un proyecto VB6 el control de código de TFS&lt;/p&gt;&lt;ol&gt;&lt;li&gt;Instalar Team Explorer, incluido en el CD de instalación de Team Foundation Server&lt;/li&gt;&lt;li&gt;Instalar el proveedor MSSCCI descargado del link mencionado previamente&lt;/li&gt;&lt;li&gt;Verificar que Visual Basic tenga aplicado el ultimo Service Pack (SP6, actualmente)&lt;/li&gt;&lt;li&gt;Cerrar y reiniciar la IDE de VB si está abierta.&lt;/li&gt;&lt;li&gt;Desde la IDE de VB, en la opción Add-ins / Add-in manager... del menú, seleccionar activar la opcion "Source Code Control", (asignarle Startup + Loaded)&lt;/li&gt;&lt;/ol&gt;Una vez cargado el add-in, pueden realizarse las operaciones normales de integracion con source control utilizando el menú contextual sobre el explorador de proyectos (check-in, check-out, etc) y las opciones de menu (Toosl / Team Foundation).&lt;br /&gt;Asimismo, al grabar un proyecto no integrado a Source Control aparecerá el diálogo consultando si se desea agregarlo.&lt;br /&gt;&lt;br /&gt;Para otras operaciones más específicas sobre el repositorio de código (ej. modificación de workspaces, operaciones de "branch" y "merge", etc) se utiliza la interfaz visual del Team Explorer.&lt;br /&gt;&lt;br /&gt;Notas:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Si en VB6 no está disponible el add-in de "Source Code Control" luego de aplicar el SP6, seguir los pasos descriptos en este artículo de la KB: &lt;a href="http://support.microsoft.com/kb/305024/"&gt;http://support.microsoft.com/kb/305024/&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Si se desea alternar entre el proveedor de TFS y el proveedor de Visual Source Safe, pueden seguirse los pasos descriptos en la sección "How to Switch MSSCCI Providers" en este artículo: &lt;a href="http://blogs.msdn.com/edhintz/archive/2006/04/10/572826.aspx"&gt;http://blogs.msdn.com/edhintz/archive/2006/04/10/572826.aspx&lt;/a&gt;&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3732630541286744699-7808697038943280988?l=blog.tercerplaneta.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Ideas3p/~4/x1U0REW3diE" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/Ideas3p/~3/x1U0REW3diE/uso-de-tfs-en-vb6-con-el-proveedor.html</link><author>noreply@blogger.com (Jose Marcenaro)</author><thr:total>0</thr:total><feedburner:origLink>http://blog.tercerplaneta.com/2007/12/uso-de-tfs-en-vb6-con-el-proveedor.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3732630541286744699.post-2708636709630829196</guid><pubDate>Wed, 21 Nov 2007 14:10:00 +0000</pubDate><atom:updated>2007-11-21T11:23:45.046-03:00</atom:updated><title>LINQ: el futuro se nos vino encima</title><description>... y cuando quisimos darnos cuenta, ya estaba acá&lt;br /&gt;&lt;br /&gt;Anteayer (19/11/07) Microsoft hizo públicos&lt;br /&gt;&lt;ul&gt;&lt;li&gt;el &lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyId=333325FD-AE52-4E35-B531-508D977D32A6"&gt;runtime de .NET Framework 3.5&lt;/a&gt;  &lt;/li&gt;&lt;li&gt;las &lt;a href="http://msdn2.microsoft.com/en-us/vstudio/products/aa700831.aspx"&gt;versiones de evaluación de Visual Studio 2008&lt;/a&gt;&lt;/li&gt;&lt;li&gt;y, para los suscriptores MSDN, &lt;a href="http://go.microsoft.com/?linkid=7783416"&gt;la versión RTM de Visual Studio 2008&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Hay tantas novedades en esta version del producto....&lt;/p&gt;&lt;p&gt;En nuestra opinion, el mayor impacto (y el mayor trabajo de difusión, discusión y esclarecimiento) gira en torno a LINQ y las extensiones a los lenguajes C# y VB que lo soportan.&lt;/p&gt;&lt;p&gt;Se abre un mundo de posibilidades que hay que explorar, entender, elegir... &lt;/p&gt;&lt;p&gt;Vuelva a este blog para más discusiones sobre el tema, en breve!&lt;/p&gt;&lt;p&gt;Jose.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3732630541286744699-2708636709630829196?l=blog.tercerplaneta.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Ideas3p/~4/vAYM5Ivipu0" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/Ideas3p/~3/vAYM5Ivipu0/linq-el-futuro-se-nos-vino-encima.html</link><author>noreply@blogger.com (Jose Marcenaro)</author><thr:total>0</thr:total><feedburner:origLink>http://blog.tercerplaneta.com/2007/11/linq-el-futuro-se-nos-vino-encima.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3732630541286744699.post-5811240342072903311</guid><pubDate>Mon, 12 Nov 2007 23:24:00 +0000</pubDate><atom:updated>2007-11-13T09:13:46.888-03:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Arquitectura</category><category domain="http://www.blogger.com/atom/ns#">Buenas Prácticas</category><title>Las buenas prácticas de desarrollo siempre pagan</title><description>En estos días estuvimos evaluando un conjunto de aplicaciones desarrolladas durante los últimos siete años por una importante cadena de supermercados en Argentina, en el lenguaje Visual FoxPro.&lt;br /&gt;&lt;br /&gt;Cuando en 2000 se inició el proyecto de reemplazo de su sistema completo de gestión comercial y de inventarios, nos convocaron para participar en la definición de la arquitectura y la construcción de un framework de clases que sirviera de base para el crecimiento futuro de la aplicación.&lt;br /&gt;&lt;br /&gt;Siete años y más de cien mil horas de horas de programación despues, nos tocó evaluar la factibilidad y costo de la conversión a .NET (C#) de toda la lógica de negocios, desarrollada en VFP por un equipo de programadores que se sucedieron en el tiempo agregando funcionalidad y nuevos módulos&lt;br /&gt;&lt;br /&gt;Para la evaluación desarrollamos un parser en C#, que realiza un análisis “drill down” del código Visual FoxPro analizando las clases y métodos y verifica cuánto del código es mapeable a expresiones simples con invocaciones a métodos básicos (y por lo tanto, es convertible en forma automática con una herramienta a desarrollar).&lt;br /&gt;&lt;br /&gt;En este proceso de evaluación constatamos algunas suposiciones iniciales, y nos llevamos algunas sorpresas:&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Arquitectura.&lt;/strong&gt; Tal como se esperaba, lo que por diseño se concibió para ser interoperable participa a la perfección en el proceso de evolución de la arquitectura:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Los componentes de negocios, todos implementados como componentes COM que intercambian XML y acceden a datos en SQL Server, pueden ser “mapeados” exactamente a los nuevos componentes en .NET implementados como servicios.&lt;/li&gt;&lt;li&gt;En la capa de presentación, el hecho de haber implementado desde el principio un “dispatcher” que centraliza las invocaciones a la capa de negocios permite introducir fácilmente un conmutador de las llamadas para encaminarlas a los componentes COM originales o bien a los nuevos servicios .NET (Strategy Pattern, GOF).&lt;/li&gt;&lt;li&gt;Esto permitirá que la conversión de la lógica de negocios y el reemplazo de componentes se realice en forma gradual, y de hecho permitiría escenarios de coexistencia de las tecnologías en forma permanente, si esa fuera la estrategia deseada.&lt;/li&gt;&lt;/ul&gt;&lt;strong&gt;Prácticas de desarrollo.&lt;/strong&gt; Con cierta sorpresa, dada la cantidad de programadores que se alternaron durante el proceso de evolucion de las aplicaciones, constatamos un muy alto nivel de calidad y de homogeneidad en las prácticas de desarrollo:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;De los más de 12000 métodos presentes en la capa de negocios, más de 7000 tienen de 1 a 10 líneas de código, y otros 2000 entre 11 y 20 líneas; con un altísimo grado de reuso de los métodos y clases base para la funcionalidad de uso frecuente. &lt;/li&gt;&lt;li&gt;El análisis sintáctico del código permite estimar en más de 8500 los métodos directamente convertibles en forma automática, por consistir en invocaciones a métodos del framework propio con expresiones o comparaciones simples (If …. Then, etc), con otros 2000 métodos que también pueden convertirse en forma automática pero requieren algun grado de revision manual.&lt;/li&gt;&lt;/ul&gt;En conclusión, y sin minimizar la magnitud que requerirá una tarea de migración tecnológica tan importante (por la evolución cualitativa que representa .NET), constatamos con satisfacción que el costo inicial de desarrollar una arquitectura distribuida, interoperable, y de establecer un marco y prácticas de desarrollo precisas, tiene un triple efecto de devolución:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;En la calidad del sistema, que permitió el crecimiento y evolución de la cadena durante estos años, y su mantenibilidad aún cuando los equipos vayan renovandose.&lt;/li&gt;&lt;li&gt;En la posibilidad concreta, y ya puesta en práctica, de integrar los componentes originales con otros desarrollados en tecnologías radicalmente nuevas, sin necesariamente encarar una reconversión completa.&lt;/li&gt;&lt;li&gt;En las enormes ventajas, en caso de encarar una reconversión, de partir con mucho terreno ganado y una proporcion muy mayoritaria de código que puede convertirse automáticamente.&lt;/li&gt;&lt;/ul&gt;Considere estos factores a la hora de encarar su próximo proyecto: “quick and dirty” (rápido y sucio) no siempre siempre resulta rápido; pero casi con seguridad va a resultar sucio y finalmente caro.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3732630541286744699-5811240342072903311?l=blog.tercerplaneta.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Ideas3p/~4/wli_dr5pqh8" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/Ideas3p/~3/wli_dr5pqh8/las-buenas-prcticas-de-desarrollo.html</link><author>noreply@blogger.com (Jose Marcenaro)</author><thr:total>0</thr:total><feedburner:origLink>http://blog.tercerplaneta.com/2007/11/las-buenas-prcticas-de-desarrollo.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3732630541286744699.post-6253225711274867563</guid><pubDate>Wed, 20 Jun 2007 22:39:00 +0000</pubDate><atom:updated>2007-06-20T19:47:15.463-03:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">ASP.NET</category><category domain="http://www.blogger.com/atom/ns#">Microsoft SQL Server</category><category domain="http://www.blogger.com/atom/ns#">Seguridad Integrada</category><title>Seguridad integrada con SQL Server en  un sitio web ASP.NET</title><description>Una consulta muy frecuente que recibimos es “como configurar un sitio web para acceder a SQL Server mediante seguridad integrada”, bajo la situación más habitual (y recomendada) que es aquella en la cual los usuarios que acceden al sitio no utilizan seguridad integrada de Windows o, aún en caso de hacerlo, no tienen asignados permisos individuales de acceso a la base de datos de la aplicación.&lt;br /&gt;&lt;br /&gt;La implementación de este escenario, en la plataforma actual de servidores Web de Windows (Windows Server 2003), consta de los siguientes pasos:&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;1. Definir un usuario del dominio para ejecutar la aplicación web y acceder al SQL Server&lt;/h3&gt;Crear una cuenta de usuario en Active Directory, designada para ejecutar las aplicaciones web y acceder al SQL Server. Es recomendable que esta cuenta no sea administrador del dominio, ni del equipo en que ejecuta el website o el SQL Server.&lt;br /&gt;&lt;h3&gt;2. Asignar permisos a ese usuario en Microsoft SQL Server&lt;/h3&gt;Mediante el SQL Server Management Studio (SQL Server 2005) o el SQL Server Enterprise Manager (SQL Server 2000) definir, dentro de la seccion Security, una cuenta (login) de seguridad integrada correspondiente a la cuenta designada del dominio; asignarle permisos sobre las bases que corresponda, solamente con los privilegios que requiera para ejeutarse.&lt;br /&gt;&lt;h3&gt;3. Preparar la cuenta para ejecutar aplicaciones ASP.NET&lt;/h3&gt;Este es un paso comunmente omitido, que resulta en la imposibildad de ejecutar correctamente el sitio.&lt;br /&gt;En el equipo en que se ejecuta el sitio Web (Internet Information Server) configurar lo siguiente:&lt;br /&gt;&lt;ol&gt;&lt;br /&gt;&lt;li&gt;Asignar a la cuenta designada permisos de control total sobre la carpeta temporaria de Windows (habitualmente C:\Windows\Temp).&lt;br /&gt;&lt;li&gt;Desde la línea de comandos posicionarse en la carpeta correspondiente al framework .NET en uso (por ejemplo C:\Windows\Microsoft.NET\Framework\ v2.0.50727) y allí ejecutar el siguiente comando:&lt;br /&gt;aspnet_regiis –ga {dominio\cuenta}&lt;br /&gt;reemplazando {dominio\cuenta} por la cuenta designada en el paso 1&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;&lt;h3&gt;4. Asignar la cuenta designada como identidad del proceso ASP.NET&lt;/h3&gt;En Windows Server 2003, eso se realiza en la consola de Administración de Servicios Internet (IIS) asignando la identidad del Application Pool que se utiliza para ejecutar la aplicación Web.&lt;br /&gt;IMPORTANTE: si la aplicación está configurada para ejecutar en el “Default App Pool”, u otro compartido con múltiples aplicaciones, puede ser conveniente definir un application pool separado para los sitios que deban ejecutarse bajo esta cuenta de usuario, y asignar los sitios al App Pool creado.&lt;br /&gt;&lt;h3&gt;5. En la aplicación ASP.NET, asegurarse que no esté activa la “impersonación”&lt;/h3&gt;Si se utiliza Authentication mode=”Windows”, asegurarse que en el archivo Web.config no exista un elemento &amp;lt;identity&gt; o, si existe, asegurarse de que tenga asignado el atributo impersonate=”false”.&lt;br /&gt;De ese modo, el proceso se ejecutará con la cuenta designada.&lt;br /&gt;NOTA: sin necesidad de impersonar, desde el código de la aplicación Web puede conocerse el nombre de la cuenta autenticada mediante la propiedad User.Identity&lt;br /&gt;&lt;br /&gt;&lt;hr /&gt;&lt;br /&gt;Con estos pasos, se lograrán los objetivos buscados:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Evitar incluir nombres de usuario y password en la configuración de la aplicación (o en cualquier otro componente de la misma)&lt;br /&gt;&lt;li&gt;Ejecutar el sitio web con una cuenta que no tenga más privilegios de los requeridos&lt;br /&gt;&lt;li&gt;Evitar otorgar permisos sobre la base de datos a los usuarios del sitio.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3732630541286744699-6253225711274867563?l=blog.tercerplaneta.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Ideas3p/~4/0a0BZPuKBNk" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/Ideas3p/~3/0a0BZPuKBNk/seguridad-integrada-con-sql-server-en.html</link><author>noreply@blogger.com (Jose Marcenaro)</author><thr:total>0</thr:total><feedburner:origLink>http://blog.tercerplaneta.com/2007/06/seguridad-integrada-con-sql-server-en.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3732630541286744699.post-7055997485344552542</guid><pubDate>Tue, 12 Jun 2007 13:01:00 +0000</pubDate><atom:updated>2007-06-12T10:40:54.228-03:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Windows Vista</category><category domain="http://www.blogger.com/atom/ns#">SQL Server 2005</category><title>SQL Server 2005 sobre Windows Vista</title><description>Dos recomendaciones muy importantes para utilizar SQL Server 2005 sobre el sistema operativo Windows Vista&lt;br /&gt;&lt;br /&gt;1) En todos los casos (se trate de las herramientas cliente, o el motor de base de datos) instalar el Service Pack 2 de SQL Server 2005&lt;br /&gt;&lt;a href="http://www.microsoft.com/downloads/browse.aspx?displaylang=es&amp;productID=9F07F9CC-C308-4EBF-A4E9-2B8530AB1EA8"&gt;http://www.microsoft.com/downloads/browse.aspx?displaylang=es&amp;productID=9F07F9CC-C308-4EBF-A4E9-2B8530AB1EA8&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;2) Adicionalmente, si se ha instalado el server (motor de base de datos) sobre uno de estos sistemas operativos, tener en cuenta que cambia el manejo por defecto de la seguridad:&lt;br /&gt;&lt;br /&gt;Al instalar un SQL 2005, automáticamente se agrega un login para el grupo BUILTIN\Administrators, con permisos de sysadmin.&lt;br /&gt;Sin embargo, el manejo de seguridad de Windows Vista hace que un usuario, aunque sea administrador del equipo, no ejecute las aplicaciones como tal salvo cuando lo hace con "privilegios elevados" (Run as administrator)&lt;br /&gt;&lt;br /&gt;Por lo tanto hay dos opciones para que un usuario administrador del equipo tenga privilegios completos de administracion del SQL Server 2005 en ese equipo:&lt;br /&gt;&lt;br /&gt;a) [No recomendado] Ejecutar el SQL Server Management Studio mediante la opción "Run as Administrator"&lt;br /&gt;&lt;br /&gt;b) [Recomendado] Empleando el "SQL Server Surface Area Configuration", agregar la cuenta del usuario para que actúe como administrador (opcion Add New Administrator)&lt;br /&gt;&lt;br /&gt;Para más información sobre las buenas prácticas de administración y operación SQL Server 2005, puede descargarse este documento de Microsoft (en inglés):&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;a href="http://download.microsoft.com/download/8/5/e/85eea4fa-b3bb-4426-97d0-7f7151b2011c/SQL2005SecBestPract.doc"&gt;SQL Server 2005 Security Best Practices - Operational and Administrative Tasks&lt;/a&gt;&lt;/strong&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3732630541286744699-7055997485344552542?l=blog.tercerplaneta.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Ideas3p/~4/3oEPjbS9e6M" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/Ideas3p/~3/3oEPjbS9e6M/sql-server-2005-sobre-windows-vista.html</link><author>noreply@blogger.com (Jose Marcenaro)</author><thr:total>1</thr:total><feedburner:origLink>http://blog.tercerplaneta.com/2007/06/sql-server-2005-sobre-windows-vista.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3732630541286744699.post-708591387553891257</guid><pubDate>Mon, 11 Jun 2007 13:27:00 +0000</pubDate><atom:updated>2009-06-12T09:30:15.303-03:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Exceptions</category><category domain="http://www.blogger.com/atom/ns#">Exception Handling Application Block</category><category domain="http://www.blogger.com/atom/ns#">Logging</category><category domain="http://www.blogger.com/atom/ns#">Exception Handling</category><category domain="http://www.blogger.com/atom/ns#">Logging and Instrumentation Application Block</category><category domain="http://www.blogger.com/atom/ns#">Excepciones</category><category domain="http://www.blogger.com/atom/ns#">Log</category><category domain="http://www.blogger.com/atom/ns#">Enterprise library</category><title>Exception Handling y Logging con Enterprise Library 3.0</title><description>&lt;p&gt;En este artículo voy a mostrar como agregar un manejo simple de excepciones, y luego logging de éstas y otros eventos usando &lt;a title="Enterprise Library 3.0" href="http://msdn2.microsoft.com/en-us/practices/bb190359.aspx" target="_blank"&gt;Enterprise Library 3.0&lt;/a&gt;, sin profundizar en todas las posibilidades que éstas librerías ofrecen.&lt;br /&gt;&lt;br /&gt;Usaremos en este ejemplo los siguientes bloques de Enterprise Library 3.0:&lt;br /&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Exception Handling Application Block &lt;li&gt;Logging Application Block (que registrará Excepciones recibidas por el bloque anterior, y otros mensajes de bitácora) &lt;li&gt;Data Application Block (para permitir al bloque anterior, Logging sobre una base de datos SQL) &lt;/li&gt;&lt;/ul&gt;&lt;p&gt;(Es condición previa en el ejemplo siguiente, agregar referencias en nuestro proyecto a los assemblies correspondientes) &lt;/p&gt;&lt;p&gt;De la aplicación de ejemplo realizada en C#, nos interesa el siguiente bloque de código:&lt;/p&gt;&lt;img style="TEXT-ALIGN: center; MARGIN: 0px auto 10px; DISPLAY: block; CURSOR: hand" id="BLOGGER_PHOTO_ID_5074807089206978882" border="0" alt="" src="http://4.bp.blogspot.com/_GcXPWR_goXk/Rm1WKP_Q6UI/AAAAAAAAAA0/c-lddcPzouY/s320/exceptionhandling1.GIF" /&gt;&lt;br /&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;Vamos a trabajar sobre este método, que resulta crítico para nuestro sistema, por lo cual queremos una bitácora de su ejecución y resultado.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Exception Handling Application Block&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Este bloque nos permite delegar el manejo de una excepción a una policy definida en archivos de configuración. En particular nos permitirá encapsular, reemplazar, absorber excepciones, o enviar éstas al Logging Application Block para registrarlas en una bitácora.&lt;br /&gt;&lt;br /&gt;Para esto basta con modificar nuestro código de la siguiente manera:&lt;/p&gt;&lt;img style="TEXT-ALIGN: center; MARGIN: 0px auto 10px; DISPLAY: block; CURSOR: hand" id="BLOGGER_PHOTO_ID_5074807368379853138" border="0" alt="" src="http://1.bp.blogspot.com/_GcXPWR_goXk/Rm1Waf_Q6VI/AAAAAAAAAA8/F0zdTRN2ft8/s320/exceptionhandling2.GIF" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;Interceptamos cualquier tipo de Exception, y la manejamos con el método estático:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:Courier New;color:#666666;"&gt;&lt;span style="font-family:Courier New;color:#666666;"&gt;&lt;/span&gt;&lt;span style="font-family:Courier New;color:#666666;"&gt;&lt;/span&gt;&lt;span style="font-family:Courier New;color:#666666;"&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="color:#2b91af;"&gt;ExceptionPolicy&lt;/span&gt;&lt;span style="color:#000000;"&gt;.HandleException()&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;Éste recibe la excepción a ser manejada, el nombre de la policy a aplicar (a continuación vamos a definir esta política), y opcionalmente un parámetro out en el que se devuelve la excepción que reemplaza a la original (esto sucede cuando la policy utilizada decide que la excepción debe ser reemplazada o contenida dentro de una nueva), si la excepción no debe ser reemplaza este parámetro toma el valor null.&lt;br /&gt;&lt;br /&gt;Este método devuelve &lt;span style="color:#3333ff;"&gt;true&lt;/span&gt;&lt;span style="color:#3333ff;"&gt;&lt;/span&gt;&lt;span style="color:#3333ff;"&gt;&lt;/span&gt;&lt;span style="color:#3333ff;"&gt;&lt;/span&gt; si la excepción (o la excepción que la reemplaza) debe ser relanzada.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Ahora sólo resta definir nuestra &lt;span style="color:#a31515;"&gt;&lt;span style="font-family:Courier New;"&gt;"TareasPolicy"&lt;/span&gt;&lt;/span&gt;&lt;span style="color:#a31515;"&gt;&lt;/span&gt;, para eso alcanza con editar el archivo de configuración (app.config, web.config, *.config) con la herramienta gráfica que incluye Enterprise Library (Enterprise Library Configuration Tool), con la cual resulta trivial lo siguiente:&lt;br /&gt;&lt;/p&gt;&lt;ol&gt;&lt;li&gt;Agregar un bloque de configuración para Exception Handling, y dentro de éste crear una nueva policy con el nombre "TareasPolicy". &lt;li&gt;Definir en esta policy para el tipo de excepción Exception (es decir para todas), un Logging Handler, y definimos para este Handler, que las excepciones produzcan entradas de Log de nivel "Error" (lógicamente), y con la categoría "Errores", vamos a ver que implica esto a continuación. &lt;/li&gt;&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;Dentro de una policy podemos definir también los siguientes Exception Handlers, que pueden utilizarse según el tipo de Exception lanzada:&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Wrap Handler&lt;/b&gt;: Envuelve la excepción lanzada dentro de una nueva.&lt;br /&gt;&lt;b&gt;Replace Handler&lt;/b&gt;: Reemplaza la excepción con una nueva.&lt;br /&gt;&lt;b&gt;Logging Handler&lt;/b&gt;: Transfiere la excepción al Logging Application Block para poder registrarla en una bitácora.&lt;br /&gt;&lt;b&gt;Custom Handler&lt;/b&gt;: Permite manejar una excepción utilizando una clase definida en nuestra aplicación.&lt;br /&gt;&lt;strong&gt;Fault Contract Exception Handler&lt;/strong&gt;: Facilita el manejo de excepciones en aplicaciones SOA.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Logging and Instrumentation Application Block&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Necesitamos ahora indicar como serán tratadas en este bloque las excepciones recibidas, pero antes es preciso definir las entidades más importantes en este bloque:&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Trace Listener&lt;/b&gt;: Manejan los eventos registrándolos o emitiéndolos en distintos medios, son los siguientes:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Formatted EventLog&lt;/strong&gt;: registra los eventos en el EventLog del sistema. &lt;li&gt;&lt;strong&gt;Flat File&lt;/strong&gt;: simplemente almacena los eventos en un archivo de texto plano. &lt;li&gt;&lt;strong&gt;Rolling Flat File&lt;/strong&gt;: utiliza un archivo de texto, que al alcanzar una antigüedad o támaño máximo se cierra y comienza uno nuevo. &lt;li&gt;&lt;strong&gt;Xml&lt;/strong&gt;: en este caso el log generado es un documento xml, asimismo las entradas pueden contener un campo xml. &lt;li&gt;&lt;strong&gt;Email&lt;/strong&gt;: envía notificaciones de eventos a traves de un servidor SMTP. &lt;li&gt;&lt;strong&gt;&lt;strong&gt;&lt;/strong&gt;&lt;strong&gt;&lt;/strong&gt;&lt;strong&gt;&lt;/strong&gt;Msmq&lt;/strong&gt;: utiliza Microsoft Message Query como destino de los eventos. &lt;li&gt;&lt;strong&gt;WMI&lt;/strong&gt;: los eventos se manejan con Windows Management Instrumentation. &lt;li&gt;&lt;strong&gt;Database&lt;/strong&gt;: Cuando recibe un evento, invoca un stored procedure con sus datos como parámetro. (Requiere el Data Access Block, para definir la base de datos a utilizar). &lt;li&gt;&lt;strong&gt;Custom&lt;/strong&gt;: Si los anteriores no son suficientes, puede manejarse los eventos mediente una clase definida nuestra aplicación. Esto nos permitiría por ejemplo, mostrar un MessageBox, enviar el error con un POST HTTP, etc.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;b&gt;Formatter&lt;/b&gt;: Se encarga de serializar eventos, para facilitar su almacenamiento, son los siguientes:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Text Formatter &lt;li&gt;Binary Formatter &lt;li&gt;Xml Formatter &lt;li&gt;Custom Formatter&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;b&gt;Event Sources&lt;/b&gt;: Representan fuentes de eventos, se les puede asociar uno o más Trace Listeners.&lt;br /&gt;Pueden definirse segun categoría de los eventos, y están predifinidas adicionalmente las siguientes sources especiales:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;&lt;strong&gt;All &lt;/strong&gt;&lt;strong&gt;&lt;/strong&gt;Events&lt;/strong&gt;: Como su nombre lo indica, recibe todos los eventos de la aplicación. &lt;li&gt;&lt;strong&gt;Unprocessed category&lt;/strong&gt;: Eventos de categorías no procesadas. &lt;li&gt;&lt;strong&gt;Logging Errors &amp;amp; Warnings&lt;/strong&gt;: Recibe errores y advertencias producidos al registrar otros eventos (por ejemplo, caída del servidor del SQL, al intentar almacenar un evento en éste), permite una especie de "manotazo de ahogado", lo que hace apropiado asociar a esta fuente el Event Handler más "infalible", por ejemplo, Formatted EventLog.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;b&gt;Filters&lt;/b&gt;: Permiten filtrar eventos, según categoría, prioridad, o mediante clases personalizadas.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Ahora utilizamos una vez más la herramienta de edición de archivos de configuración para lo siguiente:&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Definir el bloque de configuración para el Logging Application Block. &lt;li&gt;Definir el Category Source "Errores" como fue definido en el Exception Handling Block, este recibirá las Exceptions interceptadas por éste, y asociaremos a este un Database Handler, para crear nuestra bitácora en una base de datos. &lt;li&gt;Crearemos (si no existe aún) la configuración para el Data Access Application Block, donde definiremos el connection string. &lt;/li&gt;&lt;li&gt;Referenciar esta base de datos en nuestro Database Trace Listener, e indicar en éste el nombre del stored procedure que debe invocarse para agregar una entrada al log, y el stored procedure que se invoca inmediatemente después para indicar la categoría de ese evento (es por esto que el primer stored procedure, debe devolver el id de la entrada creada). &lt;li&gt;Dado que nuestra conexión con la base de datos puede fallar (y queremos saber cuando!), agregamos un Formatted Event Log Trace Listener, y asociamos este al "Logging Errors &amp;amp; Warning" Special Source, para registrar en el EventLog los errores que ocurran al intentar usar la base de datos.&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;&lt;p&gt;Por último aprovecharemos el Logging Application Block, para registrar también información adicional sobre la ejecución de nuestra tarea, para eso asociaremos nuestro Database Trace Listener al Special Source "All Events" (es posible definir un Trace Listener, o una categoría especial de eventos para este caso)&lt;br /&gt;&lt;br /&gt;Ahora podemos modificar nuestro código C# de esta manera:&lt;/p&gt;&lt;img style="TEXT-ALIGN: center; MARGIN: 0px auto 10px; DISPLAY: block; CURSOR: hand" id="BLOGGER_PHOTO_ID_5074807600308087138" border="0" alt="" src="http://3.bp.blogspot.com/_GcXPWR_goXk/Rm1Wn__Q6WI/AAAAAAAAABE/dH7Vb3WH8Gg/s320/exceptionhandling3.GIF" /&gt;&lt;br /&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;El método estático &lt;span style="font-family:Courier New;"&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="color:#2b91af;"&gt;Logger&lt;/span&gt;.Write()&lt;/span&gt;&lt;/span&gt;, puede recibir también varios parametros adicionales como categoría, prioridad, severidad, etc.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;br /&gt;Conclusiones&lt;/b&gt;&lt;br /&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Las políticas de manejo de errores y logging, son totalmente independientes del código fuente: pueden ser establecidas de forma gráfica, en archivos de configuración, sin necesidad de recompilar la aplicación. Es decir, la modificación de estas políticas pueden ser delegada a un usuario administrador.&lt;br /&gt;&lt;li&gt;Por la misma razón que el punto anterior, al agregar estos bloques a una aplicación existente, el impacto sobre el código fuente es mínimo.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;El manejo de Excepciones y Eventos de Log, es extensible definiendo "custom handlers", clases personalizadas que son invocadas para estas tareas. &lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Links&lt;/b&gt; &lt;ul&gt;&lt;li&gt;&lt;a title="Exception Handling Application Block" href="http://msdn2.microsoft.com/en-us/library/ms954830.aspx" target="_blank"&gt;Exception Handling Application Block&lt;/a&gt; &lt;li&gt;&lt;a title="Logging and Instrumentation Application Block" href="http://msdn2.microsoft.com/en-us/library/ms998162.aspx" target="_blank"&gt;Logging and Instrumentation Application Block&lt;/a&gt; &lt;li&gt;&lt;a title="Novedades en Enterprise Library 3.0" href="http://ideas3p.blogspot.com/2007/04/novedades-en-enterprise-library-30.html"&gt;Novedades en Enterprise Library 3.0&lt;/a&gt; &lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;/p&gt;&lt;br /&gt;&lt;span style="color:#000000;"&gt;&lt;strong&gt;UPDATE&lt;/strong&gt; 2009-06-12&lt;br /&gt;&lt;br /&gt;Fe de erratas!, Como comenta Ariel (ver comentario en esta entrada), la forma correcta de relanzar una excepción es mediante throw; (de forma de mantener el stack trace), asi que en todos los bloques de codigo donde dice:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;throw outEx ?? ex;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;debería leerse:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;if(outEx!=null)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;throw outEx;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;else&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;throw; &lt;/span&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3732630541286744699-708591387553891257?l=blog.tercerplaneta.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Ideas3p/~4/77FyJ2lwq14" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/Ideas3p/~3/77FyJ2lwq14/en-este-artculo-voy-mostrar-como.html</link><author>noreply@blogger.com (Benjamin Eidelman)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/_GcXPWR_goXk/Rm1WKP_Q6UI/AAAAAAAAAA0/c-lddcPzouY/s72-c/exceptionhandling1.GIF" height="72" width="72" /><thr:total>6</thr:total><feedburner:origLink>http://blog.tercerplaneta.com/2007/06/en-este-artculo-voy-mostrar-como.html</feedburner:origLink></item></channel></rss>
