Thursday, December 22, 2011

Cerrando el año


¿Qué se puede decir después de tanto tiempo sin postear? Lo cierto es que he estado demasiado ocupado últimamente como para poder volcar mis pensamientos en el blog. Entre proyectos personales y trabajo (en el cual estoy más de 8 horas cada día, porque habilitaron las horas extras), y el vicio de los video juegos ^_^ no me ha quedado mucho tiempo =).

Pero lo cierto es que sigo pensando en cosas nuevas. Así que para cerrar el año quería dejar algunos pensamientos sobre el trabajo en IT en general.

Tengo un borrador lleno de ideas para el año que viene. Cosas que me gustaría promover dentro de la empresa para mejorar tanto la experiencia nuestra como trabajadores, así como la experiencia de los clientes quienes son servidos por nosotros. ¿Ustedes hicieron la suya? Hay empresas donde proponer cambios puede ser tan imposible como caminar con la cabeza. Empresas gigantes que durante años han trabajado de la misma forma y no cambiarán, por más que tengas razón. Es muy desmotivante, y si ustedes tienen una mente creativa lo más probable es que sientan que deban irse de ahí.

Pero realizar la prueba no cuesta nada. Prueben a sus superiores y sus colegas. Olvidensé de que se trata de una super multinacional burocrática e intenten acudir al sentido común de las personas. Si eso no sirve, bien, armen las valijas y a buscar mejores rumbos; salvo claro que su permanencia tenga más que ver con el dinero. Pero nunca está mal "probar" a la empresa. Te puede pasar que hace años que están esperando una mente que se dedique a llevar las cosas a un siguiente nivel, o hasta puede pasar que consideren lo tuyo como estar disconforme con la empresa y ser una oveja negra. Los extremos siempre existen, porque son lo más común.

El término medio, eso siempre es lo más difícil de conseguir. Ser tan abierto y flexible como estructurado y organizado. Poder escuchar ideas y tener la suficiente capacidad de criticarlas/corregirlas, sin que ellas pierdan su escencia. No todos pueden hacer eso hoy en día. Pero si algo aprendí, es que podemos ser de la forma que nosotros seamos.

Por ejemplo, si nos concentramos en ser personas más tranquilas sin que ello disminuya nuestro trabajo, nuestra capacidad o nuestras responsabilidades, parecería que estamos pensando en utopías. Pero poniendo suficiente esfuerzo y MUCHA reflexión en lo que queremos, vamos a encontrar la forma. Tenemos que convencernos de lo que queremos LO NECESITAMOS. Nuestro cuerpo y cerebro es una máquina de adaptación. Si lo convencemos de que necesita algo, el cuerpo sólo se preparará para él. Pero para convencernos es necesaria la REFLEXIÓN.

Y es que a fin de año siempre llega el momento de reflexión. Ese momento donde nos preguntamos si queremos seguir trabajando donde estamos, si estamos contentos, si hubiéramos querido hacer algo más, si queremos estar o no más flacos, si queremos cambiar de vicios, si vamos o no a estrangular a nuestra novia, etcétera.

El problema viene cuando no hacemos nada de reflexión durante el año. Cuando no hemos hecho ningun cambio significante en nuestra vida durante 365 días. Hay que recordar que como mucho viviremos 100 años, quizás 110 si tenemos mucha suerte. Pero la época de grandes cambios es ahora. No podemos perder tiempo, aunque tampoco podemos dejar de disfrutar de lo que nos gusta.

Yo por ejemplo, algo que no llegué a hacer, es terminar el trabajo de campo de la facultad, porque me empecé a dedicar a otro proyecto que me consumió mucho tiempo, además de las horas extras del trabajo. Pero ya decidí que lo voy a terminar en la primer semana de enero. Ya sé que es algo que no quiero aplazar más.

Y otra cosa que me puse a hacer urgente es sacar la licencia de conducir. Ya el miércoles termino de rendir todo.

Y ustedes? Hay algo que quieran dejar de aplazar? Siempre hay algo!!

Este año que viene seguramente hableremos más de Android, que es donde me voy a estar metiendo; y como siempre mis tópicos favoritos integración de aplicaciones, frameworks (como siempre!), y gestión de proyectos. Y lo que se me cruce en la vida.

Veré si empiezo un proyecto muy ambicioso que por ahora diré que sus siglas son TNMC. Es de Investigación y Desarrollo y tiene mucha matemática, así que seguramente mis ideas sobre la programación estarán cambiando.

También arrancaré a dar clases de programación, cosa que siempre quise hacer y nunca lo hice de forma sostenida.

Se viene el 2012, es hora de poner ignición de nuevo! Felices Fiestas!

Wednesday, October 12, 2011

La documentación. Analizando el costo/beneficio.

En la universidad siempre nos dicen que debemos documentar todo, pero vayamos a donde vayamos generalmente pasa uno de los siguientes tres escenaris:
  • No hay absolutamente nada documentado. Las especificaciones son diagramas sin estándares escritos con lapicera por algún co-worker, y como mucho disponemos de e-mails para saber qué hay que hacer.
  • Hay algo documentado pero vagamente. Algunos comentarios que nos ayudan en el código, y quizás algún sistema que lleva tracking de las tareas a hacer. Pero nada que diga qué terminamos haciendo, cambiando, etcétera. Obviamente, los manuales son inexistentes o se encuentran totalmente desactualizados. Los requerimientos son correos electrónicos, y UML son tres letras juntas puestas en mayúsculas.
  • Absolutamente todo está documentado hasta el hartazgo. Tanto que cada requerimiento simple nos lleva horas y horas de documentar, y muchas veces lleva más tiempo eso que realizar el desarrollo en sí. Todo lo que no esté escrito no se realizará, y si a alguien se le corrió una coma, el sistema pasará de facturar productos informáticos a informar sobre la producción de facturas de dulce de leche en los locales de venta. La gente discute y lo único que quiere es tener la razón, y no hacer el trabajo ni ir hacia adelante.
Obviamente hay otros escenarios pero creo que estos tres son los más conflictivos en cuanto al "problema" de la documentación. Nótese cómo puse que documentar es un problema. Lo cierto es que es tanto una disciplina útil y beneficiosa como puede ser un problema molesto de todos los días.

Vamos a ver primero qué podemos documentar:
  • Requerimientos
  • Diagramas de Actividad
  • Casos de Uso
  • Diagramas de Secuencia
  • Diagramas de Clase
  • Diagramas de Colaboración
  • Diagramas de Componentes
  • Diagramas de Paquetes
  • Diagramas de Arquitectura
  • Implementaciones
  • Tickets
  • Casos de Uso de Prueba
  • Código
  • Bases de Datos
  • Documentos (sí, entramos en Inception)
  • Minutas de Reuniones
  • Minutas de Visitas
  • Anotaciones
  • Estimaciones
  • Estándares de Programación
  • Diagramas de Entidad-Relación
  • Entrevistas con Clientes
  • Mapas de Navegación
  • Procedimientos
  • Flujos de Trabajo
  • Etcétera...
Hay diez millones de cosas que podemos documentar. Existen estándares y procesos que nos indican qué deberiamos tener detallado y cómo. Sin embargo, el costo incurrido en tanta documentación debe encontrarse justificado por el beneficio que obtenemos al disponer de esa documentación. Digamos por ejemplo que decidimos comentar todo nuestro código. Si estamos en .NET usaremos los tags de <summary> y si estamos en java usaremos las herramientas que nos provee Javadoc para documentar código. Bien, después de unas buenas horas, hemos logrado colocar descripciones a todos nuestros métodos, parámetros, clases, campos y eventos. Estamos orgullosos y contentos de haber terminado con dicha tarea.

Al otro día le cae una tarea a Pepito que la resuelve sin problemas y sube su código al repositorio svn. Lo primero que notamos al actualizar nuestro working copy es que Pepito no puso ningún comentario a su código. Pues claro, otra cosa no se podía esperar. Juancito no le dijo a Pepito que de ahora en más se debe documentar todo el código, y mucho menos le dijo cómo. Entonces a Juancito se le ocurre escribir un estándar de cómo documentar el código, y lo envía a todos por e-mail, porque Juancito es rápido y organizado, y espera que los demás también lo sean. Pepito lee el documento, felizmente documenta su código y ahora sube esa nueva versión a svn. Juancito y Pepito estrechan sus manos y es otro gran éxito para el Jeropas Development Team.

Al cabo de dos días, a Juancito le piden que retoque lo que hizo Pepito, porque Pepito ahora está con algo nuevo. Muy bien dice Juancito, es la oportunidad perfecta para ver que nuestro estándar de cómo documentar el código rinda sus beneficios. Pero al cabo de media hora Juancito yace en el suelo convulsionando y delirando de fiebre. Encontró que los comentarios de Pepito eran de todo menos adecuados y legibles. La descripción de la clase Factura reza como sigue "Ese papel con tablas donde escribe Jorge los productos que se vendieron. Importante saber que está en pesos. Aguante Ferro loco."

