Mostrando las entradas con la etiqueta dotnet. Mostrar todas las entradas
Mostrando las entradas con la etiqueta dotnet. Mostrar todas las entradas

lunes, 3 de septiembre de 2007

Bitácoras, Trazas, Logs, Logging

Una consabida forma de ver que sucede con tus programas es "pintar" los valores de tus variables. Esta rústica forma de depurar también tiene otra acepción: loggear :S

¿quién dijo que poner System.out.println (javeros) o Console.WriteLine (.net) por cada línea es manejar una bitácora? No lo sé, pero en los ambientes java (que es lo que tengo más cercano) tenemos mega-archivos log de cientos de megabytes generados con poderosos System.out.println statements. Logging is cool!

Pero, eso no es logging. En casi cada aplicación "grande" o "empresarial" (lo que sea que significa esto) se incluye algún mecanismo de bitácoras. Agregar sentencias de rastreo es un mecanismo de "bajo nivel" para depurar código. Puede ser que sea la única opción por no existir un depurador para la plataforma o por que ya se trata de un ambiente multitarea/multihilos.

En el caso de una aplicación ejecutándose en un ambiente de producción, tampoco se puede hacer uso de herramientas de desarrollo o depuración. Casos así requieren que se le otorgue a los administradores u operadores herramientas que les permitan monitorear el comportamiento de los sistemas.

Para hablar de logging se requiere cumplir una serie de requisitos. Uno de ellos son los "contextos", entidades que contienen la información precisa de la ejecución de la aplicación. También se requiere distinguir diferentes niveles de severidad, desde el error fatal hasta mensajes de depuración; estas características deben poder configurarse fuera del código de la aplicación, es decir, en los programas incluimos todas las llamadas de rastreo que consideremos pero dependiendo de la configuración se van ir grabando las seleccionadas.

También tiene sus desventajas. El registro de entradas en archivos o bases de datos consume tiempo de procesador, llamadas a dispositivos que finalmente se ve como un cierto grado de lentitud en la aplicación. Si se registran demasiadas entradas, el log se torna ilegible. Si se filtran demasiados niveles de severidad, puede ser que se pierdan elementos que podrían auxiliar a resolver problemas.

