August 2008 - Artículos

Aquí les dejo la segunda parte de la explicación de este patrón. La primera parte pueden verla en [Patterns] Patrón Visitor Explicado. Les dejo también un attachment con los archivos del proyecto por si quieren ver el código más detenidamente (es sumamente sencillo).


Lucas Ontivero

Una buena para recursos humanos!

Esta entrada es para compartir una experiencia muy buena. Es que en la empresa ahora... en realidad hace ya un par de meses, tenemos el servivio de chair massage disponible para todos los empleado. La cosa es que estaba bastante tensionado y estresado por temas relacionados a lo proyectos, los deadlines, los clientes y las bolsas de bugs de los productos que mantenemos que me decidí a sacar un turno para unos masajitos, cosa que hice con bastante temor a la burla de algún que otro compañero caza metrosexuales. (Nota: es un chiste)

Esta es la segunda vez que me siento en la silla y la verdad es que considero la experiencia como sumamente positiva. Sí, lo recomiendo firmemente. ¿Se descarga tensiones?. Sí.

En mi vida dentro de las empresas he visto muchos espejitos de colores, promos, beneficios que no cuestan dinero, y otros beneficios "extraños" (una vez me dijeron "en esta empresa trabajamos con mouse OPTICOS" - un beneficio sin duda impresionante) "pensados" por las chicas de RRHH pero, esta vez le pegaron! un urra por ellas sea como sea que se escriba urra (es la primera vez en 30 años que escribo esa palabra).

Bueno, en fin, si estas mucho tiempo sentado, si estas estresado y  pensas patear el monitor, o bien ya le empezaste a hablar.... este es un buen punto para empezar.

Sí sí, son en horario laboral.

Esta es la primera parte de la explicación de este patrón. Uno de los patrones más lúcidos.Este es el último que grabo en sesiones nocturnas así que ya no me van aoir susurrando :)

 

Lucas Ontivero

Bad DesignAprender a desarrollar y a diseñar software es una tarea en la que hay que invertir muchos años. Hay que ser obsesivo, fanático, hay que equivocarse miles de veces y aprender de esos errores. No contentarse con los aparentes aciertos porque al poco de andar se descubre que no se hizo lo mejor sino que alguien más en un blogs perdido en la web lo resolvió mucho mejor que nosotros y ese alguien también encontrará mejores maneras 10 minutos después de su posteo. Pero sobre todo, hay que leer muchísimo.

En las empresas de desarrollo como mucho existe un 10%-20% de gente con este perfil (atención que hablo de perfil y no de skills) por lo que el restante 90%-80% hará código (y Dios no lo permita, diseños) que van desde extremadamente malo a bastante bueno, mientras que los más experimientados, haran código que va desde lo aceptable a muy bueno con algunos chispazos de excelencia.

El análisis estático de código intenta achicar "un poco" esa brecha haciendo posible la implementacion de estándares y mejores prácticas en la codificación. La idea es extraer conocimiento de los profesionales más experimentados y plasmarlo en un conjunto de reglas que luego guien a la tropa de desarrolladores. En cierto modo esto se logra, porque a cualquiera por más experimentado que sea, una herramienta de análisis estático de código le dirá que su código tiene aspectos a observa, esto es lo mismo que ocurre cuando escribimos 500 u 800 lineas y presionamos F5, el compilador casi siempre nos dice "Eyy! y el punto y coma?" o "Y esta variable no la pensas declarar?" y cosas por el estilo. Sí, el primer análisis estático es el que hace el compilador sobre el arbol de sintaxis. Pero al igual que en el caso del compilador, el nivel análisis que se pueden plasmar en estas herramientas, al menos por ahora, es muy reducido y voy a explicar por qué.