Obviamente es un ejemplo exageradísimo, pero de nada sirve documentar si no lo hacemos concientemente.  Es decir, debemos saber a quién va dirigida la documentación y luego hablar de una forma profesional y definida. Si un documento es para un cliente, no podemos hablar de entidades, tablas, procedimientos almacenados, vistas, clases, arquitecturas, componentes, etc (salvo claro que resulte ser un cliente con conocimientos técnicos suficientes). A un cliente le hablaremos con las palabras que conoce y que se desprenden de su glosario funcional: factura, remito, depósito, caja, configurar, pasar el lector, hacer click en el botón. No diremos que invocaremos el evento de lectura del código de barra, o que ejecutaremos una rutina X. 

Esto es más que obvio, pero también porque dí un ejemplo muy obvio. Volvamos con nuestros amigos del Jeropas Development Team. Juancito ya volvió del hospital. Su médico le dijo que estará bien y le recomendó que no pretenda que todo le salga bien la primera vez. Consolado y descansado, Juancito encara a Pepito y al resto del equipo, y discuten un buen rato sobre qué se debería poner en cada summary. Llegando las 6 de la tarde, a Jorge Luis se le ocurre una gran idea que de paso le sirve para irse en horario:
Pongamos las cosas con definiciones técnicas como clase, contrato, interfaz, propiedad, tipo... Pero utilicemos las palabras que conoce el cliente, como facturar, imputar, depositar, extraer...
Juancito lo piensa un momento y le gusta la idea. Ahora la clase factura podría decir "Clase que representa a un Comprobante que indica artículos y cantidades que serán procesadas e imputadas al cliente."

Mr Potato, el project leader del grupo, aprueba la idea con Juancito y finalmente están bien encaminados. Dos semanas después se encuentran con que Pepito tenía una clase con 54 propiedades, y todas estaban perfectamente documentadas. Pero los atributos internos también estaban documentados, y lo que hizo fué copy pastear lo mismo que puso en sus propiedades correspondientes. Entonces a Juancito se le ocurre que quizás están haciendo overkill, y están perdiendo tiempo en documentar absolutamente TODO. Una nueva reunión dá a lugar donde se decide no documentar los atributos (variables internas) ni las propiedades, salvo que estas no estén relacionadas a las columnas de la base de datos y sean realmente algo nuevo, como propiedades calculadas o propiedades de una clase de procesamiento, no de entidad de negocio.

Los chicos de JDT comienzan a trabajar de esa forma. Pronto encuentran que el entendimiento entre ellos mejoró mucho y Juancito está contento. Mr Potato vá con su superior, Mr Sarasa, y le dice que su equipo ha incrementado la producitivdad gracias a nuevas políticas de trabajo que se han aplicado. De esta forma, hace parecer que todo fué su idea. Sarasa lo felicita y le dice que continúe así, que llegará lejos. Potato se emociona y dice "vamos a explotar esto aún más". Arma otra reunión con Juancito donde terminan decidiendo que deberían documentar usando diagramas para indicar los requerimientos del cliente. De esta forma se pierde menos tiempo al explicar, dice Potato.

Juancito acepta y pronto crean su propio estándar para documentar requerimientos. Pero claro, ellos no los llaman requerimientos, porque pocos le dieron bola a los nombres de las cosas en la universidad. Ellos los separan en varios tipos: "Funcionalidades Nuevas", "Arreglo de Funcionalidades" y "Bugs". Definen y ponen la estética y el formato para tres templates de documentos que colgarán en la red y todos deberán utilizar para documentar los pedidos de los clientes. Al cabo de una semana la productividad del equipo baja increíblemente. "POTATO!!!" grita Sarasa desde su escritorio que flota en el aire, por encima de nuestras cabezas, y escupe un aire rabioso, como el de un dragón que respira sobre nuestras nucas. "¡Cómo es posible que ahora que documentan más, trabajan menos!". Potato, que no entiende un "SORONGOLIO" (estoy armando mi propio estándar de adjetivos, porque no le dí bola a la clase de lengua en la secundaria. Si ellos pueden, ¿por qué yo no?) no sabe qué decirle a Sarasa y termina echando la culpa sobre el pobre Juancito, quien es el que probablemente más se preocupa por estos temas.

Lo que ocurrió es evidente y lógico:

  • No supieron distinguir entre los 3 tipos de "requerimientos".
  • No pudieron comunicarse con los especialistas técnicos del cliente usando un lenguaje común.
  • Tardaron más en documentar que hacer.
  • A cada rato el cliente cambió o hizo agregados a los requerimientos, que los obligó a actualizar la documentación. Ahí se dieron cuenta que muchas cosas las tenían repitiéndose en varias partes del mismo documento.
  • Cosas que pidieron los clientes tenían que hacerse enseguida y no podía esperarse 30 minutos para actualizar un documento interno.
  • A causa de actualizaciones incompletas, los documentos empiezan a contradecirse.
  • A causa de la mala documentación, el código creado no sirve contra la validación de un proceso de control VyV común.
  • El cliente vé cambios como "Cambiar campo X de NVARCHAR(300) a NVARCHAR(MAX)" como un trabajo de 45 minutos, y se queja, ya que antes era una tarea de 5 minutos.
Y muchas otras cosas. Esto pasa cuando nos mandamos a hacer de nuestra empresa un mundo propio. Es como dije en el otro post, sobre la des-integración de aplicaciones. Creemos que nuestros problemas son únicos y no nos gastamos en investigar cómo se ha resuelto y cuales son las buenas prácticas utilizadas hoy en día.

No sean unos "SANGARENGONEINGOS" y denle una buena leída a todo el tema de documentación. Es muy útil pero "peligroso". Les recomiendo este artículo del gran Alex Papadimoulis: Documentation Done Right. Es una excelente lectura con una conclusión muy buena, y complementa perfectamente lo que quería poner en este post.

No sería sincero si les digo que este post de Alex no inspiró que haga uno propio, pero al menos creo que haber analizado las cosas de otro punto de vista.

Nos queda mucho por hablar sobre documentación. Apenas dí un ejemplo de una empresa que está empezando a aprender a documentar, empezó bien y pronto se encontró con mil problemas por la falta de proceso y verificación. Espero poder seguir abordando estos temas en los meses que viene.

Lo cierto es que actualmente me encuentro en una empresa que trabaja bien (aunque tiene sus cosas, como todas) pero no documenta casi nada. Empecé a implementar varias herramientas para documentar código (por algún lado debemos empezar, así que mejor empecemos por el código) así que aprovecho a comentar qué estoy usando:
  • GhostDoc: Una herramienta que con un hotkey te autodocumenta métodos, eventos, propiedades, etcétera. Y podés customizar los mensajes que te dá y agregar los que faltan. Por ejemplo no tiene por default una descripción para las clases y las interfaces. Con su UI le agregué una y vá como piña. El problema es que por ahora no es muy multilenguaje que digamos. Hay configuraciones que uno puede encontrar en la web para autodocumentar en idiomas que no sean el inglés, pero GhostDoc tiene algunas cosas que no están abiertas al customizador. Por ejemplo el método GetFirstDocument() será autodocumentado como "Gets the first document". Pero un método ObtenerPrimerDocumento, por más que tengamos la configuración española, nos dirá "Obteners the primer documento". Es decir, el análisis sintáctico/semántico está atado al inglés hoy en día. Igual es una buena herramienta para probar, y si son fanáticos del inglés como yo, les vendrá joya.
  • SandCastle: Esta excelente herramienta nos permite tomar todo nuestro código y auto generar documentación en varios formatos (web, help file, pdf) y podemos compartirla sin necesidad de tener el código. Nos crea una suerte de MSDN utilizando toda nuestra documentación XML. Ojo, su interfaz es nula, se maneja por comandos. Pero a continuación viene la solución a eso. Está bueno para usar de vez en cuando, y como la generación es automática, nos resulta barato.
  • SandCastle Help File Builder: Nos brinda una interfaz simple para utilizar el poder de SandCastle.
  • Enterprise Architect: Esto lo vengo usando hacer rato y no me canso. Es una herramienta inagotable, y lo digo en serio. Aún no le encuentro límites. Nos permite documentar lo que se nos ocurra. Centralizado primariamente en diagramas, podemos hacer todos los UML que nos plazca, aunque también posee diagramas de otro tipo como DFD, DER, etc. Recomendadísimo. Sirve para las diferentes etapas de un proyecto. Pero claro, recomiendo leer unos buenos libros de UML primero. También nos permite tomar todo nuestro proyecto y automáticamente crear los diagramas de clase. Y pronto estaré poniendo un thread sobre como auto generar los diagramas de secuencia usando el EA, que si bien no es tan straight forward, resulta muy útil.
Volviendo a la problemática de la documentación, la idea es que de a poco vaya cada empresa implementando PRACTICAS CONOCIDAS y adaptándolas a su propio contexto. Vemos que todas estas cosas derivan de un problema común global: Si no somos capaces de crecer como personas, las empresas no podrán crecer como tales. Se requiere de nuestra capacidad de aprendizaje e investigación para pasar de ser un quiosco a un almacen, luego a un supermercado, y finalmente a una multinacional. Y no nos olvidemos el eslabón final de toda empresa: Conquistar el mundo.

Oh sí.

Thursday, September 29, 2011

