Page 1

Visual Basic.NET • C# • Delphi • ASP.NET • ADO.NET • .NET Framework • Windows Server System

dotNetManía

www.dotnetmania.com

Dedicada a los profesionales de la plataforma .NET

nº10 diciembre 2004 • Precio: 6,00 € (España)

Aspectos e intercepción de métodos en .NET o cómo poner la guinda sin estropear el merengue Entrevista a Ivan Medvedev miembro del CLR Security Team en Redmond Informes y trazado de gráficas 3D en ASPNET (II) • Verificando la seguridad de nuestras aplicaciones • SQL Analysis Services (I)• Trabajando con el registro de Windows

Universidad Proyecto MoMo. Museos, Hormigas y Serialización en el Compact Framework de .Net Comunidad SpainNet Vocación de comunidad al alcance de todos Arquitectura Arquitecturas Orientadas a Servicios: Una introducción Laboratorio DevPartner Studio Professional Edition opinión

Orientación al producto versus orientación al procedimiento


dnm.editorial

dotNetManía

Misión imposible

Dedicada a los profesionales de la plataforma .NET Año I •Número 10 • Diciembre 2004 Precio: 6€ (España) Editor Paco Marín (paco.marin@dotnetmania.com)

Asesor Técnico/Coordinación Marino Posadas (marino.posadas@dotnetmania.com) Redactores Antonio Quiros, Guillermo 'guille' Som, Jorge Serrano Pérez, José Manuel Alarcón Aguín, Luis Miguel Blanco y Manuel Imaz. Colaboradores habituales Ángel Esteban, Braulio Díez, Eladio Rincón, Erich Bühler, Fernando Nogueras, Jorge Crespo Cano, José Miguel Torres, Miguel Egea, Miguel Katrib Mora (Grupo Weboo), Octavio Hernández, Pablo Abbate, Pedro Pozo, Pepe Hevia y Salvador Ramos. Además colaboran en este número Antonio López, Javier Jaén y José A. Mocholí Portada Yamil Hernández Edición y Suscripciones

.netalia c/ Robledal, 135 28529 Rivas-Vaciamadrid (Madrid)

Tf. (34) 91 666 74 77 Fax (34) 91 499 13 64 Publicidad Mediadev Sophie Mancini (sophie@mediadev.es) Tf. 93 426 22 57 - 670 99 74 64 Fax. 93 423 11 40 Imprime Gráficas Vallehermoso www.graficasvallehermoso.com ISSN 1698-5451 Depósito Legal M-3.075-2004

<<

Éste es un número con más caras nuevas de lo habitual. Se estrena Yamil Hernández, del Grupo Weboo de la universidad de La Habana, de la mano de Miguel Katrib, ¡cómo no!, quien además de escribir, nos ha diseñado la portada de este mes: “Misión Imposible” que ilustra su artículo “Aspectos e intercepción de métodos en .NET o cómo poner la guinda sin estropear el merengue”. Un artículo de once páginas en la que describe algunos mecanismos para interceptar la llamada a un método en .NET. Pero no es la única misión imposible de este mes; la otra fue conseguir acercarse siquiera a Bill Gates quien pasó por Europa con motivo del IT Forum en Dinamarca y pasó por España el viernes 19 de noviembre, entre grandes medidas de seguridad y como un auténtico fenómeno mediático, y con tantos compromisos que es de esos días que uno se alegra de no ser él. ¡Pobre hombre! Y otro estreno con el Proyecto MoMo, o de cómo programar de forma “natural”. Fijándose en el comportamiento de las hormigas cuando buscan comida, Javier Jaén, profesor de la universidad politécnica de Valencia y un equipo de estudiantes ha realizado un interesante proyecto para la visita asistida a museos.

Fueron los ganadores de la Imagine Cup en España. Espero que cunda el ejemplo y otros meses contemos con otros profesores que nos expliquen sus proyectos de investigación -a ser posible tan bien como Javier Jaén y José A. Mocholí lo han hecho esta vez-. Interesante entrevista a Ivan Medvedev, miembro del CLR Security Team en Redmond, realizada por Marino Posadas, en la que también estuvo presente “activamente” el ya mencionado Miguel Katrib. Recordarán que Miguel hablaba sobre un problema de seguridad del CLR en el número 3 de dotNetManía. Afirmación con la que Sebastian Lange program manager, precisamente del CLR Security Team en Redmond, no estaba de acuerdo y nos lo hizo saber en el número 4. Ivan y Miguel tuvieron ocasión de comentar éstos y otros temas en el Microsoft Research de este año. Por último, también se estrena Antonio Soto, Technical Account Manager de Alcatraz Solutions, quien comienza a colaborar con nosostros con su artículo “Verificando la seguridad de nuestras aplicaciones” que nos describe brevemente la utilización de la no siempre bien conocida herramienta Windows Application Verifier.

<<dotNetManía

Administración Pilar Pérez (pilar.perez@dotnetmania.com)

3


10

dnm.sumario Orientación al producto versus orientación al procedimiento

9-10

Entre las muchas encrucijadas que existen hoy en el ámbito de la Ingeniería del Software, tenemos aquella donde se cruzan dos orientaciones que, no siendo contrapuestas, marcan a veces el modo en que los equipos de trabajo se organizan y realizan su labor diaria. Se trata de la orientación al producto frente a la orientación al procedimiento.

Entrevista a Ivan Medvedev

11-13

En el evento de Microsoft Research de este año, tuvimos la oportunidad de departir con Ivan Medvedev, del CLR Security Team en Redmond.

Informes y trazado de gráficas 3D en ASP.NET (II)

14-19

En esta serie de artículos mostramos varias tecnologías que pueden ser utilizadas en aplicaciones Web y hemos elegido como excusa la creación de informes.

Aspectos e intercepción de métodos en .NET o cómo poner la guinda sin estropear el merengue

20-30

Con los recursos que brinda .NET, es posible desarrollar mecanismos para interceptar la llamada a un método. Una vez interceptada una llamada se puede entonces tomar el control y ejecutar funcionalidades relacionadas con la ejecución del método, pero que no están incluidas en el código de éste. Este artículo desarrolla y explica tres vías para llevar a cabo esta “intercepción”.

dnm.sumario

Verificando la seguridad de nuestras aplicaciones

32-34

Cada vez son más los agujeros de seguridad que explotan los códigos maliciosos, ocasionados por malas prácticas de programación. En este artículo se describe la utilización de una herramienta, Microsoft Application Verifier, que puede ser un buen primer paso para el testeo de la seguridad de nuestras aplicaciones.

SQL Server Analysis Services. ¡Hola Cubo! (I)

35-38

En esta serie de artículos presentaremos un pequeño ejemplo de un DataWarehouse, a partir del cual construiremos una base de datos multidimensional compuesta por un sólo Cubo, y que será explotada y analizada con herramientas cliente como MS Excel y MS Data Analyzer. El objetivo fundamental es que nos empecemos a familiarizar con esta estupenda herramienta que viene con SQL Server y que en la mayoría de las ocasiones no se utiliza por desconocimiento.

Museos, hormigas y serialización en el Compact Framework de .NET

40-46

Hace 4 años, en París y con sólo 2 horas para visitar el Louvre. Así nació MOMO (MuseO MÓvil) en la mente del profesor Javier Jaén. Mediante el uso de un PocketPC inalámbrico y unas cuantas hormigas el visitante puede tener a su alcance una completa información multimedia optimizada a sus gustos y al tiempo de que dispone.

Trabajando con el registro de Windows

47-49

En este artículo se muestran ejemplos de cómo trabajar con el registro de Windows usando algunas clases del namespace Microsoft.Win32.Registry.

Arquitecturas Orientadas a Servicios: Una introducción

50-52

Introducción a SOA mostrando algunos antecedentes o evolución histórica que permitan, no solamente ubicar al nuevo concepto, sino entender porqué surge, qué problemas resuelve, la forma en que los resuelve, etc.

dnm.laboratorio

53-55

DevPartner Studio Professional Edition

dnm.comunidad.net

56

SpainNet: Vocación de comunidad al alcance de todos.

dnm.biblioteca.net

57

Programming Microsoft .NET XML Web Services (Damien Foggon, Daniel Maharry, Chris Ullman y Karli Watson). Expert Web Services Security in the .NET Platform (Laurence Moroney, Brian Nantz).

dnm.desvan

58


dnm.noticias

6

noticias.noticias.noticias.noticias.noticias.noticias

<< dotNetManía

<<

dnm.noticias

Microsoft da a conocer la estrategia y nuevos lanzamientos de su división de servidores y plataformas Microsoft presentó MOM 2005, MVS 2005 y HIS 2004 como un paso más en la consecución de los objetivos de la Iniciativa Sistemas Dinámicos Microsoft Operations Manager 2005

Microsoft Virtual Server 2005

Microsoft Host Integration Server 2004

Ha sido presentado MOM 2005 en su edición para grandes corporaciones y en su edición Workgroup para medianas empresas. MOM 2005 incluye un framework integrado que ofrece interconexiones basadas en servicios Web con otros sistemas de gestión ya en uso, y una nueva consola que muestra el estado del sistema y permite el acceso al servidor integrado para la elaboración de informes. MOM 2005 ayuda a los administradores de TI a convertir los datos de gestión en tareas con el conocimiento avanzado que proporcionan los nuevos paquetes de gestión (para aplicaciones como Exchange, SQL Server, ISA Server, etc.). La nueva versión de MOM ofrece características de seguridad integradas, tales como la capacidad de autentificar mutuamente a agentes y servidores, que está diseñada para ayudar a las empresas a protegerse contra el mal uso del sistema de gestión.

MVS 2005 incluye una instalación simple y una cómoda gestión de las máquinas basada en la Web, así como un almacenaje robusto y características de networking. Además las herramientas de gestión de los servidores físicos de Microsoft y de vendedores de herramientas de gestión de terceras partes han sido actualizadas para proporcionar a los administradores de una experiencia uniforme de administración a través de la combinación de servidores físicos y virtuales. Por ejemplo, un Virtual Server 2005 Management Pack para Microsoft Operations Manager 2005 habilitará la monitorización centralizada y la administración de rendimiento de múltiples servidores físicos y virtuales. Ambas ediciones tienen las mismas características y sólo se diferencian en la escalabilidad. Virtu<al Server 2005 Standard Edition soporta hasta 4 procesadores y Virtual Server 2005 Enterprise Edition soporta hasta 32 procesadores.

HIS 2005 incluye las recientemente desarrolladas herramientas de diseño Transaction Integrator (TI), que funcionan en el contexto del entorno de desarrollo integrado de Visual Studio .NET 2003. Las herramientas TI permiten a los desarrolladores de Windows aprovechar aplicaciones existentes de sistemas host por línea de negocios como servicios web XML o componentes del servidor Microsoft .NET, que se pueden utilizar en una solución con arquitectura orientada a los servicios (SOA). HIS 2004 proporcionan a los clientes las herramientas para crear servicios web XML, que en última instancia pueden ser consumidos y reutilizados en una solución basada en SOA para alcanzar este objetivo. Además Microsoft ha realizado inversiones importantes en HIS 2004 que impulsarán la capacidad de los clientes para integrar diferentes aplicaciones y mejorar la interoperatibilidad entre los sistemas host de IBM y las bases de datos DB2 y Windows Server y SQL Server.

BETA 2 DE SQL SERVER 2005 + KIT DE RECURSOS Este mes incluimos, con la colaboración de Microsoft Ibérica, un kit (en inglés) con dos CDs y un DVD cuyo contenido es el siguiente: • SQL Server 2005 Beta 2 Developer Edition. Además de la Beta 2 se incluye documentación y ejemplos. • SQL Server 2005 Beta 2 DVD de recursos. Esta es su guía para SQL Server 2005, con documentos y recursos técnicos de gran valor que le ayudarán a empezar con SQL Server 2005. Incluye además vídeos

técnicos, herramientas y demostraciones. • SQL Server 2005 Beta 2 Laboratorios de prácticas, que ofrecen a los usuarios una experiencia práctica guiada de autoformación sobre áreas tan importantes como las herramientas administrativas, seguridad, diseño de bases de datos e inteligencia de negocio (BI). Para más información en castellano sobre SQL Server 2005 visite: www.microsoft.com/spain/SQL/2005.


<< dnm.noticias

ILOG presenta Rules for .NET, el primer sistema para gestionar políticas empresariales desde Word Es el primer sistema de gestión de reglas de negocio que se integra con Office y Visual Studio .NET y con los servicios de colaboración de SharePoint. Las reglas de negocio proporcionan una forma probada de captar la lógica de negocio de las aplicaciones empresariales. Un Sistema para la Gestión de las Reglas de Negocio o BRMS (Business Rule Management System) es una solución diseñada para modificar y gestionar las reglas de negocio fuera de estas aplicaciones. ILOG Rules for .NET permite la gestión de las reglas de negocio a lo largo del ciclo de vida de las aplicaciones de negocio de misión crítica. Para los analistas y otros usuarios de negocio, proporciona herramientas de creación y gestión integradas en Microsfoft Office System y un interface basado en la Web.

Para los arquitectos y desarrolladores de software, proporciona un conjunto de herramientas dentro de Microsoft Visual Studio .NET para integrar la tecnología de reglas de negocio de ILOG directamente en las aplicaciones .NET. ILOG Rule Studio for .NET Incluye una amplia operativilidad para desarrollar y gestionar aplicaciones de reglas de negocio: integración con Visual Studio .NET, vista del modelo de objetos de negocio, editor de reglas de negocio y ejecución directa sobre objetos .NET. ILOG Rule Engine for .NET El motor ILOG Rule para .NET proporciona a los desarrolladores de .NET el poder y la versatilidad necesaria para las exigentes aplicaciones de hoy en día: • Motor de reglas nativo de .NET. Escrito enteramente en C#, es un ensamblado que puede ser usado por cualquiera de los lenguajes de .NET. • Alto rendimiento y escalabilidad. • Soporte para distintas fuentes de datos. Puede acceder a numerosas fuentes de datos, incluyendo objetos .NET, antiguas aplicaciones COM(+), documentos XML, servicios Web, colas de mensajes, directorio activo y almacenes de datos de Exhange Server. Puede obtener más información en la web del producto en http://rulesfordotnet.ilog.com.

Infragistics NetAdvantage Volumen 3 reconocidas hoy como Microsoft Office, Windows y Outlook. Más información en www.infragistics.com. Infragistics NetAdvantage Volumen 3 salió al mercado en Octubre de 2004, pero a partir del 1 de diciembre, Abox ofrecerá una mejora en el precio. Puede consultar en www.abox.com.

dnm.noticias

<< dotNetManía

Las novedades que incluye Infragistics NetAdvantage Volumen 3 son un nuevo y completo motor de cálculo (CalcEngine) que le da toda la potencia de Microsoft Excel a sus formularios de Windows y a sus aplicaciones ASP.NET, una vista al estilo de Office 2003 y Visual Studio 2005, etc. Infragistics NetAdvantage 2004 Volumen 3 es el único entorno de componentes de presentación por capas diseñado para darle todo lo que necesita para crear GUIs pulidos y robustos para entornos Microsoft. Cuando está desarrollando en .COM, .NET o ASP.NET, NetAdvantage 2004 le trae el sistema de herramientas correcto para su trabajo, permitiéndole crear fácilmente interfaces con la sofisticación y la usabilidad que se encuentra en las aplicaciones comerciales más

7


<< dnm.noticias Microsoft IT Forum 2004 Conferencia europea para profesionales TI, arquitectos de sistemas y aplicaciones, especialistas y administradores. En días pasados, del 15 al 19 de noviembre, ha tenido lugar en la ciudad de Copenhagen el IT Forum 2004, el que quizás sea el mayor evento para IT Pros de todos los que se celebran en Europa. Este año el evento contó con la presencia de Bill Gates que participó en la primera de la keynote junto con JeanPhilippe Courtois, responsable en Microsoft para EMEA con una charla titulada “The Magic of Software”. En dicha charla resaltó la importancia del software y en general de la informática como herramienta que permita a las personas disfrutar de una vida mejor al mismo tiempo que exponía las iniciativas que están en marcha

en áreas como la gestión de identidades, anunciando el lanzamiento de una SmartCard basada en .NET, o la gestión de sistemas englobada en lo que Microsoft denomina DSI (Dynamic Systems Initiative). Posteriormente, Scott Charney ya en una segunda keynote habló sobre las iniciativas y el punto de vista de Microsoft en temas relacionados con la seguridad, área de la cuál es uno de los máximos responsables en la compañía. El evento, que se desarrolló con una logística y planificación similar a la que Microsoft nos tiene acostumbrados con eventos como el TechEd, contó con múltiples charlas en áreas como la administración y la gestión de sistemas, la gestión de datos, la planificación y despliegue de sistemas, soluciones de infraestructura, mensajería y movilidad y, por supuesto, cómo no, seguridad. A mayores múltiples Hands-On-Labs o talleres donde entrenar los conocimientos adquiridos en las conferencias y los inestimables Ask The Experts, que contaban con nombres como Ron Talmage, Gianluca Hotz o Jimmy Andersson entre muchos otros. En el capítulo de novedades o lanzamientos, los asistentes han podido trabajar ya en los Hands-On-Labs con una beta de Windows Update Services, o lo que es lo mismo, Software

<< dotNetManía

Borland presentó Delphi 2005 en Madrid y Barcelona

8

Borland, conjuntamente con Danysoft, celebró sendos seminarios en Madrid y Barcelona para presentar las novedades de Dephi 2005. Las presentaciones corrieron a cargo de Octavio Hernández, director técnico de Danysoft y Jason Vokes, jefe de producto para Delphi. La agenda de los seminarios fue: • Delphi 2005. Presentación por Jason Vokes. • Ventajas de Delphi 2005 para ADO.NET. • Desarrollo de aplicacio-

nes y servicios Web ASP.NET. • Desarrollo de aplicaciones para Win32 y .NET. • Panel de expertos. Puede obtener información de Delphi 2005 en el número 9 de dotNetManía, o en www.borland.es o en www.danysoft.com.

Update Services (SUS) 2.0. Entre las nuevas características, una muy importante: con WUS seremos capaces de distribuir actualizaciones para Windows pero además también para Office, Exchange y SQL Server. Sobrevolando en todo momento el Bella Center de Copenhagen estaba el lanzamiento de Microsoft Operations Manager (MOM) 2005 y de Virtual Server 2005, el hermano de Virtual PC 2004 orientado a servidores que cuenta con novedades interesantes como la posibilidad de desplegar sobre una misma máquina física varias máquina virtuales que conformen un cluster de Windows. Y de Copenhagen nos traemos una estupenda noticia; en el año 2005 el IT Forum tendrá lugar en… ¡Barcelona! Tomad nota, tenemos todos una cita del 15 al 18 de noviembre del año próximo en el IT Forum 2005.

Nuevo InstallShield 10.5 Macrovision ha anunciado la nueva versión 10.5 de InstallShield. Entre las nuevas características se incluye: • Característica Trialware.Puede convertir en un producto completo, uno de evaluación en pocos pasos. • Soporte para MSI 3.0. • Diseño Colaboración. Introduce ensamblados reusables, versionables y componentes modulares que pueden ser incorporados en diferentes instalaciones. • Vista de cambios XML. Permite actualizaciones automáticas de ficheros de configuración XML en las máquinas destino, sin que sea necesario escribir código cliente. • Repositorios locales y en red. Permite a los usuarios compartir y reutilizar elementos comunes entre múltiples proyectos de instalación.

dnm.noticias


Por Antonio Quirós General Area Manager Alhambra-Eidos

Orientación al producto versus orientación al procedimiento Entre las muchas encrucijadas que existen hoy en el ámbito de la Ingeniería del Software (perdón, ahora se llama Arquitectura, yo es que soy de letras y, por tanto, un poco lerdo), tenemos aquella donde se cruzan dos orientaciones que, no siendo contrapuestas, marcan a veces el modo en que los equipos de trabajo se organizan y realizan su labor diaria. Se trata de la orientación al producto frente a la orientación al procedimiento.

debe fabricarse el software. Pero, en general, podemos conceptualizar las orientaciones actuales en dos frentes diferentes: 1) Quienes ponen el acento en fabricar un buen producto. Para ellos lo importante es la calidad de la solución final sin importar tanto el método de fabricación o el modelo de colaboración que se haya puesto en práctica para regular las relaciones con él. Hablando en términos algo vulgares podríamos decir que, para los que siguen esta orientación, el fin justifica a los medios. Podemos afirmar que todos aquellos que hablan de metodologías ligeras, ágiles, Extremme Programming, etc. son los principales detentadores de esta afirmación. 2) Quienes ponen el acento en tener un procedimiento riguroso de fabricación y un modelo de colaboración con el cliente lo más determinado posible. Para ellos lo importante es el rigor en el proceso de construcción a fin de que las partes contratantes y ejecutoras del proyecto tengan en todo momento claro que la fabricación se hará de acuerdo a unas normas y que los aspectos contractuales y económicos del proyecto se cuidarán sobre cualquiera otros. CMM (Capability Maturity Model) es quizá el paradigma de los que defienden este punto de vista. Lo normal es que ambas posiciones, si se extreman, conduzcan a situaciones paradójicas que, sin duda, debemos evitar. Así, pues, no creo que un equipo de desarrollo pueda concentrarse en obte-

ner el mejor producto posible si, mientras tanto, su empresa se está arruinando porque el cliente, enfurecido por la anarquía y el caos presente durante el proceso de desarrollo, no paga ninguna de las facturas. Podemos estar orientados a realizar el mejor producto entre los posibles, pero si nos olvidamos de que hay fechas que cumplir y lo sacamos un par de años más tarde de lo que estaba previsto seguro que nuestro cliente no nos felicitará por el servicio prestado. Por el contrario, si nos concentramos en sólo la forma, si guardamos las medi-

Muchos hubieran deseado nacer en otra época o que Cobol no se hubiera acabado nunca das más reglamentarias y hacemos que la planificación del proyecto, las actas, las comunicaciones internas, etc., sean nuestras herramientas de trabajo, pero no cuidamos de modo especial la calidad del producto final, estaremos igualmente perdidos. Nuestro cliente nos mantendrá su crédito de credibilidad mientras dure el proyecto, animado por las buenas formas y un modelo de colaboración muy cuidado, pero explotará su cólera al final cuando compruebe que el producto obteni-

<<dotNetManía

<< Mucho se ha hablado, y mucho se hablará aún, acerca de cómo

9


<< dnm.opinion do no responde a los estándares de calidad necesarios para su implantación con éxito. ¿Hacia dónde debe, pues, orientarse una empresa de servicios que desarrolle software para clientes o incluso un departamento de informática interna de cualquier corporación que deba desarrollar, igualmente, proyectos de software para los distintos departamentos de la misma? La respuesta a esta pregunta no está en una afirmación rotunda hacia ninguno de los dos componentes del binomio orientación al producto / orientación al procedimiento; desde mi punto de vista, lo que tenemos que hacer es indagar acerca de la prelación que existe entre ambas orientaciones para tratar de adecuar nuestra acción empresarial y tecnológica en función de lo que descubramos.

<<dotNetManía

No es concebible que una compañía actual que esté desarrollando software no esté pensando continuamente en formar y certificar a sus técnicos.

10