Hace un par de dias, un compañero me preguntó como podia resolver un problema que el "sentía" que no lo estaba resolviendo bien. En una aplicación ASP.NET, tenia un formulario y un conjunto de botones que disparaban distintas acciones sobre los controles del formulario, ejemplo: Clear (limpiaba el formulario), Validate (validaba las entradas), Submit (posteaba el formulario previo tratamiento). El código del método Clear() era similar a este:

   1: private void Clear()
   2: {
   3:     foreach (WebControl wctrl in this.Controls)
   4:     {
   5:         switch (wctrl.GetType().FullName)
   6:         {
   7:             case "System.Web.UI.WebControls.TextBox":
   8:                 ((TextBox)wctrl).Text = String.Empty;
   9:                 break;
  10:             case "System.Web.UI.WebControls.CheckBox":
  11:                 ((CheckBox)wctrl).Checked = false;
  12:                 break;
  13:             case "System.Web.UI.WebControls.DropDownList":
  14:                 ((DropDownList)wctrl).SelectedIndex = 0;
  15:                 break;
  16:         }
  17:     }
  18: }

El problema salta a la vista muy rapidamente, una instrucción switch en cuya expresión interviene una instancia de Type!  Esta no es una solución orientada a objetos!. Aquí debe utilizarse un Adapter dije, pero el FxCop no advertía sobre esto. La opción es homogeneizar las operaciones mediante adaptadores:

   1: namespace Patterns.Test
   2: {
   3:     public partial class _Default : System.Web.UI.Page
   4:     {
   5:         private void Clear()
   6:         {
   7:             foreach (WebControl wctrl in this.Controls)
   8:             {
   9:                 ControlAdapterFactory.Instance.GetAdapter(wctrl).Clear();
  10:             }
  11:         }
  12:     }
  13:  
  14:  
  15:     interface IControlAdapter
  16:     {
  17:         void Clear();
  18:         void Submit();
  19:         void Validate();
  20:     }
  21:  
  22:     internal class TextBoxAdapter : IControlAdapter
  23:     {
  24:         private TextBox textbox;
  25:  
  26:         public TextBoxAdapter(TextBox t)
  27:         {
  28:             this.textbox = t;
  29:         }
  30:  
  31:         void Clear()
  32:         {
  33:             textbox.Text = String.Empty;
  34:         }
  35:  
  36:         void Submit() { }
  37:         void Validate() { }
  38:     }
  39:  
  40:     internal class ControlAdapterFactory
  41:     {
  42:         public static readonly ControlAdapterFactory Instance;
  43:  
  44:         private ControlAdapterFactory() { }
  45:         static ControlAdapterFactory()
  46:         {
  47:             Instance = new ControlAdapterFactory();
  48:         }
  49:  
  50:         public IControlAdapter GetAdapter(WebControl wctrl)
  51:         {
  52:             IControlAdapter adapter = null;
  53:             switch (wctrl.GetType().FullName)
  54:             {
  55:                 case "System.Web.UI.WebControls.TextBox":
  56:                     adapter = new TextBoxAdapter(wctrl);
  57:                     break;
  58:                 case "System.Web.UI.WebControls.CheckBox":
  59:                     adapter = new CheckBoxAdapter(wctrl);
  60:                     break;
  61:                 case "System.Web.UI.WebControls.DropDownList":
  62:                     adapter = new DropDownListAdapter(wctrl);
  63:                     break;
  64:                 default:
  65:                     throw new ArgumentException(
  66:                         String.Format("The control {0} has not an Adapter implemented", wctrl.Name));
  67:                     break;
  68:             }
  69:         }
  70:     }
  71: }

Así que pensé: esta regla es muy sencilla de implementar (en este caso no lo fué porque en el switch, cuando intervienen cadenas, no se utiliza el SwitchInstruction sino un infierno de IFs anidados) y me puse a escribir la regla.

Luego se me ocurrió que sería posible identificar patrones de mal diseño (antipatrones de diseño) que pudiesen mapearse con soluciones orientadas o objetos pero pronto llegué  a la conclusión de que esto no es posible debido a que el analizador, en este caso una regla de FxCop, debía "entender" primero lo que el código debia hacer para luego sugerir la solución.