La (des)integración entre aplicaciones


Escribo este post en la previa a un parcial. Por suerte, hoy me ha tocado algo simple para cualquier programador: Unos 5 patrones de diseño, y algunas cosas de encriptación y algunos conceptos básicos de OO. Lo que nos mata de esta materia es el trabajo de campo que hay que armar (una suerte de tesina) por lo que al menos los parciales no son tan pesados (repito, para los que ya son programadores).

Es muy común que en nuestras empresas se tenga más de un sistema en pleno desarrollo, e inevitablemente alguien una vez va a pedirnos que compartan datos. Y empezamos con la primera etapa de integración de aplicaciones. Parece inocente, inofensiva, un poco de trabajo para pasar datos de una tabla a otra en bases de datos diferentes. Es como primero lo vé el project leader. Se propone una solución simple, a veces con unos scripts de sql, unos triggers y listo.

Todo marcha bien después de resolver varias inconsistencias como claves que no coinciden, datos que están de un lado y no del otro, y esa clase de cosas que no previmos antes porque simplemente nos tomamos todo a la ligera.

Pasan unas semanas, o incluso unos días, ya vemos que necesitamos más que compartir datos. Por ejemplo, una base de datos requiere que cuando se ejecute cierta lógica de negocio, se impacte inmediatamente en ambos sistemas, y no se puede esperar a ningún proceso ni nada. Aquí la mayoría toma una de estas dos decisiones:

* Encapsular todo en stored procedure y que la base dueña sea X.
* Lo resuelven con triggers

Pero lo menos común es que nos pidan sólo una vez esto. Nos pedirán todo tipo de cosas. Pronto habremos inundado nuestra base de datos de un maremagnum incontrolable de instrucciones de tsql cada vez más confusas. Triggers que pisan el compartamiento de otros, resultados indeseables, clientes insatisfechos, y lo peor, horas largas después de oficina para tratar de resolver el problema. Nótese como puse que lo peor es quedarse y no que el cliente esté insatisfecho. Seamos sinceros, el cliente nunca estará satisfecho si estamos trabajando así, no hay vuelta que darle.

Entonces llega la reunión, con trompetas y banderines. Se nos acerca en su caballo real una persona de alto rango que va a participar con los líderes de ambos sistemas y sus programadores principales. Hay que resolver el problema. Nuestras aplicaciones no se integran.

Pero el primer error que todos cometen es absurdamente nefasto:

* No se miran casos de éxito.

Sin querer decir que la estrategia de implementación que utilizan es excelente, podemos igualmente ver a los productos de Office integrándose entre si e integrándose con sharepoint e internet explorer. Podemos ver aplicaciones extensibles por plugins y sistemas empresariales robustos modularizados en varios pequeños sistemas que han hecho un relativo buen trabajo (o al menos les ha funcionado, sin decir que eso es un éxito).

Y si realmente queremos integración podemos ver a Google con todas sus aplicaciones cada vez mas complejas, podemos ver como Facebook y Twitter, entre otros, permiten a cualquiera integrarse con ellos.

Tenemos de donde sacar ideas. Pero no, lo primero que hacemos es pensar que nuestro problema es único y que debemos resolverlo con nuestra inteligencia. Porque nosotros somos los cerebros del presente y no hay nadie más capacitado para planear el siguiente paso.

Y lamentablemente en la Argentina, así como en muchísimos países donde el IT ha tenido un gran auge, el personal está poco calificado y terminamos encontrándonos con ideas bizarras, no probadas y que no están lo suficientemente pensadas. Pronto entramos en el ciclo vicioso que yo llamo Anti patrón de desintegración de aplicaciones. Ok, acabo de inventar ese nombre, pero nos sirve.

Entonces en vez de iniciar con la integración de nuestros sistemas, los estamos desintegrando. Pronto habremos aumentado la complejidad en el mantenimiento, y con ello, los costos y tiempos. ¿Acaso es el precio a pagar para que nuestras aplicaciones trabajan juntas? No, sería un concepto erróneo pensar que la integración no es una inversión para obtener una ganancia futura, tanto en tiempo como dinero.

¿Cómo lograr la integración entonces?

Cada problema responde a uno o varios patrones. No son difundidos como los patrones de arquitectura, de diseño o de programación. Debemos plantearnos con qué contamos, cuales son todos los problemas, y qué se necesita. Y todo es mejor pensarlo como si todavía no tuviéramos las aplicaciones construídas. Entonces si somos capaces de ello, vendremos con una idea bastante buena.

Lo que puede pasar luego es que, por pensar que los sistemas no han sido creados, nuestra idea no puede aplicarse sin realizar una gran cantidad de breaking changes. Bueno, entonces podríamos plantearnos tres alternativas:

* Realizamos los breaking changes de manera inrcremental. A romper todo señores!
* Modificamos nuestra estrategia original para que pueda adecuarse a la situación actual. Es mejor partir de una idea buena e irla "adulterando" que partir directamente de una mala idea. De esa forma nos acercaremos más a lo que "hubiera sido" ideal.
* Si podemos, planteamos un plan de integración desacoplada, creando e implementando componentes separados de nuestras aplicaciones que se encarguen de la lógica de integración. Concepto que puede ser peligroso, pero al menos no nos inunda la base de datos de triggers.

Es un tema que dá mucho para hablar. Pero no quiero hacer un post gigantesco debido a que las posibilidades son infinitas en cuanto a integración. Y acá podría sonar a que me estoy contradiciendo ya que dije que los escenarios no son únicos. En realidad los factores lo son pero los patrones a aplicar generalmente ya existen.

Todos nos enfrentamos tarde o temprano a la integración de aplicaciones. Al menos con este post quizás alguno pueda pensarlo mejor antes de mandarse a realizarla.

Tuesday, September 13, 2011

Lógica de Negocios en Base de Datos

En algún momento nos hemos preguntado si la lógica de negocio debería ir en la base de datos o en la aplicación. A muchos nos ha pasado de ponernos en una postura y luego pensar "La verdad es que no investigué tanto en el tema como para decidirme por una postura". Y entonces cumplimos con una de las mas importantes tareas de los profesionales de IT: Investigar.

Con una rápida búsqueda en nuestro buscador de preferencia vamos a encontrar threads de diversos foros discutiendo si la base de datos debería tener lógica de negocios o no. Es realmente dificil tener una postura definitiva y única que funcione para el 100% de los escenarios. Sin embargo, siempre es bueno tener una ideología firme y saber CÓMO argumentarla.

Además, he notado que muchos (especialmente en threads nacionales, no ocurre tanto afuera) no entienden la diferencia entre estos conceptos:

  • Lógica de Acceso a Datos
  • Lógica de Negocio
  • Acceso a Datos

Nótese cómo puse que acceso a datos es diferente a la lógica de acceso a datos. Antes de comenzar a divagar sobre la lógica ubicada en las bases, vamos primero a ponernos de acuerdo en estos conceptos.

Lógica de Acceso a Datos: Son el conjunto de rutinas, instrucciones o comandos (dicho de una forma muy old-school) a partir de las cuales una aplicación accede a los datos que se encuentran resguardados en algún resguardo;  archivos de texto, bases de datos, clouds, xml, o lo que fuere. Aquí es donde cae la famosa capa "DAL", Data Access Logic, tan común en las aplicaciones empresariales de hoy en día.

Lógica de Negocio: Es el conjunto de validaciones, directivas y algoritmos (entre otras cosas) que componen al core de la aplicación y para lo cual la aplicación fué construída. Es lo que abstrae nuestra aplicación de su sistema de acceso a datos subyacente. Aquí se ubica nuestra capa de negocio, o la Business Component como Microsoft le gusta decir.

Acceso a Datos: Es el hecho de obtener datos y comunicarlos a través de algún medio para que estén disponibles a quien los solicitó. Aquí podríamos decir que nos encontramos con el servidor de base de datos y su sistema que nos abstrae del bajo nivel administrativo. Léase Oracle, SQL Server, MySql, etc.

Los datos no son más que bits almacenados. Accedemos a ellos gracias al Acceso a Datos que nos proveen los servidores y clientes de hoy en día. Accedemos a ellos con una abstracción llamada Lógica de Acceso a Datos, o DAL, la cual recibe peticiones y devuelve resultados, mensajes o simplemente ejecuta una determinada acción sobre los datos. Finalmente tenemos nuestra Lógica de Negocio que es donde más debería focalizarse un programador. Sin embargo, hoy no ocurre así debido a las pobres prácticas implementadas, muchas que tienen que ver con la arquitectura y el proceso de desarrollo. Pero todo eso lo dejaremos para otros posts.

En fin, en esto casi el 60% estará de acuerdo conmigo, el 20% no entenderá a qué me refiero exactamente, y el otro 20% estará en desacuerdo o pensará que esta forma de trabajar está llegando a su fin o que nunca funcionó. O que el hecho de que en cierta medida destruya la orientación a objetos la hace obsoleta y poco versátil, o que no aprovecha todas las herramientas que tenemos hoy en día. Nuevamente, cómo las típicas capas empresariales (donde su mayor exponente creo debe ser la Arquitectura Marco promocionada por Microsoft) destruyen o minimizan la orientación a objetos y sus consecuencias es tema de otro post.