A mí, y es una opinión estrictamente personal, no me cabe la menor duda de que el orden de prelación coloca en un nivel más relevante la orientación al producto y, en segundo lugar, la orientación al procedimiento. ¿Quiero decir con esto que lo que podemos hacer es olvidarnos de la orientación al procedimiento y centrarnos en la orientación al producto? Ni mucho menos. Simplemente quiero indicar que un cliente quizá pueda perdonarnos dificultades en el modelo de colaboración pero, desde luego, lo que no va a perdonarnos es la fabricación de software deficiente, escasamente probado, que a duras penas cumpla con los requisitos pedidos o que se encuentre obsoleto en cuanto a su concepción funcional y/o tecnológica. Las empresas, no obstante, deben cuidar ambos elementos en general. No es concebible que una compañía actual que esté desarrollando software no esté pensando continuamente en formar y certificar a sus técnicos para que sus logros tecnológicos sean cada vez mejores, pero tampoco es concebible que no esté, en paralelo, activando políticas para lograr implantar abordajes metodológicos (CMM u otro cualquiera) que hagan más viables y sencillos los proyectos. Muchos pensarán que si ya es muy fuerte el continuo tesón para estar al día tecnológicamente, lo que ya nos desborda es tener que estarlo también

en la parte metodológica y procedimental. Efectivamente, muchos hubieran deseado nacer en otra época o que Cobol no se hubiera acabado nunca, pero la realidad es bien diferente y la complejidad es una tendencia irreversible dentro de nuestro mundo. No podemos invertirla, no podemos buscar la simplicidad porque la simplicidad pertenece a un pasado mítico del hombre que ya no volverá (salvo catástrofe natural o nuclear). Por tanto no sirve quejarse sino ponerse a trabajar. Otro aspecto interesante que me gustaría resaltar es la utilización de los aspectos procedimentales como barreras para detener las lógicas pretensiones de nuestros clientes respecto a que el software construido para ellos, además de estar realizado de modo formalmente correcto, funcione. Lógica pretensión, por otra parte, si consideramos que se suelen invertir decenas de miles, centenas de miles o incluso millones de euros en proyectos cuya finalidad es la de satisfacer las necesidades de negocio de los clientes. Esto debe llevarnos a considerar que, por encima de la orientación al producto y/o de la orientación al procedimiento debe sobreponerse un valor de mucha mayor importancia que es la orientación a satisfacer las necesidades del negocio de nuestro cliente. Por esto me gusta MSF (Microsoft Solutions Framework) porque creo que coloca todos estos elementos en el orden de prelación razonable entre ellos y, desde luego, al asunto de la satisfacción de las necesidades del negocio del cliente por encima de cualquier otro. A poco que nos paremos a pensar, todo esto parece conducirnos a un consejo de radical importancia y es la reeducación de nuestras mentes para, a modo de como lo hacemos en un armario, colocar en ellas las cosas en los lugares adecuados, las camisas en las perchas, los calcetines con los calcetines y las corbatas en el corbatero. Hay muchos desarrolladores, o muchas empresas de desarrollo al completo, que tienen muy mal colocado su armario y a lo mejor han colgado los calcetines de las perchas y amontonado las camisas al lado de los zapatos. Este proceso es difícil, ya que los prejuicios y la educación amontonada durante años nos dificultan el trabajo, sin embargo es una labor imprescindible. En este proceso sólo sobrevivirán los que mejor se adapten a la complejidad de nuestro mundo, los que comprendan que nuestros clientes sólo nos contratarán si construimos software con el mejor método y con el mejor resultado posible y siempre pensando en que somos sólo una parte del engranaje de negocio de nuestros clientes y no una pieza imprescindible y autónoma. Los delirios de grandeza no nos llevarán más que al fracaso. La humildad de reconocer nuestras limitaciones y defectos es lo único que nos puede conducir a superarlos y crecer continuamente.


Por Marino Posadas MVP Visual Developer C# Alhambra-Eidos www.elavefenix.net

Entrevista a Ivan Medvedev Microsoft se adscribió a la iniciativa Trustworthy Computing (Informática Fiable) desde sus inicios. Su adopción, se extendió de forma natural a las plataformas de desarrollo, y en concreto, al propio motor de .NET Framework (el CLR). En el evento de Microsoft Research de este año, tuvimos la oportunidad de departir con Ivan Medvedev, del CLR Security Team en Redmond.

fesor Miguel Katrib de la Universidad de La Habana, quien había estado investigando temas de introspección de tipos (Reflection) y su relación con la seguridad (ver nº3 de dotNetManía). Miguel Katrib: Escribí código para “factorizar” una clase utilizando Reflection.Emit, y observamos que el sistema no comprobaba el tipo de retorno del método, pero eso sólo ocurría cuando el valor SkipVerification mostraba un valor verdadero. Mi pregunta es ¿porqué este valor está asignado a verdadero por defecto? Ivan Medvedev: Efectivamente, pero eso sólo es cierto cuando la ejecución es de código local. Lo que se pretende con eso es que el código de la propia máquina tenga los mayores permisos de cara al propio desarrollador. Hay varios niveles, uno de los cuales es FullTrust, que incluye lo anterior. Miguel Katrib: Entiendo, pero si en Visual Studio tenemos la posibilidad de prohibir la ejecución de código desde diversos escenarios, ¿por qué necesitamos que ese valor sea verdadero? Ivan Medvedev: Por que -por ejemplo- cuando trabajas en C++, algunas veces hay que trabajar sin verificación. Pongamos que trabajas con algún puntero, o acceso directo a la memoria. En esos casos, el compilador produce código no verificable y la única forma de

ejecutar ese código es tener permiso del tipo SkipVerification. Nosotros queríamos permitir que todos los programas que se ejecuten manualmente desde la máquina local tuvieran todos los permisos necesarios. La mayoría de las veces, tu código en la máquina local es propio y por tanto, seguro. Otro tema es que te bajes programas de Internet. Eso no puede ser seguro por defecto, más bien lo contrario. Miguel Katrib: ¿No hubiera sido mejor separar esos conceptos (cuando se necesitan punteros y demás) de los otros casos? Ivan Medvedev: No porque lo que pretendíamos es que existiera una flag única que otorgase los permisos para estos casos. Otra situación pensamos que

<<dotNetManía

<< Nos acompañó en esa ocasión el pro-

11


<<dotNetManía

<< dnm.directo.entrevistas

12

hubiera resultado confusa de cara al desarrollador. Marino Posadas: Bien. Vayamos una vez aclarado esto a cuestiones más genéricas de seguridad. El otro día veía un ejemplo de tu Web sobre cómo no se deben hacer algunas cosas (un colegio presentaba exámenes on-line, y las respuestas podían deducirse a partir del análisis del código fuente). ¿Crees que esa es una práctica común? Ivan Medvedev: Sucede más de lo que se piensa. También depende del nivel de conocimientos del desarrollador, claro. Por ejemplo, en Microsoft, tenemos un programa de formación llamado Monitoring Security Training, y cada ingeniero conoce el significado de la seguridad, o dónde tiene que acudir para encontrar recursos asociados a la seguridad. Quizá no pasa lo mismo en empresas más pequeñas o en algunos centros de enseñanza. Marino Posadas: Ahora sabemos que Longhorn va a ser un sistema administrado. Eso quiere decir que en gran manera la seguridad del nuevo sistema va a estar vinculada a la seguridad del propio CLR. ¿Podremos utilizar estas características en el nuevo sistema para evitar spam, spyware y otros elementos indeseables de Internet? Ivan Medvedev: Sí, por supuesto. En Longhorn va a haber muchas API's administradas, y en suma, todo el sistema va a ser mucho más seguro, por que la propia plataforma .NET lo es. Supongamos un caso típico de explotación, los buffer overrun, por que existe un control administrado de esos búferes. Y hay muchísimos otros ejemplos que podría citar aquí. También es una

forma de hacer que los programadores puedan escribir código más seguro de forma simple, gracias a que la plataforma misma lo soporte. Marino Posadas: ¿Los llamados spyware o adware utilizan igualmente esas técnicas para su intrusión? Ivan Medvedev: Podrían utilizarlas a veces para conseguir instalarse. Una vez instalados, ya no. Lo que nosotros queremos es evitar que ese tipo de software llegue a instalarse. Marino Posadas: ¿Podríamos decir que también aquí el futuro es la especialización?

cil el acceso al código fuente, pero en sí misma no es suficiente. Pero no es como convertirlo a código nativo. Ahí si que las cosas son mucho más difíciles, por que aunque uses un desensamblador, todo es mucho más difícil de leer y de entender. Marino Posadas: En tu sitio Web he leído acerca de la posibilidad de que la próxima versión de .NET no permita la posibilidad de deshabilitar la seguridad. ¿No piensas que eso es una cuestión personal? Ivan Medvedev: Ahora existen varias formas de deshabilitar la seguridad. La que yo quiero eliminar está relacionada con un parámetro de la utilidad caspol que anula todo tipo de seguridad. Esto es peligroso por que algunas veces, los usuarios que no conocen bien los problemas de seguridad, pueden provocar (y provocarse a sí mismos) problemas debido a esta técnica. Sin ese parámetro, también existe la posibilidad de deshabilitar muchas características de seguridad, pero son formas que implican un mayor conocimiento de lo que estás haciendo y sirven de recordatorio de la situación.

En Longhorn va a haber muchas API's administradas y, en suma, todo el sistema va a ser mucho más seguro, por que la propia plataforma .NET lo es

Ivan Medvedev: En Longhorn van a existir muchísimas más clases administradas, lo que va a hacer innecesarias muchas de las llamadas a las API's actuales. Pero la especialización va en aumento, sí. Marino Posadas: Desde el punto de vista de la seguridad, ¿qué piensas de la herramienta de ofuscación de código (Obfuscator) que viene con Visual Studio? Ivan Medvedev: La ofuscación no es sino una técnica más. Puede hacer que un hacker tenga bastante más difí-

Marino Posadas: ¿Crees que la utilidad FxCop debería de estar incluida en la próxima versión de Visual Studio .NET? Ivan Medvedev: FxCop es una excelente herramienta y yo la he recomendado muchas veces. De hecho hasta cierto punto yo estuve implicado en su desarrollo… Marino Posadas: No me refiero sólo a esa herramienta, en realidad, sino a si la versión 2.0 va a incluir más herramientas en su SDK…


<< dnm.directo.entrevistas

Marino Posadas: Una cuestión acerca de la política empresarial de seguridad. ¿Qué recomiendas a las empresas que hagan respecto a la seguridad? Ivan Medvedev: Creo que cualquier inversión que realicen las empresas en ese sentido va a ser crítica a medio, e incluso a corto plazo. Nadie quiere distribuir productos inseguros en un mundo como el de hoy, y los clientes empiezan a demandar esa

seguridad de las empresas que se dedican al desarrollo. Y lo que es bueno para los clientes, lo será para las empresas. Incluso podría recomendar algunos excelentes libros al respecto, como la obra de Michael Howard y David C. LeBlanc, “Writing secure code”, que en Microsoft es de lectura obligatoria para todos los desarrolladores.

Creo que los estudiantes y/o desarrolladores deberían comprender primero qué es lo que sucede si no se hace el código seguro. Entender algunas de las más importantes vulnerabilidades ayudaría a tenerlas en cuenta

Miguel Katrib: ¿Harías esa recomendación también para los profesores que enseñamos informática? Ivan Medvedev: La seguridad es una materia muy extensa. Creo que merecería un curso aparte y ser tratada en profundidad. Es difícil enseñar a la gente a escribir código seguro, especialmente a aquellos que nunca antes han pensado en la seguridad. Creo que con los buenos libros que existen actualmente sobre seguridad, se podría confeccionar un curso excelente sobre el tema. La obra que cité anteriormente, está muy bien estructurada, por ejemplo, y podría servir de modelo. Miguel Katrib: nosotros intentamos hacerlo cubriendo diferentes escenarios de seguridad. Quizá eso no abarca todo lo necesario, pero es una aproximación. Ivan Medvedev: Creo que los estudiantes y/o desarrolladores deberían comprender primero qué es lo que sucede si no se hace el código seguro. Entender algunas de las más importantes vulnerabilidades ayudaría a tenerlas en cuenta. Por ejemplo, si los usuarios comprenden bien lo que es un debilidad del tipo buffer overrrun, la próxima vez que escriban algo que tenga que ver con búferes recordarán esto y podrán sugerir soluciones.

<<dotNetManía

Ivan Medvedev: Con toda seguridad. Aunque no puedo decir que FxCop vaya a estar incluido en esta versión, pero sería una buena idea. Marino Posadas: Y una pregunta que he hecho a Rafal Luckawiecki, anteriormente, ¿la seguridad plena en la red necesitará de la Criptografía? Ivan Medvedev: Si por seguridad entendemos protección de datos, en muchas ocasiones sí, esa sería una de las mejores soluciones. En realidad, la mayoría de los algoritmos criptográficos ya están bien establecidos, y Microsoft no necesita realizar mucha investigación al respecto. Nosotros mantenemos contactos con universidades en las que se investigan las aplicaciones de esos algoritmos y más tarde los aplicamos en algunos de nuestros productos. Pero la investigación criptográfica es un esfuerzo a nivel mundial. Por el contrario, si hablamos de aplicar esos algoritmos a protocolos de comunicación muchas veces depende de dónde vengan esos algoritmos. A veces vienen de organizaciones de estandarización, como la W3C, y otras veces de compañías privadas como la nuestra. Si están bien hechas pueden reforzar la seguridad, no cabe duda. Marino Posadas: ¿Crees que la inversión en el conocimiento de estas tecnologías es una inversión recomendable? Ivan Medvedev: Completamente. En el futuro, la seguridad se va a convertir cada vez más en un elemento crucial a tener en cuenta y conocer la seguridad de diferentes productos y compañías nos ayudará a reforzar nuestros propios sistemas.

13


Por Erich Bühler .NET Framework y VB.NET MVP www.VBLibros.com

Informes y trazado de gráficas 3D en ASP.NET (II) No debo ocultar por más tiempo el objetivo de esta serie de artículos que a simple vista se centra en enseñar la vía de crear informes en ASP.NET. Se habrá dado cuenta si leyó la primera parte que en realidad he querido mostrar varias tecnologías que pueden ser utilizadas en aplicaciones Web y por ello he elegido como excusa la creación de informes.

<< Esto ha sido motivado particularmente por el hecho de que muchas de las tecnologías parecen orientadas originalmente a soluciones para ambientes Windows y finalmente la gran parte de los desarrolladores desconocen cómo sacar provecho en lo que a la Web respecta. De esta forma he decidido elegir de excusa este tema para explicar varias utilidades desconocidas quizá para muchos de ustedes y he dejado de lado solamente durante estas entregas mis clásicos artículos que apuntan a un nivel más bajo de la infraestructura. ¿Le dice algo Office Web Components 11.0 o ASP.NET Reports Starter Kit?. Si no sabe de lo que le estoy hablando es buena idea que continue con la lectura ya que de esta forma logrará dos objetivos: el primero, crear informes Web con resultados más que espectaculares; el segundo, conocer un par de tecnologías que tienen mucho para ofrecer. En el artículo anterior vimos cómo utilizar trazados GDI+ y plasmarlos en una página de servidor activo ASP.NET para finalmente enviarlo a un cliente Web (Internet Explorer, Netscape, etc.). Aquí aprenderemos un poco de arquitectura, organización y -lo que es más importante- cómo poner todo esto a funcionar en informes bajo un ambiente Web.

<<dotNetManía

Por donde empezar…

14

Por supuesto que existen varias herramientas para generar visualmente informes, muchas de las cuales son versátiles y fáciles de utilizar, aunque también algunas de éstas tienen un precio un tanto inaccesible por lo menos para mi bolsillo. Por

otro lado en algunas ocasiones se busca generar reportes sencillos o los que corresponden a los denominados “informes estándares” (relaciones, subtotales, etc.). Es aquí donde es posible encontrar otras alternativas fáciles y sin coste alguno; y un buen ejemplo de ello es ASP.NET Reports Starter Kit (www.asp.net). A diferencia de lo que se puede pensar inicialmente, esto no es una herramienta sino que se trata de una aplicación VS.NET que muestra 8 ejemplos de informes y diferentes prácticas y tecnologías que pueden ser aplicadas para resolver cada caso. Es así que ASP.NET Reports Starter Kit es un proyecto de ejemplo que enseña hábitos “sanos” de programación así como la creación de informes sin necesidad de utilizar controles de otros fabricantes. A su vez no sólo demuestra la forma de crear el mismo, sino que también la manera de realizar optimizaciones para su impresión. Pero sin lugar a dudas esto sigue siendo lo menos importante ya que a mi criterio lo que más resalta es la vía en la que está programado, esto es, utilizando gran parte de las recomendaciones de Microsoft para proyectos ASP.NET. Es así que Starter Kit es también una maravilla desde el punto de vista de programación y organización, y se incluye tanto la versión en VB.NET como C#, lo que puede ser ampliamente beneficioso si prefiere algún lenguaje en particular. Como de costumbre intentaré mostrar ejemplos en los dos lenguajes para que ambos bandos se sientan cubiertos. Pero antes de comenzar es necesario instalar ASP.NET Reports Starter Kit, el que además de esta-


<< dnm.asp.net

Figura 2

tan sólo los conceptos pueden ser utilizados. Esto es así ya que en realidad cada informe está “atado” a una tabla, sus campos y la lógica específica. Le propongo desmenuzar uno de los informes para luego jugar un poco con éste y agregarle algo de código que haga uso de Office Web Components 11.0, esto es, un conjunto de componentes que nos permitirán realzar la presentación Web mediante gráficos tridimensionales.

Desmenuzando el listado jerárquico

Figura 1

Todos ellos representan casos estándares de la programación universal como pueden ser un listado tabular, maestro/detalle, visual empleando un gráfico de tarta 2D, etc. Por supuesto que todo esto sin hacer uso de un solo control de terceros Activex/ensamblado, basado meramente en programación .NET framework. Si se accede a un informe (figura 2) podrá ver una breve explicación sobre su funcionamiento, los controles ASP.NET empleados para su construcción, sus dependencias, etc. Sin lugar a dudas que es un candidato ideal para aprender mucho sobre .NET framework, programación y más. En algunos casos el informe puede ser empleado prácticamente sin cambios, aunque debo admitir que en otros,

El listado jerárquico se compone de tres diferentes DataGrids, aunque solamente uno de ellos es visible inicialmente. El mismo contiene totales de ventas agrupados por zonas (o territorios). A su vez se cuenta con un control combo en la parte superior que hace posible seleccionar un año, lo que refrescará automáticamente al DataGrid inferior. También implementa paginación y como si fuera poco cada uno de los elementos de la lista se exhibe como un hipervínculo (figura 3).

Cuando se hace clic sobre un elemento se muestra un segundo DataGrid a la derecha con los empleados pertenecientes a dicha zona y sus subtotales presumiblemente de ventas. Finalmente si se hace clic en el empleado aparece un tercer DataGrid con la información personal del mismo. Puede seleccionar otra zona lo que hará comenzar con este ciclo nuevamente. Como se puede apreciar, la información es navegada dinámicamente lo que permite al usuario ir más allá del clásico informe estático. Básicamente este informe es un WebForm que cuenta con 3 controles DataGrid, de los cuales 2 son invisibles al comienzo. El primer DataGrid muestra sus elementos como hipervínculos lo que hace que ellos puedan ser seleccionados. Éste se encuentra enlazado al procedimiento almacenado SalesbyTerritory (ventas por territorio) y cuando se produce el clic sobre uno de los valores, el segundo DataGrid es enlazado al procedimiento almacenado GetEmployeeSalesByTerritory (obtener ventas de empleados por territorio) no sin antes utilizar la primera selección como filtro. Lo mismo sucede con el último DataGrid, el que llamará a GetEmployeeById (obtener empleado por identificador) con el parámetro seleccionado en la lista anterior y en la primera. Como vemos el segundo y tercer DataGrid dependen de la selección del inicial para exhibir sus datos. Voy a detenerme un segundo en la técnica que se emplea para el pasaje de información entre ellos, ya que creo que puede ser ampliamente utilizada en varios contextos.

Figura 3

<<dotNetManía

blecer una carpeta para el código fuente, crea una base de datos SQL Server y configura la carpeta virtual para el proyecto Web. Si no cuenta con SQL Server es posible realizar algunos cambios para adaptar este proyecto con el fin de que haga uso de otra base de datos, pero por supuesto esto implica lidiar con el código y entender cómo fue programado. Una vez instalado se habrá creado una base de datos llamada Reports y una carpeta virtual. Es factible abrir el proyecto desde Visual Studio indicando este directorio virtual o acceder directamente a la página de inicio mediante el explorador. Básicamente la página principal permite seleccionar uno de los 8 diferentes tipos de informes (ver figura 1).

15


<< dnm.asp.net <asp:templatecolumn sortexpression="Territory" headertext="Territory Name"> <itemtemplate>

(1)<asp:linkbutton

oncommand="TerritoryGrid_Click" commandname="TerritoryDrill"

(2)commandargument='<%#

DataBinder.Eval(Container, "DataItem.TerritoryDescription") %>'

(3)cssclass="hier" runat="server" id="Territorylnk" (4) text='<%# DataBinder.Eval(Container, "DataItem.TerritoryDescription") %>' </asp:linkbutton> </itemtemplate> <itemstyle width="200px"></itemstyle> </asp:templatecolumn> }

Informes en arquitectura de tres capas Fuente 1

El fuente 1 nos muestra un resumen de la plantilla del primer DataGrid, la misma provee un botón de link (1) lo que hará que el contenido sea exhibido como hipervínculo. A su vez los elementos a mostrar serán el valor del campo de la base de datos TerritoryDescription, y esto se logra mediante la evaluación en tiempo de ejecución ofrecida por la sentencia DataBinder (4). También se provee una hoja de estilo en cascada para mejorar la presentación (3). Sin embargo el punto 2 es el que hace que la “magia” funcione y que se le pase a la segunda lista el valor seleccionado en la primera. CommandArgument es una propiedad en la que es posible especificar cualquier contenido, lo interesante es que el valor incluido aquí será transferido a un argumento del evento clic del DataGrid. Veamos un segundo la línea en cuestión en el fuente 2. commandargument='<%# DataBinder.Eval(Container, "DataItem.TerritoryDescription") %>'

Aunque ésta ha sido la implementación realizada por Microsoft me atrevo a decir que en general es recomendable usar un carácter diferente a la coma (uno que difícilmente se incluya), ya que para el caso que la misma aparezca en la descripción de un territorio se producirá un fallo en la aplicación debido a que la conversión será finalmente errónea.

servidor el valor se obtiene fácilmente como detalla en el fuente 3.

Como mencioné al comienzo del artículo los informes hacen uso de dos características dignas de ser comentadas. Por un lado la lógica de cada informe no está en realidad contenida den-