Por otro lado, detectar un mal diseño puede ser factible mediante la detección de patrones de mal diseño o bien mediante algunos otros intentos como el de la "complejidad ciclomática" del código la que, amén de los falsos positivos, permite identificar puntos de mejora pero no puede recomendar nada concreto, más allá de un "divida este método en algunos otros". Sin duda este último análisis puede dar una pista que el desarrollador más experimentado puede "considerar" para un análisis pero que pone al desarrollador junior ante un callejón sin salida: "esto está mal". Pero más allá de esto, el problema mayor es que todas estas alternativas llegan tarde, cuando el esfuerzo para el desarrollo de esas piezas de software ya fueron consumidas. Esto puede verse en herramientas que hacen análisis de algunos aspectos de la arquitectura como Klocwork.

Por esto, aún cuando una herramienta pudiese identificar malos mini-diseños y proponer soluciones, no basta con solo una descripción de la solución al estilo "Reemplace este switch con un Adapter y una Factoría" sino que debería tener capacidades de refactorig que asistiese en la tarea.

Ni el análisis estático de código, ni el análisis dinámico de código nos salvan del mal código. ¿Será la programación con pares o las revisiones de código la solución?

 

Lucas Ontivero

Resulta que estaba averiguando para hacer una certificación de C++ y entre el material del curso se recomendaba un compiladore de C++ online. Como era la primera vez que veia esto lo busqué para C# y lo encontré!

Se trata de un IDE online (ver la foto de abajo) para proyectos en C# y VB.Net (por ahora) y solo permite usar el framework 2.0 (según dice también es "por ahora" al igual que los betas de Google :)

Este es el sitio: http://compilr.com/   para no tener que loguearse ni nada pueden entrar por acá: http://www.compilr.com/IDE/13/

Nota: hago este post solo porque me parece una curiosidad destacable pero no es una recomendación en ningún sentido.

Lucas Ontivero

Software FactoryHace una año comencé la serie Introducción a los Software Factory con 4 entradas: [Software Factories] Introducción (Parte 1), [Software Factories] Introducción (Parte 2), [Software Factories] Introducción (Parte 3) y [Software Factories] Introducción (Parte 4)

Hoy quiero exponer los desafios que plantea la implantación de una software factory en el mundo real.