Veamos el siguiente diagrama de lo que acabamos de decir.

Una típica arquitectura de aplicación empresarial
Esto es lo que nos enseñan en la universidad. La lógica de negocios separada de todo lo que es datos. Sin embargo, en la base de datos poseemos herramientas muy útiles e interesantes como controles de que un campo no sea vacío, o que los datos sean de cierta forma, triggers, stored procedures, etc. ¿Está mal usarlos? ¿Cuándo es bueno y cuándo no?

Por otro lado, si estamos poniendo la lógica de negocio en la base de datos nos encontramos ante la siguiente arquitectura:

La arquitectura cuando ponemos negocio en la base
Apa, es algo que a más de un fanático de poner el negocio en la base de datos no se percató. Estaríamos rompiendo nuestras sagradas enseñanzas. Ahora, eso no es algo malo en sí, puede ser muy útil. Sabemos que poner la lógica de negocio en la base de datos tiene ventajas y desventajas. Pero cuando se trata de dar mi opinión digo que hay pocas cosas tan aburridas como volverse un "Analista Programador SQL Server" (inserte link a aviso en computrabajo aquí).

Siempre todo es un "depende", pero nuestras decisiones tienen que tener una mezcla balanceada entre extensibilidad , reutilización y seguridad. Ya llegados a este momento entenderán que soy un purista de ubicar la lógica de negocios como un componente separado tanto de la aplicación como de la base de datos. Tiene sus pro y sus contra, pero a mi modo de ver, más pro que contras. Sin embargo, hay ciertos escenarios donde puede ser bueno tener la lógica en la base.

Vamos a enumerar y luego daremos ejemplos.

Ventajas:

  •  Los lenguajes de programación son mucho más versátiles y flexibles que los lenguaje de consulta (TSQL).
  • Es más fácil encontrar gente con buenas capacidades para .NET/JAVA/ETC que para SQL/ORACLE/DB2/MYSQL.
  • Para nosotros, como profesionales e individuos, programar nos brinda un mejor futuro profesional que simplemente pasárnosla revisando datos, armando scripts y realizar la penosa tarea de debuguear 8 stored procedures gigantes que se llaman entre sí, algunos recursivamente.
  • Con buenas prácticas, el copy paste anti pattern tiende a nulo.
  • Un lenguaje de programación nos pemite trabajar con cualquier sistema de base de datos subyacente. Nos dá mas libertad en este sentido.
  • Algoritmos matemáticos son más fácilmente aplicables en un lenguaje de programación que en un lenguaje de consultas.
  • Las clases, métodos, propiedades, eventos, y demases son una forma mucho mas organizada de tener la lógica de negocios que con stored procedures, donde como mucho podemos organizar por Schema y Nombre.
  • Manejar una o cien base de datos, dentro de una arquitectura correctamente pensada, es indiferente para nosotros.
  • Cuando la aplicación es una y las bases de datos son miles, la lógica de negocio en BD es muy cara y nada práctica.
  • Permite utilizar todo el poder de la orientación a objetos.
  • Provee una forma mucho más eficiente y simple de Reflexión (Disculpen que no conozca los equivalentes en otros lenguajes de programación, que los tienen obvio).
  • La escalabilidad en algoritmos y componentes es algo propio de las aplicaciones bien armadas. Las bases de datos tienen escalabilidad de OTRAS COSAS.
  • Fácil reutilización y muchos patrones de diseño de cuales elegir.
  • Más fácil conseguir componentes hechos, ayuda, soporte, e ideas que si tuvieramos que buscar lo mismo en base de datos.
  •  No mezclamos las aguas. Poniendo la lógica de negocio en la BD nunca puede hacerse en un 100%, siempre tendremos que tener algo en la aplicación.

Desventajas:

  • La reutilización debe hacerse a mano. Es decir, si tenemos 20 aplicaciones contra la misma base de datos, vamos a tener que disponer del componente de lógica de negocio en las 20.
  • Para implementar cambios debemos re-implementar.

Algunos dirán que la base de datos es más performante, pero lo cierto es que estamos poniendo toda la carga de procesamiento en el servidor y no lo estamos distribuyendo. Las bases de datos distribuídas son un recurso MUY poderoso, pero no fueron hechas simplemente para repartir carga, se usan con muchas mas aplicaciones. Tener que hacer bases de datos distribuidas para cualquier cosa no está bueno.

Sinceramente no se me ocurren muchas más, ya que tengo la mente un poco ya seteada para pensar que todo debería ir en la aplicación. Asi que mientras se me ocurren otras, vamos a empezar a analizar los escenarios.

Imaginemos que tenemos la siguiente tabla donde guardamos algo llamado Categoria:

IdCategoria NUMERIC(18, 0) IDENTITY(1, 1) NOT NULL PRIMARY KEY,
Nombre NVARCHAR(300) NOT NULL,
IdUsuarioAlta NUMERIC(18, 0) NOT NULL,
IdUsuarioModificacion NUMERIC(18, 0) NULL,
FechaAlta SMALLDATETIME NOT NULL,
FechaModificacion SMALLDATETIME NULL,
Timestamp TIMESTAMP NULL

Primer escenario que se me ocurre. El nombre es NOT NULL, es decir, obligatorio. Bueno, en la aplicación deberíamos validar que el dato Nombre que nos llega no sea vacío ni nulo. De repente ya la validación por base de datos no es suficiente: Un simple valor vacío no nulo sería incorrecto y sin embargo está permitido. Podríamos tener un Stored Procedure para cada operación (INSERT, UPDATE, DELETE) y tener aparte un stored procedure que valide los datos que nos vienen, como el Nombre. Bien, logramos solucionarlo, a un alto costo, y dificilmente reutilizable entre varias tablas.

Si fuese por la aplicación, podríamos utilizar componentes de validación que nos ayuden con la capa de presentación, y si aún así el campo llega vacío a nuestra lógica de negocio, lo validamos allí. Y si el día de mañana hacemos algo dinámico (porque no sé, quizás nuestro producto es un empaquetado que usan muchos clientes) entonces podríamos tener aparte toda la configuración para cada Entidad (generalmente 1 a 1 con las tablas). Y allí diríamos si Nombre es Obligatorio o no. Ya de repente no tenemos que programar, simplemente configurar (ojo, si nuestra interfaz para configurar es mala, tardaremos mucho, aunque no perdamos la escalabilidad).

Ahora, tenemos el Id de Usuario Alta que está relacionado a la tabla USUARIO. Bien, una FK nos viene PERFECTO. Es un excelente recurso de normalización que no deberíamos nunca dejar de usar: SIN EXCEPCIÓN! Desde la lógica de negocios no veo tan necesario que validemos que el usuario exista como tal en la base de datos. Sin embargo, en un escenario donde nuestras aplicaciones cliente son 20 y no solo una, podríamos querer centralizar toda la lógica de negocio (los WebServices son útiles para ello por ejemplo) y ahí podríamos ver la necesidad de validar que el dato exista antes de mandarlo, ya que nos serviría para mejorar nuestro mensaje al usuario o simplemente la confiabilidad de que los datos serán consistentes incluso si la base de datos no tiene el FK. Esto siempre es "DEPENDE DEPENDE". Pero suponiendo que debamos hacerlo, vamos a tener que validar contra la BD, realizando un acceso por cada validación. Algo incómodo.

Mi consejo, que la base de datos se encargue de la consistencia y referencia integral de los datos. NOSOTROS nos encargaremos de la validación y estado de los mismos. Se tratan de cosas MUY diferentes señores.

Ahora, pensemos que tenemos una aplicación web con webservices distribuidos. Los clientes no son de intranet sino que son clientes de la empresa que adquieren información a través de nuestro sitio. Nosotros debajo poseemos 3 o 4 bases de datos relacionales y unos 20 cubos con información masiva. ¿Dónde ponemos la lógica de negocios? Sería impráctico repartirla entre cubos y bases de datos relacionales. Aquí es un claro ejemplo para poner la lógica en la aplicación (probablemente en los web services). Recordemos que tenemos muchas arquitecturas cliente-servidor. No se queden con una sola. Mi consejo es una recomendación.

Ahora imaginemos que tenemos una base de datos relacional gigante que engloba contabilidad, administración, despacho de mercadería, depósito y almacenaje, recursos humanos (alguien quiere modificar el campo sueldo de su legajo :P?), y demases cosas que puede tener una empresa. Por otro lado, tenemos 1 aplicación para cada dominio. Evidentemente acá estamos en una encrucijada. Más de uno diría "Ves, acá te conviene poner todo en la base de datos porque es una sola, mientras que el resto son varias aplicaciones". Incorrecto, en este ejemplo las aplicaciones forman parte de lo que llamamos Solución. Cada aplicación aplica una lógica de negocios diferente, y se integra (debería) con el resto, ya sea por servicios o lo que fuere. Entonces, administración carga e imputa facturas, y le avisa a contabilidad para que las registre (es más complejo que eso, pero es un ejemplo). Los dos sistemas interactúan. La solución es la misma. Tengamos 7 exes o 1 solo es una decisión de diseño que no modifica el problema real. Tenemos 1 CONTEXTO (empresa), un grupo de PROBLEMAS y un RESGUARDO. Vemos que aquí se trata de un 1 a 1. Por ende también recomiendo poner la lógica de negocios en las aplicaciones.