protected void TerritoryGrid_Click(Object sender, CommandEventArgs e) { // Obtiene el valor del campo seleccionado. string territoryName = e.CommandArgument.ToString().Trim(); ... // Utiliza el valor como filtro del segundo DataGrid ETTableColumn.Visible = true; ETHeader.Text = territoryName; BindList_EmpTerr(territoryName); ... }

Fuente 3

La implementación del tercer DataGrid es similar a lo que ya vimos en el segundo, salvo que en vez de indicarse tan solo un valor se deben pasar 2, esto es, el territorio seleccionado en la primera lista más la selección actual (fuente 4).

tro del formulario Web. En realidad se ha separado el código utilizando clases para representar los diferentes objetos de negocio (funcionalidades). Cada informe invoca su propio conjunto de métodos de clases, las que llevan lógicamente adelante las diferentes opera-

commandargument='<%# (String) DataBinder.Eval(Container, "DataItem.EmployeeName") + ","+ DataBinder.Eval(Container,"DataItem.EmployeeID").ToString() %>'

Fuente 4

<<dotNetManía

Fuente 2

16

En este caso el evento clic recibirá el contenido del campo de la fila seleccionada por el usuario, el que es utilizado para filtrar el segundo DataGrid. Incluso se podría especificar un campo de la base de datos diferente al mostrado en la lista, este es el caso cuando se tiene un código y una descripción y se desea exhibir uno pero filtrar por el otro. En el lado del

En el evento clic es necesario aplicar un pequeño truco para aislar los 2 datos. Como exhibe el fuente 5 esto se logra convirtiendo al resultado en una matriz utilizando de delimitador la coma.

ciones. Esto mejora ampliamente la reutilización ya que hace viable que incluso la interfaz gráfica pueda ser una aplicación de Windows, o lo que es más interesante, exponer esta lógica mediante servicios Web con el fin de que sea

string[] cmdArgs = e.CommandArgument.ToString().Split(','); string employeeName = cmdArgs[0]; int employeeID = Convert.ToInt32(cmdArgs[1]);

Fuente 5


<< dnm.asp.net

Debido a que los informes están siempre orientados a listas de elementos la transferencia de información entre los componentes de negocio se hace utilizando colecciones personalizadas basadas en la clase ArrayList. Esto facilita posteriormente la gestión y pasaje de la información entre métodos de las clases. El fuente 6 nos muestra parte de su implementación. public class HierarchicalReportCollection : ArrayList { public enum HierarchicalReportFields { InitValue, Territory, SalesTotals, EmployeeName } //Sigue...

Fuente 6

A su vez se implementan algunos métodos como ser Sort, el que hace posible ordenar alfabéticamente sus miembros. Sin embargo esta técnica tiene varias ventajas y por supuesto desventajas. La parte buena es que se tiene en todo momento la tecnología intellisense para consultar los campos de la base de datos, los que en realidad son implementados en la colección mediante un enumerado. Adicionalmente colección rima con orientación (a objetos), lo que hace que sea mucho más liviana para el pasaje entre componentes en comparación con un DataSet. Sin embargo el punto oscuro es que si se agrega un nuevo campo a la base

de datos hay que modificar la implementación de la colección y el código si se desea tener acceso al mismo. Recomiendo evaluar en cada caso ventajas y desventajas de aplicar esta técnica.

Bloque de aplicación de acceso a datos Como comenté anteriormente el acceso a datos se realiza empleando procedimientos almacenados y por supuesto ADO.NET. Aquí se utiliza el llamado Bloque de Aplicación de acceso a datos. Básicamente éste es un conjunto de clases orientadas a SQL Server, las que encapsulan llamadas a ADO.NET con el objetivo de brindar una vía más sencilla, rápida y clara de lidiar con una base de datos. A mi criterio utilizar ADO.NET es tedioso, por lo que Microsoft a implementado esta biblioteca para mejorar la expeFigura 4 riencia. Para los curiosos debo decir que se ofrecen los fuentes en C# y Visual Basic .NET incluido en los ejemplos de inicio rápido (Quick Start Samples). Esto permite personalizar cada una de las facetas, aunque en general con lo que se ofrece es más que suficiente. La compilación del proyecto de Bloque de aplicación de acceso a datos produce una biblioteca denominada Microsoft.ApplicationBlocks.Data.dll. Dentro de ésta se incluye una clase principal SqlHelper que ofrece el núcleo de funcionalidades (hay otras pero las dejaremos de lado para no extendernos). A su vez se ofrecen varios métodos estáticos lo que hace posible invocar a varios de sus miembros directamente. He incluido dos pequeños ejemplos de utilización en el fuente 7. //Obtiene un DataSet de una consulta estándarDataSet ds = SqlHelper.ExecuteDataset( "SERVER=MiServidor;DATABASE=Northwind;INTEGRATED SECURITY=sspi;", CommandType.Text, "SELECT * FROM Clientes"); //Obtiene un DataSet invocando a un procedimiento //almacenado con 1 parámetro. DataSet miDataset = SqlHelper.ExecuteDataset(""SERVER=MiServidor;DATABASE=Northwind;INTEGRATED SECURITY=sspi;", "ObtenerCliente", "1133");

Fuente 7

En ADO.NET se necesitarían varias líneas para llevar adelante esta tarea, sin embargo utilizando la clase citada se reduce a una sola línea. Si está interesado en conocer más acerca del bloque le recomiendo que lo baje del sitio de Microsoft (msdn.micro-

<<dotNetManía

consumida por terceros. A su vez el código relacionado con el acceso a datos se comprende dentro de una clase común a toda la aplicación, lo que brinda el beneficio de poder modificar la implementación de conexión al origen de datos y que siempre y cuando se conserve la interfaz (métodos) la aplicación siga funcionando. Seguramente ya sepa de lo que le estoy hablando, de una bonita aplicación en 3 capas (presentación, lógica de negocio y lógica de acceso a datos -se muestran en la figura 4-).

17


<< dnm.asp.net soft.com/library/default.asp?url=/downloads/list/bda.asp). Hemos visto hasta aquí el funcionamiento más que interesante de ASP.NET Reports Starter Kit y sus condimentos. En el próximo apartado aprenderemos cómo añadir al informe jerárquico, un gráfico 3D utilizando los componentes Web de Office 2003.

<<dotNetManía

Utilizando Office Web Components 11.0

18

Un requerimiento común de un informe en estos días es ofrecer algún tipo de gráficos. Cuando se piensa en una aplicación de Windows esto es bastante sencillo ya que hay varias bibliotecas que cumplen este fin, incluso se tienen varios controles ActiveX que pueden brindar una solución sencilla en pocas horas de programación. Proveer la capacidad gráfica a una aplicación Web también puede tenerse sin demasiadas complicaciones si se conocen las herramientas adecuadas. Básicamente existen dos posibles soluciones: la primera es utilizando controles ActiveX o ensamblados a ejecutarse del lado del explorador. Esto ofrece una excelente interactividad y posibilita que el propio usuario pueda interactuar con la gráfica. Sin embargo además de no ser una solución multiplataforma, esta opción puede verse opacada por temas de seguridad, el usuario puede tener una política restrictiva que no le permita ejecutar el control. La segunda solución es crear la gráfica del lado del servidor para luego enviarla al explorador dentro de una página Web. Esta alternativa no es interactiva, aunque se consiguen ciertas características de este tipo escribiendo código script del lado del cliente en conjunto con el servidor. Afortunadamente Microsoft cuenta con un motor de gráficos bastante potente que cubre ambas alternativas llamado Microsoft Web Components y la versión 11 es la más reciente. OWC es la biblioteca que utiliza Microsoft Office 2003 para generar las gráficas, aunque también se pueden hacer muchas, pero muchas cosas más. Vale la pena destacar que no es necesario tener instalado Microsoft Office 2003, es posible bajar e instalar gratuitamente este paquete de

la Web de la siguiente dirección (si tiene el CD de Office podrá encontrar allí esta utilidad): www.microsoft.com/downloads/details.aspx?displaylang=es&FamilyI D=7287252c-402e-4f72-97a5e0fd290d4b76. Tenga presente la ruta de instalación ya que la utilizaremos luego para localizar las ayudas. Ahora bien si hace uso del modo interactivo deberá contar con una licencia de Office en el servidor, pero si por el contrario usa el modo estático esto no es necesario, por lo menos en base a lo que dice la licencia la que podrá leer y evaluar tranquilamente (support.microsoft.com/default.aspx?scid=kb; en-us;555075).

Entendiendo como trabaja OWC 11.0 OWC es una colección de componentes COM que ofrecen clases con sus respectivos métodos, los que pueden ser accedidos desde cualquier aplicación .NET framework. Es viable utilizar los mismos en modo interactivo -como control ActiveX del lado del explorador- o en modo estático, cosa que elegiré ya que nos permitirá crear mediante código de servidor los gráficos que serán insertados en el formulario Web como imagen. Lo primero que debemos hacer una vez bajado e instalado este paquete es agregar una referencia COM en nuestro proyecto de Visual Studio .NET, lo que nos permitirá interactuar con cada una de las facilidades provistas por la biblioteca (figura 5).

siguientes dos líneas será de utilidad para configurar las clases al espacio predeterminado. using OWC11; Imports OWC11

OWC cuenta con varias ayudas y componentes, la tabla 1 muestra los archivos de documentación de las distintas funcionalidades. Antes de escribir una sola línea que haga referencia a OWC he creado un formulario Web vacío que será el encargado de implementar al código que dibujará al gráfico. Este formulario será insertado dentro de la página del informe jerárquico que vimos anteriormente utilizando una etiqueta de IFRAME (si desea compatibilidad con Netscape utilice un marco estándar). Ella permite en forma muy sencilla y modular adicionarle nuevas características a la página del informe, simplemente insertando al nuevo formulario Web dentro del que contiene al informe. <iframe id=MiIframe name=MiIframe frameborder=no runat=server width=90% height=330 src=Grafico3D.aspx> </iframe>

La página que contendrá al gráfico tomará de una variable de sesión los datos a mostrar, por lo que bastará con guardar allí el DataSet para que la serie sea representada automáticamente. Ahora centraremos nuestra atención en la parte programática. Para dibujar un gráfico es necesario crear un objeto de tipo ChartSpaceClass. Esta clase en realidad hace posible contener una o más gráficas; de hecho podríamos tener varios dibujos contenidos en el mismo espacio. La siguiente línea muestra cómo añadir un gráfico al espacio previamente creado. EspacioGráfico.Charts.Add(0)

Figura 5

Dependiendo de si se trata de Visual C# o Visual Basic .NET una de las

El próximo paso es bastante sencillo ya que solamente hay que configurar algunos valores estéticos como el estilo de la gráfica, el fuente del texto a utilizar, el color de borde, etc; todo


<< dnm.asp.net Archivo de ayuda

Descripción

Chart

OWCDCH11.chm

Referencia para tiempo de diseño del componente para creación de gráficas.

PivotTable

OWCDPL11.chm

Referencia para tiempo de diseño del componente de tabla Pivote.

Spreadsheet

OWCDSS11.chm

Referencia de tiempo de diseño del componente de hoja de cálculo.

Spreadsheet

OWCFUN11.chm

Referencia de funciones del componente de hoja de calculo.

DataSource, Chart, Referencia de programación para todos OWCVBA11.chm PivotTable y Spreadsheet los componentes. Tabla1. Resumen de espacios en GDI+

esto interactuando directamente con las propiedades de la clase. Mostraré tan sólo unas pocas líneas para no extenderme en demasía, puede luego si lo desea bajar el código fuente completo y depurarlo paso a paso para analizar el resto de las líneas, aunque le advierto que no se llevará mayores sorpresas (fuente 8).

ción de cómo los datos serán mostrados. Aquí se define la vía en la que se plasmarán la información en colores, tipos de letra, centrado de los valores, etc. (fuente 9). Como último paso es necesario cargar en el gráfico de tarta los valores de la serie a representar. Lamentablemente si bien este control

EspacioGráfico.Border.Color = "white" EspacioGráfico.Charts(0).HasTitle = True EspacioGráfico.Charts(0).Type = ChartChartTypeEnum.chChartTypePie3D EspacioGráfico.Charts(0).Title.Font.Bold = True

Figura 6

Fuente 8

EspacioGráfico.Charts(0).SeriesCollection(0).DataLabelsCollection(0).Font.Name = "verdana" EspacioGráfico.Charts(0).SeriesCollection(0).DataLabelsCollection(0).Font.Size = 10 EspacioGráfico.Charts(0).SeriesCollection(0).DataLabelsCollection(0).Font.Bold = True EspacioGráfico.Charts(0).SeriesCollection(0).DataLabelsCollection(0).Font.Color = "red" EspacioGráfico.Charts(0).SeriesCollection(0).DataLabelsCollection(0).Position = ChartDataLabelPositionEnum.chLabelPositionCenter

Fuente 9

Ahora es necesario establecer una nueva serie que contenga la informa-

niente ya que el informe jerárquico utiliza este medio como fuente de información. Sin embargo se admite una matriz como origen, por lo que he creado una pequeña rutina que convierte el DataSet en un objeto de este tipo. La primera línea establece la matriz conteniendo las categorías (descripciones), mientras que la segunda configura los valores a representar (fuente 10). El enumerado ChartDimensionsEnum indica qué tipo de serie se cargarán en cada caso -descripciones o valores-, mientras el valor chDataLiteral de ChartSpecialDataSourcesEnum especifica que los datos deberán ser tomados del último argumento del método SetData, en este caso la matriz.

es muy flexible no acepta un DataSet como origen de datos, cosa inconve-

Finalmente el gráfico resultante se retorna al formulario Web utilizando la técnica que explicamos en el artículo anterior que se basaba en escribir sobre el objeto de respuesta el binario conteniendo la imagen resultante. La figura 6 nos muestra lo que podemos lograr haciendo uso de ASP.NET Reports Starter Kit y OWC 11. Espero que lo que traté aquí le haya servido para conocer algunas técnicas, trucos, y tecnologías aplicadas a ASP.NET. Por mi parte me despido esperando como siempre vuestros comentarios.

EspacioGráfico.Charts(0).SeriesCollection(0).SetData(OWC11.ChartDimensionsEnum.chDimCategories, Convert.ToInt32(OWC11.ChartSpecialDataSourcesEnum.chDataLiteral), MatrizCategorias) EspacioGráfico.Charts(0).SeriesCollection(0).SetData(OWC11.ChartDimensionsEnum.chDimValues, Convert.ToInt32(OWC11.ChartSpecialDataSourcesEnum.chDataLiteral), MatrizValores)

Fuente 10

<<dotNetManía

Componente

19


Por Yamil Hernández y Miguel Katrib Grupo Weboo Universidad de La Habana

Aspectos e intercepción de métodos en .net o cómo poner la guinda sin estropear el merengue Aspectos e Intercepción

<<

<< 1 2

Con los recursos que brinda .NET, es posible desarrollar mecanismos para interceptar la llamada a un método.Una vez interceptada una llamada se puede entonces tomar el control y ejecutar funcionalidades relacionadas con la ejecución del método, pero que no están incluidas en el código de éste. Este artículo desarrolla y explica tres vías para llevar a cabo esta “intercepción”.Se propone además un patrón de cómo aprovechar la intercepción para, mediante el uso de los atributos de .NET, poder “intercalar” funcionalidad para asociar a la ejecución del método interceptado.Se muestra cómo esta funcionalidad puede expresarse en términos de atributos.Esto sirve de base a lo que se suele llamar “entretejido” de código (weaving) y con ello dar soporte a la aplicación de las ideas de la Programación Orientada a Aspectos (AOP1) en el desarrollo de software sobre .NET.

El sueño de muchos desarrolladores de software se manifiesta en tener un mundo en el que desarrollar aplicaciones se sustente en ensamblar componentes de software que interactúen vía simples llamadas a métodos. Sin embargo, por lo general esto pasa por alto que ciertos aspectos de las aplicaciones suelen afectar a todas las partes de un programa. A la larga los programas tienden a contaminarse con “cachitos”2 de código que intentan lidiar con aquellos aspectos de las aplicaciones que no son el foco central del problema que éstos intentan solucionar. Con frecuencia estos aspectos suelen entrometerse en el código original afectando con ello la aspiración de obtener soluciones reutilizables. Esta es el área que aborda lo que se ha dado en llamar Programación Orientada a Aspectos (AOP)1 al intentar proveer estrategias de reutilización para solucionar los problemas mencionados. Ejemplos tradicionales de estos “aspectos” que pueden estar presentes o no en muchas componentes de software, con independencia del dominio del problema al que están dedicados, son la seguridad, la serialización, la sincronización, la transaccionalidad, etc. De hecho la infraestructura de .NET trae integrada, a través de Visual Studio, los compiladores, la BCL y el CLR, soluciones para estas categorías de aspectos. Lamentablemente no hay aún en .NET un mecanismo directo e integrado para que, de forma simple, los desarrolladores puedan implementar sus propios aspectos personalizados. Sin embargo, .NET sí dispone de tres recursos básicos, que utilizados y desarrollados integradamente, pueden permitirnos dar un soporte para la implantación de estas ideas. Estos tres recursos son la infraes-

Siglas del inglés Aspect Oriented Programming. A ver si aceptamos esta palabra, tan sonora en español, como sustitución del término en inglés snippet.


tructura de intercambio de mensajes, el mecanismo de reflexión y emisión de código que nos permite hacer introspección de un ensamblado y generar dinámicamente código, junto con la capacidad de incrustar metainformación en un ensamblado a través de una novedosa maravilla aportada por .NET (y lamentablemente no lo suficientemente reconocida aún en su verdadera valía) que son los atributos. Consideremos como simple ejemplo una clase C que hace de código servidor de una componente:

Entonces se puede hacer preceder cada llamada a F con el incremento de dicha variable: Global.llamadasaF++; c.F();

Un código cliente de C para invocar a la funcionalidad ofrecida por el método F debe hacer: C c = new C(); ... c.F();

Supongamos que más adelante, por razones de auditoría o evaluación, se desea además contar las veces que esta funcionalidad F es invocada. Esto claro podría lograrse modificando el código de F como se muestra a continuación: class C { static int llamadasaF=0; public void F() { llamadasaF++; ... código original de F } ... }

Pero esta es una solución “invasiva”, del estilo de las que mencionamos que contamina al código existente, ya que obliga a introducir dentro de F un códi-

go que realmente no tiene que ver con la propia funcionalidad de F3. Imagine que queremos aplicar una contabilidad similar a otros métodos. Habría que estar metiendo, en cada uno de ellos, cachitos similares de código. Otra manera de lograr este efecto es “pasarle el problema” al código cliente. Definiendo la variable llamadasaF en algún contexto accesible a todos los que puedan llamar a F: public class Global { public static int llamadasaF=0; ... }

Integrando Intercepción y Atributos La solución que se propone en este artículo para aplicar aspectos en .NET se basa en poder “decorar” un código (el merengue) con determinados atributos personalizados que harán de

Aún cuando se disponga del código fuente de F esto no es una buena práctica porque por este camino podríamos llegar a hacer ilegible la funcionalidad esencial de F, por no decir que al meter las “garras” en el código fuente de F podemos dañar lo que ya funcionaba de F. 4 Que estén juntas pero no revueltas. 3

<<dotNetManía

class C { public void F(){...} ... }

Pero ésta tampoco es una alternativa atractiva porque obliga a hacer modificaciones en el código cliente y en todos los puntos en los que éste haga una llamada a F. Otros intereses similares podríamos plantearnos para relacionar a F con otras funcionalidades, como por ejemplo desplegar un mensaje que indique que se ha llamado a F con el objetivo de llevar una traza de la ejecución, comprobar si se cumple determinada condición antes de permitir la ejecución de F, ejecutar una acción alternativa si durante la ejecución de F se disparó una excepción, etc. Si se considera entonces que la ejecución de un método es una primitiva básica de computabilidad, presente en cualquier sistema de software, entonces es conveniente, para este objetivo de “mezclar funcionalidades”4, poder “interceptar” la llamada a un método de modo de poder incorporar o ejecutar acciones asociadas a dicha llamada. La sección que sigue a continuación ilustra cómo usar en .NET los atributos para, de forma declarativa y no invasiva, expresar estos aspectos e integrarlos a la intercepción de una llamada. En las secciones posteriores se proponen tres vías de cómo se puede lograr esta intercepción en .NET y ejecutar entonces la funcionalidad indicada por los atributos.

21


<< dnm.plataforma.net “aspectos” (las guindas) sin que éstos distorsionen o confundan la comprensión del código original, y en poder interceptar la llamada a un método para aplicar la “funcionalidad” que expresan estos atributos-aspectos. De este modo se aspira a que un código cliente que quiera contar las llamadas al método F de la clase C, le baste con escribir algo como: class C { [CountingCalls] public void F(){...} ... }

Y luego recuperar la cantidad de llamadas a F haciendo CountingCalls.Calls["F"] sin que el conteo de las llamadas a F se entremezcle con el código de F. En las secciones siguientes veremos tres enfoques de cómo interceptar la llamada a un método. Cualquiera que sea el mecanismo de intercepción que apliquemos, consideraremos que en la intercepción se puede disponer de la información necesaria (esto se verá en cada mecanismo) para aplicar el método InterceptionHandler que se describe a continuación: public delegate object MethodCall(object, MethodBase, object[], AspectAttribute[]); class Interceptor { public static MethodCall InterceptionHandler{...} ...

<<dotNetManía

}

22

El tipo delegate MethodCall describe la información asociada con la llamada a un método y a los atributos que hacen de aspectos decorando a dicho método: • El tipo object de retorno indica el resultado a devolver producto de la llamada que ha sido interceptada. Hay que destacar que no necesariamente el valor devuelto será el resultado de ejecutar el método llamado por el código cliente, ya que esto depende de la funcionalidad a intercalar en la intercepción que, de hecho, puede decidir no ejecutar el método llamado sino otro sustituto. Pero lo que sí que no puede alterarse es la devolución al código cliente de un objeto del tipo que él espera. • El primer parámetro, de tipo object, será el objeto receptor de la llamada que está siendo interceptada. Es decir, que si el código cliente hace x.F() entonces el primer parámetro que se le pasa al InterceptionHandler es el objeto valor de x.

• El segundo parámetro, de tipo MethodBase, denota al objeto (Reflection) que describe al método que está siendo llamado. Es decir para una llamada c.F() sería el objeto de tipo MethodBase que describe el método F de la clase C. • El tercer parámetro, de tipo object[], es un array con los parámetros que se han pasado en la llamada que está siendo interceptada. Se aprovecha aquí otra de las grandes ventajas de la infraestructura de .NET porque si hubiese parámetros que fuesen de algún tipo primitivo éstos pueden pasarse transparentemente como de tipo object (es decir, sin mediación del código cliente) gracias al mecanismo de boxing. Será pasado null en el caso en que el método no tenga parámetros. • El cuarto parámetro, de tipo AspectAttribute[], es un array con los atributos aspectos que decoran a dicho método. La clase abstracta AspectAttribute (fuente 1) describe el tipo de atributo que hará de aspecto para ser asociado a una clase o interfaz (decora a dicho tipo) o a un método (decora a dicho método) y que tendrá una funcionalidad con la intercepción de una llamada. Un atributo que decore a una interfaz se interpretará como que decora a todos los métodos de la interfaz.

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, AttributeTargets.Interface Inherited = true) ] public abstract class AspectAttribute: Attribute { public abstract object Action(object target, MethodBase method, object[] parameters, object result); } public abstract class BeforeAttribute: AspectAttribute { } public abstract class AfterAttribute: AspectAttribute { }

Fuente 1

Cada clase concreta que herede de AspectAttribute debe definir en el método Action una acción posible a realizar con la intercepción de una llamada. La idea es que la llamada sea interceptada antes de que el método llamado se ejecute (esto sería lo que en la jerga de la AOP suele ser denominado point cut).


<< dnm.plataforma.net

5