Veamos....

  1. Al hablar hoy de software factories uno puede revivir el sentimiento de frustración que sentia 15 años atras cuando hablaba de programación orientada a objetos. Nadie sabe muy bien de que se trata pero en lugar de interiorizarse y comprarse un buen libro, prefieren dejar volar su imaginación y crear sus propias definiciones. Recuerdo a una profesora de la universidad inventando toda una teoría paralela mientras que alumnos atormentados se preguntaban si un caso de herencia múltiple entre una clase Hombre y otra Lobo daba por resultado un Hombre-Lobo o algún otro ser mitológico. Con los conceptos de SF hoy sucede exactamente lo mismo. 

    Otros confunden las clases con los objetos en el sentido de que piensan que los software factories son SCSF, WSSF, WCSF o simplemente "cosas que se hacen con VS". Es decir, no diferencian entre un conjunto particular de instancias de SFs horizontales, en este caso hechas por MS como son SCSF y WCSF, y los conceptos en los que se sustentan.

    Esto trae aparejado el siguiente pensamiento:
    1. ¡Nooo, pero para eso falta muchísimo!. (visión developer) Esta es con total seguridad la más común y se compone de dos facciones, los que están en lo cierto (hay avances pero estamos en veremos) y los que piensan que desarrollar software con una SF es algo parecido a "tomo un módulo de ventas, se lo incrusto a este otro de stock... lo pego con dos piecitas de biztalk, lo envuelvo en este estandard y listo!!", esto es producto de las desafortunadas analogías con industrias como la automotríz o la aeronáutica las cuales son de producción y no de desarrollo.
    2. ¡Es muy riesgozo y nosotros ya tenemos un proceso de producción de software!. (visión PL/PM) Esta es la misma pero con una diferencia importante: aquí es posible hablar de reducción de costos, tailorización de procesos, beneficios en el time-to-market, es decir, es mucho más sencillo traducir los conceptos al idioma de un PL que habla en $$$ al de los desarrolladores que hablan en C++. También es posible interesarlos con los casos de éxito de HP, IBM, Nokia y otros, o alinearlo con objetivos de negocios o con las iniciativas de mejora de la calidad y de reuso de software o alguna otra.
       
  2. Si los manager entienden del tema todavia es muy dificil por cuanto se trata de una "inversión" que posiblemente no se alcance a recuperar por lo que querran estudiar el tema (lógico!). Si después de que los números los convenzan, si logran ignorar a los miedosos, deben esponsorear el proyecto de cambio que, piloto de por medio, movilizará a referentes de todas partes a tomar acciones como:
    1. Tailorizar el o los procesos para adecuarlos a la manera de trabajar que se lleva en los proyectos de esa familia de productos.
    2. Gestionar la comunicación interna para informar a todos los involucrados sobre la nueva manera de pensar y hacer software. Estos cambios siempre despiertan curiosidad y motivación en la gente por lo que abre las puestas para que se los involucre en las nuevas tareas. Además todo el mundo tendrá preguntas y sugerencias. Si esto no se hace lo que se generará será alguna variante del temor.
    3. Seleccionar al equipo de desarrolladores que construirá  el SF. Aquí el arquitecto es pieza clave y debe tener ante todo un conocimiento muy profundo sobre el dominio.
    4. etc. Digo etc. porque estos puntos y otros ya los traté en las introducción (parte 2)

 

En una lista de consideraciones tan escueta podemos ver que existen varias condiciones que probablemente al principio no se tenian en cuenta como que llevan tiempo y dinero y que la fase de codificación es solo una pequeña parte de la cuestión, que involucran a roles de administración de proyectos, gestión de la configuración, especialistas de testing, ingenieros de campo, desarrolladores obviamente y otros, que habrá que mantener la SF, que tendrá que capacitarse a la gente que la utilizará, que debe verse como una inversión a recuperar y que esto sucederá a medida que se vayan entregando proyectos en los cuales se hayan reducido los costos gracias a la utilización del SF, que es una apuesta a largo plazo, y otras cuantas más, pero la síntesis seria algo así como: "Creiste que era más facil ¿no?"

 

Existen pruebas de que esto no es facil, solo hay que ver como los distintos elementos que conforman el sistema de una SF se han ido utilizando como quick fixs que de a uno logran verdaderamente muy poco. Hay quienes todo lo pretenden resolver con un framework, otros intentan sin exito entender para qué sirven los DSLs y cual es la diferencia con los frameworks, otros utilizan VS (GAT/GAX) para verdaderas nimiedades, los procesos apenas si se alteran en algo.Pero ayer me he dado con una prueba curiosa pero contundente de que esto no es facil, al toparme con este paper de M. L. Griss del año 1993 en el que se plantea la necesidad de crear SFs, y los llama así: Software Factories. Griss comenta los casos de éxito en las iniciativas de SF de distintos monstruos de la economia. Hoy seguimos hablando de los mismos temas.

 

Lucas Ontivero

El XML es un gran invento pero sinceramente prefiero rodearme de monos con navajas que de desarrolladores con xml. Desde la primera vez que tuve contacto con el Extensible Markup Language hasta el dia de hoy he visto una cantidad de estupideces sorprendentes gracias al mal uso,  y al sobre uso de este lenguaje. Voy a ir comentando de a uno los casos reales en que pude comprobar como la fórmula (XML*Inconciencia) da por resultado un verdadero desastre económico.