Ahora, lo que vemos que necesitamos para dar más crédito a la lógica de negocio en las bases de datos es LÓGICA DE NEGOCIO REPETIDA. Es decir, necesitamos crear la necesidad de reutilizar la lógica de negocio en más de una aplicación. Un ejemplo fácil sería una web de red social. La podemos acceder desde una PC de escritorio, por WAP, por Iphone/BlackBerry/Celulares avanzados, llamando a Tinelli por teléfono y lo vemos holográficamente en el espejo de nuestro baño cuando vamos a hacer nuestras necesidades. Lamentablemente para cada ÁMBITO debimos desarrollar una interfaz de PRESENTACIÓN diferente. La reutilización de todo lo que está debajo de la presentación debería ser posible; es decir, tener un assembly (o varios) que todos referencien. Sin embargo, me he topado que (en .NET) no puedo usar assemblies hechos para PC en una apicación de Windows CE. Los namespaces, clases e interfaces son iguales, pero hay 2 problemas:

* Hay funcionalidad que no está (interfaces iguales pero incompletas)
* Referencias a assemblies no aptos para CE

Entonces sí, terminamos copy pasteando todo porque casi no hay que hacer cambio salvo que usemos cosas que no estén disponibles en CE, por ejemplo encriptación SHA256. Si encriptamos las contraseñas de usuarios con SHA256 para guardarlas en base de datos vamos a estar un buen rato a los gritos hasta encontrar un componente por internet o hasta que desarrollemos y probemos uno propio. Ahora, imaginemos que tuvimos que copy pastear todo entre 5 aplicaciones. Es impráctico, no estamos REUTILIZANDO. Podría servirnos poner todo en la base de datos.. Sí. Pero les doy una mejor alternativa: WebServices. Que cada aplicación tenga su capa de presentación y una capa de agentes de servicio y listo, que todo vaya a WebServices, que pueden estar distribuidos.

Para los que no sepan, la capa de agentes de servicio es una capa que nos maneja las comunicaciones entre nuestras peticiones y los servicios que están detrás, para que nuestro código no tenga que tener lógica de eso.

¡Casi íbamos a poder decir que la lógica de negocios estaba bien en la base de datos! Y es que cada mundo tiene sus desventajas, y esperé hasta aquí para mencionar esta. La reutilización de lógica de negocio entre diferentes plataformas no es tan simple. Pero estoy convencido que la base de datos no es lugar para el negocio.

Finalmente, vamos a abordar el motivo número 1 por el cual ciertos programadores ponen todo en la base de datos: CORRO UN SCRIPT Y YA ESTÁ.

Ese es el gran problema. Estamos pensando que está perfecto hacerlo así para ahorrar tiempo y dinero en implementación. Lo cierto es que esto es una incorrepta percepción de lo que se está haciendo: No hiciste una gran decisión de diseño, estás aprovechando la capacidad de SQL Server para implementación rápida de elementos.

Vamos a explicarnos. Yo en una aplicación instalo varios componentes (Configs, Dlls, Exes, etc). En una base de datos yo tengo un nivel mucho más granular: Tablas, Vistas, Stored Procedures, Triggers, Datos. Cada uno es accesible y modificable por script. Si pudiéramos simplemente reemplazar una clase, o un grupo de clases, de repente implementar sería mucho más rápido. Imaginen correr un script que sea ALTER CLASS y abajo todo el código C#. Obviamente es un tema mucho más complejo. La naturaleza y las HERRAMIENTAS de las bases de datos nos permiten implementar objetos de base de datos casi instantáneamente. El día que tengamos algo igual para componentes de aplicación (lo va a haber, y se puede hacer hoy en día, pero es un desarrollo avanzado) entonces vamos a ver que era lo mismo.

Con una MALA decisión, ganamos TIEMPO. Ahora, esto es porque tuvimos una visión mediocre, o al menos poco informada. Si nosotros planeamos correctamente nuestra aplicación no necesitaremos vivir codeando en base de datos. Veamos las aplicaciones más complejas y completas con actualizaciones automáticas que se descargan desde internet. La mayoría de estas actualizaciones realizan cambios en el filegroup, no en la base de datos (salvo que justamente cambie el modelo relacional de entidades). Además, podría ser muy mala idea que el cliente tenga acceso a nuestro código fuente de negocios. Es decir, ellos podrán acceder a su propia base de datos por lo que lo que para vos es lógica de negocios es también tu código fuente (probablemente no controlado por un sistema de versionamiento).

Seamos honestos, nos persiguen y corren con el tiempo para cerrar todo rápido y nunca nos permiten tener al menos 1 hora al día para desarrollar las ideas que tenemos todos los programadores día a día. Yo trato siempre de hacerme tiempo. Hacer un patcher, un framework, controles personalizados de interfaz de usuario, librerías de diversas cosas, etc. Si pudiéramos dedicar un poco de tiempo todos los días a incrementar la calidad de nuestros desarrollos, creando nuevas herramientas para escalar aún más en el futuro, entonces ya no estaríamos tan tentados a trabajar por base de datos.

Y este tipo de calidad es un doble filo. Por un lado incrementa los costos porque estamos usando tiempo para desarrollar las herramientas. Sin embargo, a mediano y largo plazo, los costos disminuyen al aplicar dicha herramienta. Claro, estamos hablando de que hicimos algo que realmente funciona y sirve. Es un gran problema si desarrollamos un framework y al año nos damos cuenta que no sirve, y ya es tarde porque migramos nuestras apicaciones al mismo. Habremos perdido tiempo desarrollándo y lo que es peor, la CONFIANZA en nuestro trabajo y en nuestras ideas.

Y otra cosa, recordemos que el control de fuentes está hecho para proyectos de aplicaciones. El control de fuente para base de datos ha sido siempre un lugar complicado, y ademáse es mucho menos explorado y estudiado. En control de fuente de aplicación nadie dice "no es bueno". En cambio, en base de datos siguen habiendo muchas controversias y opiniones encontradas.

Mi consejo: Las aplicaciones que hoy ya están por base de datos, continuar manteniéndolas así. Salvo que sean Core o algo que se sabe que se va a tener que estar desarrollando para siempre. En ese caso, informarse sobre procesos de refactoración para ir mutando la aplicación hacia otra arquitectura de manera paulatina. Ahora si se trata de una nueva aplicación, dejemos los lenguajes de consultas para los datos, y los lenguajes de programación para todo lo demás.

Y finalmente, si aún no logré convencerlos, recomiendo leer algunos libros de arquitecturas para aplicaciones empresariales de diverso tipo. Lean casos de éxito y pregunten a otros qué tan bueno les parece el IDE de la base de datos como plataforma de desarrollo.

PD: Este post lo dedico a mi amigo Fabián y a otros defensores del Stored Procedure Business.

No se enojen si no coincidimos :).

Monday, August 8, 2011

¿Por qué los proyectos iniciados por otros fracasan?

¿A quién no le pasó que le cayó de paracaidista un proyecto que ya ha iniciado "otro equipo", o un proyecto de un cliente que dice que terceriza algunas partes del mismo? ¿Y a quién no le sonó que algo andaba mal con ese proyecto de entrada?

Aunque no entendamos exactamente por qué tenemos esa extraña sensación negativa, lo cierto es que nuestro cerebro es más inteligente de lo que pensamos. Sabe que hay algo mal, que hay un peligro cercano.

Podríamos ver las consecuencias de tomar un proyecto hecho/iniciado por otros, pero con ello no llegaríamos a la raíz del por qué. De todas formas, vamos a enumerar un par de problemas que se nos presentan para ponernos en contexto:

* Hay que atender a estándares que no son performantes, no son a lo que estamos acostumbrados o son incompatibles con nuestra forma de trabajar.

* Se suman miembros al equipo que no son adecuados, que no trabajan o que aportan negativamente. Esto es típico. Los clientes suelen designar un arquitecto propio y esperar que el mismo controle a los desarrolladores tercerizados. Lo mismo puede pasar con analistas técnicos o líderes de proyecto. Si bien es "común" que los recursos tercerizados sean los ineficientes, muchas veces es al contrario, y de repente nos encontramos haciendo equipo con miembros ineficientes o que ponen trabas constantemente.

* Se tienen que estimar fechas sin siquiera conocer el sistema, ya que la fecha es un motivo de aceptar o no la licitación, por lo que no tendremos nada de código fuente hasta que no esté la estimación de fecha y de dinero.

* Los miembros de equipo del cliente no integran a los tercerizados, los rechazan o los usan para echarles la culpa de todo.

* El código fuente, una vez develado, es un desastre. Un maremagnum de anti-patrones que lleva a plantearse, ya desde el inicio de un proyecto, si el mismo va a dar pérdidas. El problema es que generalmente en este punto uno ya se comprometió, y quizás no para un requerimiento sino para varios. Y ni hablemos si firmó una multa en caso de no cumplir o terminar repentinamente el contrato.