efecto sea posterior a la ejecución del método llamado). public static object InterceptionHandler(object targetObject, MethodBase method, object[] parameters, AspectAttribute[] attributes) { foreach (AspectAttribute b in attributes) if (b is BeforeAttribute) b.Action(targetObject, method, parameters, null); object returnValue = targetObject.GetType().GetMethod ( method.Name, GetParameterTypes(method) ).Invoke(targetObject,parameters); //Una acción After puede necesitar del resultado de haber evaluado el //método por eso se le pasa returnValue foreach (AspectAttribute a in attributes) if (a is AfterAttribute) a.Action(targetObject, method, parameters, returnValue); return returnValue; }

Fuente 2

El mecanismo de reflexión de .NET no recupera necesariamente los atributos en el orden en que éstos están incluidos en el código fuente. De modo que en este caso el orden en que se ejecutan entre sí los diferentes atributos Before y After es no determinista. Es el programador el responsable de

public class CountingCalls: BeforeAttribute { static Dictionary calls; public override object Action(object targetObject, MethodBase targetMethod, object[] parameters, object result) { if (calls == null) calls = new Dictionary(); if (calls[targetMethod.Name] == null) calls[targetMethod.Name] == 1; else calls[targetMethod.Name] = ((int)calls[targetMethod.Name])+1; } public static int Calls[string methodName] { get { if (calls == null) return 0; else if (calls[methodName] == null) return 0; else return (int)calls[methodName]; } } }

Esto dependerá de cómo se implemente el mecanismo de intercepción.

Fuente 3

<<dotNetManía

La(s) acción(es) a “intercalar” estará(n) definida(s) en el método Action de los atributos que decoren al método (esto sería lo que en la jerga de la AOP suele ser denominado advice). Pero esto no quiere decir que la forma de “entretejer” esta acción con la llamada (lo que en la jerga de la AOP se denomina weaving) sea ejecutarla antes de ejecutar la llamada. Es la implementación del InterceptionHandler la que decidirá cómo, cuándo y cuáles Action de cuáles atributos (porque un método puede estar decorado con varios) “entretejerá” con la llamada. Así podemos, entre otros, tener un atributo que especifique una acción para: • Ejecutar antes de ejecutar el método llamado. • Ejecutar después de ejecutar el método llamado. • Que pueda servir de precondición para poder ejecutar el método llamado. • Ejecutar en sustitución del método llamado. • Ejecutar en el caso de que la ejecución del método llamado dispare una excepción. • Ejecutar en el caso de que la ejecución del método llamado haya sobrepasado un timeout. • Transformar el resultado devuelto por el método llamado. • Deshacer la acción del método llamado. Por razones de espacio en este artículo sólo consideraremos los dos primeros casos, es decir, atributos que describen acciones para ejecutar antes y atributos que describen acciones para ejecutar después de ejecutar el método llamado (ver en el fuente 1 los tipos BeforeAttribute y AfterAttribute que heredan de AspectAttribute). Lo que se pretende5 es que el manejador de la intercepción (InterceptionHandler) aplique la acción descrita por un atributo Before antes de ejecutar el método decorado por dicho atributo y que aplique la acción descrita por un atributo After después de ejecutar el método. Para esto el InterceptionHandler evalúa los métodos Action de los atributos Before, luego ejecuta el método llamado y a continuación evalúa los métodos Action de los atributos After que decoran al método llamado (el fuente 2 muestra la implementación de éste). Toda excepción en la ejecución de un método Action será considerada como una excepción en la ejecución del método llamado y reportada por tanto al código cliente que ha realizado la llamada. Los diferentes parámetros que se pasan al método Action son: • target, objeto receptor de la llamada interceptada. • method, objeto que describe (Reflection) el método llamado. • parameters, array con todos los parámetros pasados en la llamada interceptada. • result, resultado de la evaluación de la llamada (para poder ser utilizado por una acción cuyo

23


<< dnm.plataforma.net no basar la lógica de su aplicación en un determinado orden6. El fuente 3 muestra cómo se podría definir un atributo CountingCalls para intercalar la funcionalidad de nuestro ejemplo que pretende contar las veces que se llama a un método. Como hay que poder distinguir entre los distintos métodos, hay que tener un contador de llamadas por cada método que se decore con este atributo. Esto se controlará en la propia semántica del atributo. Por ello se incluye un diccionario global (static Dictionary calls) con una entrada por cada método. Note que la funcionalidad del método F es independiente de la funcionalidad del aspecto CountingCalls que se le quiere asociar y que la implementación del atributo no disturba la implementación de la clase. Incluso si el código cliente de C no usase el mecanismo de intercepción entonces el atributo CountingCalls es inocuo y no incide en la ejecución de una llamada. Esto se corresponde a lo que en la jerga de la AOP se le conoce como separación de incumbencias (concerns). Para completar la descripción del mecanismo propuesto es necesario proponer un patrón de cómo decorar el código con los aspectos y cómo lograr la intercepción. Las tres secciones a continuación describen diferentes soluciones para lograr esto.

public class Interceptor: RealProxy { object targetObject; Type interfaceType; MethodBase interceptedMethod; private Interceptor(Type t):base(t){} public static object Create(object targetObject, Type interfaceType) { Interceptor newobject = new Interceptor(interfaceType); newobject.targetObject = targetObject; newobject.interfaceType = interfaceType; return newobject.GetTransparentProxy(); } public static object Create(object targetObject) { MarshalByRefObject marshalTarget = (targetObject as MarshalByRefObject); if (marshalTarget == null) { throw new Exception("El tipo del parámetro \" targetObject \" no es MarsalByRefObject"); } else { Interceptor newobject = new Interceptor(targetObject.GetType()); newobject.targetObject = targetObject; return newobject.GetTransparentProxy(); } } public override IMessage Invoke(IMessage msg) { AspectAttribute[] aspectAttributes;

<<dotNetManía

Intercepción basada en proxies de .NET

24

El .NET CLR provee una rica arquitectura (namespace System.Runtime.Remoting) para modelar las invocaciones a métodos como intercambio de mensajes. La clave para comprender dicha arquitectura está en examinar qué es lo que hace el CLR cuando ejecuta una llamada a un método. El CLR se basa en una máquina con memoria de pila (stack) y en que ejecutar un método es esencialmente provocar una transformación en esa memoria de pila7. El código IL al que queda traducida una llamada a un método pone los parámetros correspondientes en la pila (uno de estos parámetros es el objeto receptor de la llamada) y pasa el control al código del método que se encarga de procesar esos parámetros y reescribir la pila para indicar en ella los resultados de procesar el método. En esta arquitectura del System.Runtime. Remoting, .NET ofrece medios para interceptar una llamada y poder trabajar con el contenido de la pila interpretando éste como un mensaje, lo cual nos permitirá en nuestro caso invocar a nuestro manipulador de intercepción y pasarle la información adecuada para nuestro propósito de aplicación de aspectos. Explicar esta arquitectura en toda su complejidad se 6

7

IMethodCallMessage methodMessage = msg as IMethodCallMessage; interceptedMethod = methodMessage.MethodBase; if (interfaceType != null) aspectAttributes = Helper.AspectUnion( (AspectAttribute[])interfaceType.GetCustomAttributes( typeof(AspectAttribute),true), (AspectAttribute[])interceptedMethod.GetCustomAttributes( typeof(AspectAttribute),true)); else aspectAttributes = (AspectAttribute[])interceptedMethod. GetCustomAttributes(typeof(AspectAttribute), true); object returnValue = InterceptionHandler(targetObject, interceptedMethod, methodMessage.Args, aspectAttributes); ReturnMessage returnMessage = new ReturnMessage(returnValue, methodMessage.Args, methodMessage.ArgCount, methodMessage.LogicalCallContext, methodMessage); return returnMessage; } ... }

Ciertamente se podría incluir algún mecanismo de prioridades en la definición de los propios atributos pero para mantener la simplicidad esto no se ha incluido aquí. De hecho los puristas de la programación funcional reducen a esto la definición de una función (método).

Fuente 4


<< dnm.plataforma.net lo que si se quiere interceptar la llamada entonces hay que evitar que esto ocurra. Para ello el mecanismo de intercepción exige que el tipo del objeto receptor implemente una interfaz para que sea a través de la cual que el código cliente invoque al método10. Tenemos entonces que para lograr la intercepción del método F de la clase C de nuestro ejemplo, la clase debe estar definida de la forma siguiente: interface IC { void F(); } class C: IC { public void F(){...} }

El patrón a seguir para lograr la intercepción es crear los objetos de la forma siguiente: IC c = (IC)Interceptor.Create(new C(), typeof(IC));

El .NET CLR provee una rica arquitectura para modelar las invocaciones a métodos como intercambio de mensajes. La clave para comprender dicha arquitectura está en examinar qué es lo que hace el CLR cuando ejecuta una llamada a un método del objeto original. De este modo será el proxy el que se encargará de hacer la intercepción. Para lograr interceptar lo que sería una llamada en el código fuente hay que lograr que ésta realmente exista en el código IL generado. Muchos compiladores .NET convierten, cuando pueden, una llamada a un método en la aplicación inline del código del método, por 8

9 10

Hay otra forma de lograr esto sin exigir que C implemente una interfaz. Para ello la clase C debe heredar del tipo MarshalByRefObject: class C: MarshalByRefObject { public void F(){...} }

Y entonces hacer: C c = (C)Interceptor.Create(new C());

Veamos la implementación del método Create(object, Type) (fuente 4) para ilustrar cómo se ha utilizado aquí el mecanismo ofrecido por .NET. Este método crea un objeto de tipo Interceptor a cuyo constructor le pasa como parámetro el tipo Interface . El tipo Interceptor lo hemos definido como derivado de la clase .NET RealProxy cuyo constructor (llamada a base(interfaceType) en el fuente 4) debe recibir un parámetro de tipo Type pero que sea tipo interfaz (o MarshalByRefObject). Note que en la clase Interceptor tenemos también una variable targetObject en la que guardamos el objeto original para el que se está construyendo el proxy. La clase .NET RealProxy tiene un método GetTransparentProxy que devuelve un TransparentProxy. Para el CLR el TransparentProxy puede verse como si fuese del mismo tipo del tipo que le fue pasado al constructor del RealProxy. Por ello es correcta la operación de casting que hace el cliente cuando escribe: IC c = (IC)Interceptor.Create(new C(), typeof(IC))

Un TransparentProxy es un objeto muy especial de esta maquinaria de .NET que transforma una llamada a un método en un intercambio de mensajes de la máquina de pila (estos mensajes se describen con el tipo IMessage). Pero el TransparentProxy mantiene un nexo con el RealProxy a través del cual fue creado, de modo que cuando en el código cliente se hace c.F() el CLR llama al método Invoke al que le pasa como parámetro un objeto msg de tipo IMessage (que contiene el contenido de la pila que describe la llamada original y sus parámetros). Esta es la clave (simplificada) del mecanismo que ofrece .NET para rea-

Muchas de las herramientas de desarrollo .NET (Visual Studio .NET como su principal exponente) hacen un gran uso de proxies para hacer más transparente y simple el trabajo de programación. Factory Pattern. Todos los métodos que implementen una interfaz son invocados realmente a través de la tabla de métodos virtuales y una llamada a estos no se sustituye entonces por código inline.

<<dotNetManía

sale del alcance de este artículo (el lector puede ampliar con la propia documentación de MSDN o en [2][3][4]) por lo que en lo que resta de esta sección nos limitaremos a presentar simplificadamente sólo algunos elementos de interés para nuestro propósito. Para realizar la intercepción nos basaremos en que entre el código cliente y el objeto receptor de la llamada va a haber un objeto intermediario (proxy). Lo que pretenderemos es hacer lo más transparente posible, para el código cliente, la participación de un tal proxy8 en la comunicación del código cliente con el objeto servidor, receptor de una llamada. La clase Interceptor es la que describe este trabajo de crear y colocar el proxy. En Interceptor (fuente 4) tenemos dos métodos estáticos Create que servirán de patrón factoría9 para la creación de un objeto que sirva de proxy a un objeto receptor, de tal modo que el código cliente pueda invocar a los métodos del objeto receptor a través del proxy, pero de la misma forma (sintaxis) con la que lo haría a través

25


<< dnm.plataforma.net lizar la intercepción de una llamada. Lo que resta ahora es redefinir el método Invoke (que es abstracto en la clase RealProxy) para personalizar lo que queremos hacer luego de haber interceptado la llamada. Note (fuente 4) que al hacer msg.args el método Invoke extrae del mensaje msg, que le ha pasado el CLR, los argumentos con los que el código cliente llamó al método. Para "recrear" la llamada original se necesitaría el objeto receptor de la llamada ya que es el TransparentProxy el que está ocupando su lugar. Hay que notar que no es el mecanismo de .NET el que se ocupa de conservar el objeto original. Es nuestro método Create el que en el momento de la creación del objeto Interceptor se ha cuidado de guardar el objeto original (variable targetObject) para luego poderlo utilizar dentro de la implementación de Invoke. A partir del objeto MethodBase, que se extrae del mensaje msg, se pueden obtener los atributos que sean aspectos (su tipo es algún subtipo de la clase AspectAttribute). Con toda la información anterior el método Invoke llama al InterceptionHandler. Luego se conforma el mensaje de retorno (ReturnMessage). Es este ReturnMessage el que el CLR retorna a través del TransparentProxy, al código cliente que hizo la llamada original .

se Interceptable podría ser la vía para colocar la estrategia a aplicar al hacer la intercepción. Lamentablemente .NET no ofrece algo similar. La segunda vía basada en contextos, que exploraremos a continuación, intenta lograr algo parecido a esto.

[AttributeUsage(AttributeTargets.Class|AttributeTargets.Interface| AttributeTargets.Struct, Inherited = true)] public class Interceptable : ProxyAttribute { class InterceptingProxy : RealProxy { private MarshalByRefObject target; private Type targetType; private object returnValue; private object targetObject; private MethodBase method; private object[] args; public InterceptingProxy(MarshalByRefObject target, Type t): base(t) { this.target = target; } public override IMessage Invoke(IMessage msg) { IMethodCallMessage methodMsg = msg as IMethodCallMessage; if( methodMsg is IConstructionCallMessage ) { targetType = methodMsg.MethodBase.DeclaringType; targetObject = System.Runtime.Serialization.FormatterServices. GetUninitializedObject(targetType); method = methodMsg.MethodBase; args = methodMsg.Args; RealProxy rp = RemotingServices.GetRealProxy(target); rp.InitializeServerObject((IConstructionCallMessage)methodMsg); MarshalByRefObject tp = (MarshalByRefObject) this.GetTransparentProxy(); IMessage ctorRetMsg = EnterpriseServicesHelper. CreateConstructionReturnMessage( (IConstructionCallMessage)methodMsg,tp); return(ctorRetMsg); } else { newMsg = methodMsg as MethodMessage; args = newMsg.Args; method= newMsg.MethodBase; returnValue = InterceptionHandler( targetObject, method, args, (AspectAttribute[])method.GetCustomAttributes( typeof(AspectAttribute),true) ); return new ReturnMessage(returnValue, methodMessage.Args, methodMessage.ArgCount, methodMessage.LogicalCallContext, methodMessage); }

Intercepción basada en contextos Un inconveniente del mecanismo de intercepción anterior es que exige que el objeto a interceptar tenga que crearse con alguno de los dos patrones factoría, es decir: C c = (C)Interceptor.Create(new C());

o IC c = (IC)Interceptor.Create(new C(), typeof(IC));

Hubiese sido más transparente si .NET dispusiese también de alguna suerte de atributo Interceptable de modo que si se decora una clase C en la forma: [Interceptable] class C { ... }

} public override MarshalByRefObject CreateInstance(Type t) { MarshalByRefObject target = base.CreateInstance(t); RealProxy rp = new InterceptingProxy(target, t); return (MarshalByRefObject)rp.GetTransparentProxy(); }

Entonces el código cliente puede crear los objetos de tipo C en la forma tradicional de:

<<dotNetManía

C c = new C();

26

Con la garantía de que las llamadas a través de C serían interceptadas. En tal caso la implementación de un método como Invoke dentro de la cla-

}

Fuente 5


<< dnm.plataforma.net .NET ofrece la clase ContextBoundObject para crear objetos que tienen un contexto asociado. Si una clase C que herede de ContextBoundObject se decora con un atributo derivado de ProxyAttribute (digamos InterceptableAttribute): [Interceptable] class C: ContextBoundObject { public void F(){...} }

Entonces el CLR intercepta la ejecución del operador new cuando se van a crear objetos de tipo C, es decir al ejecutar el código IL .ctor correspondiente al código cliente new C(). En este caso el CLR invoca en su lugar al método: public virtual MarshalByRefObject CreateInstance(Type targetType); Figura 1

Intercepción con proxy generado al vuelo (vía Reflection y Emit) Las dos soluciones de las secciones anteriores tienen cierta carga de ineficiencia porque se basan en que las llamadas se tratan vía mensajes. Además como ambas soluciones se aplican para objetos creados con el mecanismo de mensajes remotos entonces esto implica que todas las llamadas a métodos a través de esos objetos serán tratadas por mensajes, independientemente de que el método no esté decorado con ningún atributo de

aspecto y que por tanto no nos interesa interceptar. Esto podría ser aceptable cuando de todos modos, por otros intereses de la aplicación original, el objeto receptor (servidor) tenga que ser remoto, pero no cuando pretendemos interceptar objetos que podrían ser locales. En esta sección exploraremos una alternativa basada en generar un tipo Proxy al vuelo (on the fly). Es decir, generar un tipo dinámicamente (durante la ejecución) cuyas instancias nos harán de intermediarios entre el código cliente y el código servidor. Serán las llamadas a través de estos intermediarios las que serán interceptadas. La infraestructura de Reflection del .NET Framework ofrece un poderoso mecanismo de introspección que permite obtener información de los objetos. Haciendo uso de esta información, es posible que un código pueda generar nuevos tipos durante la propia ejecución de dicho código. Esto se logra utilizando los recursos del System.Reflection y System.Reflection.Emit (esto fue tratado también en un artículo anterior de dotNetManía [5]).

En esta nueva variante no será el CLR quien interprete las llamadas como intercambio de mensajes, sino que a partir de un objeto original se generará dinámicamente un tipo Proxy, se creará un objeto de dicho tipo Proxy y si se sustituye en el código cliente al objeto original por el Proxy; entonces éste será el encargado de interceptar una llamada y llamar al InterceptionHandler (figura 1). El código cliente debe entonces crear los objetos en la forma: IC c = (IC)Interceptor.Create(new C(), typeof(IC));

En este caso el método factoría Interceptor.Create(object targetObject, Type interfaceType) crea el tipo Proxy y genera un objeto

creado a partir de este tipo, el cuál hará de intermediario con el objeto targetObject. El tipo generado implementará el tipo interfaceType. En el tipo generado se emite un método por cada uno de los métodos existentes en el interfaceType (verificando que tengan una implementación concreta en el tipo del objeto targetObject). Note que la ventaja es que esto no exige que el tipo del objeto

<<dotNetManía

De la clase ProxyAttribute. Redefiniendo entonces adecuadamente este método en la clase Interceptable podemos colocar un TransparentProxy en lugar del objeto de tipo C y este TransparentProxy sería el que el CLR le entrega al código cliente que hizo el new. A partir de aquí estamos en situación de seguir una estrategia similar (fuente 5) a la de la sección anterior, pero con la comodidad de que el código cliente sigue creando los objetos con la notación new C(), en lugar de con el patrón factoría como en la sección anterior.

27


<< dnm.plataforma.net targetObject haya sido definido como que explícitamente implementa el tipo interfaceType, sino sólo

que tenga una implementación por cada método de la misma signatura existente en interfaceType. Esta solución nos permite entonces decorar con aspectos a una clase C ya existente y compilada a una DLL (de la cual no tenemos ni que disponer del fuente) que en el momento de su definición no se pensó con este propósito. Esto se logra siguiendo los pasos siguientes: class C { public void F(){...} ... }

Esta segunda llamada a Interceptor.Create no debe duplicar la creación de un mismo tipo dinámico que asocie al tipo C con el tipo IC. Para ello el método EmitProxyType comprueba si no ha creado previamente tal tipo. EmitProxyType emitirá entonces un método por cada método existente en el tipo interfaz (parámetro interfaceType), comprobando que exista uno de igual signatura en el tipo del objeto targetType). De este modo, por cada llamada del tipo pc1.F() en el código cliente se estará llamando al correspondiente método generado en el tipo Proxy. El código del método correspondiente en el Proxy es el que se encarga, durante su ejecución, de colocar en la pila la información necesaria para invocar al delegate InterceptionHandler. Note que la línea del código emitido con:

Se escribe ahora una interfaz que corresponda con C que es la que se decora con aspectos: interface IC { [CountingCalls] void F(); }

Y entonces el código cliente puede crear sus objetos a interceptar haciendo:

il.EmitCall(OpCodes.Callvirt, typeof(MethodCall).GetMethod("Invoke"), null);

Es la que hará la llamada al método Invoke correspondiente al InterceptionHandler (el Invoke es el método que ejecutan los delegates). El resultado que quedará en la pila al ejecutarse este Invoke es el que a su vez se retornará al código cliente.

IC c = (IC)Interceptor(new C(), typeof(IC));

<<dotNetManía

Vea la implementación de Interceptor en el fuente 6. El método Create llama a EmitProxyType(targetObject.GetType(), interfaceType) que emitirá dinámicamente el tipo Proxy (en el que se guardará la referencia al objeto receptor original targetObject)11. Luego usando el método de reflection de .NET Activator.CreateInstance se crea una instancia Proxy de este tipo generado, pasándole como parámetros para su construcción el objeto targetObject y el tipo interfaz interfaceType . El método Activator.CreateInstance recibe un tipo y un array de objetos object[] y crea una instancia de dicho tipo seleccionando entre los constructores de éste, aquél que reciba como parámetros los que se indican en el object[] (por razones de espacio se ha omitido del fuente 6 la emisión del constructor). Note que si el código cliente hace:

28

C c1 = new C(); IC pc1 = (IC)Interceptor.Create(c1, typeof(IC)); ... C c2 = new C(); IC pc2 = (IC)Interceptor.Create(c2, typeof(IC));

11

public class Interceptor{ . . . public static object Create(object targetObject, Type interfaceType) { Type proxyType = EmitProxyType( targetObject.GetType(), interfaceType); return Activator.CreateInstance(proxyType, new object[] { targetObject, interfaceType }); } private static Type EmitProxyType(Type targetType, Type interfaceType) { createBuilders(assemblyName, moduleName, access); Type type = modBuilder.GetType(asmBuilder.GetName().Name + ".__Proxy" + interfaceType.Name + targetType.Name); if (type == null) { typeBuilder = modBuilder.DefineType(asmBuilder.GetName().Name + ".__Proxy" + interfaceType.Name + targetType.Name,TypeAttributes.Class | TypeAttributes.Public, targetType.BaseType, new Type[] {interfaceType, typeof (IEmitedInfo)}); fbTarget = typeBuilder.DefineField("target", baseInterface, FieldAttributes.Private); fbIface = typeBuilder.DefineField("iface", typeof(Type), FieldAttributes.Private); EmitCtor(typeBuilder,fbTarget,fbIface); MethodInfo[] methods = interfaceType.GetMethods(); foreach (MethodInfo m in methods) EmitProxyMethod(m, typeBuilder); Type[] ifaces = targetType.GetInterfaces(); foreach (Type iface in ifaces)

Esto está inspirado en una idea similar a la que utilizamos en un artículo anterior de dotNetManía [5].

Fuente 6 (sigue...)


<< dnm.plataforma.net { typeBuilder.AddInterfaceImplementation(iface); EmitMethod(iface, typeBuilder); } type = typeBuilder.CreateType(); } return type; } protected static void EmitMethod(Type interf, TypeBuilder proxyBuilder) { MethodInfo[] methods = interf.GetMethods(); foreach (MethodInfo method in methods) { Type[] argsTypes = MethodHelper.GetParameterTypes(method); MethodInfo coreMethod = fbTarget.FieldType.GetMethod(method.Name, argsTypes); MethodBuilder methodBuilder = proxyBuilder.DefineMethod(method.Name, MethodAttributes.Public | MethodAttributes.Virtual, method.ReturnType, argsTypes); ILGenerator il = methodBuilder.GetILGenerator(); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldfld, fbTarget); for (int i = 0; i < argsTypes.Length; i++) il.Emit(OpCodes.Ldarg, i+1); OpCode callCode = OpCodes.Call; if (coreMethod.IsVirtual) callCode = OpCodes.Callvirt; il.EmitCall(callCode, coreMethod, null); il.Emit(OpCodes.Ret); } } public static void EmitProxyMethod(MethodInfo m, TypeBuilder builder) { Type[] paramTypes = Helper.GetParameterTypes(m); MethodBuilder mb = builder.DefineMethod(m.Name, MethodAttributes.Public | MethodAttributes.Virtual, m.ReturnType, paramTypes);

//InterceptionHandler) pues el GetCurrentMethod devuelve //su equivalente en el Proxy. il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldfld, (FieldInfo)fbTarget); il.EmitCall(OpCodes.Call, typeof(object).GetMethod("GetType")); il.EmitCall(OpCodes.Call, typeof(MethodBase). GetMethod("GetCurrentMethod"), null); //Segundo parámetro InterceptionHandler: MethodBase method il.EmitCall(OpCodes.Call, typeof(Helper).GetMethod("GetMethodFromType"), null); //Tercer parámetro InterceptionHandler: object[] parameters il.Emit(OpCodes.Ldloc,parameters); //Poner en la pila el método en la interface equivalente al //que devuelve GetCurrentMethod del Proxy para extraerle los //AspectAttributes. il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldfld, (FieldInfo)fbIface); il.EmitCall(OpCodes.Call, typeof(MethodBase).GetMethod("GetCurrentMethod"), null); il.EmitCall(OpCodes.Call, typeof(Helper).GetMethod("GetMethodFromType"), null); //Poner en la pila los parámetros del GetCustomAttributes //Primer parámetro: Type attributeType il.Emit(OpCodes.Ldtoken,typeof(AspectAttribute)); il.Emit(OpCodes.Call, typeof(Type).GetMethod("GetTypeFromHandle")); //Segundo parámetro: bool inherit il.Emit(OpCodes.Ldc_I4,1); il.EmitCall(OpCodes.Callvirt, typeof(MethodInfo).GetMethod("GetCustomAttributes", new Type[] { typeof(Type), typeof (bool) }), null); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldfld, (FieldInfo)fbIface); //Primer parámetro: Type attributeType il.Emit(OpCodes.Ldtoken,typeof(AspectAttribute)); il.Emit(OpCodes.Call, typeof(Type).GetMethod("GetTypeFromHandle"));

ILGenerator il = mb.GetILGenerator();

il.Emit(OpCodes.Ldc_I4, paramTypes.Length); il.Emit(OpCodes.Newarr, typeof(object)); il.Emit(OpCodes.Stloc, parameters); for (int i=0; i<paramTypes.Length; i++) { il.Emit(OpCodes.Ldloc,parameters); il.Emit(OpCodes.Ldc_I4, i); il.Emit(OpCodes.Ldarg, i+1); if (paramTypes[i].IsValueType) il.Emit(OpCodes.Box, paramTypes[i]); il.Emit(OpCodes.Stelem_Ref); } //Poner en la pila el InterceptionHandler y //sus respectivos parámetros. il.EmitCall(OpCodes.Callvirt, typeof(Interceptor).GetProperty("InterceptionHandler"). GetGetMethod(),null); //Primer parámetro InterceptionHandler: object targetObject il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldfld, (FieldInfo)fbTarget); //Obtener el método en el objeto original(parámetro para el

//Segundo parámetro: bool inherit il.Emit(OpCodes.Ldc_I4,1); il.EmitCall(OpCodes.Callvirt, typeof(Type).GetMethod("GetCustomAttributes", new Type[] { typeof(Type), typeof (bool) }), null); //Cuarto parámetro del InterceptionHandler: AspectAttribute[] aspects il.EmitCall(OpCodes.Callvirt, typeof(Helper).GetMethod("AspectUnion"), null); //Invocar al InterceptionHandler il.EmitCall(OpCodes.Callvirt, typeof(MethodCall).GetMethod("Invoke"),null); //Dejar en la pila el valor del retorno de forma adecuada if (m.ReturnType == typeof(void)) il.Emit(OpCodes.Pop); else if (m.ReturnType.IsValueType) { il.Emit(OpCodes.Unbox, m.ReturnType); il.Emit(OpCodes.Ldind_Ref); } il.Emit(OpCodes.Ret); } ... }

(continuación...) Fuente 6

<<dotNetManía

//Convertir los parámetros del método en un object[] LocalBuilder parameters = il.DeclareLocal(typeof(object[]));

29


<< dnm.plataforma.net

Las propuestas de intercepción que se han analizado se han dedicado a la intercepción de “grano fino”,es decir,a interceptar a nivel de código IL y CLR

<<dotNetManía

Conclusiones

30

En [6] se describe una alternativa para incorporar aspectos en .NET basada en el uso de contextos e intercambio de mensajes. Esta alternativa exige que el código cliente conozca cómo funciona esta infraestructura de intercambio de mensajes. En dicho artículo cada uno de los atributos que se definan para usar con objetivo de aspecto tiene que “repetir” un mismo patrón en su implementación, lo cual es, en cierto modo, una paradoja porque esto mismo es parte de lo que la AOP pretende evitar. La estrategia propuesta en el presente trabajo es más genérica porque pretende independizar, la forma de definir y usar los atributos que harán de aspectos, del mecanismo de intercepción utilizado. Desafortunadamente, la infraestructura de contextos y de proxies reales y proxies transparentes no está aún ampliamente documentada en .NET. Uno de los objetivos de los dos primeros modos de intercepción que expusimos en este artículo ha sido el de simplificar y ejemplificar el uso de esta infraestructura de .NET. Hay otros enfoques (ver por ejemplo [7]) que se basan en usar preprocesadores, o herramientas adicionales, o depender de que se implementen nuevos compiladores para colocar e implementar los aspectos que hagan el “entretejido” de código. Sin embargo, uno de los objetivos de las soluciones que hemos propuesto en este trabajo, ha sido el de basarse en los propios recursos existentes en .NET y en proponer un patrón de cómo utilizarlos. Las dos primeras estrategias presentadas tienen un costo adicional en eficiencia porque se basan en el mecanismo de .NET remoting lo que implica que las llamadas a cualquier método a través de esos objetos serán tratadas por mensajes, independientemente de que el método en particular no esté decorado con ningún atributo-aspecto. Por otra parte la primera solución, que estuvo basada en proxies de .NET, obliga a que el tipo del objeto a interceptar tenga que implementar una interfaz, para luego tratar al objeto a través de dicha interfaz. De modo que no podría ser aplicable a un tipo que ya estuviese definido y que no indicase que implemente una interfaz. La segunda solución, la basada en contextos, exige que el tipo de los objetos a interceptarle las llamadas ten-

ga que ser un tipo que herede de ContextBoundObject. De modo que tampoco podría ser aplicable a un tipo ya definido y que no herede de ContextBoundObject. Como además en .NET no hay herencia múltiple tampoco podría ser aplicable a un tipo que quisiéramos que heredase de alguna otra clase. La tercera alternativa de lograr el equivalente a la “intercepción” se basó en la generación dinámica de un tipo que emule al original. Con esta alternativa se puede lograr, no sólo una variante más eficiente de intercepción, sino más viable si pretendemos poner aspectos a los métodos de una clase ya existente. En otras palabras, mezclar sin revolver o poner sin estropear. Las propuestas de intercepción que se han analizado se han dedicado a la intercepción de “grano fino”, es decir, a interceptar a nivel de código IL y CLR. Otra concepción de intercepción de “grano grueso”, por ejemplo a nivel de servicios web, también podría ser considerada pero ése no ha sido el caso que pretende ilustrar este trabajo. Por razones de espacio, y para simplificar la comprensión, sólo se ha mostrado el patrón de “entretejido” más común: poner acciones a aplicar antes de ejecutar el método llamado y acciones a aplicar después de ejecutar el método llamado. Una derivación interesante de esta propuesta es usar atributos e intercepción para poder intercalar, en un tipo y sus métodos, precondiciones, postcondiciones e invariantes, dando con ello soporte en .NET a la metodología conocida como Programación por Contratos. Esto será objeto de un futuro artículo de dotNetManía. Se pueden desarrollar otros patrones de entretejido de funcionalidades (algunos se mencionaron en este trabajo) basados en las soluciones propuestas. Esperamos que algún lector interesado se nos una a ello.

Bibliografía [1]Gregor Kiczales and others, Aspect Oriented Programming, Springer Verlag, Proceedings of ECOOP 1997 [2]Don Box, Chris Sells Essential .NET: The Common Language Runtime, Addison-Wesley 2003 [3] Juval Löwy, Programming .NET Components, O'Reilly 2003 [4] Tom Barnaby, Jason Bock, Applied .NET Attributes, APress 2003 [5] Mario del Valle, Miguel Katrib, El poder de la reflexión en .NET, dotNetManía No 3, Abril 2004 [6] Drama Shukla, Simon Fell, Chriss Sells AspectOriented Programming Enables Better Code Encapsulation and Reuse¸MSDN Mag, March 2003. [7] Vladimir Safonov, Aspect.NET: Concepts and Architecture, .NET Developer's Journal, October 2004.


Por Antonio Soto Technical Account Manager Alcatraz Solutions

Verificando la seguridad de nuestras aplicaciones El desarrollo de aplicaciones seguras es un proceso realmente complejo, y que en la mayor parte de las aplicaciones no se tiene en cuenta en su conjunto. Los programadores estábamos acostumbrados, hasta no hace no mucho tiempo, a no pensar en esto, y dejar los temas de la seguridad en mano de los administradores de sistemas. Sin embargo, cada vez son más los agujeros de seguridad que explotan los códigos maliciosos, ocasionados por malas prácticas de programación. En este artículo se describe la utilización de una herramienta, Microsoft Application Verifier, que puede ser un buen primer paso para el testeo de la seguridad de nuestras aplicaciones.

<< dotNetManía

<< Hace un par de meses recibimos el encargo de anali-

32

zar la aplicación de un cliente desde el punto de vista de la seguridad. Lo primero que se me vino a la cabeza fue intentar buscar alguna herramienta que nos permitiese automatizar tests de prueba de la aplicación, en busca de agujeros de seguridad. Cuál fue mi sorpresa cuando encontré que la propia Microsoft dispone de una herramienta que nos permite hace un primer análisis de las operaciones que realiza una aplicación para averiguar si es posible que alguna de esas operaciones sea explotada malintencionadamente. Dicha herramienta es Windows Application Verifier (que ya va por su versión 2.5 y que el equipo de desarrollo promete continuar mejorando, sobre todo desde el punto de vista de la seguridad) que forma parte del Microsoft Windows Application Compatibility Toolkit. (http://www.microsoft.com/windows/appcompatibility ), que es el primer paso que una aplicación debe de superar en el caso de que deseemos poseer la especificación de Aplicación Diseñada para Windows XP. AppVerifier es una herramienta de testeo diseñada para ayudar a los desarrolladores a crear mejores aplicaciones, sacando a la luz los errores más comunes desde el punto de vista del desarrollo. La herramienta inspecciona nuestra aplicación cuando este se está ejecutando y monitoriza su com-

Microsoft Application Verifier Microsoft Application Verifier forma parte de un conjunto de herramientas denominado Microsoft Windows Application Compatibility Toolkit. Este conjunto de herramientas nos permite comprobar la compatibilidad de una aplicación en una determinada configuración proporcionando descripciones detalladas de varias metodologías de testeo. Entre ellas destacamos: • Instrucciones detalladas para distribuir parches para la compatibilidad de aplicaciones a través de varios métodos. • Guías de desarrollo para mantener la compatibilidad con diferentes sistemas Windows. • Comprobación de los requisitos para que la aplicación pueda disponer de la certificación y el logo de “Windows Logo anda Certification”. • Más de 200 conjuntos de síntomas/resoluciones para el mantenimiento de compatibilidad.

portamiento interceptando las llamadas que la aplicación realiza a determinadas APIs. Al colocarse entre la aplicación y el sistema operativo, nos per-


<< dnm.plataforma.net recupera ante los errores, registrar los cambios que la aplicación realiza en el registro o en el sistema de ficheros, etcétera.

Figura 1.- Pantalla Principal de Windows Application Verifier

Cómo trabajar con AppVerifier El modo de funcionamiento de la herramienta es realmente sencillo. Como se puede ver en la figura 1, la aplicación dispone de una única pantalla desde la que deberemos ir agregando, en el panel de la izquierda, las aplicaciones que deseemos analizar. Una vez hayamos seleccionado las aplicaciones, en el panel de la izquierda disponemos de los tests que la aplicación nos permite automatizar; una vez seleccionados, desde el botón de Run, ejecutaremos la aplicación, y a partir de ese momento AppVerifier comenzará a registrar las operaciones relacionadas con los tests que hayamos seleccionado. Lo único que debemos hacer es trabajar normalmente con la aplicación, de forma que AppVerifier pueda interceptar las llamadas que ésta realiza y hacer sus comprobaciones. Una vez hayamos finalizado, podremos ver los resultados en los logs generados por la herramienta, que además podremos exportar y recuperar posteriormente. Podemos ver uno de estos logs en la figura 2.

Cómo controlar la seguridad de nuestra aplicación con AppVerifier A la hora de comprobar la seguridad de nuestras aplicaciones, el equipo de desarrollo de Windows Application Verifier recomienda que como mínimo se habiliten los siguientes tests:

Figura 2.- Registro de Errores

• PageHeap. Detecta los problemas que puedan ocurrir en la pila en el momento en el que se producen. • Handles. Nos asegura que una aplicación no intenta utilizar handles inválidos. • Locks. Nos asegura que nuestra aplicación utiliza los recursos críticos de forma adecuada. • SecurityChecks. Registra aquellas situaciones en las que un código malicioso podría ejecutarse.

<< dotNetManía

mite, por ejemplo, chequear los parámetros que se le pasan a las funciones APIs, inyectar parámetros erróneos para comprobar cómo la aplicación se

33


<< dnm.plataforma.net Los puntos que los tests de seguridad comprueban son: • Avisa al usuario sobre las ACLs que tienen controles de seguridad cuestionables. AppVerifier comprueba las listas de permisos de los objetos creados, copiados o movidos por la aplicación, registrando aquellos casos en los que se asigne una DACL NULL, o la predeterminada que le asigna el permiso de Control Total a todos los usuarios. El test también considera erróneo que un usuario que no sea administrador tenga privilegios para cambiar los permisos de un objeto. • Comprueba que determinadas APIs, como CreateProcess , se utilizan adecuadamente. Concretamente, comprueba que los parámetros de dichas funciones estén correctamente formados y no sean nulos. • Avisa al usuario cuando se utilizan funciones que son susceptibles de sufrir un ataque de buffer overrun. • Chequea las configuraciones de las APIs de comunicaciones. Asegurándose de que se utiliza el flag SO_EXCLUSIVEADDRUSE, preveiendo así accesos no autorizados a esos puertos.

Ejecutar los tests de seguridad que nos proporciona AppVerifier es el primer paso que debemos dar para asegurarnos de que nuestras aplicaciones cumplen con determinadas políticas de seguridad, pero evidentemente no es suficiente para asegurarnos de que nuestra aplicación es segura cuándo queremos que “rompa” en el depurador y qué depurador queremos utilizar, y en el que podemos indicar el depurador del CLR (dbgclr.exe). Otro de los problemas con los que nos encontramos, fue que, a pesar de que AppVerifier, es una muy buena herramienta para el chequeo de nuestras aplicaciones, no automatiza los tests que realiza, por lo que deberíamos realizar las pruebas de forma manual, navegando por todas las opciones de menú y casuísticas de nuestras aplicaciones, lo que evidentemente reduce mucho la posibilidad de dar con determinados errores. Por ello intentamos utilizarlo junto con la herramienta con lo que habitualmente realizamos nuestro juego de pruebas -y de la que hablaremos más en profundidad en dotNetManía- NUnit, y el resultado fue espectacular, conviven sin ningún problema, y de este modo conseguimos realizar los tests de forma automatizada.

Figura 3.- Opciones de Configuración

<< dotNetManía

Conclusiones

34

A la hora de realizar estos tests, podemos decidir cómo queremos que AppVerifier interactúe con nuestra aplicación gracias a los dos modos de funcionamiento de que disponemos: registro y depuración. En el modo registro AppVerifier tan solo registra, como vimos en la figura 2, los eventos que genera la aplicación, en base a los tests que nosotros hemos seleccionado. Sin embargo, disponemos de la posibilidad de configurar AppVerifier de forma que, en el momento en el que detecta un mal comportamiento lance un depurador y nos lleve a la línea de código que está generando dicho comportamiento. Para ello, como se puede apreciar en la figura 3, disponemos, en el botón de opciones de las configuraciones, de la posibilidad de indicarle

Ejecutar los tests de seguridad que nos proporciona AppVerifier es el primer paso que debemos dar para asegurarnos de que nuestras aplicaciones cumplen con determinadas políticas de seguridad, pero evidentemente no es suficiente para asegurarnos de que nuestra aplicación es segura. El proceso de desarrollo de aplicaciones seguras es casi una ciencia que afecta a todos los pasos en el ciclo de vida del desarrollo de una aplicación. Este tipo de herramientas ayudan, y mucho, pero no sustituyen a las buenas prácticas de desarrollo respecto a la seguridad.


Por Salvador Ramos SQL Server MVP HelpDNA.net

SQL Server Analysis Services ¡Hola Cubo! (I) En esta serie de artículos os presentaré un pequeño ejemplo de un DataWarehouse, a partir del cual construiremos una base de datos multidimensional compuesta por un sólo Cubo, y que será explotada y analizada con herramientas cliente como MS Excel y MS Data Analyzer. El objetivo fundamental es que nos empecemos a familiarizar con esta estupenda herramienta que viene con SQL Server y que en la mayoría de las ocasiones no se utiliza por desconocimiento. Será algo así como el famoso “¡Hola mundo!” de los que se inician en la programación.

los Analaysis Services de SQL Server, intentando ser lo más prácticos y didácticos posibles, entrando lo mínimo posible en conceptos como DataWarehouse o DataMart, OLAP, o el tan de moda Business Intelligence. Simplemente iré indicando las definiciones necesarias para que lo aquí expuesto sea entendido, dejando para otra ocasión un artículo más teórico sobre estos temas tan interesantes. Y por supuesto quedan también excluidos todos los temas de arquitectura y diseño, ya que el enfoque que aquí expongo es para que un desarrollador pueda crear un pequeño ejemplo y dejen de “sonarle a chino” estas herramientas y conceptos. Pues manos a la obra, empezaremos a hacer las definiciones mínimas para que los artículos sean entendidos, voy a intentar ser lo más breve posible. OLAP son las siglas de On-Line Analytical Processing, que lo podemos traducir por “Proceso Analítico En Línea”. Se trata de unos servidores cuyas bases de datos están diseñadas y optimizadas para permitir consultar con una gran flexibilidad y eficacia, sin formatos establecidos o predefinidos, obteniendo rápidamente respuestas a una gran variedad de preguntas (lo que se conoce como consultas “ad-hoc”). Dichas bases de datos son multidimensionales, no son relacionales.

Por ejemplo, pensemos en las preguntas: • “¿Cuáles fueron las ventas al contado (incluyendo importe y cantidad) realizadas por clientes de Murcia en el primer trimestre de 2001?”. • “¿Cuántas unidades fueron vendidas del artículo 512 en las provincias de Murcia y Almería durante los meses de marzo y abril de 2001?” • “¿A cuánto ascendieron las ventas por familia, por producto y por tiempo?” Es importante conocer la arquitectura de una infraestructura de este tipo, y conocer que el DataWarehouse se suele alimentar de datos procedentes de sistemas transaccionales, llamados también OLTP (On-Line Transaction Processing).

Figura 1. Ejemplo de una arquitectura OLTP y OLAP típica.

<<dotNetManía

<< La idea fundamental de estos artículos es dar a conocer

35


<< dnm.servidores.sql

Una de las habilidades principales en la navegación y manipulación de estructuras de datos en una BDM es que el cubo se puede rotar, girar, cortar porciones o extraer parte de su estructura. En las Bases de Datos Relacionales (BDR en adelante) el objeto en el que se almacena la información es la tabla, que consta de dos dimensiones, filas y columnas. En las Bases de Datos Multidimensionales (BDM en adelante) la información se almacena en Cubos, que pueden tener varias dimensiones. Todos los que ya conocéis las estructuras bidimensionales (tablas) en las que sólo tenéis dos perspectivas de la información, habéis podido comprobar por vuestra experiencia la gran cantidad de información que se puede extraer de ellas. Pues ahora imaginaos esa potencia multiplicada por N veces, al disponer de N perspectivas para analizar la información. Así os haréis una idea inicial de lo potente, ágil y flexible que puede resultar el modelo multidimensional. El cubo es el objeto que tiene los datos analíticos con los que queremos trabajar. Los cubos tienen una estructura multidimensional organizada en dimensiones y medidas. Para obtener los datos referentes a las tres preguntas iniciales referentes a las ventas, debemos obtener los datos de las dimensiones Cliente, Provincia, Forma de Pago, Artículo y Tiempo, y de las medidas Importe y Cantidad. A estas estructuras se les ha dado el nombre de cubo (supongo que porque no somos capaces de representar gráficamente más de tres dimensiones), pero no se limi-

ta a mostrar únicamente datos tridimensionales, sino en N dimensiones. En el párrafo anterior hemos utilizado cinco dimensiones y dos medidas. Una de las habilidades principales en la navegación y manipulación de estructuras de datos en una BDM es que el cubo se puede rotar, girar, cortar porciones o extraer parte de su estructura. Ahora vamos a entender otros de los conceptos que hemos nombrado. Las medidas son los datos numéricos que queremos analizar. Para cada medida del cubo, éste contiene un valor en la celda, en función de las dimensiones y niveles que se estén mostrando. La medida es el valor numérico que obtenemos en la intersección de las diversas dimensiones del cubo. Una dimensión es cada uno de los ejes que forman el cubo, o sea cada una de las perspectivas desde las que el usuario quiere ver la información. Las dimensiones son jerárquicas y, en la mayoría de los casos, sus miembros están organizados en una configuración de tipo piramidal. Están estructuradas jerárquicamente en niveles y sus miembros (cada uno de los elementos o valores que hay en la dimensión) suelen tener una configuración de tipo piramidal. Por ejemplo, la dimensión Factory Location consta de los siete miembros siguientes: Todas Factory Location East Maine Ohio West

<<dotNetManía

Idaho Texas

36

Figura 2. Cubo formado por tres dimensiones (Product, Time, Factory Location) y una medida (unidades vendidas).

(1) (2) (3) (4) (5) (6) (7)

Figura 3. Comparativa de una estructura piramidal de una dimensión con la estructura de una tabla en una base de datos relacional.


<< dnm.servidores.sql Una vez instalados los Analysis Services y el último service pack para éstos, tenemos disponible la herramienta con la que vamos a implementar y administrar las bases de datos multidimensionales que vamos a desarrollar, el Analysis Manager.

Niveles: Provincia

Niveles: Familia Artículo

Figura 5. El Analysis Manager.

Niveles: Año Trimestre Mes Día

Niveles: Cliente

Vamos a partir de una BDR donde ya hemos extraído y transformado los datos desde nuestros sistemas OLTP (la que en la figura 6 aparece con el nombre “DataWarehouse”). Esta es una base de datos sobre la que podremos lanzar todas las consultas que deseemos en lenguaje SQL, que podrá ser aprovechada al estar denormalizada y ser independiente de nuestros sistemas OLTP para que éstos tengan una menor carga de consultas. A partir de ella vamos a cargar la información en nuestra BDM, que llamaremos “dotNetMania”, donde vamos a crear el cubo “Ventas”.

Niveles: Forma de Pago Figura 4. Dimensiones del ejemplo a desarrollar según se ven en el Analysis Manager.

Aunque lo que acabamos de indicar es la situación típica de este tipo de desarrollos, aquí vamos a partir de la base de datos DataWarehouse ya cargada con los datos, y no incluiremos el resto de DBR de los sistemas OLTP, ni los procesos de extracción, transformación y carga utilizados. Como anticipación al siguiente capítulo mostraremos unas imágenes que nos amplíen la visión de lo visto hasta ahora:

<<dotNetManía

Una dimensión puede tener diversos modos de almacenamiento, los más habituales son: OLAP Multidimensional (MOLAP) u OLAP Relacional (ROLAP). MOLAP es el modo de almacenamiento que utilizaremos en nuestro ejemplo. Queda fuera del ámbito de este artículo la explicación de cada uno de estos sistemas de almacenamiento, y cuándo es aconsejable utilizar cada uno de ellos. Bien, pues una vez hecha esta pequeña introducción, vamos a centrarnos en SQL Server Analysis Services y en el ejemplo que vamos a implementar.

Figura 6. Esquema de las Bases de Datos y herramientas de acceso.

37


<< dnm.servidores.sql

[ [ Importante

Figura 7. Esquema relacional de DataWarehouse realizado con la herra-mienta de diagramas incluida en el administrador corporativo de SQL Server.

Es muy importante que sepa que los service packs de SQL Server y de los Analysis Services se instalan por separado, son dos ejecutables totalmente independientes. No interprete que por tener instalado el último service pack de SQL Server tiene también instalado el de los Analysis Services, ni viceversa.

Figura 8. Cubo de Ventas visto desde el Editor de Cubos del Análisis Manager.

Aunque tanto el cubo “Ventas” como el “DataWarehouse” utilizan las mismas tablas, esto es debido a que hemos montado un mini-DataWarehouse que sólo contiene la información imprescindible para el ejemplo. Como puede suponer un DataWarehouse real será inmensamente mayor, tanto en número de tablas como en filas por tabla, ya que éste contiene información histórica y procedente de diversos sistemas OLTP. A continuación presentamos la información como respuesta a las tres preguntas efectuadas al principio del artículo:

Figura 10. ¿Cuántas unidades fueron vendidas del artículo 512 en las provincias de Murcia y Almería durante los meses de marzo y abril de 2001?

<<dotNetManía

Figura 11. ¿A cuanto ascendieron las ventas por familia, por producto y por tiempo?

38

Figura 9. ¿Cuáles fueron las ventas al contado (incluyendo importe y cantidad) realizadas por clientes de Murcia en el primer trimestre de 2001?

Próximamente, partiremos ya del DataWarehouse aquí definido y crearemos paso a paso la base de datos multidimensional “dotNetMania”, y en ella el cubo “Ventas” para analizar la información referente a las ventas de nuestra empresa ficticia, y finalmente explicaremos cómo obtener información de ella utilizando MS Excel y MS Data Analyzer.


Por Javier Jaén y Jose A. Mocholí Proyecto MOMO Universidad Politécnica de Valencia

Museos, hormigas y serialización en el Compact Framework de .NET Hace 4 años, en París y con sólo 2 horas para visitar el Louvre. Así nació MOMO (MuseO MÓvil) en la mente del profesor Javier Jaén. Mediante el uso de un PocketPC inalámbrico y unas cuantas hormigas el visitante puede tener a su alcance una completa información multimedia optimizada a sus gustos y al tiempo de que dispone.

<<dotNetManía

<< En el pasado los museos han sido considerados como meros

40

“contenedores visuales” de obras de arte, esto es, su principal labor era la conservación física: mantenimiento, restauración y seguridad de cierto patrimonio artístico. Afortunadamente, esta visión arcaica y estática del papel que deben jugar los museos en el abanico cultural de una sociedad ha sido renovada en los últimos años. Como consecuencia de esta nueva visión han surgido nuevas responsabilidades a desempeñar por este tipo de instituciones. Entre ellas cabe destacar: en primer lugar, la labor de conservación intelectual entendida como el estudio, interpretación, catalogación y valoración de las obras de arte en cuanto a objetos de carácter estético que constituyen las huellas culturales de la humanidad; y, en segundo lugar, la labor de dinamización cultural, mediante la cual los antiguos contenedores “dejan atrás su silencioso aposento para dialogar con el arte y con la sociedad, interrogando constantemente, relacionándose y modificando el entorno”. Es fácil encontrar expresiones de estas nuevas responsabilidades en la práctica totalidad de los museos españoles dado que la gran mayoría organiza conferencias y talleres, edita publicaciones explicativas, posee bibliotecas de arte, son centros de atracción turística, e incluso, los más atrevidos, utilizan tecnologías de la información para hacer llegar sus contenidos al mayor número posible de ciudadanos. Sin embargo, todavía existen nuevas metas o mecanismos innovadores que

permitirían desarrollar el papel dinamizador de los museos. El arte y la tecnología pueden fusionarse en el seno de estas instituciones facilitando el diálogo con el arte, haciendo más accesible el patrimonio cultural, promocionando su conocimiento “in situ”, y en definitiva, convirtiendo a los museos en instituciones más dinámicas y cercanas a los ciudadanos.

Los museos y las TICs En [1] se presenta un estudio detallado en el que se cuantifica el grado de presencia y desarrollo de las tecnologías de la información en los museos españoles en comparación con los museos de mayor relevancia internacional. Dicho estudio analiza desde distintas perspectivas 53 museos de arte y ciencias y revela que a pesar de que más de un 93% de los museos estudiados tiene presencia en Internet, sólo el 4,5% posee un nivel alto de desarrollo global (figura 1), es decir, “el grado de aproximación del museo al ciudadano ... mediante, entre otros, la gestión de trámites, el fomento de la participación o la personalización de la información” es deficiente en la inmensa mayoría de los museos estudiados, excepto en “el Museo Thyssen-Bornemisza de Madrid y el Centro de Cultura Contemporánea de Barcelona que son los dos museos españoles que presentan un nivel alto de desarrollo en el cómputo final”. Cabe destacar, sin embargo, para no dar


<< dnm.universidad.net en los museos. iTour [4] es un proyecto llevado a cabo en el Museo de Arte Blanton de la Universidad de Texas (UT) conjuntamente entre el museo y el Departamento de Tecnologías de la Figura 1. Nivel de desarrollo global tecnologías Información de UT. El de la información proyecto utiliza la plataforma PocketPC en la una visión demasiado catastrofista, que memoria de la cual se almacenan los en el ámbito de la fidelización (aquél datos de las obras y los contenidos mulrelacionado con la existencia de visitimedia que más tarde se mostrarán al tas virtuales, correo electrónico, conusuario. La información se muestra al sultas telemáticas, etc.) este mismo usuario a través de una aplicación diseestudio concluye que el 80% de los ñada en Flash [7] y programada usando museos tiene un nivel “medio-alto”. Dicho de otro modo, la inmensa mayoría de los museos ha utilizado las nuevas tecnologías para implementar visitas virtuales accesibles en la Web. Esto, que a priori parece un dato realmente positivo, no debe llevar a conclusiones prematuras dado que el estudio no se acompaña con estadísticas de uso de dichos servicios de fidelización. Dado que carecemos de estos datos, utilizaremos otros datos indirectos para llegar a conclusiones razonablemente acertadas. Si consideramos que en [2] se afirma que en el primer trimestre de 2004 sólo un 26.9% de los hogares Action Script. Durante la visita se van españoles disponía de acceso a capturando datos sobre los patrones Internet, y que según [3] la penetra(tiempo empleado en cada obra, orden ción de la banda ancha en los hogares de visita de cada página, etc.) de realide España es sólo de un 12% (aspecto zación de la visita con iTour, que son fundamental para visitas virtuales de almacenados en un fichero XML que gran riqueza sensorial) podemos, cuanmás tarde se pasará a un PC para que sus datos sean almacenados en una base to menos, cuestionar la eficacia de de datos, de manera que se puedan readichas estrategias a la hora de contrilizar estudios de utilización. El proyecbuir a la promoción de la cultura y la to Multimedia Tour [5] forma parte de comprensión del arte por parte de la los esfuerzos de la Tate Modern gran mayoría de los ciudadanos. Si Gallery por introducir las visitas mulademás corroboramos que muchos timedia en los últimos dos años. La fase amantes del arte se sienten defraudaactual del proyecto cuenta con dos al realizar visitas virtuales debido PocketPCs en las que se muestran cona la poca riqueza sensorial que dichas tenidos multimedia, realizados en Flash, visitas poseen podríamos concluir que vía una aplicación desarrollada por un la situación actual de uso de nuevas partner del proyecto, Antenna Audio. tecnologías en los museos en general, El contenido que se muestra al visitany de los españoles en particular, no es te puede estar tanto en el dispositivo en absoluto la deseable. móvil como en un servidor central, del Para resolver este problema, existen que se recibirá vía la red inalámbrica del varias iniciativas relacionadas con la museo. El proyecto cuenta con tres tipos introducción de las nuevas tecnologías

de tours: el Multimedia Highlights, que está específicamente diseñado para una audiencia entre los 16 y los 25 años y que se centra en un único conjunto de obras del museo; el British Sign Language, que va dirigido a los visitantes sordos del museo y les muestra vídeos de una persona explicando la obra en lengua de signos; y el Collections Tour, que hace uso de la información almacenada (textual en su mayor parte) relacionada con las obras de que dispone la galería. El museo J. Paul Getty, junto con Sun Microsystems, ha desarrollado el proyecto GettyGuide [6] para complementar la red de quioscos multimedia con la que ya contaba. Para el proyecto se eligió como plataforma Palm y

El arte y la tecnología pueden fusionarse en el seno de los museos facilitando el diálogo con el arte, haciendo más accesible el patrimonio cultural, promocionando su conocimiento “in situ”, y en definitiva, convirtiendo a los museos en instituciones más dinámicas y cercanas a los ciudadanos el uso de Flash para mostrar los contenidos multimedia que recibe del servidor central a través de la red inalámbrica del museo. El visitante puede buscar las obras que quiere ver realizando búsquedas por autor, género, estilos, etc., o bien puede acercarse a una obra de su interés para recibir la información.

Los ejemplos anteriores presentan serias carencias, bien por no soportar interacción social, por no presentar contenidos dinámicos e incluso, lo que es más grave, por no guiar al usuario de una forma inteligente por el museo. El proyecto MoMo desarrollado en la Universidad Politécnica de Valencia resuelve todas estas carencias e implementa una serie de componentes inte-

<<dotNetManía

MoMo:.NET al servicio del arte

41


<<dotNetManía

<< dnm.universidad.net

42

ligentes para hacer de la visita una experiencia más enriquecedora, todo ello usando la tecnología .NET tanto a nivel de servidor como en los dispositivos inalámbricos. Entre las componentes inteligentes desarrolladas destaca la que permite a los usuarios disfrutar de una visita lo más rica posible en un tiempo limitado, esto es, garantiza que el visitante pueda ver el máximo número de obras de arte populares sin sobrepasar un tiempo de visita dado. Esto que puede parecer un problema trivial, no lo es, dado que hay que tener en cuenta los tiempos de visita a cada obra, las popularidades de las mismas, los tiempos de desplazamiento entre salas en el museo y las posibles desviaciones (adelantos o retrasos) que el visitante pueda sufrir en su transcurso por el museo. Este problema tiene una formulación matemática conocida como The Orienteering Problem (OP), la cual tiene una gran similitud con la formulación del clásico problema del Viaje de Comercio. La complejidad de dicho problema en términos computacionales es alta y no es posible obtener soluciones óptimas en tiempo de orden polinomial. De hecho, las implementaciones realizadas hasta la fecha para resolver el OP han hecho uso de estaciones de trabajo o computadores de altas prestaciones. ¿Hemos, pues, de obligar a los museos a realizar una inversión en hardware prohibitiva? ¿No es posible con los recursos de que disponen resolver el OP y guiar de forma inteligente a los visitantes?. Afortunadamente, como veremos a continuación, es posible resolver el OP sin hacer uso de grandes infraestructuras de computación. La sabia naturaleza ha ideado mecanismos muy efectivos para la resolución de problemas complejos. Por ejemplo, cuando una colonia de hormigas se emplea en la dura tarea de encontrar comida se pueden observar mecanismos de coordinación y de colaboración muy sofisticados. Las hormigas dejan señales químicas (feromonas) cuando van en busca de comida. Estas señales químicas son intensificadas a medida que varias hormigas pasan por un mismo camino. El resultado final es que aquellos caminos que conducen a lugares donde existe comida quedan intensamente señalados mientras que los caminos no conducentes a comida ven evaporadas sus feromonas. Actuando de esta manera las hormigas pueden llegar hasta la comida y volver al hormiguero de una forma efectiva. Siguiendo con esta analogía, podríamos decir que en un museo las obras que tienen gran popularidad son la “comida”, que los visitantes (“hormigas”) desean alcanzar, pero claro, no parece una gran idea invitar a los usuarios del museo a ir dejando feromonas a su paso... La pregunta es, en cambio, si es posible diseñar un algoritmo que imite el comportamiento de las hor-

Figura 2. Caminos con feromonas de hormigas en busca de alimento

migas y que sirva para resolver el OP. La respuesta es afirmativa y dicho algoritmo ha sido propuesto en [8,9]. La idea es representar los sitios de interés (en nuestro caso salas de un museo) como nodos de un grafo. Dichos nodos tienen un peso que representa su popularidad (calculada en base a las obras de arte que contienen). Además los arcos de dicho grafo conectan salas y tienen asociado un peso que representa el tiempo que cuesta ir desde una sala a otra (si ello es posible). Las hormigas van recorriendo dicho grafo, bien de forma aleatoria o bien utilizando las feromonas que han dejado otras compañeras. Cada vez que se encuentra un buen camino, éste es notificado al resto de las hormigas para que tengan en cuenta las feromonas de ese camino. Al final del proceso, aquellos caminos en el museo que tienen gran cantidad de obras de arte populares quedan enormemente intensificados y por tanto se obtiene una visita (secuencia de salas) que tendrá un gran número de obras de arte populares.

Figura 3. Mecanismo de Grid Computing en pocketPCs


<< dnm.universidad.net

Figura 4. Solución al OP obtenida mediante una colonia de hormigas

de baja popularidad real pasaría a formar parte siempre de las visitas generadas mediante el algoritmo y vería incrementado el numero de personas que irían, dirigidos por nuestro sistema, a visitar dicha sala. Otro aspecto que es importante describir es el hecho de que el algoritmo propuesto tiene mecanismos para recalcular dinámicamente una visita en el caso de que un visitante se esté atrasando o adelantando respecto al horario previsto. En este caso las hormigas, de nuevo dirigidas por la hormiga reina, recalculan una nueva visita teniendo en cuenta el tiempo restante para que el usuario no llegue al final de su visita más tarde o temprano de lo inicialmente previsto.

Implementación Para hacer realidad las ideas descritas con anterioridad hemos diseñado un algoritmo distribuido en .NET donde cada hormiga es un programa escrito en C# que residirá en cada pocketPC a la espera de órdenes para ponerse a calcular caminos óptimos en el museo. Dichas órdenes son establecidas por la hormiga reina que reside en el hormiguero y que viene representada como un servicio Web. Utilizar un servicio Web para la hormiga reina nos proporciona una gran ventaja tecnológica dado que no hay que definir protocolos propietarios para comunicar y coordinar a las hormigas obreras con el hormiguero y simplemente nos tenemos que concentrar en los aspectos específicos del algoritmo. Sin embargo, ciertas carencias en la serialización de objetos complejos en el Compact Framework (CF) y la estrategia que sigue la plataforma para decidir qué clases, de las necesarias para comunicarse con el servicio web, serán accesibles en el cliente a través del espacio de nombres del proxy del servicio Web, nos hicieron tener que desarrollar un serializador propio que, utilizando los mecanismos que la reflexión en .NET nos ofrece, tratase de forma genérica todas las clases utilizadas en la comunicación con los servicios Web del proyecto y que pasamos a explicar a continuación. El desarrollo que realizamos no sustituye al serializador de la plataforma, sino que se basa en sus capacidades y solventa las carencias que nos impedían utilizar todas las clases del proyecto (problemas con la serialización de clases complejas en el CF, clases que se quedaban “ocultas” al no estar expuestas directamente por el servicio Web, …), por lo que tal vez podríamos definirlo como un preserializador encargado de preparar los objetos utilizados en la comunicación con el servicio web para que el serializador de la plataforma sí que pueda trabajar con ellos. Su funcionamiento, en pocas palabras, consiste en transformar los objetos de unas determinadas clases en

<<dotNetManía

Mediante este algoritmo es posible resolver de forma colaborativa el OP, ahora bien, ¿necesitamos todavía un computador de altas prestaciones que permita trabajar a múltiples hormigas de forma paralela?. La respuesta es NO. No hemos de olvidar que en un museo tendremos decenas de visitantes con un pocketPC en sus manos y que dichos dispositivos, aunque limitados en su capacidad de computación, pueden de forma conjunta proveer de ciclos libres de CPU para resolver el OP. Esta estrategia de computación no es nueva y se conoce como Grid Computing o Utility Computing[10] (ver figura 3). Aplicando las ideas de esta novedosa estrategia de computación es posible obtener soluciones al OP mediante el uso de pequeños ordenadores como son los PocketPCs. En la figura 4 se observa una solución obtenida para el museo del Prado donde hemos coloreado en rojo las salas muy populares que contienen obras de grandes pintores como Velázquez, Rubens y Goya entre otros, en marrón las salas de una popularidad intermedia y en azul aquellas salas que son de baja popularidad. Hay que destacar que la solución que mostramos ha sido obtenida mediante este esquema de computación distribuida en sólo unos segundos con sólo 6 hormigas. También hay que señalar que este algoritmo puede ser aprovechado por los propietarios del museo para redirigir a los visitantes a nuevas salas que inicialmente tienen poca densidad de visitas. El museo podría marcar una sala como muy popular (aunque en realidad no lo sea) de forma que esta sala atrajera a las hormigas cuando están generando visitas dinámicas. Así pues, una sala

43


<<dotNetManía

<< dnm.universidad.net

44

una serie de objetos de tipos que la plataforma sí puede tratar. El funcionamiento del serializador es el siguiente. Tenemos una clase, PPCSerializer, que expone dos métodos, uno para la serialización de objetos (SerializeInstance) y otro para la deserialización (DeserializeInstance). El método para la deserialización tiene una sobrecarga para permitir especificar un espacio de nombres que incluya el nombre del ensamblado en el cuál queremos que el serializador busque la clase de la que es instancia el objeto a deserializar. Como podemos observar, tanto el resultado de la serialización como la entrada de la deserialización es un vector de objetos de tipos simples que el serializador de CF sí puede tratar (fuente 1). Cuando se invoca el método de serialización sucede lo siguiente: haciendo uso del método TypeSize, se calcula el tamaño necesario para que el vector de objetos pueda contener toda la información; se crea el vector con el tamaño calculado y se procede a serializar el objeto, siguiendo una estrategia recursiva en el caso de objetos complejos hasta encontrar tipos simples (fuente 2). En la deserialización, los pasos son muy similares al proceso de serialización y empiezan con la comprobación de si estamos trabajando con el valor nulo. Luego, se recupera el tipo del siguiente objeto con el que se va a trabajar, teniendo en cuenta (si fuese el caso) el ensamblado y el espacio de nombres especificado. Usando reflexión sobre el tipo, recuperamos un constructor sin parámetros válido (la existencia de un constructor sin parámetros en las clases cuyas instancias se va serializar, es una restricción que también forma parte del serializador de .NET) y creamos una instancia del mismo. Después procedemos a recuperar los atributos públicos y las propiedades públicas (que se puedan leer y escribir) del tipo, y a deserializar y a intentar asignar el siguiente objeto al atributo o a la propiedad en la que estemos. Si el tipo del objeto fuese uno simple, la deserialización se limita a realizar un cast. Si se tratase de una enumeración, bastaría con indicar el nombre de la enumera-

public class PPCSerializer { public static object[] SerializeInstance(object o){…} public static object DeserializeInstance(object[] serialized_instance){…} public static object DeserializeInstance(object[] serialized_instance, string target_namespace){…} }

Fuente 1

ción y el valor serializado para obtener el valor asociado de la enumeración (fuente 3). Como ejemplo de uso del mecanismo de serialización descrito podemos

observar cómo una hormiga obrera se comunica con el servicio Web de la hormiga reina. En concreto en este ejemplo la hormiga obrera informa a la hormiga reina sobre su existencia median-

public static object[] SerializeInstance(object o) { int size = 0; TypeSize(o, ref size); object[] serialized_instance = new object[size]; int count = 0; SerializeInstance(o, ref serialized_instance, ref count); return serialized_instance; } protected static void TypeSize(object o, ref int size) { size ++; if (o != null) { if ((o.GetType().IsClass) && (!(o.GetType().Equals(typeof(string)))) && (!(o.GetType().BaseType.Equals(typeof(Array)))) && (!(o.GetType().Equals(typeof(ArrayList))))) { FieldInfo[] fields = o.GetType().GetFields(); foreach (FieldInfo field in fields) { if (!field.IsStatic) { TypeSize(field.GetValue(o), ref size); } } PropertyInfo[] props = o.GetType().GetProperties(); foreach ( PropertyInfo prop in props ) { if (prop.CanRead) { TypeSize(prop.GetValue(o, new object [] {} ), ref size); } } } else if (o.GetType().Equals(typeof(ArrayList))) { ArrayList list = (ArrayList)o; size++; foreach (object list_member in list) TypeSize(list_member, ref size); } else if (o.GetType().BaseType.Equals(typeof(Array))) { Array list = (Array)o; size++; foreach (object list_member in list) TypeSize(list_member, ref size); } else { size++; } } }

Fuente 2


<< dnm.universidad.net

Fuente 3

te el método antAlive, sobre su disposición a realizar trabajo mediante el método antReady y notifica nuevas soluciones mediante el método antsCommandDone (fuente 4).

Resumen En este artículo hemos hecho una revisión de los proyectos que utilizan ordenadores de bolsillo para la realización de visitas multimedia en museos. En todos los proyectos revisados se han encontrado serias carencias en cuanto a las funcionalidades proporcionadas. También hemos presentado el proyecto MoMo, que suple todas las carencias de los proyectos existentes hasta la fecha y está implementado íntegramente utilizando el lenguaje C# y la plataforma .NET. Hemos de decir que la productividad en la

La productividad en la programación de dispositivos móviles utilizando la plataforma .NET es muy superior a la de otras plataformas y lenguajes que hemos probado como por ejemplo Flash y ActionScript programación de dispositivos móviles utilizando esta plataforma es muy superior a la de otras plataformas y lenguajes que hemos probado como por ejemplo Flash y ActionScript. Gracias a la potencia del lenguaje de programación y a las facilidades para definir aplicaciones basadas en servicios Web hemos podido implementar un algoritmo distribuido para el Orienteering Problem que permite generar visitas dinámicas de tiempo

<<dotNetManía

protected static void DeserializeInstance(out object new_instance, object[] serialized_instance, ref int pos, string target_namespace) { if (“null”.Equals((string)serialized_instance[pos])) { new_instance = null; pos++; } else { Type type = FindType((string)serialized_instance[pos++], target_namespace); if ((type.IsClass)&&(!(type.Equals(typeof(string))))&& (!(type.Equals(typeof(ArrayList))))&& (!(type.BaseType.Equals(typeof(Array)))) && (!(type.BaseType.Equals(typeof(Enum))))) { ConstructorInfo constructor = type.GetConstructor(new System.Type[0]); new_instance = constructor.Invoke( BindingFlags.CreateInstance, null, new object[0], null); FieldInfo[] fields = type.GetFields(); foreach (FieldInfo field in fields) { if (!field.IsStatic) { object field_instance; DeserializeInstance( out field_instance, serialized_instance, ref pos, target_namespace ); field.SetValue(new_instance, field_instance); } } PropertyInfo[] props = new_instance.GetType().GetProperties(); foreach ( PropertyInfo prop in props ) { if (prop.CanRead) { object prop_instance; DeserializeInstance( out prop_instance, serialized_instance, ref pos, target_namespace); if (prop.CanWrite) { prop.SetValue(new_instance, prop_instance, new object [] {}); } } } } else if (type.Equals(typeof(System.Collections.ArrayList))) { new_instance = new ArrayList(); int num_elements = (int)serialized_instance[pos++]; int initial_pos = pos; for (int i=initial_pos; i<initial_pos + num_elements; i++) { object list_member; DeserializeInstance( out list_member, serialized_instance, ref pos, target_namespace ); ((ArrayList)new_instance).Add(list_member); } } … … else if (type.BaseType.Equals(typeof(Enum))) { new_instance = System.Enum.ToObject(type,serialized_instance[pos++]); } else { DeserializeValue(out new_instance, type, serialized_instance, ref pos); } }

45


<< dnm.universidad.net using using using using

Referencias

System; System.Collections; System.Net; MoMo.Ant.Algorithm;

[1] e-España, Informe Anual sobre el Desarrollo de la Sociedad de la Información en España (2002). www.fundacionauna.org/ areas/25_publicaciones/publi_251 _2.asp.

namespace AntPocket { /// <summary> /// Summary description for PocketWrapper. /// </summary> public class PocketWrapper : WSWrapper{ MasterQueenService.MasterQueenService mq;

[2] Las TIC en los hogares españoles (2004); Ministerio de Ciencia y Tecnología. www.mcyt.es/asp/ministerio_ informa/prensa/pdf/balance_ene04. pdf.

public PocketWrapper() { mq = new MasterQueenService.MasterQueenService(); } public GraphDescr antAlive(int graphVersion) { int type = 1; string name = Environment.OSVersion.ToString(); string remString = “Microsoft “; if (name.StartsWith(remString)) name = name.Substring(remString.Length, name.Length-remString.Length); string ip = “”; try { ip = Dns.GetHostByName(Dns.GetHostName()).AddressList[0].ToString(); } catch (Exception) {} return (GraphDescr)PPCSerializer.DeserializeInstance(mq.antAlive(graphVersion, type, name, ip), “MoMo.Ant.Algorithm.GraphDescr”); }

www.archimuse.com/mw2004/papers/ wilson/wilson.html.

[6] J. Paul Getty Museum Re-Architects Technology to Enhance Visitors' Experience; David S. Marshak. www.sun.com/service/about/ success/recent/getty.html

public void antDead(int antid) { mq.antDead(antid); }

[7] Macromedia Flash.

}

www.macromedia.com/software/ flash/

}

Fuente 4

<<dotNetManía

[4] The Blanton iTour, An Interactive Handheld Museum Guide Experiment; Anne Manning, Glenda Sims.

[5] Multimedia Tour Programme at Tate Modern; Gillian Wilson.

public ArrayList antCommandsDone(int queenid, SolutionPath solution) { object[] o = mq.antCommandsDone( queenid, PPCSerializer.SerializeInstance(solution)); if (o != null) return (ArrayList)PPCSerializer.DeserializeInstance(o, “MoMo.Ant.Algorithm.AntCommand”); return null; }

46

observatorio.red.es/gaptel/ informes/trimestrales.html.

www.archimuse.com/mw2004/papers/ manning/manning.html

public ArrayList antReady(int antid) { return (ArrayList)PPCSerializer.DeserializeInstance(mq.antReady(antid), “MoMo.Ant.Algorithm.AntCommand”); }

restringido garantizando la máxima riqueza de las mismas. Para ello se han utilizado los propios dispositivos móviles para la computación de dicho algoritmo demostrando que éstos son perfectamente válidos para la resolución de problemas complejos de forma colaborativa. En la implementación de este algoritmo complejo hemos implementado un serializador de clases complejas que solventa las limitaciones que existen en la actualidad en el CF de .NET y que puede ser utilizado de forma genérica en cual-

[3] Banda Ancha, (2004); GAPTEL (Grupo de Análisis y Prospectiva del sector de las Telecomunicaciones).

quier aplicación implementada en esta plataforma.

Agradecimientos El presente trabajo ha sido desarrollado gracias al apoyo de los laboratorios de Microsoft Research Cambridge mediante su programa MSR Excellence Awards for Embedded Systems. También hemos de agradecer el apoyo recibido por Microsoft Ibérica durante el concurso Imagine Cup 2004 tanto en su fase nacional como internacional.

[8] An Ant Colony Approach to the Orienteering Problem, Yun-Chia Liang and Alice E. Smith, IEEE Transactions on Evolutionary Computation, October 2001. [9] A Parallel Implementation of Ant Colony, Marcus Randall, Journal of Parallel and Distributed Computing 62, 1421-1432 (2002). [10] The anatomy of the grid: Enabling scalable virtual organizations. Ian Foster, Carl Kesselman, and Steve Tuecke. International Journal of Supercomputer Applications, 2001.


Por Jorge Serrano Visual Basic y .NET MVP www.PortalVB.com

Trabajando con el registro de Windows En no pocas ocasiones debemos utilizar ficheros de inicialización para almacenar determinados valores que serán utilizados por nuestra aplicación. Sin embargo, y según el tipo de proyecto, en algunas ocasiones resulta especialmente útil trabajar con el registro de Windows.

<< A continuación, veremos cómo trabajar con el registro de Windows desde nuestras aplicaciones. En concreto, utilizaremos Visual Basic .NET como lenguaje de programación, sin embargo, migrar estos ejemplos a C# u otro lenguaje .NET es una mera anécdota. Lo principal, es aprender a acceder al registro, cosa que sabrá hacer cuando termine de leer este artículo.

Carpeta de registro

Clase

HKEY_CLASSES_ROOT

ClassesRoot

HKEY_CURRENT_CONFIG

CurrentConfig

HKEY_CURRENT_USER

CurrentUser

HKEY_DYN_DATA

DynData

HKEY_LOCAL_MACHINE

LocalMachine

HKEY_PERFORMANCE_DATA

PerformanceData

HKEY_USERS

Users

¿Quién es el responsable?

Tabla 1. Clases a utilizar por cada carpeta del registro

Carpeta de registro

Clase

REG_SZ

ClassesRoot

REG_EXPAND_SZ

CurrentConfig

REG_DWORD

CurrentUser

REG_MULTI_SZ

DynData Tabla 2.Valores a utilizar en el registro de Windows

<<dotNetManía

Para acceder al registro de Windows, debemos hacer uso de un nombre de espacio, que será el comunicador directo con las clases que nos darán acceso al registro de Windows. El nombre de espacio Microsoft.Win32.Registry nos facilita, por lo tanto, gran parte de este trabajo. Dentro de este nombre de espacio, tenemos un conjunto de clases preparadas para acceder a las diferentes partes del registro. Recordemos que el registro de Windows está dividido en pequeños directorios dónde almacena muchas variables y valores de las aplicaciones y configuraciones que se ejecutan en el sistema. De esta manera, tenemos las clases y valores a utilizar por cada carpeta del registro en las tablas 1 y 2. El uso de estas clases, nos facilitará el acceso a cada una de las carpetas del registro. En este artículo, sólo veremos algunas de las funciones genéricas con el registro de Windows. Todas esas funciones son aplicables a las carpetas del registro de Windows.

47


<< dnm.plataforma.net La figura 1, representa una ventana típica del registro de Windows.

tro creada anteriormente: HKEY_CURRENT_USER\ Ejemplo.

Dentro de esa carpeta de registro, crearemos el nombre de valor MiNombre y como valor, un valor determinado. La teoría vista en la práctica quedaría como se detalla a continuación:

Figura 1Ventana típica del registro de Windows

Observando esta figura, vemos que hay cuatro partes a tener en cuenta (enumeradas para facilitar la comprensión). El primer número corresponde con la carpeta y subdirectorios del registro de Windows; el segundo número corresponde con el nombre del campo; el tercer número corresponde con el tipo de valor contenido en el campo nombre; el cuarto número, corresponde con el valor almacenado en la variable nombre. ¿Ahora bien, cómo accederemos a esta información?. Esto y mucho más será lo que veremos a continuación.

Imports Microsoft.Win32 [...] ‘HKEY_CURRENT_USER\Ejemplo Dim MiRegKey As RegistryKey = Registry.CurrentUser.OpenSubKey(“Ejemplo”, True) ‘Asignamos un Nombre y Valor (texto) MiRegKey.SetValue(“MiNombre1”, “MiValor1”) ‘Asignamos un Nombre y Valor (entero) MiRegKey.SetValue(“MiNombre2”, 2004) ‘Cerramos el objeto MiRegKey.Close()

Fuente 2

Este ejemplo añade dos nombres y valores de diferente tipo a nuestro registro de Windows, tal y cómo se muestra en la figura 2.

Creando una carpeta en el registro Una de las posibilidades que nos ofrece el registro de Windows es la de crear una subcarpeta con valores. En primer lugar, veremos como crear una carpeta, que la situaremos en: HKEY_CURRENT_USER\Ejemplo. Esto lo conseguiremos hacer ejecutando la siguiente instrucción:

Imports Microsoft.Win32 [...] ‘HKEY_CURRENT_USER Dim MiRegKey As RegistryKey = Registry.CurrentUser ‘HKEY_CURRENT_USER\Ejemplo MiRegKey.CreateSubKey(“Ejemplo”) ‘Cerramos el objeto MiRegKey.Close()

<<dotNetManía

Fuente 1

48

Figura 2. Registro de Windows con los nombres y valores creados

Leyendo un valor en una carpeta de registro Accederemos nuevamente en esta ocasión a HKEY_CURRENT_USER\Ejemplo para leer el contenido

de los valores almacenados en esa carpeta. Esto lo conseguiremos con el código del fuente 3. Como podemos ver, recuperamos todos los nombres de la carpeta indicada y los recorremos recuperando sus valores.

Escribiendo un valor en una carpeta de registro

Eliminando un valor en una carpeta de registro

Aprovechando el ejemplo anterior, crearemos un nombre y valor dentro de la carpeta de regis-

Nuestro cometido ahora, será el de eliminar un nombre y valor situado dentro de una determinada carpeta. Seguiremos utilizando para ello la car-


<< dnm.plataforma.net

Para acceder al registro de Windows, debemos hacer uso de un nombre de espacio, que será el comunicador directo con las clases que nos darán acceso al registro de Windows. El nombre de espacio Microsoft.Win32.Registry nos facilita por lo tanto, gran parte de este trabajo. peta que creamos en este artículo y que corresponde con HKEY_CURRENT_USER\Ejemplo.

Imports Microsoft.Win32 [...] ‘HKEY_CURRENT_USER\Ejemplo Dim MiRegKey As RegistryKey = Registry.CurrentUser.OpenSubKey(“Ejemplo”) ‘Recuperamos los nombres declarados dentro ‘de la carpeta anterior Dim ListaNombres() As String = MiRegKey.GetValueNames() Dim strNombre As String ‘Recorremos la lista de nombres para recuperar ‘sus valores For Each strNombre In ListaNombres MessageBox.Show(strNombre & “ = “ & MiRegKey.GetValue(strNombre)) Next ‘Cerramos el objeto MiRegKey.Close()

Fuente 3

Para eliminar un nombre y valor dado, deberemos hacerlo como se indica en el siguiente código:

o Predeterminado para nuestras aplicaciones. Es muy normal dejar ese valor inutilizado, pero en algunos programas o aplicaciones, puede resultarnos especialmente útil su uso. Usando la carpeta actual, HKEY_CURRENT_USER\Ejemplo, modificaremos manualmente el valor Default o Predeterminado, según como aparezca en su sistema operativo (depende del idioma). El acceso por código a este valor, sería tal y como podemos ver en el fuente 5.

Imports Microsoft.Win32 [...] ‘HKEY_CURRENT_USER\Ejemplo Dim MiRegKey As RegistryKey = Registry.CurrentUser.OpenSubKey(“Ejemplo”) ‘Obtenemos el valor Default o Predeterminado Dim strValor As String = CType(MiRegKey.GetValue(strValor, “DEFAULT-VALUE”), String) ‘Mostramos el contenido de este valor MessageBox.Show(strValor) ‘Cerramos el objeto MiRegKey.Close()

Fuente 5

Fuente 4

Accediendo al valor por defecto de una carpeta de registro Una de las particularidades sobre la que prácticamente nadie cae, es la de usar el valor Default

Conclusiones Como hemos podido observar en este artículo, el uso del registro en Windows es muy sencillo. Con el nombre de espacio Microsoft. Win32.Registry, tenemos acceso a las clases de acceso al registro. Lo que sí hay que tener siempre en cuenta, es la creación y tratamiento de los nombres y valores; tratamiento que según la complejidad que le hayamos dado, se puede llegar a producir en forma de árbol. Por último, me gustaría destacar que a veces el registro de Windows es especialmente útil para almacenar en él ciertos valores encriptados que debemos utilizar en nuestras aplicaciones.

<<dotNetManía

Imports Microsoft.Win32 [...] ‘HKEY_CURRENT_USER\Ejemplo Dim MiRegKey As RegistryKey = Registry.CurrentUser.OpenSubKey(“Ejemplo”, True) ‘Eliminamos el nombre y valor MiRegKey.DeleteValue(“MiNombre2”) ‘Cerramos el objeto MiRegKey.Close()

49


Por Manuel Imaz Consultor Independiente imaz@acm.org

Arquitecturas Orientadas a Servicios: Una introducción Cuando se intenta definir o describir algún nuevo concepto de una disciplina, es interesante mostrar algunos antecedentes o evolución histórica que permitan, no solamente ubicar al nuevo concepto, sino entender porqué surge, qué problemas resuelve, la forma en que los resuelve, etc.

<< En el caso de las Arquitecturas Orientadas a los Servicios, consideramos que una breve descripción de: • Sistemas Distribuidos • Servicios Web Pueden permitirnos entender el origen de algunos conceptos que, en el caso de SOA o Arquitecturas Orientadas a Servicios, han adquirido un sentido más general o un desarrollo más completo.

<<dotNetManía

Sistemas Distribuidos

50

Los sistemas distribuidos aparecen en los años 80 y el marco que intentaba definir la forma de integrar diversos elementos que posibilitaran dicha solución se denominó DCE (Distributed Computing Environment) o Entorno de Informática Distribuida. DCE brinda una infraestructura completa para la implementación de sistemas que son el resultado de ejecutar funciones en un conjunto de nodos distribuidos en una red local o una de área amplia. Este marco se denominó middleware -o tecnología posibilitadoradebido a que estaba en un nivel intermedio entre el sistema operativo y la aplicación -distribuida- que se ejecutaba. El organismo que regulaba este conjunto de componentes era el OSF (Open Software Foundation), que luego se convirtió en el Open Group, y tenía como objetivo brindar los servicios necesarios para llevar

a cabo la implementación de los sistemas distribuidos. Entre estos servicios se cuentan los de seguridad -para permitir la protección y el control de acceso a los datos, los de nombres -que posibilitan la ubicación de los recursos distribuidos, de persistencia que brindan una interfaz para almacenar los datos en bases de datos, etc. La evolución de DCE fue la de CORBA (Common Object Request Broker Architecture), un equivalente de DCE en términos de la tecnología de objetos. Esta arquitectura se basa fundamentalmente en la distribución de componentes a través de un bus lógico que permite la conexión de todos los elementos necesarios para ejecutar una aplicación de objetos distribuidos. Los servicios ofrecidos por CORBA ampliaban los originales de DCE e incluían aspectos tales como los de ciclo de vida (con operaciones para la creación, desplazamiento o borrado de componentes en el bus), el servicio de eventos (para registrar o eliminar el interés de determinados tipos de eventos), el servicio de transacciones (para posibilitar la coordinación de los commits en dos fases), etc. Pero lo que debemos tener en cuenta de esta arquitectura es la oferta de distintos tipos de servicios que permiten garantizar una serie de funciones que no requieren ser contempladas en cada una de las aplicaciones implementadas. Esta arquitectura en la que las aplicaciones se basan en marcos (horizontales y verticales) que a su vez se asientan en los servicios CORBA y éstos a su vez en


<< dnm.arquitectura un bus común de objetos puede representarse de la siguiente manera, usando la metáfora de capas que hemos visto en los artículos anteriores.

requiere ajustarse a ninguna plataforma o conjunto tecnológico. El tipo más ampliamente aceptado de servicio es el Servicio Web XML1 (de aquí en adelante llamado servicio Web o simplemente servicio). Estos servicios tienen dos requisitos fundamentales: • Se comunican vía protocolos Internet (más frecuentemente HTTP2) • Envían y reciben datos formateados como documentos XML La amplia aceptación del modelo de diseño de servicios Web ha determinado la emergencia de un conjunto de tecnologías suplementarias que se han convertido en estándares de facto. Un servicio estándar de la industria se supone que va a: • Suministrar una descripción del servicio que, como mínimo, consiste en un documento WSDL3. • Ser capaz de transportar documentos XML utilizando SOAP4 sobre HTTP.

Figura 1. La arquitectura CORBA

Una visión completa de la Arquitectura Orientada a Servicios implica el manejo de innumerables acrónimos cuyo significado es necesario conocer para que la perspectiva de dicha arquitectura resulte adecuada. Aunque el concepto de servicio comienza a ser utilizado en CORBA, en dicha arquitectura el concepto está ligado al de componente, es decir un bloque constructivo independiente que en conjunto representan un entorno de la aplicación. Pero a diferencia de los componentes tradicionales, los servicios tienen un número de características únicas que les permite participar en una arquitectura orientada a los servicios. Una de estas cualidades es su completa autonomía respecto de otros servicios. Esto significa que cada servicio es responsable de su propio dominio, lo que se traduce normalmente en limitar su alcance a una función específica de negocio (o un grupo de funciones relacionadas). Este enfoque de diseño desemboca en la creación de unidades aisladas de funcionalidad de negocio que están débilmente ligadas mediante la conformidad a marcos de comunicación estándar. Debido a la independencia de que gozan los servicios dentro del marco, la lógica de programación que encapsulan no 1 2

3

4

Esto significa que los servicios Web no encajan en el modelo clásico de cliente-servidor. En su lugar, tienden a establecer un sistema peer-to-peer -P2P-, en el que cada servicio puede jugar el rol de cliente o de servidor Además, es frecuente en relación con estos servicios que: • Sean capaces de ser al mismo tiempo el peticionario y suministrador de un servicio. • Estén registrados por un agente descubridor a través del cual puedan ser ubicados.

XML -o eXtensible Markup Language- es un lenguaje apuntado (o marcado) para crear documentos con información estructurada. El HTTP es uno de los protocolos más recientes (1996), que se ha expandido internacionalmente gracias a Internet. Su función fundamental es la de interfaz con WWW (World Wide Web) y, en consecuencia, con HTML (Hyper-Text Markup Language), el lenguaje que está a la base de los documentos hiper-textuales. HTTP ha sido proyectado como un protocolo "state-less", es decir, sin memoria. WSDL (Web Services Description Language) es un formato XML para describir servicios de red como un conjunto de puntos finales operando sobre mensajes que contienen información ya sea orientada a documentos u orientada a procedimientos.Los documentos WSDL definen los servicios como colecciones de puntos finales de red o puertos. En WSDL, la definición abstracta de puntos finales y de mensajes se separa de la instalación concreta de red o de los enlaces del formato de datos. SOAP es un protocolo ligero basado en XML,para el intercambio de información en un ambiente descentralizado y distribuido.El SOAP permite la intercomunicación entre objetos de cualquier tipo - sobre cualquier plataforma, en cualquier lenguaje.

<<dotNetManía

Servicios Web

Estas tecnologías no alteran la funcionalidad central de un servicio Web en tanto y en cuanto mantienen su habilidad para representarse a sí mismos y comunicarse de una forma estándar. Muchas de las convenciones arquitectónicas asumen que tanto SOAP como WSDL forman parte del marco definido de servicios Web.

51


<< dnm.arquitectura

Figura 2. Servicios Web intercambiando sus roles en una conversación

En una conversación típica con un servicio Web, el cliente que inicia la petición es también un servicio Web. Es decir que cualquier interfaz expuesta por un “servicio cliente” lo convierte en un servicio del cual otros servicios pueden solicitar información. Esto significa que los servicios Web no encajan en el modelo clásico de cliente-servidor. En su lugar, tienden a establecer un sistema peer-to-peer -P2P- (de par a par, de igual a igual o entre pares o iguales), en el que cada servicio puede jugar el rol de cliente o de servidor.

protocolo común de comunicaciones. Cuando se utilizan servicios Web para establecer este marco de comunicaciones, eso representa básicamente una implementación basada en la Web de una AOS. La arquitectura resultante establece esencialmente un paradigma de diseño dentro del cual los servicios Web son un bloque constructivo clave. Esto significa que cuando migramos nuestra arquitectura de la aplicación a una AOS, nos estamos comprometiendo a aplicar los principios de diseño de servicios Web y de las tecnologías que los acompañan como partes centrales del entorno tecnológico. Una AOS basada en servicios Web XML construye en base a capas de tecnología XML bien establecidas con el foco en exponer la lógica de las aplicaciones existentes como servicios débilmente acoplados. Soportando este modelo, una AOS promueve el uso de mecanismos de descubrimiento de los servicios a través de un broker de servicio o agente descubridor.

Arquitectura Orientada a Servicios (AOS)

<<dotNetManía

En general, no hay demasiados problemas en añadir unos cuantos servicios Web a una aplicación. Esta integración limitada puede ser adecuada como una experiencia de aprendizaje o para ampliar una arquitectura de aplicación existente con una pieza de funcionalidad basada en servicios que se ajusta a un requisito de un proyecto específico. Pero esto, de por sí, no constituye una arquitectura orientada a servicios. Una AOS es un modelo de diseño con un concepto sumamente arraigado de encapsular la lógica de la aplicación dentro de servicios que interactúan a través de un

52

En general, no hay demasiados problemas en añadir unos cuantos servicios Web a una aplicación. Esta integración limitada puede ser adecuada como una experiencia de aprendizaje o para ampliar una arquitectura de aplicación existente... Pero esto, de por sí, no constituye una arquitectura orientada a servicios

Figura 3. Relación entre Peticionario, Proveedor y Broker de servicio

Por supuesto, antes de que un cliente -o peticionario- pueda solicitar un servicio, necesita encontrar el proveedor (el cual ha publicado previamente el servicio). Este servicio de ubicar un posible proveedor es realizado por el broker de servicio, el cual opera típicamente con un repositorio. Cuando se le solicita, el broker de servicio devuelve un documento que permite al cliente, primero localizar, y luego unirse con el proveedor. Un cliente puede requerir múltiples servicios, cada uno con un proveedor diferente. El hecho de registrar los servicios en un registro central -repositorio- en el que los clientes pueden buscar, les brinda la flexibilidad necesaria para realizar búsquedas basadas en conjuntos de criterios que cambian dinámicamente y, de esta forma, no estar ligados estáticamente al proveedor. Sin dicho registro, el cliente debería estar obligado a codificar la ubicación del proveedor del servicio y complicar así el mantenimiento.


Por Pedro Pozo Clikear clikear.com

DevPartner Studio Professional Edition A qué desarrollador no le gustaría tener un experto a su lado comentándole qué mejoras puede hacer a su código,en qué partes está consumiendo más memoria o que métodos están penalizando el rendimiento de su desarrollo. DevPartner es ese experto que nos ayuda en la puesta a punto de nuestros desarrollos.

es que se integra como un Add-In de Visual Studio .NET; con eso ya nos hacemos a la idea de que es una herramienta que está desarrollada con la mirada puesta en este entorno de desarrollo. DevPartner nos permite realizar las siguientes tareas: • Revisión de código. • Análisis de aplicaciones distribuidas. • Detección de errores. • Análisis de rendimiento. • Análisis de memoria. • Análisis de alcance. Y todo esto podemos hacerlo sin salir de Visual Studio .NET, ya que se integra a la perfección con el entorno de desarrollo permitiendo realizar cualquiera de estas tareas. Como único inconveniente, los más clásicos, echamos en falta un manual en papel, aunque por supuesto vienen en el disco de instalación varios manuales en formato PDF que podemos imprimir. DevPartner además de integrarse en Visual Studio .NET, nos permite ejecutarlo desde la línea de comandos para poder integrarlo, por ejemplo, en revisiones nocturnas de código, pudiendo realizar una explotación de la información extraída en Access para la creación de informes personalizados.

Revisión de código Una de las funcionalidades que mas gustará a los programadores es la revisión de código que realiza

DevPartner. Se trata de una utilidad que nos permitirá afinar al máximo nuestro código, mejorando el rendimiento, seguridad, mantenimiento y escalabilidad de nuestros desarrollos. Tan sólo pulsando un botón nos creará un amplio informe con las posibles mejoras que podemos realizar a nuestro código fuente. Este informe nos indicará las posibles mejoras del código, mostrándonos una amplia explicación del motivo por el cual deberíamos modificarlo. También cabe destacar que no sólo lleva una explicación de cómo mejorar el código, sino que también incluye, en la mayoría de los casos, ejemplos con código de cómo realizar las mejoras. La detección de estas posibles mejoras se realiza a través de reglas, siendo éstas totalmente configurables. Esto permite una gran flexibilidad a la hora de realizar revisiones de código, pudiendo personalizar esa revisión a gusto del desarrollador. DevPartner incluye un completo gestor de reglas que nos permite añadir, modificar o eliminar las reglas que deseemos, para así obtener unos informes personalizados de las posibles mejoras del código y comprobando que se cumplen en todo el proyecto las reglas que determine el usuario.

Análisis de aplicaciones distribuidas Las aplicaciones Web utilizan numerosos recursos de distinto tipo, como un servidor de páginas Web, una base de datos, un lenguaje para el servidor o un lenguaje de script para el cliente. Todo esto supone

<<dotNetManía

<< Cuando instalamos DevPartner lo primero que comprobamos

53


<< dnm.laboratorio.net que nos indican lo que ocurre cuando sucede cada evento en una máquina, un proceso o un hilo de ejecución.

Detección de errores

<<dotNetManía

Figura 1. DevPartner - Análisis de aplicaciones distribuidas.

54

que realizar un análisis de las posibles mejoras de una aplicación de este tipo, o detectar los cuellos de botella o posibles errores de programación sea bastante complejo. DevPartner permite analizar aplicaciones Web a través de un entorno propio, cuyo interfaz podemos ver en la figura 1. Analiza todos los eventos que ocurren en la aplicación, y así genera informes sobre errores, código poco optimizado, y rendimiento de la aplicación. A través de la herramienta que incluye DevPartner para analizar aplicaciones distribuidas se van revisando todos los eventos que van ocurriendo en la aplicación que hemos decidido monitorizar. Así se va registrando todo lo que ocurre en nuestras páginas Web, los ficheros que se cargan, los objetos, los scripts, y llegando a un nivel de detalle que permite localizar mas fácilmente cualquier problema en la aplicación. Los resultados del análisis los podemos ver en un panel de resultados y en un panel de eventos y métricas. En el panel de resultados aparecen los datos clasificados en Alarms, Hints o Alerts. Alarms indican que existe un pro-

blema en el código analizado y que debe investigarse una posible mejora; Hints nos ofrecen valiosas sugerencias que nos pueden ayudar a mejorar el rendimiento de nuestra aplicación en trozos de código que son analizados y son susceptibles de mejora ya que si no pueden penalizar el rendimiento de nuestra aplicación; y por último Alerts nos muestran los valores que exceden de un límite determinado en nuestra aplicación y

A través del analizador de errores, podemos lanzar sesiones de nuestra aplicación que serán analizadas y guardadas para su posterior estudio por parte del desarrollador. Se genera un informe de todos los métodos por los que hemos pasado por la sesión analizada. Este informe nos indicará el tanto por cierto de líneas de código revisadas, así como el número de llamadas a cada proceso; incluso podemos profundizar un poco más y ver el número de veces que se ha ejecutado cada línea de código. De esta forma podemos comprobar por dónde ha pasado la ejecución del programa y dónde no, para así poder localizar errores y posibles mejoras. El sistema de detección de errores también nos permite, entre otras cosas, detectar el mal uso de memoria, uso incorrecto a las llamadas al API de Windows, uso incorrecto de punteros, y analizar llamadas de código manejado a código nativo.

Si necesitamos realizar una puesta a punto de nuestro desarrollo, mejorar el rendimiento, localizar los cuellos de botella, reducir el consumo de memoria y en definitiva mejorar nuestro código, DevPartner nos ayudará a realizar todas estas tareas puede causar por tanto problemas en nuestros desarrollos. En el panel de eventos y métricas, podemos ver todos los eventos que se han producido en la aplicación, organizados de una forma jerárquica, y unos gráficos

Análisis de rendimiento Para mejorar el rendimiento de nuestra aplicación, DevPartner también dispone de una interesante funcionalidad que nos genera un informe que nos indica el tiempo que ha gastado cada uno de los


<< dnm.laboratorio.net rimientos tanto de hardware como de software son los que tenga nuestro entorno de desarrollo. En la siguiente tabla podemos ver las recomendaciones mínimas:

Requisitos mínimos

métodos de nuestro código fuente, incluso el tiempo consumido por cada una de las líneas de nuestro código. De esta forma tendremos un completo informe que nos permitirá ver cuáles son los cuellos de botella de la aplicación, y dónde podemos mejorar el rendimiento. Si queremos tener una visión más atractiva de nuestro informe podemos ir a cualquiera de los métodos de nuestra aplicación y ver un gráfico del análisis realizado, dónde nos mostrará un gráfico con nodos. Aparecerá un nodo con el método que hemos elegido y los nodos representando a los métodos hijo del método analizado. Podemos ver un ejemplo de estos gráficos en la figura 2. El análisis de rendimiento no sólo se realiza en el código escrito por nosotros, también realiza un análisis de código hecho por terceras partes o de los procesos del sistema operativo, permitiendo así descubrir dónde están produciéndose los cuellos de botella.

Análisis de memoria Especialmente interesante en el desarrollo es el análisis de la memoria, y por supuesto DevPartner se encarga de manera detallada. El informe que nos genera DevPartner de la memoria es muy completo; nos mostrará desde la memoria consumida por cada uno de los objetos pudiendo verlos ordenados por consumo, hasta la memoria consumida por cada método. Dentro de una página podremos ver a través de gráficos cuánto ha con-

sumido cada uno de los métodos que se ejecutan. Así de esta forma visual, podremos ver rápidamente cuáles son los procesos que más recursos están consumiendo.

Análisis de alcance Esta herramienta de DevPartner nos permite localizar código que no ha sido probado, disminuyendo así el tiempo de pruebas, y haciéndolas más fiables para no dejar ningún cabo suelto a la hora de probar nuestra aplicación. Este análisis también nos permite almacenar los datos utilizados en nuestra aplicación y poder recopilar los datos de servidor y de cliente, pudiendo así hacer una comparativa de ambos. Si tenemos varias personas realizando las pruebas, podemos almacenar todos los datos generados por estas personas en las pruebas y luego compararlos para poder así localizar mejoras del código o errores. También soporta múltiples lenguajes como Visual Basic, C#, Visual C++, incluso lenguajes de script como Javascript y VBScript. Además tenemos la posibilidad de realizar un análisis integrado con detección de errores en una misma sesión.

Requisitos del sistema Hay que destacar que DevPartner está preparado para funcionar en Visual Studio 6, Visual Studio .NET 2002 y Visual Studio .NET 2003. Al tratarse de una aplicación integrada en Visual Studio .NET los reque-

Software

Pentium III 733 Mhz

Microsoft Internet Explorer 5.01 o superior

256 MB memoria Microsoft Script Ram DebuggerVersion 1.0a 500 MB espacio libre en disco

Microsoft Windows 2000, XP ó 2003

Unidad CD ó DVD

Conclusiones Si necesitamos realizar una puesta a punto de nuestro desarrollo, mejorar el rendimiento, localizar los cuellos de botella, reducir el consumo de memoria y en definitiva mejorar nuestro código, DevPartner nos ayudará a realizar todas estas tareas. Desde los programadores hasta los arquitectos de software, pasando por los departamentos de calidad del software, DevPartner puede ser utilizado para mejorar las aplicaciones que desarrollemos, y será de gran utilidad para conseguir código de calidad y en consecuencia aplicaciones de calidad.

Ficha técnica Nombre

Devpartner Studio Professional Edition

Versión

7.2.0

Fabricante

Compuware

Web

www.compuware.com

Categoría

Visual Studio Add-In

Precio

A partir de 2.850€ (con mantenimiento)

Valoración

<<dotNetManía

Figura 2. Grafico de nodos.

Hardware

55


dnm.comunidad.net

<<

dnm.comunidad.net

SpainNet Vocación de comunidad al alcance de todos Ni tan siquiera la tercera generación de Internet sustituye el calor de una buena reunión entre colegas. Romper la barrera de nuestra interacción individual y sumar esfuerzos en construir actividades que sean útiles a un colectivo virtual por excelencia, es una de las mejores experiencias para los miembros de SpainNet

<<dotNetManía

<< La común_unidad, no es una reunión a

56

la que los vecinos de escalera deben asistir una vez al año, a pesar de que muchos lo crean así, si bien es cierto que existen muchos tipos de comunidades. SpainNet nace en el año 2001, como vinculo entre profesionales, estudiantes y aficionados compartiendo un espacio común. En la base y en espíritu SpainNet, más que un punto de encuentro, es una función vital de unir y representar a la comunidad de desarrolladores de una manera plural, independiente y al alcance de todos, además de divulgar y compartir los conocimientos de la misma, entre sus miembros. Fundamentado en un marco no lucrativo, potenciamos al máximo tres valores: la comunicación, la divulgación y el aprendizaje, todo ello respaldado por los recursos de la propia comunidad y la ayuda de entidades sociales colaboradoras. No es nada nuevo ver la formación de grupos de profesionales, estudiantes o aficionados, organizados alrededor de inquietudes y dificultades. Sin embargo SpainNet crece rompiendo ciertas barreras, ¿porqué no?; Pretendemos mejorar y promocionar la interacción y la comunicación entre los desarrolladores de todo el Estado, así como aportar, compartir y divulgar el conocimiento del grupo en bien de sus miembros, con independencia de su nivel, posición o situación. Nuestro lema inicial fue “Conocimiento y Tecnología Patrimonio de Todos”. Queremos ser la parte visible de un colectivo excesivamente virtual. Ayudar a romper el mito del “lerdo”, cualquier persona debe ser capaz de utilizar herramientas de desarrollo o hacer uso de cualquier medio, que

dé rienda suelta a su creatividad. Es nuestra tarea como grupo, y apoyados en nuestros voluntarios, minimizar la dependencia tecnológica a nivel social, organizando encuentros, cursos, talleres y otros eventos, fundamentados en mecanismos que no sirven a intereses comerciales ni políticos. Nuestra infraestructura es la plataforma donde cualquier iniciativa o idea pueda tomar forma; disponemos del suficiente bagaje para poder encontrar o negociar recursos que permitan materializar prácticamente cualquier propuesta. Todo ello es posible gracias a nuestra condición cooperativista y no productiva; el mero hecho de no tener que soportar una estructura económica, nos desvincula de cualquier otro interés. Todo lo que hacemos es por la ilusión de compartir y materializar nuestro conocimiento, renunciando a comercializar nuestro excedente y aprovechando el de la sociedad del bienestar. Construimos por lo tanto, con un potencial probablemente mayor que el de la inteligencia... ¡la ilusión! Nos llena de satisfacción declarar que ¡NO HAY NINGÚN OTRO MOTIVO! Hacemos asequible para nuestros miembros y personas afines, recursos como charlas de expertos, literatura técnica, material informático o electrónico, etc. Todo ello gracias a nuestros acuerdos de colaboración y esponsorias con diversas instituciones y entidades, así como a través de nuestra relación con otras asociaciones de ámbito nacional e internacional, como por ejemplo INETA.

Lo que realmente es un hecho consumado, es la consolidación del grupo con aproximadamente 94 personas, 40 de las cuales participan de una manera habitual y 15 de ellas se comprometen al extremo de dedicarle un montón de horas semanales. En todo caso hemos sido capaces de atender el interés de unas 265 personas, y la cosa crece. Es importante comentar en su medida, la entrada en funcionamiento de nuestro portal unido a la propiedad de un servidor exclusivo para nuestra comunidad, en una ADSL de 2Mb. Aparte, lo más significativo de este año lo dejamos atrás en tres sesiones intensas en la universidad, hablando sobre .NET Framework, XML, Longhorn, Indigo, Yukon en Febrero. Cabe destacar a finales de Julio la organización del evento del Visual Basic 2005 Tour por Europa en España. Así como nuestra colaboración en la Semana Digital que organiza el Ayuntamiento y la Universidad en Vic, para terminar merendando una de 30 horas de ASP.NET, Web Matrix, Visual Basic.NET y MSDE durante este mes de noviembre. Si la cosa da para más, esperamos poder estar ayudando en la semana digital ExpoEnter en Orense, así como poderos explicar importantes iniciativas para este próximo año. Podéis encontrarnos en www.ineta.org/latam en www.panoramabox.com y provisionalmente en http://weblogs. golemproject.com/spainnet. Pep Lluis Baño es Presidente de SpainNet


<< dnm.biblioteca.net

dnm.biblioteca.net

Programming Microsoft .NET XML Web Services Damien Foggon, Daniel Maharry, Chris Ullman y Karli Watson Editorial: Microsoft Press ISBN: 0735619123 Páginas: 698 Publicado: Agosto-2003

Este mismo año ha visto la luz esta completa obra sobre programación de servicios Web con .NET, a la que -sin duda- debo de calificar como una de las más completas de su género. Recorre todo el escenario de construcción de servicios y de implantación de clientes, desde los fundamentos donde se basan los estándares de creación, SOAP, WSDL, DISCO y UDDI, hasta las implantaciones prácticas y sus soluciones de optimización.

Expert Web Services Security in the .NET Platform Laurence Moroney, Brian Nantz Editorial: APress ISBN: 0735615551 Páginas: 456 Publicado: Noviembre-2004 Obra muy recientemente aparecida, que podríamos considerar, desde algunos puntos de vista, como complementaria de la anterior. Los autores describen previamente los fundamentos en los que puede basarse la seguridad en servicios Web dentro de los estándares actualmente establecidos, y basándose en las últimas versiones, tanto de Visual Studio, como de las Extensiones de los Servicios Web, e Internet Information Server, para pasar a profundizar en el uso de estas extensiones, haciendo especial hincapié en WSSecurity, WS-Attachments, WS-Routing, WS-Authorization y WS-Encryption, como modelos de desarrollo. Especialmente notables son las páginas dedicadas a la criptografía, incluyendo un interesante análisis sobre criptografía de clave pública, y lo que los propios autores denominan “criptografía asíncrona”, por oposición a la tradicional “criptografía simétrica”.

<<dotNetManía

<<

Además, incluye tratamiento de datos, gestión de estado, cuestiones de rendimiento y seguridad, y -muy importante- una exhaustiva explicación del funcionamiento de las Web Services Extensions, con muchos ejemplos de funcionamiento y despliegue.

57


<< dnm.desvan

noticias.noticias

Marino Posadas

Microsoft no planea incluir la navegación multipágina en IE, sino la potenciación de sus complementos (IE plug-ins) En una entrevista concedida a BetaNews, Gary Schare, Director of Windows Product Management en Microsoft, declaraba que no habría grandes cambios en el navegador hasta la aparición de Longhorn, a mediados de 2006. "Hacerlo, supondría romper don muchas cosas ya en funcionamiento por parte de terceros, a los que debemos apoyar también. Lo mismo sucede con las posibles extensiones del estándar CSS de Hojas de Estilo. Existen muchas aplicaciones y soluciones corporativas que utilizan ActiveX para extender las posibilidades de IE. Además algunas de esas características romperían políticas de seguridad que no estamos dispuestos a romper." (Recordemos al lector, que IE en realidad, consta de dos partes: la interfaz de usuario de navegación y un núcleo de interpretación de páginas -ampliable mediante ActiveX- llamado SHDOCVW.dll, que puede ser usado para procesos de automatización). Otras fuentes, confirman -además- esta

idea, valorando las actualizaciones automáticas del software que Microsoft piensa seguir haciendo, lo que coincide con el hecho de que ya se haya publicado la continuación de WUS (Windows Update Services), cuya beta está ya disponible y cuya versión final verá la luz a mediados de 2005 (www.eweek.com/article2/0,1759,1728284,00.asp).

Disponible una “Preview” de Avalon Paralelamente, los avances en la implementación de las API's de Longhorn para otras plataformas, se suceden. A finales de noviembre, se hizo pública una CTP (Community Technology Preview) de Avalon, el subsistema de gráficos que utilizará Longhorn y que será instalable en Windows XP y Windows 2003. La beta "oficial" de Avalon, se espera para el próximo verano, junto con la primera beta de Longhorn. Y a todo esto, hay que añadir la aparición de versiones de terceras partes, como XAMLON (www.xamlon.com) y LASZLO (www.laszlosystems.com)

Documentos en la Red Cómo reinstalar todo el software en un PC seriamente amenazado: Cuando la amenaza es seria, el problema radica en volver a dejar todo como estaba antes. Tremenda labor, en la que siempre se queda algo en el camino. El documento How To Re-Install All The Software On A Seriously Gummed-Up PC, pretende servir de ayuda en tan ingrata tarea. Se encuentra en www.securitypipeline.com/showArticle.jhtml?articleId=53200389

“The ADO Object Model” y “Referential Integrity Explained: Bonding Tables Together”, son dos interesantes documentos para desarrolladores, publicados por ASP.FREE recientemente. El lector puede acceder a ellos en www.aspfree.com/c/a/ASP.NET/The-ADO-Object-Model y www.aspfree.com/c/a/Database/Referential-Integrity-Explained-BondingTables-Together/ respectivamente.

Enlaces del mes

<<dotNetManía

Sitio Web del MVP Alejandro Mezcua, gran experto en MS-Exchange y programación de dispositivos móviles. Contiene noticias, artículos y rutinas de interés. www.byteabyte.net.

58

Sitio Web de Michelle Lerroux Bustamante, una de las mejores divulgadoras de tecnologías Web de la actualidad, especializada en servicios Web y arquitectura SOA. Contiene interesantes ejemplos gratuitos de utilización con código fuente incluidos. (Ver www.dotnetdashboard.net/ark/wstutorial.aspx).

A Marcos que vio la luz mientras buscábamos el tema de la tira cómica del mes :-). Esperamos que esto sea augurio de una vida divertida.


Suscripción a dotNetManía ❑ Deseo suscribirme a dotNetManía por un año (11 ejemplares) y beneficiarme de la oferta del 10% de descuento por un importe total de 60 € para España; o por 75 € para el resto de Europa; o por 90 € para el resto del mundo (IVA incluido). ❑ Deseo suscribirme a dotNetManía por un año (11 ejemplares) por un importe de 45 € por ser estudiante (IVA incluido). Aporto fotocopia del carné de estudiante o sello del centro académico (IMPRESCINDIBLE). OFERTA VÁLIDA SÓLO PARA ESTUDIANTES RESIDENTES EN ESPAÑA. IMPORTES VÁLIDOS HASTA NUEVA OFERTA DATOS DE FACTURACIÓN CIF/NIF . . . . . . . . . . . . . . . . . . . . .Empresa . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Nombre y apellidos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Dirección . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Población . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Código Postal . . . . . . . . . . . . . . . . . . . Provincia . . . . . . . . . . . . . . . . . . . . . . . . . Teléfono . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Fax . . . . . . . . . . . . . . . . . . . . . . . . . . . email . . . . . . . . . . . . . . . . . . . . . . . . . . . . DATOS DE ENVÍO (sólo si son distintos de los datos de facturación) CIF/NIF . . . . . . . . . . . . . . . . . . . . .Empresa . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Nombre y apellidos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Dirección . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Población . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Código Postal . . . . . . . . . . . . . . . . . . . Provincia . . . . . . . . . . . . . . . . . . . . . . . . . Teléfono . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Fax . . . . . . . . . . . . . . . . . . . . . . . . . . . email . . . . . . . . . . . . . . . . . . . . . . . . . . . .

FORMA DE PAGO ❑ Talón nominativo a nombre NETALIA, S.L. ❑ Transferencia bancaria a nombre de NETALIA, S.L. a: La Caixa - Número de cuenta 2100 4315 48 2200014696 (Indique su nombre en la transferencia) ❑ Domiciliación Bancaria (con renovación automática, previo aviso) Indique su número de cuenta: ❑ Tarjeta de crédito ❑ VISA ❑ MASTERCARD Número de su tarjeta: Fecha de caducidad:

/

(imprescindible)

Firma y/o sello (imprescindible) a

❑ Nº3

❑ Nº4

❑ Nº5

de

❑ Nº6

Usted autoriza a la mecanización de estos datos. El responsable y destinatario de éstos es Netalia, S.L. Usted tiene derecho a acceder a sus datos, modificarlos y cancelarlos cuando lo desee. Sus datos no serán cedidos en ninguna de las formas posibles a terceras partes y no se utilizarán más que para el buen funcionamiento de su suscripción a la revista dotNetManía y para informarle de las actividades comerciales que realice la editorial Netalia, S.L. Si no desea recibir información comercial de dotNetManía marque la casilla siguiente ❑

de 20

❑ Nº7

❑ Nº8

Si desea algún otro número indíquelo

Puede enviar los datos al email suscripciones@dotnetmania.com, al FAX (34) 91 499 13 64 o al teléfono (34) 91 666 74 77. También puede enviarlo por correo postal a la siguiente dirección:

C/ Robledal, 135 28529- Rivas Vaciamadrid Madrid (España)

❑ Nº9


dotNetManía #010  
Read more
Read more
Similar to
Popular now
Just for you