Como ya es costumbre, el mundo java ha pasado por esto antes y gracias a la colaboración de muchas personas se construyó un framework para este tipo de necesidades. Ha sido tal el éxito de esta iniciativa que se desarrollaron componentes similares para otras plataformas y lenguajes (C++/PHP/Ruby) e incluso se incluye en algunos productos comerciales, BEA WebLogic Server por ejemplo (aunque ninguno de los programadores que conozco lo usan, siguen con sus pinchis println's) y obvio, también se construyo para .NET.

En este caso, log4net respeta todos los principios de su ancestro log4j y tenemos archivos de configuración, contextos, jerarquía de loggers e implementaciones de "appenders" que nos permiten tener diferentes destinos para nuestros logs. Ahora si, "logs".

El primer ejercicio de muestra del uso de log4net lo pueden encontrar en mi repositorio de ideas Google Code. Mediante subversion pueden obtener una copia de trabajo y trastear un rato con él.

Finito.

jueves, 23 de agosto de 2007

La construcción de los Helpers

Derivado del desarrollo de Operación PyME y un poco de sentido común aparece la tarea de construir un framework para construir más rápidamente y fácilmente la aplicación.

Se ha vuelto un concepto casi obligado el utilizar un framework de objetos de negocio pero ¿qué entendemos por esto? Un conjunto de clases que permiten modelar los objetos de un dominio y nos permitan olvidarnos de las tareas mundanas. La idea de fondo es utilizar la mayor parte de nuestra energía solucionando problemas de negocio y la menos posible en los problemas de tecnología.

Así han aparecido en el medio infinidad de frameworks con este objetivo, en todos los lenguajes y en todas las plataformas. Hasta parece que ya se ha llegado a un punto de saturación para estos proyectos. Sin embargo siguen apareciendo.

No existe el framework perfecto, como tampoco el lenguaje perfecto ni la plataforma perfecta. Y siguiendo nuestro inevitable anhelo de perfección vamos creando más proyectos tratando de solventar los errores que encontramos en otros.

No existe una metodología perfecta para construir un framework, generalmente la construcción es influenciada por el tema de moda: aspectos, programación orientada a objetos, inyección de dependencias, objetos auto-suficientes. Algunas empresas han publicado documentos para describir como han concebido y construido los frameworks que ofrecen. Entre estas últimas aparece notoriamente Microsoft.

Después de lanzar al mercado la tecnología .NET, Microsoft ha batallado duramente para posicionarla como una tecnología empresarial (cualquiera que sea su significado). Parte de esos esfuerzos ha sido el desarrollo de bibliotecas de componentes que faciliten el desarrollo de aplicaciones. El esfuerzo inicial dio como resultados los elementos que se conocieron como Application Blocks.

Estos eran conjuntos de clases con un objetivo delimitado. Lo más interesante fue que las construyeron a partir de un análisis que compartieron en forma de guías. En estos documentos exponen los elementos que se consideraron durante el diseño describiendo detalladamente los escenarios y la manera de aplicar la tecnología .NET para construir estas bibliotecas.

Estas bibliotecas fueron rápidamente adoptadas por la comunidad de desarrolladores quienes además fueron enriqueciendo con sus experiencias propias la funcionalidad de las clases incluidas e incluso se combinaron en un nuevo producto que se conoce como Enterprise Library. Sin embargo, tras la aparición del proyecto Mono, que permite la ejecución de programas desarrollados con .NET en plataformas no Windows, se incluyó en la licencia una cláusula que impide la ejecución de los Application Blocks en sistemas operativos distintos a los construidos por Microsoft.

Así que ahora, a pesar de ser elementos tan útiles, los Application Blocks no pueden ser utilizados en Linux o Mac OSX. Existen en el mundo del código abierto cada vez más proyectos basados en .NET y algunos de ellos pudieran resolver los mismos escenarios que se presentan en el diseño de las bibliotecas de Microsoft el ejemplo de inicio es log4net, una biblioteca de clases para registrar entradas en diferentes destinos que forma parte del proyecto Logging Services de la Fundación Apache.

Y también existen otros proyectos que ofrecen alternativas para los otros Application Blocks existentes sin embargo la principal ventaja de la oferta de Microsoft es la unificación que han conseguido y que en los proyectos de software libre se encuentran dispersos e inmersos en otros proyectos y una implementación sencilla, directa y única simplemente no existe.

Así que esta iniciativa (si, una más) es la de tener en un solo conjunto esta funcionalidad partiendo en primer lugar de proyectos ya existentes, como log4net, mostrando como es que se cumplen los escenarios descritos en la documentación de Microsoft y construyendo los elementos necesarios retomando código o creando nuevo para satisfacer las necesidades planteadas por las guías de referencia.

Y si no fuera suficiente... habrá más sobre el tema.

Finito.

martes, 26 de junio de 2007

PartnerApi Library: Por fin ve la luz

Hace algunos años fui contratado para integrar un CRM y Salesforce (se llamaba así en ese entonces). Para realizar la integración usé C# y el Enterprise API de Salesforce para llevar los datos del CRM al repositorio en línea de Salesforce. Un ejercicio harto interesante. También leí algo acerca de la PartnerApi y de ahí surgió la inquietud de utilizarla.

El objetivo que se me presentó en mi mente fue crear una biblioteca que simplificara el uso de esta PartnerApi y pues después de mmuuuucho tiempo aquí está.

Acabo de publicar el código, licenciado bajo LGPL, para que todo mundo lo revise, lo use y ojalá y contribuya a este proyecto.

Cualquier comentario, sugerencia o pregunta son bienvenidas.

Finito.

miércoles, 9 de mayo de 2007

Entre servicios te veas

En una prueba de integración entre una aplicación .NET y otra desarrollada en Java nos apareció este mensaje:

Exito: 0
Código Error: 100
Desc. Error: mx.gob.imss.sigoi.quejaVerbal.exception.ValidaCampoException:
El campo Calidad de la persona que se comunica es requerido.
El campo Nombre de la persona que se comunica es requerido.
El campo Apellido paterno de la persona que se comunica es requerido.
El campo Lada de teléfono particular de la persona que se comunica tiene que ser numérico.
El campo Lada de teléfono particular de la persona que se comunica tiene una longitud no valida, menor a 2 Caracteres
El campo Teléfono particular de la persona que se comunica tiene que ser numérico.
El campo Teléfono particular de la persona que se comunica tiene una longitud no valida, menor a 8 Caracteres
El campo Teléfono celular de la persona que se comunica tiene que ser numérico.
El campo Teléfono celular de la persona que se comunica tiene una longitud no valida, menor a 12 Caracteres
El campo Correo electrónico de la persona que se comunica no tiene un formato adecuado
Se tiene que incluir al menos un medio de contacto valido de la persona que se
comunica: Lada y número de teléfono particular, número de teléfono celular, correo electrónico, o dirección completa
Es necesario capturar el NSS de la persona que se comunica
Es necesario capturar el NSS de la persona que solicita el servicio
El campo Calidad de la persona que solicita el servicio es requerido.
El campo Teléfono celular del usuario que solicita el servicio tiene que ser numérico.
El campo Teléfono celular del usuario que solicita el servicio tiene una longitud no valida, menor a 12 Caracteres
El campo Entidad federativa del usuario que solicita el servicio tiene que ser numérico.
El campo Entidad federativa del usuario que solicita el servicio no es un valor válido de catálogo
El campo Clasificación de la solicitud del planteamiento tiene que ser numérico.
El campo Clasificación de la solicitud del planteamiento no es un valor válido de catálogo
El campo Tema del planteamiento tiene que ser numérico.
El campo Tema del planteamiento no es un valor válido de catálogo
El campo Subtema del planteamiento tiene que ser numérico.
El campo Subtema del planteamiento no es un valor válido de catálogo
El campo Delegación de Adscripción del planteamiento no es un valor válido de catálogo
El campo Unidad Medica de Adscripción del planteamiento tiene que ser numérico.
El campo Unidad Medica de Adscripción del planteamiento no es un valor válido de catálogo
El campo Delegación o UMAE involucrada en la gestión o queja del planteamiento tiene que ser numérico.
El campo Delegación o UMAE involucrada en la gestión o queja del planteamiento no es un valor válido de catálogo
El campo Subdeleación y/o Unidad involucrada en la gestión o queja del planteamiento tiene que ser numérico.
El campo Subdeleación y/o Unidad involucrada en la gestión o queja del planteamiento no es un valor válido de catálogo

¿Qué tiene de malo? (aparte de algunas faltas de ortografía) Son dos servicios que están intercambiando mensajes entre sí. No tienen interacción con el usuario, así que este tipo de mensajes, descriptivos y detallados, son completamente desaprovechados en este contexto.

Entonces ¿cuál es el modo correcto de devolver errores en este caso? No sé cual sea el modo correcto. Lo que a mi me gusta es el estilo de AppExchange Web Service API.

AppExchange (anteriormente conocida como Salesforce) es una empresa que ofrece software as a service (SaaS), en particular un CRM que compite directamente contra los grandes: Siebel, SAP y otros. Les ha ganado una gran tajada del mercado y sigue abriendo áreas de oportunidad. La API que comento la ofrecen mediante servicios web y tiene la funcionalidad de agregar, actualizar, borrar y buscar items de su mega repositorio de datos.

Así, en esas operaciones obviamente se envían y devuelven resultados en un contexto de integración de servicios. ¿Cómo le hacen? Va la referencia del API:

SaveResult[] = sfdc.create(sObject[] sObjects);


Tenemos la llamada create que recibe un arreglo de sObjects (tipo nativo de AppExchange) y como resultado devuelve un arreglo de objetos SaveResult. Ahora veamos SaveResult:

private Error[] errorsField;
private string idField;
private bool successField;


Nos devuelve un objeto con el identificador único (idField), una bandera de éxito o fracaso (successField) y un arreglo de objetos Error, igualmente veamos:

private string[] fieldsField;
private string messageField;
private StatusCode statusCodeField;


En fieldsField tenemos el o los nombres de los campos que provocaron el error; messageField es el texto descriptivo del error y finalmente statusCodeField que es el código que identifica el error dentro de un catálogo disponible en el WSDL del servicio.

Si bien tenemos un texto descriptivo, tenemos otras referencias (statusCodeField, successField) que nos permiten atender el problema y darle solución dentro de un contexto de integración.

A mi parecer es la falta de comprensión de los escenarios en los que se trabaja lo que provoca este tipo de diseños. Ya se requiere cambiar el modelo y empezar a modelar servicios. En algún momento habrá un servicio que se encargue de interactuar con el usuario y habrá que darle la suficiente información para que resuelva los problemas que lleguen a aparecer.

Por eso, entre servicios te veas, comportate como un servicio.

Finito.