* Escaso o nulo soporte. Falta de recursos y materiales. Lo que nos dicen que instalar tomaría 5 minutos en realidad nos llega a tomar una semana hacerlo andar.

* Trabajando concurrentemente podemos encontrarnos con breaking changes constantes no informados, lo que lleva a grandes dolores de cabeza y extensos insultos al aire.

Y así podríamos seguir toda la tarde. Lo cierto es que todos estos problemas son la consecuencia de algo más profundo. Analicemos un momento "por qué" alguien tercerizaría un proyecto ya iniciado:

* Falta de personal.

* El proveedor original no dió a basto con los requerimientos o las fechas.

* El proveedor original terminó el contrato repentinamente.

* Falta de expertise para llevar a cabo el proyecto

* Si es un proyecto que se terceriza a varias consultoras, entonces se puede tratar del descontento con los proveedores actuales.

Pero siempre hay una que suele sobresalir entre todas las demás: "No se dió a basto". ¿Y cuándo nos pasa eso? Sinceramente, yo soy del fuerte pensamiento de que un proyecto sólo puede fracasar (desde lo técnico) cuando el mismo no está bien elaborado. Es decir, cuando un producto de software posee una calidad baja.

Además, podríamos usar el siguiente pensamiento para darnos cuenta de por qué fallan estos proyectos:

"¿Cuáles son las probabilidades de que un proyecto desarrollado por terceros, que debe continuarlo otra empresa, esté desarrollado bajo un concepto de buenas prácticas, con las pruebas realizadas correctamente, y con una calidad en general elevada?" Me atrevería a decir que un 0%. Antes decía 0.01% pero si me abstengo a las estadísticas personales de mi experiencia en IT tengo que decir 0%.

Resulta tan shockeantemente obvio que nos preguntamos cómo no nos dimos cuenta antes. Lo cierto es que siempre que un proyecto esté desarrollado por otros "Y" necesite de nuevos proveedores, SIEMPRE va a tener un sinfín de problemas. Es un proyecto enfermo. Algo le ocurre, es evidente.

Todo este post viene a raíz de un proyecto en el cual tuve que participar como líder durante 3 meses. Ha sido la peor experiencia de mi vida en lo concerniente a software. Nunca ví tantos anti patrones y tantos problemas juntos. Encima en un ambiente donde absolutamente nadie se cuestionaba si se estaban haciendo las cosas mal. Ya desde el vamos, el proyecto estaba destinado a dar pérdida. Enumero a continuación algunos de los tantos problemas que tuve:

* Instalar un ambiente local para desarrollo debía tardar 5 minutos. Lo cierto es que terminaron siendo 22 días hábiles (un mes entero). Algo tan increíblemente ridículo que todavía me pregunto cómo puede ser que haya ocurrido.

* El analista funcional designado era una persona incapaz que no se acordaba siquiera lo que vió en reuniones con los funcionales del cliente. Finalmente, debido a ello y otras cosas, tuve que hacerlo remover del proyecto. Este fué un error de la empresa proveedor (de la cual soy parte), al integrar a alguien no compotente y desinteresado.

* La complejidad del proyecto era elevada, debido a la cantidad de anti patrones y a la inflexibilidad del sistema.

* Me asignaron sólo un recurso para ayudarme en el desarrollo, y no tres como se había establecido que hacían falta para cumplir las fechas.

* Dicho recurso era Junior y no Senior o Semi Senior como necesitaba un proyecto de complejidad ALTA.

* La creatividad permitida en el proyecto era BAJA, casi NULA diría. Para poder cumplir con las fechas (que establecí yo, y no que estableció la empresa, que habían caducado antes de hacer andar el ambiente de desarrollo) tuve que desligarme de la pésima forma de trabajar que tenía el cliente.

Como anécdota, les me tocó estar un par de días en las oficinas del cliente para darles soporte con la implementación. Lo cierto es que tenían un modelo de source control totalmente ligado a la problemática del merge que permiten algunas aplicaciones de source control actuales. De vez en cuando puede venir bien trabajar por merge, pero no el 100% del tiempo. Era increíble ver en todas las pc de los desarrolladores las MISMAS pantallas. Todos codeando sobre lo mismo.

Y lo que es peor, eran las mismas pantallas que nos tocaron retocar a nosotros, y como si eso fuera poco, también a otros dos proveedores. Caótico. Al final estuve 2 días sin hacer nada porque pretendían hacer el merge entre los proveedores y lo que ellos estaban haciendo, encontrando breaking changes por todos lados.

Entonces esto nos dá para pensar en la siguiente idea. Consideremos los siguientes parámetros:

* Complejidad del proyecto: No sólamente la complejidad de lo que hay que hacer, sino tambien el CÓMO está hecho. Recordemos que estamos teorizando sobre proyectos pre-existentes.
* Creatividad permitida del proyecto: Si los estándares son duros e inflexibles, programadores experimentados podrían sentirse muy incómodos al tener que adaptarse a un estándar, especialmente si el mismo no vá acorde con las buenas prácticas y sus ideas particulares.
* Nivel requerido en el programador: Esto vá de la mano con la complejidad del proyecto. Si el proyecto es muy complejo, vamos a encontrarnos que quizás sí o sí necesitemos programadores muy experimentados (y por ende, caros).
* Cantidad de recursos requeridos: Otro valor que multiplica sobre el nivel requerido en los programadores. Cuanto más recursos necesitemos (para hacer varias tareas a la vez y demás cosas), mayor será el costo del proyecto.

Bajo el ejemplo que cité, y asignando valores en el rango de NULO-BAJO-MEDIO-ALTO podemos ver que en el proyecto en el que estuve se encuentran los siguientes valores de parámetros:

* Complejidad del proyecto: ALTA. El código es un desastre.
* Creatividad permitida: BAJA. No pongo nula porque al final terminé haciendo mis shenanigans.
* Nivel requerido: ALTO. Es tan malo el código que para poder trabajar de una forma medianamente eficiente y rápida se necesitan recursos de un mínimo nivel Senior.
* Cantidad de Recursos: 3. Aquí el número no fué dado al azar sino pensado tras haber realizado estimaciones y paralelización de tareas. Ví que por etapas podíamos tener 7 programadores contínuos, pero que generalmente todo redondeaba a 3. Viendo que era imposible pedir 7, pedí 4, esperando que me dieran 2 aunque sea. De pedo metieron uno.

Entonces aquí podríamos tener un objeto de estudio: La viabilidad motivacional.

Si tu proyecto es de una alta complejidad pero de una creatividad baja o nula, entonces requerís programadores muy experimentados que no tengan problema con ser "code monkeys". O sea, gente muy profesional que esté dispuesta a renunciar a la creatividad. Es algo bastante complicado de conseguir. Te diría que cualquiera que sepa en lo que se está metiendo va a tratar de aumentar su costo en un 40%. Yo ni llegando a las 5 cifras me metería en ese proyecto de nuevo.

Es un estudio de viabilidad que tiro como idea. Jamás lo ví en ningún lado, por lo que puede resultar interesante cuestionarse "¿cuál será el nivel de motivación de los recursos ante este proyecto?".

En resumen, los proyectos que vengan hechos de afuera SIEMPRE serán un dolor de cabeza. Queda en ustedes evaluar si la ganancia económica hace valer la pena el estrés que adquirirán inevitablemente.

Tuesday, July 12, 2011

Generadores de código - Un programador más

¿Han pensado en este concepto? Un programador en la Argentina es un analista, un codeador, una persona que resuelve problemas. A veces incluso es organizador, anticipador, y se prepara para lo que viene. Toma decisiones y colabora junto a los demás para realizar sus tareas.

En cambio un generador de código es una máquina boba de escupir código. Es un mono que programa a una velocidad rampante. Pero no sabe ni qué está programando, ni qué está escribiendo. Él sólo escupe código. Para eso lo inventaron, y para eso está. No realizará análisis ni tomará decisiones.

Quien puede hacer eso es quien usa al generador de código como una herramienta. El decide qué debe crearse y cómo.

Ahora, todo esto me parece correcto pero quedándonos con sólo esta idea nos podríamos confundir un poco. Podríamos pensar que el código que se "escupe" puede ser redundante y sin reutilización. ¡Total, se re-hace en un segundo!. Es una de las principales premisas que veo en los generadores de código empresariales. Hacen un código desastroso, con casi ninguna herencia ni orientación a objetos, porque igualmente lo podemos re-generar con los cambios en un segundo. El tema es que nos encontramos con los siguientes problemas con el código una vez generado.

La reutilización no se tuvo en cuenta, por ende se hace difícil utilizarlo el código hecho en un futuro.

Por ejemplo, generamos automáticamente las clases de acceso a datos. Lo que no se tuvo en cuenta es que dicho código utilice algún framework ORM propietario o de terceros, cosa de que el código sea más reutilizable y legible.