1.- XMLs a la Dase de datos. Un grupo que desarrollaba un producto de Record Management System para una verdadera multinacional de tecnología concluyó que el modelo relacional, con varios años de existencia y desarrollo, no era lo suficientemente bueno para ellos porque no les daba la suficiente "flexibilidad" que su capilla sixtina necesitaba por lo que decidieron... atención a esta!... crear una tabla con solo dos campos a saber:  entityID int not null y, data text. Obviamente en el campo data, del tipo "text", va un enorme y amorfo xml que contendrá los datos que ahora, gracias a esta genialidad, serán libres de toma la forma que quieran.

Como las consultas sobre estos datos se complicaron un poquito se desarrolló toda una libreria para facilitar las busquedas pero funcionaba de la siguiente manera: por cada registro levanto el xml en memoria con DOM y mediante xpath compruebo si es lo que busco o no. Todavia no he visto como resolvieron los outer left joins y las agrupaciones pero sospecho que ya lo tienen en la bolsa.

Esto mismo lo vi muchas veces en muchos lugares así que no es una excepción.

2.- Una alternativa al paso de parámetros. En una migración de un producto grandioso desde Visual Basic 6 a VB.Net, el nuevo equipo decidió que el paso de parámetros entre métodos podía hacerse mucho mejor si todos los datos necesarios se fueran compartiendo en un xml de modo que cada método guardase o añadiese información de contexto (una especie de patrón Context pero "más flexible") a este xml. Así que todos los métodos recibian un solo parámetro del tipo XmlDocument y extraian aquello que les así falta, agregaban más datos y modificaban otros. Una especie de todos los antipatrones juntos: que encapsulamiento ni que ocho cuartos!

Bueno, más allá de que cada desarrollador le agregaba sus datos (y banderas también!) al xml y que modificaba los que habian puesto los otros desarrolladores, el problema fue la performance. Procesador al 100% el 100% del tiempo. Otro problemita se daba cuando un desarrollador nuevo invocaba un método... ya sabia que parametro recibia pero ¿que deia contener el xml? a mirar el código señores.

Pero ueno, de acá a 7 u 8 años, con los nuevos equipos, este producto tendrá un desempeño aceptable.

3.- La doble transformación. Un producto de eLearning se construyó con lo que en esa empresa alguien llamó "la arquitectura de doble transformación", y funcionaba así: ante una petición del usuario se invocaba a un componente que gracias a un XML determinaba que consultas debia tirarle a la base de datos y luego convertia todos esos resultados en un gran XML el cual pasaba por dos "transformaciones", dos XSLTs, el primero hacia operaciones sobre los datos y luego el segundo transformaba (creaba) la UI o lo que obtenia el usuario. De esta manera  si mañana salia un nuevo requerimiento para exportar esos datos a .pdf, excel o a cualquier cosa solo se debia tocar el XSLT de la segunda transformación, mientras que lo demas permanecia igual.

¿Alguien puede imaginar lo que habia que hacer para depurar el código JavaScript que se habia generado con un XSLT?

De locos!

4.- El super app.config. Es tan fácil leer desde el app.config, o web.config, que todo lo que alguien no quiere hardcodear lo pone en el app.config. Incluso hasta recursos como los strngs en lugar de ponerlos en archivos de recursos van a parar a los archivos de configuración. Parece que me estoy equivocando, después de todo, no hay motivo por el que no se puedas poner string en estos archivos pero un equipo de trabajo del box de al dado tiene un web.config de casi 3 MB que me resulta sospechoso.

5.- (N)Ant. Escribir scripts con xml como Ant es una burrada. No tiene sentido implementar un leguaje script con XML y solo se justifica por el echo de que es fácil leerlo y nos evitamos la tarea de crear los analizadores léxico y sintáctico sino que solo tenemos que levantarlo con DOM.

Lucas Ontivero