Por ejemplo, quizás estas clases de acceso a datos se generan con SQL Server en la cabeza, y cuando necesitamos pasar a Oracle tenemos que ir a re-generar el código (en el mejor de los casos!). Y cuando re-generamos nos encontramos con que:

  1. El comportamiento del código es diferente
  2. Interfaces desactualizadas o incompatibles.
  3. Hay métodos que recibían objetos de un tipo y ahora reciben de otro
  4. La nomenclatura de procedures y parámetros que está utilizando es diferente al implementado
  5. Los scripts SQL generados tienen errores
  6. Los templates de generación de código nunca se probaron

O sea que podemos caer en una situación incómoda. En realidad nosotros deberíamos tener una clase de LÓGICA de acceso a datos. De ahí viene el nombre "DAL". Data access LOGIC. Pongo LÓGICA en caps porque para mí eso significa que debe manejar "cómo" se deben acceder los datos y de qué forma se traducen a entidades/objetos del sistema. Para mí NO debe tener detalles de bajo "qué" están dichos datos.

Utilicemos clases de acceso a datos inteligentes, como si las hubiera programado un programador decente. Que utilicen un framework que nos permita cambiar la base de datos simplemente cambiando la configuración, no re-generando todo el código.

Terminamos con un archivo donde "tocar" y un archivo donde "no tocar"

Esta también es típica. Para una clase nos genera dos archivos de partial class, donde uno tenemos un cartel gigante que dice "NO MODIFICAR". Esto para mí es un conocidísimo anti patrón. Tener 2 archivos para una clase es un tema. Tener 100 archivos para 50 clases es otra.

Otra cosa que he visto a veces es que todo el código generado lo pegan en un sólo archivo universal (que a veces alcanza las decenas de miles de líneas de código) y luego es un desastre regenerar algo. Esto es obviamente una respuesta poco pensada al hecho de darse cuenta que tener tantos archivos que no se pueden pisar es inútil.

Lo cierto es que nuestros generadores deberían ser inteligentes. Tomar el código que deben reemplazar y listo. No que debamos regenerar todo y pisar los fuentes, eso es medio negrada. Simple y puede ser efectivo si se controla como corresponde, pero a la larga trae problemas.

Para lograr esto tendríamos que tener metainformación sobre las clases generadas. Y qué mejor para eso que Reflection!. En .NET al menos podemos consultar cómo está compuesta una clase, y luego el generador puede decidir qué reemplazar y qué no, y ante un código que no sabe que hacer, dejarnos la decisión a nosotros.

Esto nos permitiría, además, pensar en regeneraciones parciales de clases. El código que debe crearse debe tener la menor cantidad de correspondencias privadas internas entre métodos y propiedades posibles, sin sacrificar la cohesión y la reutilización.

De repente algunos eslabones de la cadena de archivos generados no sirve

A veces, por la arquitectura seleccionada, algunos eslabones no sirven para nuestro sistemas. Imaginemos, por ejemplo, que nuestro generador nos crea unos webservices que luego llama desde la UI, por decir una boludez. Quizás nuestro sistema posee una arquitectura donde la UI se comunica directamente con la capa de negocio. Por ende, estaríamos teniendo que realizar un trabajo manual de adaptación sólamente para nuestro sistema.

Lo que deberíamos tener es una configuración de cómo se interconectan las capas generadas. Cada capa tiene sus propios templates que generan sus archivos, pero sería bueno que nuestro generador reconozca la configuración que nosotros deseamos, y nos genere las dependencias correctamente con nuestra arquitectura. Entonces puedo generar que la UI se enlace a WebServices, o que la UI se enlace a Negocio, o que la UI se enlace a la base de datos (horrible) según me convenga a mí. Y eso sólo con unas configuraciones. Es más fácil de armar de lo que parece.

Tomamos decisiones de arquitectura basándonos en nuestras herramientas y no en nuestros conocimientos

Este punto es importantísimos. Supongamos que creamos un generador de código que nos crea las siguientes capas:

  • Capa de Acceso a datos
  • Capa de Entidades
  • Objetos Estáticos tipo Facade que se comunican con la base de datos (una especie de Negocio pero con una implementación fea)
  • UI en archivos ASPX que se comunican sólamente con los objetos estáticos.

Cuando nuestros profesionales analicen y decidan "che, tengo una arquitectura mucho mejor", no la podrán aplicar hasta re-escribir los templates (en el mejor de los casos) o el generador de código. Los proyectos iniciarán y habrá una desmotivación por no poder aplicar una mejor arquitectura solucione los problemas de esta arquitectura auto-generada, simplemente por temas de tiempo (Que probablemente perdamos mas adelante).

Y así podríamos seguir mencionando problemas de los generadores de código actuales. Lo mejor sería tener un generador compuesto por pequeñas partes que nosotros podamos ir mejorando de forma independiente, manteniendo ciclos de desarrollo cortos, como para poder irlo mejorando seguido, y no tener que esperar a tener 3 meses con poco trabajo, que generalmente nunca ocurre. Todos los software se actualizan constantemente. Pero los de uso interno rara vez. ¿No habrá un problema ahí?

Los dejo con esta idea.

Monday, June 27, 2011

El rol del arquitecto

Cada vez está más de moda tener un "arquitecto de software" en el sector de sistemas. Sin embargo, muchos son los que se quejan de que dicho rol es un invento, o una mera forma de hacerte creer que te ascendieron o que cambiaron tus responsabilidades.

Existen empresas donde esta realidad es cierta. Donde los arquitectos son simplemente desarrolladores con otro título. Donde en vez de darle todo el aumento de sueldo que quería esa persona, le dieron la mitad y le propusieron ascenderlo de puesto. Todo muy lindo, todo muy rico (diría un amigo) pero es cualquiera eso.

El arquitecto de verdad debe poder ver a través de una gran cantidad de aspectos en los desarrollos de software. Tiene tareas a nivel micro como a nivel macro. Por ejemplo, un arquitecto debería ser quien dictamine los estándares de calidad de la empresa a nivel código, base de datos, interfaces, etc. Sin embargo, también debe ser alguien capaz de unir dos sistemas gigantes e integrarlos para que funcionen correctamente.

Mi opinión personal es que además debe ser un programador innato, capaz en cualquier aspecto que involucre esa función:

  • Código
  • Conocimiento de tecnologías
  • Mentalidad científica
  • Capaz de depurar cualquier cosa
  • Mente abierta
  • Etc
Además de ser un programador, debe poseer algunas habilidades sociales. Las suficientes para interactuar con otros colegas programadores y con personal de jerarquía. Ya que un arquitecto debe poder:
  • Entender qué es lo que se necesita
  • Crear ideas novedosas que puedan impulsar la productividad
  • Idear proyectos de desarrollo para esas ideas
  • Impulsar la aprobación de dichos proyectos
  • Y muchas veces, liderar los mismos
O sea que tiene que tener algunas características de líder de proyecto y de analista funcional y técnico.

¿Entonces un arquitecto es un gurú?

No necesariamente. Aunque siempre conviene que sea así. La razón es simple: El arquitecto implícitamente toma decisiones a mediano y largo plazo, que afectarán el futuro de la empresa de acá a unos 2, 5, o hasta 10 años. Incluso más.

Las propuestas y las micro y macro decisiones que tome van a enmarcar el futuro de la forma de hacer software en la empresa. Este es un punto que generalmente todos pasan de largo. La responsabilidad de un arquitecto es tal que puede llevar a la empresa al fracaso de no haber sido bien elegido o de haberse tomado malas decisiones. Y lo que es peor, no lo vas a ver venir hasta que sea tarde.

Claro que esto es un idealización de lo que debería ser un arquitecto. Un transformador interno de los sistemas de información de la empresa. En lo posible, una persona devota que no sólo estudie y se actualice constantemente, sino que también busque participar de la comunidad de investigación en software, para llevar el software cada vez a un nivel mayor.

No se trata solamente de hacer frameworks, o se dictaminar cómo deberían relacionarse unas clases. Esas serían tareas de un arquitecto junior. El arquitecto de verdad debe ver el futuro, pesar los diferentes factores y tomar decisiones. 

Decisiones bien tomadas podrían hacer que la empresa pueda iniciarse en otras tecnologías que antes no exploraba (como por ejemplo, una empresa dedicada a .NET que pueda moverse a IPHONE, por dar un ejemplo).

Y si el presupuesto y el conocimiento son suficientes, podrá desarrollar productos tan baratos y fáciles de mantener que los márgenes de ganancia serían muy importantes.

¿Ahora, cuál es el seniority de un arquitecto?

Esta pregunta me hace acordar a un aviso de computrabajo que ví hace un tiempo. Buscaban un project leader "junior". Entonces me puse a pensar... qué significa ser junior en este cargo?

¿Debe saber programar? Mínimamente, para poder estimar las tareas con precisión. Porque sino serán los desarrolladores quienes las estimen, y no él (esto no quiere decir que no pueda corroborar fechas con los dev).

¿Debe saber analizar? Totalmente. Muchas veces los requerimientos deben ser analizados por el TL al no haber un analista técnico disponible. Aún así, el TL debería tener en claro de qué vá el software a desarrollarse, y no ser una mera máquina de métricas y estimaciones.

¿Debe tener estudios? Absolutamente. No me parecería correcto que un líder de proyecto "lidere" a personal que es más capaz que el mismo. La típica frase "El que sabe, sabe, y el que no, es jefe" es tan triste y real que lo llegamos a tomar como una joda. Pero la posta es que las situaciones donde se aplican son justamente los grandes baches que una empresa debe corregir al instante. Un "jefe" o "líder" incapaz provocará grandes daños económicos imperceptibles a la empresa, por el simple hecho de que no genera ni la mitad de lo que puede generar un TL decente.

Un poco me estuve yendo de tema, y podría seguir analizando qué clase de background debería tener un TL, que si bien se fijan, no analicé ninguna de las tareas que tiene que hacer un TL.

Pero a lo que voy es que en ese aviso me imaginé "si pido más de X no me van a tener en cuenta" y simplemente concluí "gano más como desarrollador". Es evidente que si incluyeron la palabra JUNIOR en un aviso es porque quieren pagar poco. Además, conozco personas que no tienen idea de sistemas y arrancaron a trabajar de project leader DIRECTAMENTE, sin background alguno. "¿Qué es una tabla?" <--- No se sorprendan cuando les pregunten eso. De pedo conocen una tabla en excel en el mejor de los casos. Desconfíen muchísimo de gente así. No es culpa de ellos que los hayan endulzado con un cierto sueldo y responsabilidades, cargo y beneficios, cuando ellos no tenían idea de lo que se necesita para ser efectivo en ese puesto. Pero después estarán atrapados por siempre al menos que decidan estudiar por su cuenta. Ser TL y después moverse a un puesto de desarrollador Junior no es una opción.

Lo mismo ocurre con los arquitectos. No pueden ser arquitectos quieren no tienen un importante background en programación. Es evidente. ¿Qué arquitectura vas a diseñar si todavía no sabes lo que es un patrón? ¿Qué clase de decisiones vas a tomar si nunca tuviste que romper y re-armra un sistema? No señores, un arquitecto JUNIOR debe ser como mínimo un programador Senior. Y estamos hablando de unos 4 años de experiencia continuada como mínimo.

Yo tengo una idea del seniority del arquitecto que quizás no aplica a la concepción actual de muchos. Estamos acostumbrados a ver el seniority como un simple título que se gana con el tiempo. Sin embargo, tenemos desarrolladores que después de 5 años siguen siendo unos soquetes. Y después ta el pibe ese que hace un año que está y es un bocho. Sin embargo, quien es "Senior"?

Se pueden ir imaginando hacia donde voy:
  • JUNIOR: Alguien que ha programado mucho pero no ha adquirido grandes conocimientos en arquitectura y desarrollo de software. No lideró equipos ni tiene demasiados conocimientos técnicos mas allá de los que ganó con su experiencia laboral. Sin embargo, DEBE ser un Senior en programación, al menos en términos temporales. El JUNIOR en Arquitectura es alguien dispuesto a aprender, y nunca puede ser el cabecilla del sector. Es decir, no puede tomar decisiones que afecten demasiado al futuro de la empresa. Es probable que en esta categoría apenas esté aprendiendo UML.
  • SEMI-SENIOR: Es aquel que ya tiene muchos más conocimientos que el JUNIOR, y obviamente es SENIOR en programación. Conoce UML, conoce arquitecturas, conoce patrones, conoce tecnologías. Sin embargo, le falta aprendizaje, y probablemente, capacidad. Quizás no tenga la mente muy abierta, o no sea tan creativo como uno quisiera, por lo que sus decisiones pueden ser erradas muchas veces, debido a un mal proceso de análisis, o porque simplemente no vió las fallas básicas en sus propuestas. En mi opinión, es un recurso útil, siempre y cuando esté bajo un arquitecto SENIOR.
  • SENIOR: Este es el real transformador de la empresa. El que destruye y re-construye los cimientos bajo los cuales se produce software. Es como que levante una máquina de ensamblaje diferente todos los días en una fábrica de hamburguesas. Es el que toma las decisiones y generalmente son acertadas (luego analizaremos el concepto de decisióna acertada en arquitectura). Es el cabecilla del sector de arquitectura y el que se debe encargar de resolver los problemas de sistemas. Porque sistemas resuelve los problemas de todos, pero nadie resuelve los problemas de sistemas.
Es dentro de este concepto de Arquitecto Senior que para mí se encuentra la verdadera utilidad del rol del arquitecto. Conozco sólo 2 arquitectos de este calibre. Uno es un ingeniero que se nota que sabe, y el otro es un magíster que rediseño muchísimas cosas a nivel sistemas en una multinacional monstruosa. Mas allá de que las cosas que hizo no fueran lanzar un cohete a la luna, el apoyo a la propuesta y la implementación que logro son dignas de notar.

Es decir, que esta clase de Arq Senior son pesos pesados. Y obviamente, ¿a quién vas a dejar que tome las riendas de cómo se hace el software en tu empresa? A un peso pesado! Uno capaz de hacerse cargo de tremenda tarea.

Lamentablemente este no es el concepto de SENIOR que se maneja hoy en día. Pero esta consideración es más para las empresas que para los empleados. Para que analicen si lo que realmente quieren es un arquitecto, y si lo quieren, entonces que estén dispuestos a encontrar un "Senior" de verdad.

Esto no indica que los Junior y SemiSenior (según mi concepción) no sean útiles, pero no son suficientes.

Finalmente, para ir cerrando. 

¿Qué es una decisión acertada en arquitectura de software?

Desde mi propio punto de vista, una decisión acertada puede ser de diferente índole. La primera que nos vamos a encontrar, que creo que es la más común, es aquella decisión que es una mejora aceptable o incluso considerable sobre un esquema de trabajo actual.

Es decir, una decisión que permite al esquema evolucionar en el sentido necesario para que la arquitectura pueda seguir evolucionando más adelante. Por dar un ejemplo bobo, pasar de no tener capas de aplicación a tener UI, negocio y datos, es una mejora notable y acertada. Algo considerablemente acertado sería cambiar el framework actual de base de datos que no tiene soporte para nada excepto SQL SERVER  a un framework que soporte cualquier tipo de base de datos, y sólo requiera que se desarrolle algún que otro componente para hacerlo compatible con ORACLE, DB2, etc.

Pero esas decisiones acertadas son las más simples. Son transformadoras a nivel micro ya que cambian nuestra forma de programar y producir software, pero no cambian radicalmente el modo en que opera la empresa.

Pensemos ahora qué pasaría si mis decisiones permiten a la empresa aumentar en un 300% la productividad, aligerando la carga de trabajo de todos los desarrolladores, pudiendo dentro de unos pocos meses poder estar con viento a favor en las fechas de entrega en vez de estar siempre atrasados. Esa "magia" que logró el arquitecto (que podría ser con un framework empresarial potente, bien diseñado, y con capacitaciones eficaces a los programadores) podría realmente transformar la realidad de la empresa. Quizás ahora se puede aceptar más trabajo sin reclutar recursos adicionales. Este tipo de decisión acertada "que tiende a macro" es transformadora, pero no abrió ningún mercado nuevo. Como mucho puede llevar a la empresa a otro nivel económico, pero es sólo una inyección de evolución. Este es otro tipo de decisión acertada, que grotescamente llamada inyección evolutiva, o podríamos llamar como transformadora de la productividad.

Ahora que pasaría si gracias a nuestras decisiones la empresa puede competir con grandes gigantes como IBM, Microsoft, Apple, etc? Sigue siendo una transformadora de productividad, pero de tal nivel que el cambio es muy "sarpado", a falta de mejor palabra. Transforma tu empresa mediana en un conglomerado y temido competidor. Pero no deja de ser el mismo tipo de decisión.

Ahora, podríamos llegar a decidir hacer un framework para una tecnología que no conocemos. Imaginemos que somos expertos en .NET y decidimos ampliar nuestros conocimientos para desarrollar en IPHONE, IPAD, etc. Necesitaríamos investigación, tiempo, presupuesto, personal, y mucho brainstorming. Pruebas de concepto, pruebas de todo tipo, proyectos piloto, etc. Pero a la larga, si nuestras decisiones fueron correctas, hemos transformado a la empresa y ampliado el mercado en el cual puede participar. Nuestras decisiones aquí fueron posibilitadoras de un cambio muy importante. Tiene su nombre en la teoría de sistemas de información, pero ya me olvidé cual es. Vamos a llamarle por ahora decisión de expansión de mercado.

Es parecido, aunque no es lo mismo, hacer todo eso pero para MOVERSE de mercado, y no ampliarse. Abandonar .NET en este ejemplo. Eso sería una decisión transformadora de dirección.

Ahora, ¿cuándo es acertada la decisión y cuando no?

Pues cuando te vá bien chamaco. Y eso se vé cuando lo notas tanto en los empleados, en la empresa, y en los clientes y proveedores.

Hay más tipos de decisión que creo que existen, como las transformadoras de proceso (cambiar la forma en la que se gestiona), transformadoras de mentalidad, etc. Pero el post ya me ha quedado larguísimo y yo tengo que volver a trabajar!

Después de tanto tiempo inactivo al menos les dejo con un buen super post. Y me viene bien hacer este brainstorming para "idealizar" qué es un arquitecto de software, cargo que empiezo a cubrir desde hoy.