Qué es WSE 2.0? - Tecnología, Tips y Programación por Sergio
Transcripción
Qué es WSE 2.0? - Tecnología, Tips y Programación por Sergio
nº16 junio 2005 • 6,00 € (España) 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 ¿Qué es WSE 2.0? Una visión de alto nivel de qué es WSE y cómo se integra con .NET Entrevista a Nuria Oliver Investigadora de Microsoft Research en EEUU Comunidad.net El sitio de “El Guille”, un sitio con más de ocho años de historia ToDotNet Q&A Acceso a datos y contenedores de datos MVP Online Aviso para navegantes Legal De igual a igual: ¿es legal el intercambio de ficheros en la Red? Generando hojas Excel con ASP.NET • Creación de complementos en Visual Studio .NET • Interfaces • Herencia: ¿To be or not to be? dnm.editorial dotNetManía Hawaii Vol. II •Número 16 • Junio 2005 Precio: 6€ (España) Editor Paco Marín ([email protected]) Administración Pilar Pérez ([email protected]) Asesor Técnico/Coordinación Marino Posadas ([email protected]) Redactores Antonio Quirós, Dino Esposito, Guillermo 'guille' Som, Jorge Serrano, José Manuel Alarcón, Luis Miguel Blanco, Miguel Katrib (Grupo Weboo) y Pedro Pozo. Colaboradores habituales Ángel Esteban, Braulio Díez, Eladio Rincón, Erich Bühler, Fernando Nogueras, Jorge Crespo Cano, José Miguel Torres, Miguel Egea, Octavio Hernández, Pablo Abbate, Pepe Hevia, Rodrigo Corral y Salvador Ramos. Además colaboran en este número Carlos J. Quintero, César de la Torre, José Antonio Suárez Lozano y Reyes García 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 ([email protected]) 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 << Ya es público: Hawaii es el nombre en clave de la “segunda siguiente versión” de Visual Studio, o sea, la que seguirá a Orcas, que es el nombre en clave de la que seguirá a Whidbey que, a su vez, siguió a Everett y ésta a Rainier... ¡Cómo me gustan los codenames! ¿No me dirá que Hawaii no suena bien? Para SQL Server aún no sabemos cuál será el codename de la “segunda siguiente versión” de SQL Server 2005. Sólo sabemos que el de la siguiente versión será Acadia, y que muy probablemente se llamará SQL Server 2007. Y un triste adiós a Magneto porque a partir mayo es Windows Mobile 5.0. Me pregunto por qué no dejarán estos codenames como definitivos, ¡a mí me gustan más! Bienvenidos al número 16 de junio de 2005 de dotNetManía. En este número entrevistamos a la primera mujer –será difícil llegar a la paridad en esto por ahora–: Nuria Oliver, una joven investigadora española que realiza sus trabajos de investigación para Microsoft Research en EEUU. Éste es un mes de estrenos: de caras nuevas, de nuevos autores que aportarán también cosas nuevas y de una nueva sección: dnm.inicio.*, dirigida por “El Guille” y dedicada a difundir las bases de .NET Framework desde un punto de vista teórico (dnm.inicio.fundamentos), y desde un punto de vista práctico (dnm.inicio.taller) y que no sólo vendrá bien a los que están empezando –¿a estas alturas? se preguntará; pues sí, aún hay muchas personas que están empezando o que no lo han hecho todavía–, sino también a algunos profesionales que a pesar de serlo y ejercer como tales, tienen algunas lagunas y que nos vienen demandado artículos de este tipo. Ojo, que no será una sección para dummys ni mucho menos. Empezamos por dar la bienvenida a una mujer: Reyes García, la primera también, quien empieza colaborando con Braulio Díez, con el artículo “Generando hojas Excel con ASP.NET”, siguiendo éste con su visión práctica que, al menos a mí, tanto me gusta. Tengo que dar la bienvenida igualmente a César de la Torre, de uno de los Microsoft Gold Partner: Renacimiento, quien nos escribe el artículo “¿Qué es Microsoft WSE?”. Espero que podamos contar más con él para que nos cuente más en profudidad sobre las especificaciones WS-* y, sobre todo de Indigo. Y también doy la bienvenida a Carlos J. Quintero, autor de las MZTools y MVP de Visual Developer .NET quien nos escribe de lo que más sabe, de cómo crear complementos en Visual Studio .NET en su artículo “Creación de complementos en Visual Studio .NET”. Espero que Carlos quiera seguir escribiendo sobre estos temas que de seguro le interesará. En la sección arquitectura y metodologías Daniel Mazzini escribe un buen artículo sobre los patrones Delegado y Superclase Abstracta. Tenemos planes para continuar hablando de patrones básicos, de creación, de UI y UIP, de estructura y de comportamiento. Dino Esposito, como siempre explicando cosas complejas con sencillez, toca temas como el acceso a datos, remontándose a los oscuros tiempos del RDO hasta ADO.NET y también nos ayuda a elegir entre la gran cantidad de clases de colecciones que hay en el .NET Framework. No se pierda el próximo mes que tenemos un extenso monográfico de SQL Server 2005, donde han colaborado muchas personas para hacerle llegar la mejor información. Espero que le guste. <<dotNetManía Dedicada a los profesionales de la plataforma .NET 3 16 dnm.sumario De igual a igual: ¿es legal el intercambio de ficheros en la Red? 10-11 La legalidad de las copias de las obras de creación, y especialmente de las musicales y cinematográficas, efectuadas por usuarios finales mediante el recurso a las redes de intercambio de ficheros de igual a igual (p2p) ha sido defendida y contradicha en numerosas ocasiones en España. Tal vez sea el momento para hacer una aproximación al fenómeno con una cierta mayor distancia y, especialmente, dejando al usuario la opción de elegir cual debe ser su conducta al respecto. Entrevista a Nuria Oliver 12-14 Nuria Oliver es investigadora en Microsoft Research en Estados Unidos. Previamente estuvo en el mítico Media Lab del MIT (Massachusetts Institute of Technology). Su trabajo se basa fundamentalmente en la interacción de las máquinas con el ser humano a través de la percepción de éstas del mundo que les rodea. Generando hojas Excel con ASP.NET 15-19 Hoy en día las hojas Excel se han convertido en un estándar para representar información financiera, de control de stock, etc. Cuando hablamos de ASP.NET solemos tener asociado el HTML como formato de representación de la información, otras alternativas nos hacen pensar en problemas de rendimiento, o herramientas con un coste elevado, ¿existe alguna forma sencilla de hacer esto con .NET? dnm.sumario ¿Qué es Microsoft WSE? 20-26 Microsoft WSE es un nuevo módulo de componentes .NET que permite extender el marco de trabajo de .NET Framework 1.1 para poder desarrollar servicios Web XML con características avanzadas. WSE es algo que, sin embargo, al no tenerlo disponible directamente con Visual Studio 2003 no es muy conocido por el momento, pero si se quiere desarrollar un servicio Web XML complejo, hoy en día, la única opción es basarse en WSE 2.0. La intención de este artículo es simplemente dar una visión de alto nivel de qué es WSE y cómo se integra mediante SOAP con .NET 1.1 y Visual Studio 2003. Creación de complementos en Visual Studio .NET 28-34 Aunque Visual Studio .NET es uno de los mejores entornos de desarrollo jamás creados, siempre habrá funcionalidades que echemos en falta. Afortunadamente Microsoft ya pensó en ello y nos permite añadir nuestras propias funcionalidades a medida mediante complementos, que aprenderemos a crear en este artículo. Interfaces.Yo implemento, tu implementas,... ¡implementemos todos! 36-39 En este primer artículo de esta nueva seccción explicamos los Interfaces. Los interfaces son unos de esos elementos de .NET Framework que juegan un papel bastante importante, pero que, a pesar de estar por todas partes, aparentemente pasan desapercibidas... Herencia: ¿To be or not to be? 41-46 En este artículo se demuestra por medio de patrones cuando la herencia es una buena opción y algunos síntomas que nos pueden indicar cuando usarla se puede convertir en un problema y cómo resolverlo. dnm.mvp.online 47-48 Aviso para navegantes dnm.comunidad.net 50-51 El sitio de “El Guille”, un sitio con más de ocho años de historia dnm.todotnet.qa 52-54 Acceso a datos y contenedores de datos. dnm.biblioteca.net 57 ADO.NET and System.Xml 2.0 (Alex Homer, Dave Sussman y Mark Fussel) C# 2.0: Practical Guide for Programmers (Michel de Champlain y Brian Patrick) dnm.desvan 58 dnm.noticias 6 noticias.noticias.noticias.noticias.noticias.noticias << dotNetManía << dnm.noticias Microsoft celebró el Developer Days de Madrid Microsoft reunió a cerca de mil desarrolladores a los que hizo partícipes de las novedades tecnológicas deVisual Studio Studio 2005 y SQL Server 2005 el entorno de ejecución .NET 2.0”, una de las más esperadas, en la nos habló del soporte para 64 bit del nuevo CLR y de la librería de clases, así como de la depuración, con las nuevas características, como la tan demandada “editar y continuar” a la que estaban acostumbrados los desarrolladores de Visual David Salgado,David Carmona y Fernando Guerrero Basic 6 y que ahora volveremos a profiles como una de las novedades más tener, incluso los desarrolladores de C#, difundidas y también solicitadas por los así como de otras mejoras del depuradesarrolladores, así como un breve repador. Además habló, cómo no, de los so a los nuevos controles. Pero no menos genéricos (generics), y de sus venimportante, por no decir que más, era tajas y desventajas. Terminó con aprender sobre el acceso a datos y comun extenso resumen de las noveponentes de negocio. Con los nuevos dades de los lenguajes VB.NET controles como el GridView o el y C#. DetailsView y, sobre todo, cómo traDespués de un merecido bajar en dependencia de la caché de descanso, vino la ponencia SQL. Por último, un vistazo a los nue“Desarrollo de clientes intelivos servicios de seguridad y Webparts. gentes: Windows Forms 2.0 y Después de la comida, Fernando Visual Studio Tools for Office” Guerrero, de Solid Quality Learning, que expuso Pablo Peláez, de que como Regional Director estuvo en Visual Programming y Regional su primer DevDays. Su conferencia Director de Microsoft, en la que “SQL Server 2005 para desarrolladores” nos explicó cómo desarrollar Mauricio Ulargui para MS Office 2003 desde en la que hizo un repaso a todas las novedades de SQL Server 2005 que al menos .NET con esta nueva versión, desde las Este año, las conferencias tuvieron nos sirvió para tener una visión genérinovedades, como la integración del disecomo denominador común las nuevas ca de las principales novedades: ño, el soporte para controles adminiscaracterísticas y mejoras de Visual Studio Integación del CLR, mejoras de T-SQL, trados, las mejoras del modelo de pro2005 y SQL Server 2005. XML y SQL Server 2005, especialmengramación, las nuevas capacidades de la Después de la pequeña charla de prete del Service Broker (del que hablará más caché, el soporte ClickOnce, etc. sentación de Mauricio Ulargui, director extensamente en el próximo número de Entonces intervino César de la de desarrolladores .NET de Microsoft dotNetManía) y algunas de las mejoras Torre, de Renacimiento, uno de los Ibérica, empezaron las charlas técnicas de ADO.NET. profesionales que más sabe de Web con Alejandro Mezcúa, de byteabyte.net Enseguida nos relajamos un poco Services en este país y que, sin embarcon su sesión “Dispositivos móviles en con la ponencia “Gestión del ciclo de go, nos habló de ASP.NET 2.0 :-). Su Visual Studio 2005”. En esta sesión se vida completo de un proyecto software: charla fue “Novedades en el desarrollo vieron las principales novedades y difeVisual Studio Team System”, también de aplicaciones Web ASP.NET 2.0”. Por rencias de .NET Compact Framework muy esperada y en la que Pablo Peláez, supuesto, tuvo que hablar sobre las nue2.0 con respecto a la versión anterior. De David Salgado y David Carmona (estos vas master pages, los themes y skins y los la misma forma, se mostró cómo se ha últimos de Microsoft Ibérica) mejorado Visual Studio para nos explicaron de una forma incorporar nueva funcionalidad divertida la utilidad de las ediorientada al desarrollo para disciones Team System. positivos. Por último, se hizo hinPara finalizar, Pablo capié en las mejoras con respecto Motos, un cómico español, al acceso a datos y se demostró consiguió hacernos reír un rato cómo crear y utilizar bases de datos con uno de sus monólogos y así SQL Mobile desde dentro del relajarnos un poco después de entorno de desarrollo de Visual una jornada maratoniana. Studio 2005. Sirve este DevDays como En la siguiente ponencia, aperitivo de su hermano mayor: Leonardo Díez, de Danysoft, Tech-Ed 2005. expuso su charla “Novedades en Microsoft organizó el día 17 de mayo en los cines Kinépolis, el Microsoft Developer Day de Madrid al que asistieron alrededor de 1000 personas. Éste es un evento gratuito que organizan también en otros muchos lugares del mundo, las oficinas locales de Microsoft con el apoyo de los Regional Directors y otros partners, donde se reúne a la comunidad de desarrolladores, para hacerles partícipes de las novedades tecnológicas y que pretende ser un punto de encuentro entre Microsoft y los desarrolladores. << dnm.noticias dotNetManía nº 17 julio/agosto: Monográfico SQL Server 2005 Estamos preparando para el próximo número, el del verano, un monográfico sobre Microsoft SQL Server 2005, en un número que tendrá más páginas de lo habitual y con el que esperamos poder repartir entre los suscriptores la última versión CTP de SQL Server 2005 (aún por confirmar). Por supuesto, contaremos con algunos de los mejores profesionales. El borrador del índice es el siguiente: - Una nueva generacion de sistemas de gestión de la información (Fernando Bocigas). - Entrevista a Paul Flessner (vicepresidente senior de aplicaciones de servicdor en Microsoft)(aún por confirmar) y a César Galindo-Legaria (del equipo de desarrollo de SQL Server 2005 en Redmond) (Marino Posadas). - Alta Disponibilidad en SQL Serveer 2005 (Miguel Egea). - Business Intelligence en SQL Server 2005 (Salvador Ramos) - Introducción a SMO: SQL Server 2005 como modelo de objetos programable (Marino Posadas) - Service Broker (Fernando Guerrero) - Soporte XML en SQL Server 2005 (Eladio Rincón) - Integración del CLR en SQL Server 2005. Ejecutando código administrado desde el núcleo del motor de datos.(Luis Miguel Blanco) - T-SQL 2005, más productivo que nunca (Pepe Hevia) - SQL Server 2005 Mobile Edition, continúa la evolución (José Miguel Torres) - SQL Server 2005 Express Edition, el menor de la familia (Pedro Pozo). Además de algunos contenidos extras en algunas de las secciones habituales, como:TodotNet Q&A, MVP online, biblioteca, desván, opinión, etc. Avalon e Indigo Beta1 RC pública Microsoft acaba de hacer pública el conjunto de herramientas para el desarrollador de Longhorn WinFx que comprende por ahora a Avalon, el próximo susbsitema de presentación e Indigo, el próximo subsistema de comunicaciones, y que actualmente estaban sólo disponibles para suscriptores a MSDN o betatester. Estas tecnologías están disponibles para ser ejecutadas desde Windows XP o Windows Server 2003 y están pensadas para que los desarrolladores podamos empezar a experimentar con estas nuevas tecnologías antes de la aparición del sistema operativo Windows Longhorn. Esta beta 1 RC soporta Visual Studio 2005 Beta 2 y .NET Framework 2.0 Beta 2. Al conjunto se le ha llamado “Avalon” and “Indigo” Beta1 RC, y puede descargarse de la página de descargas de Microsoft o llegar desde los centros de desarrollo de Avalon (http://msdn.microsoft.com/longhorn/understanding/pillars/avalon) o Indigo (http://msdn.microsoft.com/ Longhorn/understanding/pillars/Indigo) donde además podrá encontrar toda la información que precise. Más información sobre Indigo en este mismo número en el artículo “¿Qué es WSE?” Solid Quality Learning University celebró su primer SQLU Summit en Madrid Durante los días 25 al 29 de mayo pasados, Solid Quality Learning organizó de común acuerdo con Microsoft Ibérica, el primer SQLU Summit en España para enlazar sin fricciones con la temática general de los seminarios de SQL Server. Este evento, que va a tener una periodicidad anual en cada ciudad, se trasladará tras el verano al otro lado del Atlántico, para volver a España de nuevo el año 2006. Mientras tanto este mismo tipo de evento va a ser organizado en los Estados Unidos de Norte América y otros países de habla inglesa. dnm.noticias << dotNetManía Estos seminarios los impartieron un total de 12 mentores de Solid Quality Learning, expertos en diferentes especialidades, llegados hasta Madrid tanto desde diferentes lugares de España como desde varios países de América. Estos mentores son en su gran mayoría MVP y Directores Regionales de Microsoft, y enfocaron el evento desde una vertiente puramente práctica y tendente a ofrecer consejos concretos a los asistentes al mismo. El objetivo de este summit era el de ofrecer formación avanzada y de calidad a los usuarios avanzados de SQL Server y .NET de España. Un total de 75 profesionales asistieron a este evento, desde importantes empresas y entidades públicas, formando un grupo de sumo interés por la variedad de sistemas y necesidades específicas que reunía, enriqueciendo enormemente el evento con sus experiencia particulares. El evento cubrió temas de .NET pero fundamentalmente en lo que se refiere a técnicas de acceso y representación de datos, 7 << dnm.noticias Nuevo Microsoft Windows Mobile 5.0 Hawaii, sucesor de Orcas Microsoft presentó Windows Mobile 5.0 (Magneto) en el Mobile & Embedded DevCon Hawaii es el nombre en clave del nuevo Visual Studio que sucederá a Orcas, sucesor de Visual Studio 2005, todavía en beta2 Desde el año 2000 que apareció el primer Pocket PC 2000 y más tarde 2002, hasta los Windows Mobile 2003, 2003 Second Edition y finalmente 5.0 (¿por qué no le habrán llamado Windows Mobile 2005?) han pasado sólo 5 años en los que hemos asistido a un avance y aceptación increíble de estos dispositivos. Bill Gates hizo público el anuncio de la disponibilidad, a partir del 10 de mayo, de Windows Mobile 5.0, la nueva plataforma para dispositivos móviles en la conferencia Microsoft Mobile & Embedded DevCon, donde destacó algunas de las mejoras y nuevas características introducidas, muchas de ellas a petición de los partners, entre las que se encuentran: Versión de Windows Media Player 10 Mobile; una nueva versión de Office Mobile, que incluye un nuevo Powerpoint Mobile; soporte nativo para redes de alta velocidad 3G, WiFi y mejoras en el soporte Bluetooth; soporte para teclado QWERTY; orientación de la pantalla en modo panorámico; mayor capacidad de almacenamiento y soporte adicional para dispositivos USB 2.0; nuevas mejoras en la seguridad, cumpliendo con el estándar FIPS 140-2 del gobierno de EEUU; un nueva aplicación de fotografía y vídeo, soporte de ActiveSync 4.0, el uso de la tecnología gráfica D3DMobile, etc... Además de estas nuevas características y mejoras para los usuarios de este sistema, también incluye novedades para los desarrolladores tanto de código nativo como de código administrado. El nuevo SDK de Windows Mobile 5.0 está diseñado para Visual Studio 2005 y SQL Server 2005 y puede funcionar con las betas actuales de ambos productos. De hecho ya pueden descargarse los correspondientes SDK, tanto para Pocket PC como para SmartPhone desde la página de descargas de Microsoft. Windows Mobile 5.0 soporta código administrado, en tanto que todos los dispositivos que lo lleven, tendrán el .NET Compact Framework 1.0 SP 3 instalado en la ROM, y aporta un conjunto de nuevas API accesibles desde el código administrado de .NET. Más información - Página de Microsoft para desarrolladores de Windows Mobile 5.0: http://msdn.microsoft.com/ mobility/windowsmobile. - Instrucciones para la instalación con la beta 2 de Visual Studio 2005: http://msdn.microsoft.com/ mobility/windowsmobile/howto/windowsmobile5/install. - Página independiente donde encontrará una revisión exhaustiva de Windows Mobile 5.0: http://www.mobile-review.com/pda/articles/ wm2005-magneto-en.shtml. Según publica Darryl K. Taft de eWEEK en su artículo “'Hawaii': A Visual Studio Paradise for Developers?”, la nueva versión que sucederá a Orcas se llama en clave Hawaii. Quizá lo menos importante sea lo del nombre, sobre todo si tenemos encuenta que en el citado artículo se asegura que será una versión totalmente remodelada de Visual Studio. Según la citada fuente, mientras que Whidbey nos ayudará a acercarnos a Longhorn, Orcas será la versión que nos permitirá “cabalgar” en lo que la compañía llama “la ola de Longhron” y conectar con las nuevas características de dicho sistema operativo. Hawaii vendrá poco después de Orcas, para aportarnos más funcionalidad específica de Longhorn. Según Tony Goodhew, product manager de Microsoft, “estamos sentando las bases para una completa rearquitectura de Visual Studio post Orcas”. Sin determinar la fecha, se piensa que Microsoft tiene pensado tener en el mercado estas dos versiones antes de 2010. Sin embargo, largo nos lo fían, estaremos pendientes de Orcas, como hace Anders Hejlsberg, que está trabajando duramente en la mejora de los compiladores para la siguente versión. Si está interesado, puede leer el artículo completo (en inglés, eso sí) en: (http://www.eweek.com/article2/0%2C1759% 2C1815855%2C00.asp) Se inaugura campusMVP << dotNetManía Campus MVP es una iniciativa de formación eLearning con contenidos de alta calidad en tecnologías Microsoft impartidos por los mejores expertos del sector. 8 Desde mediados del pasado mes de mayo inició su andadura campusMVP, el nuevo proyecto de formación online de Krasis. Realizado con la colaboración de algunos de los Más Valiosos Profesionales (MVP) de Microsoft, ofrece formación en-línea de calidad en tecnologías de Microsoft. campusMVP ofrece cursos cortos, especializados y asequibles dirigidos especialmente a profesionales de la informática y departamentos técnicos de empresas que necesiten mantenerse al día en su trabajo o ampliar conocimientos dentro de su plan de progresión profesional o de formación continua. En la Web de campusMVP (www.campusmvp.com) encontrará toda la información sobre el proyecto, el catálogo de cursos en los que se podrá matricular directamente on-line, un boletín de novedades, así como importante información acerca de cómo conseguir los cursos de manera gratuita si es usted un trabajador en activo de una empresa española. También dispone de la posibilidad de realizar un primer curso gratuito. Se trata de “Seguridad avanzada de Internet Information Server”. dnm.noticias dnm.legal José Antonio Suárez De igual a igual: ¿es legal el intercambio de ficheros en la Red? La legalidad de las copias de las obras de creación, y especialmente de las musicales y cinematográficas, efectuadas por usuarios finales mediante el recurso a las redes de intercambio de ficheros de igual a igual (p2p) ha sido defendida y contradicha en numerosas ocasiones en España. << En la polémica, que ya tiene una cierta antigüedad, en tér- José Antonio Suárez es socio director de Suárez de la Dehesa Abogados, despacho especializado en Propiedad Intelectual e Industrial y Nuevas Tecnologías. minos de lo que los usuarios de la Red entienden como antiguo, ha prevalecido el ruido mediático de quienes defienden, muchas veces con más voluntad que conocimiento jurídico, lo que llaman la legalidad de la copia en red. Y la prueba de ello es que en tales defensas se han manejado conceptos sociales y políticos, y casi nunca jurídicos. Tal vez sea el momento de hacer un análisis de la cuestión empleando exclusivamente los argumentos que se han descartado, es decir, los argumentos los jurídicos. Y hacerlo empleando un lenguaje que haga el discurso accesible a quien simplemente sepa leer. Para que el intercambio de ficheros que contienen obras de creación (música, películas) sea posible, es preciso que una persona acceda al soporte de fijación de dichas obras (grabadas en CD o DVD), reproduzca (copie) dicha obra en un sistema de almacenamiento (por ejemplo un disco duro fijo o removibles de su ordenador) y permita a terceros el acceso, libre o condicionado, a tal reproducción. Acceso que se produce a través de una red, como es el caso de Internet. Una vez que la obra fijada es accesible desde la red, cualquier tercero que tenga acceso a dicho sistema de almacenamiento podrá hacer una nueva reproducción de ella en su propio sistema. Almacenamiento que, a su vez, puede ser accesible a otros terceros que cumplan sus mismas condiciones, con lo que el número de posibles copias crece de forma exponencial, como lo acredita el dato de que las copias en red sólo de obras cinematográficas sobrepasan los cinco millones de ejemplares diarios. La copia de una obra de creación contenida en un soporte es un acto de reproducción, que, como norma general, requiere de la autorización de su titular. El artículo 31.1º del español Texto Refundido de la Ley de Propiedad Intelectual, como los sistemas jurídicos de nuestro entorno, reconocen al propietario de un soporte legítimo, la posibilidad de copiar la obra que contiene para su uso personal, y siempre que dicha copia no sea objeto de utilización colectiva ni lucrativa. Se trata, en definitiva, de un límite al derecho del titular; o, si se quiere, de una excepción al derecho de autorizar la reproducción. Pero lo que nunca será es Es evidente, más allá de toda duda, que cuando la copia realizada para uso privado se expone al uso, y en este caso la reproducción, de terceros, pierde su carácter de copia privada, pues incumple el requisito de que no sea objeto de uso colectivo << dnm.legal ...la difusión al público de una obra de creación sin autorización de su titular, el acto es ilegal Es más, tanto quienes ponen a disposición como quienes copian en la redes de intercambio no sólo obtienen una ganancia (aunque sea en forma de no gasto), sino que causan un perjuicio a terceros, desde los autores a los intérpretes, pasando por los productores. Y cuando en una conducta defraudadora de los derechos de propiedad intelectual concurren ánimo de lucro y perjuicio de tercero, nos estamos adentrando en un territorio verdaderamente peligroso, como es el del Código Penal. Bien es verdad que en Derecho, como en todas las ciencias sociales, y en las exactas desde Einstein, todo es relativo, pero lo cierto es que pocas veces la letra de la Ley es tan clara. Por ello, quien ponga a disposición ficheros conteniendo obras protegidas, aunque las copie para su uso personal, debe ser consciente del riesgo que ello conlleva, en caso de ser descubierto. <<dotNetManía un derecho del propietario del soporte, ya que quien compra tal soporte no adquiere derecho de propiedad alguno sobre la obra que contiene, como claramente indica el artículo 3º del Texto Refundido de la Ley de Propiedad Intelectual, algo que, por cierto, dice, desde 1888, el artículo 377 del Código Civil. Es evidente, más allá de toda duda, que cuando la copia realizada para uso privado se expone al uso, y en este caso la reproducción, de terceros, pierde su carácter de copia privada, pues incumple el requisito de que no sea objeto de uso colectivo. Por ello, tal copia debe calificarse de ilegal, y a quien la ha confeccionado de infractor de los derechos de propiedad intelectual. Cuando el sistema de almacenamiento en el que se ha alojado dicha copia ilegal se abre a terceros a través de una red de comunicaciones, se está haciendo posible el acceso a las personas que emplean dicha red a las obras copias; sin que para ello haya sido necesario entregar a cada una de dichas personas un ejemplar del soporte de la obra. Conducta ésta que nuestro sistema legal (artículo 20.1 del Texto Refundido de la Ley de Propiedad Intelectual), y los de más de ciento ochenta países, califican de acto de comunicación pública, y, por tanto, también sujeto a la autorización de su titular, y no sujeto a límite alguno de uso privado, pues la limitación o excepción del artículo 31.1º sólo se refiere al copiado, y no a la comunicación pública. Por ello, la difusión al público de una obra de creación sin autorización de su titular, el acto es ilegal. En este preciso punto podemos concluir que el copiado de música o películas cinematográficas contenidas en soportes (CDs o DVDs) y su posterior puesta a disposición de terceros a través de redes de intercambio de igual a igual, supone la comisión de dos tipos de infracciones perfectamente identificadas en nuestro Texto Refundido de la Ley de Propiedad Intelectual. La persona que a través de una red de intercambio accede a la obra y es sorprendida puede pretender ignorar todo lo anterior, y alegar en su defensa que ignoraba la ilegalidad tanto de la copia como de la puesta a disposición del promotor de tal cadena. A priori no hay razones para no respetar el principio de presunción de inocencia, pero ésta no parece que concurra en quien, a su vez, pone a disposición de terceros las obras que ha copiado, aunque dicha copia se haya hecho de las obras puestas a disposición por otros. O en quien, sin pago alguno, obtiene copias de aquellas obras de reciente aparición en el mercado musical o cinematográfico, y no precisamente de forma gratuita. Aunque tales copias sean para su exclusivo uso personal. Uno de los argumentos más utilizados para excusar estas conductas, que, como vemos, inciden en la ilegalidad, es declarar que en tales conductas no hay ánimo de lucro. Declaración que sólo quiere evitar que el problema se traslade al ámbito penal. Sin pretender entrar en el análisis de lo que por ánimo de lucro entienden nuestros Tribunales, es preciso recordar que “ánimo de lucro” no es equivalente a buscar y obtener una ganancia económica directa para sí, sino que en Derecho es sinónimo de cualquier provecho, beneficio, ventaja o utilidad que se obtenga por el propio individuo, incluido el ahorro de costes, o que éste consiga para un tercero, aún en el caso de que él mismo no se beneficie en forma alguna. 11 Por Marino Posadas MVP Visual Developer C# Alhambra-Eidos www.elavefenix.net Entrevista a Nuria Oliver Nuria Oliver es investigadora en Microsoft Research en Estados Unidos.Previamente estuvo en el mítico Media Lab del MIT (Massachusetts Institute of Technology). Su trabajo se basa fundamentalmente en la interacción de las máquinas con el ser humano a través de la percepción de éstas del mundo que les rodea. << Revisando tu currículo, veo que tus comienzos en la ciencia fue- Marino Posadas es asesor técnico y redactor de dotNetManía, MVP de C# y formador de Alhambra-Eidos ron en la Universidad Politécnica de Madrid. El año pasado, coincidí precisamente con la profesora Carmen Costilla en unas conferencias que dimos para la Universidad de Santiago de Compostela, donde yo hablaba de Longhorn y ella de la Web semántica. ¿La conoces? ¿y crees que la Web semántica, -como ella lo ve- es la Web inevitable dentro de pocos años? Me parece buena idea y probablemente necesaria para garantizar la supervivencia del World Wide Web. El objetivo es crear un modo eficiente de representar los datos en el World Wide Web como una base de datos conectada globalmente. De esa manera, la información podría ser procesada fácilmente por máquinas en todo el mundo. Tim Berners-Lee, el inventor de WWW, URLs, HTTP y HTML, propuso el concepto de la Web semántica y hay un equipo en el consorcio W3C dedicado a mejorar, extender y estandarizar la Web. Antes de pasar a temas más próximos a tu trabajo, una cosa más sobre Internet: Si el objetivo es que el usuario estándar tenga cada vez más ancho de banda, en un largo viaje hacia Internet2, ¿cómo va cambiar nuestras vidas cuando eso sea así? Tú misma, comentas que ahora realizas una buena parte de tu trabajo en casa... << dnm.directo.entrevistas Una consecuencia obvia es que estaremos conectados a Internet todo el tiempo, desde cualquier lugar: la oficina, casa, el teléfono móvil, etc… El mundo digital y el mundo físico estarán más interconectados que nunca. Podremos trabajar desde cualquier lugar. Estaremos conectados no sólo a toda la informacion del WWW, pero también a familiares y amigos; podremos ver, transmitir y recibir vídeo y audio en tiempo real… hay tantas posibilidades… al mismo tiempo, creo que es muy importante para nuestra salud mental y física el saber y poder desconectar. El exceso de informacion causa ansiedad y confusión. Háblanos algo de tu experiencia en MIT (Massachusetts Institute of Technology). En un artículo tuyo para El Heraldo de Aragón lo defines como centro mítico... ¿Es cierto? ¿En MIT se ve el futuro antes que en ninguna otra parte? Y, ¿conoces a otros españoles que estén allí en labores de investigación? Te lo pregunto, por un artículo tuyo: “El modelo educativo del Media Lab”. El MIT es una de las mejores universidades del mundo –si no la mejor—para las ingenierías y la informática. Tanto los estudiantes como los profesores de MIT son excepcionales. La vida en MIT es muy intensa, una experiencia única. Yo estuve investigando durante cuatro años y medio en el Media Lab de MIT, que es un centro muy especial. Fue fundado por Nicholas Negroponte en 1985 y la idea era crear un centro de investigacion multi-disciplinar que innovara y, en cierto sentido, delineara el futuro en áreas tan diversas como la música, el arte digital, la educacion, la comunicación hombre-máquina, el cine, la informática cuántica, etc… En ese sentido, el Media Lab es único. En los últimos años parece haber sufrido un cierto declive y creo que ahora están reinventando cuál es el futuro papel del centro dentro de MIT y de la comunidad científica. En cualquier caso, todavía se respira esa energía creativa que lo caracteriza y estoy segura de que seguirá innovando como hasta ahora. Una característica importante del estilo de investigación americano es la de asumir riesgos e intentar cosas que van en contra del status quo y que parecen estar destinadas al fracaso. Pienso que no se puede innovar sin arriesgarse. Es importante analizar los riesgos y ser realista, pero también con cierto optimismo. Tú ya tienes experiencia como investigadora en España, y en EE.UU, dentro y fuera de la Academia. ¿Cuál es mejor? ¿La empresa privada -Microsoft-, o un centro como MIT, rodeada de monstruos como Marvin Minsky y otros? El principal motivo por el que estoy en EEUU es laboral: hasta ahora no he encontrado el modo de poder realizar mi trabajo en España con condiciones similares a las que tengo en EEUU. Soy consciente de que el Gobierno actual esta proponiendo nuevas iniciativas para fomentar la investigacion en ciencia y tecnologia en España. Me encantaría poder regresar a mi país y contribuir con mi trabajo a la mejora de la calidad de vida de las personas. Pero de momento, pienso que donde mejor puedo realizar mi trabajo es aquí, en EEUU. Con respecto a Academia versus empresa privada, hay aspectos similares y diferencias. El aspecto más importante para mí, que son los proyectos de investigación en los que trabajo, es básicamente igual en una empresa privada que en una universidad. En los laboratorios de investigacion de Microsoft tenemos total libertad para trabajar en lo que queramos. Una gran ventaja es que no tenemos que solicitar grants para financiar los proyectos. Nunca he tenido ningún problema para financiar ninguno de mis proyectos. También tenemos total libertad para publicar artículos en congresos y revistas científicas. Microsoft Research tiene una presencia muy fuerte en la comunidad científica. Otra ventaja es que no tenemos que dar clase. A mí me gusta dar clase, con lo que no me importaría ese aspecto de la vida en la universidad, pero al mismo tiempo, las horas de clase son horas en las que no estás investigando…Una diferencia importante es que no trabajamos con estudiantes tanto como se trabaja en la universidad. Es quizás el aspecto más negativo de trabajar en un laboratorio privado. Me encanta trabajar con estudiantes. Ahora mismo estoy trabajando con un estudiante de la Universidad Autónoma de México y estoy disfrutando muchísimo. Normalmente tenemos estudiantes que vienen a trabajar con nosotros en el verano, durante unos tres << dnm.directo.entrevistas meses. Excepcionalmente tenemos estudiantes durante el invierno, como yo ahora. En Microsoft Research también podemos colaborar con universidades, dar clases en la Universidad de Washington, etc…realmente es un paraiso para la investigación. Finalmente, otro aspecto muy importante para mí es la flexibilidad en el trabajo. Podemos trabajar desde casa, tener horario flexible, etc… Hoy en día, me parece fundamental ofrecer opciones de flexibilidad en el trabajo. Studio con el que nos comuniquemos oralmente, por ejemplo? Pienso que las herramientas de desarrollo cambiarán, porque cambiará la naturaleza de nuestra interacción con los ordenadores. Hay muchas áreas en las que el desarrollo de software se vería afectado: por ejemplo, si el ordenador tuviese acceso al estado emocional del programador, podría adaptar su estilo de comunicacion, ofrecer diferentes estrategias de ayuda, etc… Jim Gray me comentaba el pasado verano que lo que hacía falta no era sólo inteligencia en las máquinas, sino en la información misma. En la forma de acceder a ella. ¿Cuál es tu opinión al respecto? Hoy en día estamos inundados por información, por datos que a veces son útiles, y otras veces no son mas que spam, basura. Si no disponemos de modos inteligentes para acceder a la misma, para discernir lo que es información de lo que no lo es, corremos el riesgo de que el sistema entero se vuelva inútil. Por lo tanto, es muy importante disponer de algoritmos inteligentes para acceder a la información que es relevante en cada momento. Esos algoritmos estarán en algun tipo de ordenador y por lo tanto la inteligencia de las máquinas se traducirá en modos más inteligentes de acceder a la información. Por último, y, a propósito de “Yo Robot”, ¿crees que en 2025, -pongamos- podrán existir robots del estilo de los que vemos en la película? No me refiero a Sony, sino a los de la generación anterior... ¿O es algo todavía tan lejano como la Computación Cuántica? Lamentablemente no he visto la película, porque no tuvo buenas críticas, pero conozco el tema. La película sucede en Chicago en el año 2035 y, gracias al trabajo del Dr. Lanning, los robots son parte de la vida diaria. Para asegurar que los robots nunca dañen o desobezcan a los seres humanos, Lanning los ha programado siguiendo ciertas leyes… hasta que aparece el modelo NS-5 y las cosas se complican… Hoy en día disponemos de electrodomésticos inteligentes, aspiradoras que aspiran solas (como Roomba), coches plagados de sensores, perritos de juguete que reconocen ciertos comandos, juegan con pelotas, etc... en cierto sentido, estamos rodeados de robots. También hay robots humanoides, como ASIMO de Honda. Estamos dando los primeros pasos en el área, pero hay muchísimos centros de investigación, tanto a nivel universitario como industrial, trabajando en robótica y pienso que los robots –tanto humanoides como no—estarán cada vez más integrados en la fibra de nuestra vida cotidiana. <<dotNetManía Hay muchas áreas en las que el desarrollo de software se vería afectado: por ejemplo, si el ordenador tuviese acceso al estado emocional del programador, podría adaptar su estilo de comunicacion, ofrecer diferentes estrategias de ayuda, etc… 14 Dentro de tus areas de interés científico, observo la presencia constante de la búsqueda de patrones y modelos matemáticos que describan el comportamiento humano. ¿Cuál te parece que va a ser el siguiente gran salto en la informática? ¿Ves un futuro (o no tan futuro) sistema operativo que se comunique con el usuario mediante voz? ¿Para cuándo podría estar lista una cosa así? ¿Podría Blackcomb, previsto para 2011 llevar algo parecido? Esto viene por otro artículo tuyo en el que anticipas algo así: “GWindows: Towards Robust Perception-Based UI” Hay muchas áreas de investigacion que podrían constituir un gran salto en la informática: ordenadores cuánticos, sistemas híbridos con componentes biológicos, ciberorganismos, nanotecnología, y, por supuesto, la inteligencia artificial y la percepción por ordenador, que son mis áreas de investigacion. Dentro de mi campo, sí pienso que cada vez vamos a ver más ordenadores con capacidad de percibir qué es lo que sucede a su alrededor, reconocer la situación y reaccionar en consecuencia. Hoy en día ya hay, por ejemplo, robots humanoides que pueden comunicarse con las personas, tienen capacidad de visión y de habla (un tanto limitadas, pero aún así existentes), pueden caminar, etc… Hay muchas áreas de nuestra vida cotidiana que se verían muy afectadas (y espero que en sentido muy positivo) si pudiésemos comunicarnos con los ordenadores de modo similar a como lo hacemos con otras personas, si hubiese ordenadores en el ambiente, en nuestra ropa, con capacidad de monitorizar señales vitales, por ejemplo. ¿Cómo crees que van a cambiar las herramientas de desarrollo? ¿Qué puede ofrecer un futuro Visual dnm.asp.net Braulio Díez Reyes García Generando hojas Excel con ASP.NET Hoy en día las hojas Excel se han convertido en un estándar para representar información financiera, de control de stock, etc. Cuando hablamos de ASP.NET solemos tener asociado el HTML como formato de representación de la información, otras alternativas nos hacen pensar en problemas de rendimiento, o herramientas con un coste elevado, ¿existe alguna forma sencilla de hacer esto con .NET? ma dinámica sin apenas consumir recursos del sistema. Para ello utilizaremos las siguientes tecnologías: • XML (para los datos que queramos introducir en la hoja Excel). • XMLSS/XSL: El formato XML de Excel (usaremos XSL para construirnos una plantilla). Reyes García Ha sido consultora “todo terreno”. Hoy día se dedica al gratificante mundo de la docencia. Braulio Díez colabora habitualmente con dotNetManía. Es MCSD en programación distribuida con Visual C++. Trabaja como Solutions Developer de Avanade. El proceso consiste en formatear los datos de entrada a XML, y aplicarles una plantilla XSL obteniendo así el fichero Excel que enviaremos al cliente. ¿Complicado? ¿Laborioso? .NET Framework y Office 2002 nos harán el 90 % del trabajo, veamos cómo: • XML: Si leemos de la base de datos utilizando un dataset, podemos guardar los resultados en formato XML gracias a un método que esta clase nos ofrece. • XMLSS/XSL: No tenemos que estudiarnos los entresijos del formato XML de Excel, podemos hacer directamente la plantilla con Office y a la hora de grabar decirle que lo haga en formato XMLSS. Para pasarlos a XSL sólo tendremos que hacer unos pequeños cambios sobre el fichero generado. ¡Manos a la obra! Para ver cómo funciona todo esto, vamos a crear un ejemplo sencillo; una hoja de trabajo que calcule el total de horas extras que hemos hecho en un periodo de tiempo (suponemos que trabajamos de lunes a viernes y que la jornada laboral es de 8 horas). La hoja Excel de nuestro ejemplo tiene dos fórmulas, una que calcula el número total de horas extras que se han realizado en un día (muy complicada… “8 - total”), y otra que suma el total de todas las horas extras de ese periodo de tiempo. En la figura 1 se puede observar cómo quedaría. Figura 1. Hoja Excel que vamos a crear Para crearlo ejecutamos MS Excel, le decimos que queremos crear una nueva hoja, y añadimos las siguientes celdas: 1 2 A Fecha B Horas Totales C Extras 2/07/200 10 =B2-8 <<dotNetManía << En este artículo vamos a ver cómo generar hojas Excel de for- 15 << dnm.asp.net Dejamos una fila en blanco y, a continuación, mostramos los totales en las celdas B4 y C4 (esta última, al igual que C2, es una fórmula): <?xml version="1.0"?> <Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet" <?xml version="1.0"?> B C <<dotNetManía 4 Total Extras =SUM(INDIRECT("C$2:C"&ROW()-2)) 16 La formula de la celda C4 no es más que un sumatorio de todos los valores desde la columna C2 hasta la actual (la de total) menos dos; de esta forma cuando añadamos más elementos nos calculará los datos de manera satisfactoria. Ya tenemos la hoja prácticamente montada, vamos a darle algo de formato para que tenga mejor pinta: seleccionamos desde la celda A1 hasta la C1, y a través de las opciones de menú “formato” y “celdas”, las ponemos con fuente negrita y color de fondo gris. Guardamos la hoja Excel, pero seleccionamos el formato “XML Spread Sheet” (en español “Hoja de cálculo XML”), y el nombre del fichero lo ponemos como ”fichero_original.xls” (entre comillas y con la extensión .XLS, para que lo grabe sin extensión .XML). Si hacemos doble clic sobre el fichero, veremos como Excel lo abre sin problemas. Ya tenemos un fichero Excel en formato XML, ahora vamos a transformarlo en una plantilla XSL que nos sirva para cargar datos de forma dinámica. Copiamos el fichero fichero_original.xls y le ponemos el nombre plantilla.xls. En los fuentes 1a, 1b, 1c y 1d podemos ver una comparativa entre el fichero original y el que modificaremos, las partes que se insertan están marcadas en amarillo, y las que debemos eliminar en rojo. Abrimos plantilla.xls con cualquier editor de texto (por ejemplo Notepad) y hacemos los siguientes cambios: • Añadimos las etiquetas xsl:template y xsl:stylesheet para definir el fichero como una plantilla XSL; ponemos como raíz TestDataSet que será el nombre del DataSet del que extraeremos los datos más tarde (fuente 1a). • Añadimos al final del fichero las etiquetas de cierre de las dos etiquetas anteriores <xsl:template> y </xsl:stylesheet> (fuente 1b). • En la entrada <table> quitamos el parámetro que indica cuántas filas hay en la hoja (ss:ExpandedRowCount), ya que el número de filas varará en función de los datos de entrada (fuente 1c). • Para introducir los campos añadimos una sentencia foreach y cambiamos los datos de la segunda fila por lo que vamos a leer de la base de datos, que en nuestro caso son: fecha en la que se trabajo y número de horas (fuente 1d). <xsl:stylesheet version="1.0" xmlns="urn:schemas-microsoft-com:office:spreadsheet" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:user="urn:my-scripts" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet" > <xsl:template match="TestDataSet"> <Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet" Fuente 1a. Datos para definir la plantilla XSL. </Worksheet> </Workbook> </Worksheet> </Workbook> </xsl:template> </xsl:stylesheet> Fuente 1b. Etiquetas de cierre <Worksheet ss:Name="Sheet1"> <Table ss:ExpandedColumnCount="4" ss:ExpandedRowCount="4" x:FullColumns="1" x:FullRows="1"> <Worksheet ss:Name="Sheet1"> <Table ss:ExpandedColumnCount="6" x:FullColumns="1" x:FullRows="1"> Fuente 1c. Quitamos ss:ExpandedRowCount, número de filas variable <Row> <Cell ss:StyleID=”s21”> <Data ss:Type=”DateTime”>2004-07-02T00:00:00.000</Data></Cell> <Cell><Data ss:Type=”Number”>10</Data></Cell> <Cell ss:Formula=”=RC[-1]-8”><Data ss:Type=”Number”>2</Data></Cell> </Row> <xsl:for-each select=”t_horas”> <Row> <Cell ss:StyleID=”s21”> <Data ss:Type=”String”> <xsl:value-of select=”Fecha”/> </Data> </Cell> <Cell> <Data ss:Type=”Number”> <xsl:value-of select=”Horas”/> </Data> </Cell> <Cell ss:Formula=”=RC[-1]-8”><Data ss:Type=”Number”>2</Data></Cell> </Row> </xsl:for-each> Fuente 1d. foreach y nombre de campos. << dnm.asp.net public DataSet CreateTestDataset() { // Ojo con el nombre, tenemos que usar el // mismo en el XSL de Excel DataSet testData = new DataSet("TestDataSet"); // Lo mismo aquí con el nombre DataTable dtHoras = new DataTable("t_horas"); // Creamos las columnas de nuestra "tabla" DataColumn dcHoras; dcHoras = new DataColumn(); dcHoras.ColumnName = "Fecha"; dcHoras.DataType = Type.GetType("System.String"); dtHoras.Columns.Add(dcHoras); El código que aplica la plantilla Excel a cualquier DataSet, lo he encapsulado en una clase para que pueda ser reutilizado fácilmente en otros proyectos. Ésta contiene dos métodos: SendExcelStreamToClient y SendExcelStreamToFile. • SendExcelStreamToClient: se le pasa como parámetro el DataSet y el objeto Response. Transforma el primero a una hoja Excel y usa el segundo para enviarla al navegador del cliente. • SendExcelStreamToFile: se le pasa como parámetro el DataSet y la ruta completa de un fichero. Transforma el primero a una hoja Excel y usa el segundo para guardarlo en la ruta especificada (por si se quiere utilizar en una aplicación desktop). En el fuente 3 se puede ver el código del primer método, y en el fuente 4 cómo se usa la clase y su método al pulsar el botón de “Exportar a Excel”. /// <summary> /// Carga la plantilla, la aplica contra el fichero XML, /// tomamos el stream generado, y lo enviamos al cliente /// como un fichero Excel /// </summary> /// <param name=”Ds”></param> /// <param name=”response”></param> /// <returns></returns> public void SendExcelStreamToClient( DataSet Ds, System.Web.HttpResponse response) { try { XslTransform xslTrans = new XslTransform(); dcHoras = new DataColumn(); dcHoras.ColumnName = "Horas"; dcHoras.DataType = Type.GetType("System.Int32"); dtHoras.Columns.Add(dcHoras); // Cargamos nuestro XML que genera el DataSet XmlDataDocument doc = new XmlDataDocument(Ds); // Le añadimos unos cuantos datos DataRow curr = dtHoras.NewRow(); curr["Fecha"] = "01/06/2004"; curr["Horas"] = 10; dtHoras.Rows.Add(curr); // Cargamos la plantilla de Excel que hemos creado xslTrans.Load(_pathToExcelXslTemplate); // Creamos un XPathNavigator que usaremos en la transformación XPathNavigator nav = doc.CreateNavigator(); curr = dtHoras.NewRow(); curr["Fecha"] = "02/06/2004"; curr["Horas"] = 8; dtHoras.Rows.Add(curr); // Transformamos y enviamos los datos response.AddHeader( “content-disposition”, “attachment; filename=Testeo.xls”); response.ContentType = “application/vnd.ms-excel”; response.Charset = string.Empty; xslTrans.Transform(nav, null, response.OutputStream, null); curr = dtHoras.NewRow(); curr["Fecha"] = "02/06/2004"; curr["Horas"] = 8; dtHoras.Rows.Add(curr); response.Flush(); response.Close(); curr = dtHoras.NewRow(); curr["Fecha"] = "03/06/2004"; curr["Horas"] = 11; dtHoras.Rows.Add(curr); } catch(System.Exception Ex) { // Sólo relanzamos la excepción, implementar a gusto // del consumidor :-) throw Ex; } curr = dtHoras.NewRow(); curr["Fecha"] = "04/06/2004"; curr["Horas"] = 12; dtHoras.Rows.Add(curr); testData.Tables.Add(dtHoras); return testData; } Fuente 2. Creando nuestros datos de test } Fuente 3. Este es el método que coge el DataSet, le aplica la plantilla XSL que hemos creado y envía al cliente la nueva hoja generada <<dotNetManía ¡Ya tenemos lista nuestra plantilla XSL!, sólo nos queda crear una página ASP.NET que lea los datos de una base de datos, los transforme a una hoja Excel y la envíe al cliente. Creamos una aplicación Web que llamaremos ExcelSimple y en la página por defecto le añadimos una etiqueta y un botón. A éste lo llamaremos btnExportExcel y nos suscribimos a su evento OnClick. En dicho evento, cargaremos los datos de una base de datos, le aplicaremos la plantilla XSL que hemos creado y le enviaremos stream de memoria con el fichero Excel a nuestro cliente. Para mantener el ejemplo lo más sencillo y fácil de instalar posible, he creado el DataSet que obtendríamos de leer de base de datos en tiempo de ejecución (ni qué decir tiene que en las aplicaciones reales debemos leer de una base de datos de verdad), ver fuente 2. 17 << dnm.asp.net private void btnExportExcel_Click(object sender, System.EventArgs e) { // Tomamos como path de la plantilla excel // el de la aplicación web string TemplatePath = System.AppDomain.CurrentDomain.BaseDirectory+ “plantilla.xls”; try { MsExcelTransformer msExcelTransformer = new MsExcelTransformer(TemplatePath); msExcelTransformer.SendExcelStreamToClient( CreateTestDataset(), Response); } catch(System.Exception Ex) { Response.Write(“<p>”); Response.Write(“<i>El proceso ha fallado, “ + ¿ existe este fichero en tu disco duro ? </i>” + TemplatePath); Response.Write(“<BR>”); Response.Write(“<b>Información Extendida:</b> “ + Ex.Message); Response.Write(“/p”); } } Fuente 4. El código que ejecutamos cuando se pulsa el bóton de nuestra página. Antes de arrancar el ejemplo tenemos que asegurarnos de que la plantilla XSL que hemos creado está en la ruta de la aplicación (en mi caso es C:\Inetpub\wwwroot\ExcelSimple). Ya está todo listo, ejecutamos el ejemplo, pulsamos el botón y… ¡voila!, nos aparece un mensaje de Internet Explorer, que nos pregunta si queremos abrir el fichero Excel o guardarlo a disco..., lo abrimos y vemos nuestro fichero Excel con los datos del DataSet que le habíamos introducido. En la figura 2 podemos ver la página ASP de nuestro ejemplo, y en la figura 3 la hoja Excel con los datos que hemos cargado. Figura 3. La hoja Excel que se carga en el cliente Otras opciones Hay más formas de generar ficheros Excel, dependiendo de las necesidades se puede optar por las que siguen. Automation Si lo que se desarrolla es una aplicación desktop, puede usar Automation, esto es, arrancar Excel como un objeto COM EXE. La ventaja es que se puede hacer todo lo que se quiera con Excel; las desventajas son su lentitud, los recursos que consume, los cambios entre versiones de Office y los problemas que da con algunas herramientas de antivirus. Para más información, un buen punto de partida está en la MSDN, referencia Q316126, “HOW TO: Use Visual C# .NET to Automate a Running Instance of an Office Program”. Librerías gratuitas específicas Una que tiene muy buena pinta es la desarrollada por Carlos Aguilar Mares (http://www.carlosag.net/Tools/ ExcelXmlWriter). Componentes comerciales Si lo que se necesita es generar archivos binarios de Excel, se puede optar por librerías como la de Soft Artisans (http://www.asp.net/ControlGallery/ ControlDetail.aspx?Control=1002&tabindex=2 ), o como la de Aspose (http://www.aspose.com/Products/Aspose.Excel). <<dotNetManía CSV (Comma Separated Values) 18 Si es necesario dar soporte a versiones muy antiguas de Excel, esto puede valer. Consiste en importar de un fichero de texto que separa cada celda por comas y cada fila por un retorno de carro, puede encontrar más información en: http://www.creativyst.com/Doc/Articles/CSV/ CSV01.htm Figura 2. La página ASP de nuestro ejemplo << dnm.asp.net Si no es necesario soportar versiones anteriores a la 2002 de Office, el formato XML de Excel (XSSL) combinado con las tecnologías XML/XSL se presenta como un gran aliado a la hora de generar hojas de cálculo de forma dinámica Nota: Depende de la versión de IE que tenga, le aparecerá dos veces el mensaje de “Abrir / Guardar”, esto es un fallo conocido del navegador y hay parches que lo arreglan. Este ejemplo está disponible en la Web de la revista, en www.dotnetmania.com. Limitaciones No todo el monte es orégano… si bien esta forma de generar Excel es limpia y consume pocos recursos, tiene varias limitaciones: • El cliente necesita tener instalado Office 2002 o superior para que pueda leer este formato. • No se pueden incluir imágenes, ni objetos ActiveX en la hoja (al menos en Microsoft Office 2002). Conclusión Si no es necesario soportar versiones anteriores a la 2002 de Office, el formato XML de Excel (XSSL) combinado con las tecnologías XML/XSL se presenta como un gran aliado a la hora de generar hojas de cálculo de forma dinámica. Aquí tiene unos enlaces en los que podrá encontrar más información sobre estás tecnologías (los que no tienen link, son de la MSDN, http://msdn.microsoft.com): • “Q285891. How to use Visual Basic or ASP to create an XML Spreadsheet for Excel 2002”: Otro ejemplo sobre cómo crear XMLSS. • “XML Spreadsheet Reference2”: Descripción completa del formato XML de excel (XMLSS). • Un tutorial de XSLT: http://www.w3schools.com/xsl trucos.trucos.trucos Leyendo y modificando hojas Excel Además de generar hojas Excel, hay veces en las que nos es necesario poder leerlas y/o modificarlas, en este caso ADO .net nos será de gran ayuda. Cubrir este tema a fondo queda fuera del alcance de este artículo, no obstante, vamos a ver un pequeño ejemplo que lea nuestra “hoja de horas” y la vuelque por pantalla: Puede encontrar más información en los siguientes links: • MSDN: “How To Use ADO.NET to Retrieve and Modify Records in an Excel Workbook With Visual Basic .NET” [kb316934] • “Import from Excel using ADO.NET” (ejemplo simple y útil): http://www.dotnetspider.com/technology/kbpages/1080.aspx static void Main(string[] args) { string strConnectionString =string.Empty; // OJO ! Cuidado con el Path al fichero Excel, si nos equivocamos nos da // un error que despista un poco... "Could not find installable ISAM" strConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;" + @"Data Source=C:\ejemplo.xls;" + "Extended Properties=\"Excel 8.0;HDR=Yes;IMEX=1\""; while (reader.Read()) { for(int i =0; i < reader.FieldCount; i++) Console.Write(" " + reader[i].ToString()); Console.WriteLine(); } reader.Close(); } <<dotNetManía OleDbConnection cn =new OleDbConnection (strConnectionString); cn.Open(); OleDbCommand cmdSelect = new OleDbCommand (@"SELECT * FROM [Sheet1$]", cn); OleDbDataReader reader = cmdSelect.ExecuteReader(CommandBehavior.CloseConnection); 19 César de la Torre ¿Qué es Microsoft WSE? Microsoft WSE es un nuevo módulo de componentes .NET que permite extender el marco de trabajo de .NET Framework 1.1 para poder desarrollar servicios Web XML con características avanzadas.WSE es algo que, sin embargo, al no tenerlo disponible directamente con Visual Studio 2003 no es muy conocido por el momento, pero si se quiere desarrollar un servicio Web XML complejo,hoy en día,la única opción es basarse en WSE 2.0.La intención de este artículo es simplemente dar una visión de alto nivel de qué es WSE y cómo se integra mediante SOAP con .NET 1.1 y Visual Studio 2003. << ¿Qué es WSE? Bueno, literalmente significa Web Services César de la Torre Es Microsoft MVP en XML-Web-Services, MCSE y MCT. Profesionalmente es Arquitecto de Software y Socio Cofundador de Renacimiento Sistemas, empresa consultora Microsoft GOLD Certified Partner Enhancements, por lo que simplemente por el nombre vemos que tiene mucho que ver con Servicios Web XML y con aspectos avanzados de éstos. Sin embargo, antes de meternos de lleno en qué nos proporciona WSE, vamos a remontarnos un poco a los orígenes de los servicios Web XML y ver las razones de por qué surgen estos nuevos servicios avanzados para ellos. Los servicios Web XML surgen debido a necesidades de interoperabilidad entre diferentes plataformas y aplicaciones (antes era un infierno comunicar aplicaciones, por ejemplo COM, con aplicaciones CORBA, JAVA, etc.), marcándose como objetivo el basarse en estándares (como XML, SOAP, HTTP, etc.). Es muy importante que las comunicaciones entre aplicaciones (servicios) sean independientes de la plataforma (.NET, Java, etc.), del lenguaje, de los objetos e incluso de los mecanismos de llamada y protocolos de transporte. Estos objetivos son los que conforman SOA (Service Oriented Architecture). SOA “ve el mundo” de una forma distinta: todas las aplicaciones deben ser servicios autónomos donde se definan fronteras explícitas y se asuma la heterogeneidad y colaboren plataformas dispares (por ejemplo, comunicar aplicaciones .NET con aplicaciones Java). Para esto, en lo que ya es la “implementación de SOA en el mundo real” es imprescindible hablar un mismo idioma, es decir, compartir el mismo formato de datos (XML) y los mismos esquemas XML (esquema de mensajes de comunicación SOAP). SOA (Service Oriented Architecture), como algo lógico o “filosofía”, podía haberse implementado con cualquier mecanismo “a inventar”. En este caso la implementación de SOA, hoy por hoy, se ha basado en los servicios Web XML implementados con cualquier tecnología (.NET, Java, etc.). Los servicios Web XML básicos (y ya centrándonos en plataforma Microsoft) nacen inicialmente como una tecnología básica (protocolo y definiciones de mensajes SOAP, implementados con SOAP Toolkit para lenguajes compatibles con COM como VB 6.0, etc.), diseñada ésta y sus estándares de forma abierta (especificaciones teóricas de servicios Web definidas por diferentes organizaciones como MS, IBM, Sun, etc.) para que fuera evolucionando en el futuro con otras plataformas y lenguajes (en este caso de Microsoft), es decir, .NET Framework. Efectivamente, cuando apareció .NET (.NET 1.0 y Visual Studio .NET), esta nueva plataforma nos proporcionaba una serie de clases .NET y un tipo nuevo de proyecto de Visual Studio para desarrollar servicios Web XML de una forma extremadamente fácil (basándonos en ASP.NET y atributos). Como cualquier desarrollador en .NET habrá podido com- SOA “ve el mundo” de una forma distinta: todas las aplicaciones deben ser servicios autónomos donde se definan fronteras explícitas y se asuma la heterogeneidad y colaboren plataformas dispares Especializados en tecnología Microsoft desde 1995 • www.renacimiento.com dnm.comunicaciones Los servicios Web necesitan aspectos más avanzados como cifrado, firma, mensajería asíncrona, enrutamiento de mensajes SOAP, etc. Entonces, centrándonos en los servicios Web XML básicos proporcionados tanto .NET 1.0 con Visual Studio .NET como .NET 1.1 con Visual Studio .NET 2003, lo que se nos ofrecía son las siguientes características: • Comunicaciones entre aplicaciones mediante estándares de Internet (HTTP). • SOAP como formato de mensajes de comunicación. • WSDL como definición y descripción de los servicios (aplicaciones WebServices). • UDDI como localizador de servicios Web. • Al implementar los servicios Web XML con ASP.NET (Web-Methods ASMX) tenemos también acceso a toda la funcionalidad de ASP.NET (sesiones, seguridad, extensiones, etc.). • Los servicios Web XML de .NET 1.0 y 1.1 consiguen una comunicación básica: - Proporcionan un intercambio básico de mensajes XML. - Permiten la interconexión entre sistemas heretogéneos. - La compartición de esquemas permiten mayores abstracciones. Pero, la mayoría de las aplicaciones distribuidas corporativas o comerciales necesitan más… Se necesitan aspectos más avanzados (no soportados por los servicios Web básicos en .NET 1.0 y 1.1) como: - Modelo de seguridad orientado a mensajes (cifrado, firma, etc.). - Mensajería estable y confiable. - Soporte de transacciones entre diferentes servicios Web. - Mecanismos de direccionamiento y ruteo de mensajes SOAP. - Mensajería asíncrona. - Metadatos para “políticas” de servicios Web. - Soporte para datos binarios. La teoría: Especificaciones estándar (WS-*) Para definir todas estas necesidades avanzadas, diferentes empresas (Microsoft, IBM, HP, Fujitsu, BEA, VeriSign, SUN, Oracle, CA, Nokia, CommerceOne, Documentum, TIBCO, etc.) han estado y continúan definiendo unas especificaciones teóricas que conformen cómo deben funcionar los aspectos extendidos de los servicios Web XML. A todas estas especificaciones teóricas se las conoce como las especificaciones WS-*. Si alguien quiere conocer en detalle estas especificaciones, lo puede estudiar en: http://www.oasisopen.org. El siguiente esquema muestra a alto nivel las diferentes funcionalidades que trata de resolver WS-*. Especializados en tecnología Microsoft desde 1995 • www.renacimiento.com Figura 1. <<dotNetManía probar, desarrollar un servicio Web XML y consumirlo desde una aplicación cliente remota (ya sea WinForm o ASP.NET) es algo sumamente sencillo y es la forma recomendada de realizar aplicaciones distribuidas en tecnología Microsoft para sustituir el antiguo esquema (componentes COM y DCOM como protocolo de invocaciones remotas). Por supuesto, en .NET, además de los servicios Web XML podemos hacer uso de .NET Remoting, pero esto, a pesar de que actualmente ofrece algunas ventajas (mayor rendimiento, posibilidad de singleton, diferentes tipos de serialización, etc.), Microsoft lo desaconseja actualmente en la medida de lo posible, porque primero, .NET Remoting no es interoperable con otras tecnologías (requiere .NET en ambos extremos) y segundo .NET Remoting probablemente se descontinúe con la aparición de Indigo y Windows Longhorn (aunque esta última afirmación de descontinuación de .NET Remoting todavía no es algo completamente oficial). Así pues, el caso es que .NET Remoting lo dejamos a un lado en este artículo porque tiene poco que ver con WSE, que es nuestro objetivo. 21 << dnm.comunicaciones Todos los módulos centrales (seguridad, mensajería confiable, transacciones y metadatos) son precisamente las funcionalidades de las que carecen los sevicios Web XML básicos y lo que trata de definir WS-*. Las especificaciones WS-* están así mismo formadas por subconjuntos de especificaciones: • • • • • WS-Security WS-Messaging WS-Transaction WS-Reliability WS-Metadata Éstos a su vez se vuelven a dividir en otros subconjuntos de especificaciones aún más definidas, como muestra el siguiente cuadro: <<dotNetManía Especificaciones WS-* 22 Messaging • WS-Addressing • WS-Eventing • MTOM (Attachments) >> Reliability • WS-ReliableMessaging >> Security • WS-Security • WS-Trust • WS-SecureConversation • WS-Federation >> Messaging • WS-Coordination • WS-AtomicTransaction • WS-BusinessActivity >> Security • WS-Policy • WS-PolicyAssertions • WS-PolicyAttachment • WS-SecurityPolicy • WS-Discovery • WS-MetadataExchange WSE realmente tiene ya un largo camino, pero debido a que su nacimiento está paralelo a la evolución constante de las especificaciones WS-*,WSE ha ido también cambiando y creciendo.Al principio solamente teníamos algunas especificaciones implementadas y cada vez vamos teniendo más. Cuando lleguemos a Indigo, deberíamos de tener la mayoría. La cronología es la siguiente: << WS-* son las especificaciones y estándares, no las implementaciones >> Cronología y futuro de WSE Tabla 1. WSE 1.0 WSE 1.0 + SP1 WSE 2.0 WSE 2.0 + SP1 WSE 2.0 + SP2 WSE 2.0 + SP3 WSE 3.0 Indigo Diciembre de 2002 Marzo de 2003 Mayode 2004 Julio de 2004 Diciembre de 2004 Febrero de 2005 ? de 2005 (única versión de WSE que MS promete será interoperable con Indigo) ? de 2006 ? Como iréis viendo ya, las especificaciones WS-* son prácticamente todo un mundo; no es algo pequeño y limitado que simplemente extienda un poco a los servicios Web XML. Además, son especificaciones todavía en evolución y no cerradas definitivamente. Bien, hasta ahora solamente hemos hablado de especificaciones, teoría, pero para que la teoría funcione en el mundo real (desarrollo de servicios Web XML) hacen falta implementaciones de dichas teorías y especificaciones. Cada fabricante podrá crear su propia implementación de WS-*, pero lo importante es que cumpliendo la teoría e interfaces de WS-*, todas las implementaciones de WS-*deberían ser compatibles unas con otras. ¡Es aquí donde aparece Microsoft WSE! WSE (Web Services Enhancements) es la implementación actual (de Microsoft) de las especificaciones WS-* (por ahora, en la versión 2.0 de WSE solamente de parte de las especificaciones). Me parece muy importante recalcar que WSE es realmente una implementación temporal y en evolución hasta que Microsoft ofrezca su plataforma completa que debería abarcar la totalidad de WS-*. Esa futura plataforma que abarcará WS-* y muchos más aspectos de comunicaciones es Indigo (parte de la siguiente versión de Windows Longhorn). Sin embargo, hasta que dispongamos de Indigo, tenemos que volver al presente y a lo que podemos utilizar ahora para desarrollar servicios Web avanzados, es decir, WSE. Por otro lado, que nadie se asuste. El hecho de que WSE esté en evolución no significa que sea una beta. Es una plataforma de la que van saliendo dife- Especializados en tecnología Microsoft desde 1995 • www.renacimiento.com << dnm.comunicaciones rentes versiones (actualmente estamos en la versión WSE 2.0 SP3), pero todas ellas están soportadas, es decir, son versiones release con soporte por el departamento de soporte técnico de Microsoft, por lo tanto, WSE es perfectamente apto para desarrollar proyectos y ponerlos en un entorno de producción. Pero vuelvo a destacar que, al estar en evolución WSE, es posible que de una versión a otra no tengamos compatibilidad hacia atrás en los interfaces y definiciones de clases de WSE. el marco de trabajo de los servicios Web básicos de .NET (ASMX) con WSE. Bueno, y ¿como se hace esto?. Pues precisamente mediante SOAP, el cual métodos de interfaces necesarios (ProcessMessage, etc.), con lo que conseguimos implementar un filtro propio dentro del procesamiento de mensajes SOAP (ver figura 2). ¿Dónde estamos? Para resumir y tener una visión global, repasemos la tabla 2. Plataformas Servicios Web .NET >> >> >> ASMX (parte de ASP.NET) es la plataforma actual de WS en .NET • Soporta funciones básicas para servicios sencillos. • No implementa las especificaciones WS-*. WSE 2.0 es una extensión de la plataforma actual • Puede utilizarse para extender el comportamiento de ASMX (como Security). • Puede utilizarse de forma separada sin ASMX (como Messaging). • Implementa algunas de las especificaciones WS-*. Figura 2. Funcionamiento de filtros propios basados en SoapExtension da la “casualidad” que en sus cabeceras está preparado para añadir extensiones (¿casualidad?, no, SOAP se definió precisamente con “puertas abiertas” a ampliaciones futuras). Soap Extensión Framework Lo que voy a contar ahora no es algo que necesitemos hacer cada vez que vayamos a desarrollar con WSE, al contrario, es explicar como Microsoft ha “enganchado” WSE con la implementación actual de servicios Web XML (ASMX). ASMX proporciona un framework para la extensibilidad. Podemos desarrollar una clase nuestra que será invocada antes y después del procesamiento de cada mensaje SOAP. Estas clases tienen que heredar de la clase SoapExtension (clase de .NET Framework 1.1) e implementar los En estos filtros o extensiones desarrollados por nosotros podríamos implementar lo que quisiéramos, como por ejemplo un log de mensajes SOAP recibidos y enviados, o un mecanismo de seguridad propio donde hiciéramos comprobaciones a nivel de mensajes, etc. Bueno, pues ¡eso es precisamente lo que hace WSE basándose en SoapExtension!, pero en este caso, en lugar de inventarse los mecanismos y filtros (como haríamos nosotros) WSE sigue al pie de la letra las especificaciones estándar marcadas por WS-*. WSE necesita lo siguiente: • Escribir cabeceras en los mensajes SOAP de salida y leer de los mensajes de entrada. • Transformar el bodyde los mensajes. Así pues, como hemos dicho, implementa estas acciones mediante filtros SOAP (SoapExtension). Indigo es la siguiente generación de plataforma de Web Services • Proporcionará una solución completa WS-*. Bien, entonces estamos actualmente en un punto en que todavía falta bastante hasta que dispongamos de Indigo, pero queremos desarrollar servicios Web XML con aspectos avanzados. Para eso tenemos que extender Figura 3. Especializados en tecnología Microsoft desde 1995 • www.renacimiento.com <<dotNetManía Tabla 2. 23 << dnm.comunicaciones <webServices> <soapExtensionTypes> <add type="Microsoft.Web.Services2.WebServicesExtension, Microsoft.Web.Services2, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" priority="1" group="0" /> </soapExtensionTypes> </webServices> Fuente 1 Siguiendo el mismo esquema, WSE implementa un filtro por casi cada aspecto de WS-* que habilita, como políticas, seguridad a nivel de mensajes, trazas, lógica de Addressing en el filtro de Referal, etc. cio Web XML .ASMX (con HTTP) donde implementásemos cifrado de datos y firma electrónica mediante el módulo de Security de WSE. 2.- La segunda forma de desarrollar servicios Web XML es sin basar- nos en ASMX (sin extender los servicios Web de ASP.NET 1.1) y sin usar siquiera HTTP. Realmente, el desarrollo de un servicio Web implica solamente el basarnos en SOAP y por lo tanto también en XML como formato de datos, pero no es obligatorio basarse en HTTP como protocolo. Teóricamente, el protocolo a utilizar por un servicio Web XML debería ser transparente (en .NET 1.1 no es así, solamente nos podemos basar en HTTP), y en WSE empieza a verse esta independencia del protocolo. De hecho, utilizando Messaging de WSE, podemos desa- Sobre Indigo WSE extiende los servicios Web con nuevos filtros gracias a SoapExtension En la figura 3 se muestra el funcionamiento de dichos filtros implementados por WSE. Donde se configura dicho enlace en el servicio Web (servidor) entre la SoapExtension y los assemblies (las DLL) de WSE (los assemblies que realmente implementan dichos filtros en el Web Service) es en la sección <soapExtensionTypes> del web.config, donde debe aparecer unas líneas similares a las del fuente 1. La comunicación entre los filtros y el código de nuestro servicio Web XML será por supuesto mediante la clase SoapContext. <<dotNetManía Desarrollando con WSE 24 Básicamente hay dos formas de desarrollar servicios Web XML con WSE: 1.- Extendiendo ASMX (servicios Web XML y HTTP): Haciendo uso del framework .ASMX y extendiéndolo mediante el mecanismo que hemos visto antes (basándonos en la extensibilidad de SOAP y la clase SoapExtension). Ejemplos de este tipo de WS sería un servi- Indigo es una plataforma de componentes que proporcionará una infraestructura de comunicaciones que habilitará a aplicaciones distribuidas o componentes el mandar y recibir datos mediante un sistema de mensajería unificado. La incorporación de Indigo permitirá asegurar el flujo de mensajes transaccionales, seguros y confiables entre diferentes aplicaciones o servicios que empleen los mismos protocolos estándares compartidos. Indigo será el futuro y evolución de las siguientes tecnologías actuales: servicios Web XML,WSE, .NET Remoting,ASMX, System.Messaging, y .NET Enterprise Services (transacciones distribuidas, etc.), pero aglutinando las funcionalidades de todo lo anterior y muchas otras nuevas en una única tecnología unificada. Indigo unificará y ofrecerá lo siguiente: • Amplio rango de transportes, incluyendo HTTP,TCP, UDP, IPC y abierto a otros protocolos asíncronos como SMTP, etc. • Mecanismos de seguridad como claves públicas y simétricas y certificados. • Topologías, como punto-a-punto y extremo-a-extremo mediante intermediarios, peer-to-peer y publicación-suscripción. Debido a que la interoperabilidad es un objetivo importante, Indigo tiene un gran compromiso con XML, SOAP y todas las especificaciones emergentes de servicios Web XML avanzados (WS-*) para proporcionar seguridad, confiabilidad y transacciones a aplicaciones basadas en SOAP. Como parte de Longhorn,Indigo estará disponible para cualquier aplicación basada en este sistema operativo. Sin embargo, Microsoft afirma que también Indigo (en su versión definitiva) estará disponible como un instalable separado para poder instalarlo sobre Windows XP y Windows Server 2003, si bien algunas funcionalidades solamente estarán disponibles en Longhorn y en la siguiente versión de Windows Server.Actualmente también se puede bajar una versión beta 1 RC de Indigo desde http://msdn.microsoft.com/Longhorn/understanding/pillars/Indigo. Especializados en tecnología Microsoft desde 1995 • www.renacimiento.com << dnm.comunicaciones rrollar un servicio Web XML que utilice como protocolo simplemente TCP basándonos en el puerto TCP que nosotros queramos y se comunique con otro servicio Web de una forma similar a aplicaciones peer-to-peer. Otro ejemplo de protocolo a emplear (todavía no disponible directamente en WSE) sería SMTP, un protocolo ideal para servicios Web asíncronos. También podemos utilizar en WSE un protocolo InProcess para comunicaciones dentro del mismo proceso. Simplemente resaltar que este nuevo tipo de servicios Web XML se desarrollan en nuestros propios procesos (por ejemplo, un servicio Windows) y no necesitan para nada de ASP.NET ni siquiera de IIS. Vamos a centrarnos en el primer caso, que es el más inmediato y similar a los servicios Web XML actuales (el segundo caso requeriría un artículo completo sobre WSE Messaging). Podemos desarrollar con WSE 2.0 extendiendo ASMX de ASP.NET o también podemos desarrollar un servicio Web directamente con Messaging en nuestro propio proceso sin utilizar ASP.NET. la clase proxy también se llamará Service1 y si miráis en el fichero donde está definida (Reference.cs en C# o Reference.vb en VB.NET) veréis que hereda de la clase del Framework llamada System.Web.Services.Protocols.SoapHttp ClientProtocol. Pues bien, si habilitamos el uso de WSE en nuestra aplicación cliente (luego veremos cómo), Visual Studio nos crea dentro del mismo fichero Reference.cs una segunda clase proxy que se llama igual que la original pero acaba en el literal ‘Wse’ y que en este caso deriva de una nueva clase base llamada Microsoft.Web.Services2.WebServicesClientProtocol, que como véis pertenece a un espacio de nombres nuevo Microsoft.Web.Services2 que no está dentro de System (puesto que WSE está en evolución, por coherencia es mejor que, por ahora, no esté integrado dentro del namespace Sytem). En nuestro ejemplo anterior, esta segunda clase proxy se llamaría Service1Wse. Una vez que disponemos de esta nueva clase proxy, si cuando vamos a llamar a un WebMethod lo hacemos mediante un objeto instancia de la nueva clase proxy (en este caso Service1Wse) entonces estaremos utilizando el nuevo marco de trabajo de WSE. Por el contrario, si la invocación al WebMethod lo hacemos mediante un objeto instancia de la antigua clase proxy, seguiremos empleando el marco de trabajo de servicios Web XML básicos de .NET 1.x. Es así de simple su utilización y siempre podemos utilizar los dos caminos (invocación a nuestro servicio Web por WSE o por servicios Web básicos, a elección nuestra). Cómo instalar y habilitar WSE en Visual Studio 2003 En este caso, está claro que si nos basamos en .ASMX y ASP.NET, estamos, entonces, hablando de servicios Web XML basados en HTTP. La gran mayoría del código nuevo a implementar en aplicaciones que usen WSE está mas bien en el lado cliente (aplicación que consume el servicio Web XML) casi más que en el lado del servidor (por supuesto, depende de lo que haga el WS). Repasando el desarrollo básico de cómo consumir servicios Web XML en ASP.NET de .NET Framework 1.1, recordaréis que cuando desde una aplicación cliente añadimos una referencia Web a un servicio Web XML, Visual Studio nos genera una clase proxy con el mismo nombre que la clase del servicio Web. Posteriormente, usábamos un objeto instancia de esta clase proxy para invocar los WebMethods del servicio Web. Por ejemplo, si la clase del servicio Web se llamaba Service1, pues Instalación de WSE WSE 2.0 no lo tenemos disponible directamente en Visual Studio 2003. Es lógico, porque su aparición es posterior a Visual Studio 2003. Para poder trabajar con las librerías de WSE 2.0 e incluso tenerlo integrado con el IDE de Visual Studio 2003, es necesario bajar el paquete de instalación del sitio público de Microsoft en Internet. En concreto, la dirección de download es: http://msdn.microsoft.com/webservices/downloads/default.aspx Y ahí, seleccionar el último download de WSE. Actualmente, la última versión es WSE 2.0 con el Service Pack 3. Una vez instalado (por supuesto, siempre teniendo ya primero instalado Visual Studio 2003), si hemos elegido la opción de instalación para “Desarrollo”, Especializados en tecnología Microsoft desde 1995 • www.renacimiento.com <<dotNetManía Desarrollando extendiendo ASMX de ASP.NET 25 << dnm.comunicaciones entonces, además de tener disponibles los assemblies de WSE, también se nos habrá integrado una pequeña aplicación de configuración de WSE dentro de Visual Studio 2003. Habilitar WSE en un proyecto Para que un proyecto de Visual Studio 2003 (tanto un servicio Web como una aplicación cliente que consuma al servicio Web) pueda hacer uso de WSE, simplemente tenemos que tener acceso a los assemblies (Microsoft.Web.Services2.dll), namespaces (Microsoft.Web.Services2, Microsoft.Web.Services2.Security, etc.) y adicionalmente conocer configuraciones específicas de WSE que se codifican en el XML del web.config de cada proyecto (como las secciones <microsoft.web.services2>, <diagnostics>, <security>, etc.). Sin embargo, la integración de WSE con Visual Studio 2003 nos facilita mucho la vida y la mayoría de las operaciones anteriores (añadir en references, o añadir secciones del web.config, etc.) las hace por nosotros dicha aplicación de configuración integrada en el IDE de Visual Studio 2003. Esta aplicación se ejecuta desde la opción “WSE Settings 2.0...” del menú de contexto de cada proyecto de Visual Studio 2003: Figura 5 Por ejemplo, seleccionando la opción “Enable this Project for Web Services Enhancements” básicamente lo que hace es añadir a nuestro proyecto las referencias que necesitamos. Esto se puede hacer, por lo tanto, en un proyecto de servicio Web XML pero también en el proyecto cliente (ASP.NET, WinForms, etc.) que consume al servicio Web. Sin embargo, la opción “Enable Microsoft Web Services Enhancements Soap Extensions” solamente es posible en proyectos ASP.NET de servicios Web XML, porque lo que hace por debajo es configurar WSE 2.0 como una soapExtension de forma que se pueda extender el comportamiento de SOAP mediante cabeceras nuevas. Esto es lo que nos añade al web.config automáticamente la segunda opción (solamente el elemento <add>): tenemos con los servicios Web XML de .NET Framework 1.1. Es importante volver a destacar que WSE es algo temporal y en constante evolución debido a que los estándares y especificaciones en los que está basado están también en evolución (especificaciones WS-*). Esta temporalidad y evolución de servicios Web XML se entiende que quedará consolidada y como plataforma completa y estable cuando aparezca Indigo (siguiente gran salto en componentes y desarrollo de aplicaciones distribuidas basadas en estándares y sobre todo en servicios Web). Indigo es uno de los módulos principales de Windows Longhorn, aunque ya tenemos disponible una versión beta instalable de Indigo sobre Windows XP o Windows Server 2003. Actualmente (versión 2.x de WSE) Microsoft advierte que el modelo de objetos y programación es muy diferente de WSE a Indigo, sin embargo, cuando aparezca WSE 3.x, dentro de muy poco tiempo, Microsoft promete que será interoperable con Indigo. Por último, destacar otra vez que aunque WSE está en evolución, esto no significa que estemos trabajando con betas. Al contrario, WSE está plenamente soportado por Microsoft y es una plataforma de componentes probada y disponible para desarrollos de aplicaciones en entornos de producción. No estamos hablando de productos beta. <webServices> <soapExtensionTypes> <add type="Microsoft.Web.Services2.WebServicesExtension, Microsoft.Web.Services2, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" priority="1" group="0" /> </soapExtensionTypes> </webServices> Fuente 2 Conclusiones y próximos pasos <<dotNetManía Figura 4 26 Eligiendo dicha opción, aparece la aplicación de configuración según muestro a continuación: Como conclusión y resumen, podemos decir que WSE son nuevos componentes que nos permiten desarrollar servicios Web Xml avanzados (con WS-SECURITY, WS-MESSAGING, etc.) extendiendo en su mayoría el mismo marco de trabajo que Especializados en tecnología Microsoft desde 1995 • www.renacimiento.com El presente artículo cubre solamente una introducción a WSE y muestra cómo está integrado a .NET 1.1. Sin embargo, no nos hemos introducido realmente en los módulos interesantes de WSE (Security, Messaging, etc.) porque sería necesario un artículo específico para cada módulo. Quizás en un próximo número de dotNetManía... dnm.plataforma.net Carlos Quintero Creación de complementos en Visual Studio .NET Aunque Visual Studio .NET es uno de los mejores entornos de desarrollo jamás creados, siempre habrá funcionalidades que echemos en falta. Afortunadamente Microsoft ya pensó en ello y nos permite añadir nuestras propias funcionalidades a medida mediante complementos, que aprenderemos a crear en este artículo. << Hace ya bastantes años que los entornos de desarrollo de Carlos J. Quintero es Microsoft MVP de .NET desde principios del año 2004. Es autor del popular complemento MZTools 3.0 para VB6,VB5 y VBA, y de MZ-Tools 4.0 para Visual Studio .NET 2002/ 2003, ambos disponibles en http://www.mztools.com Microsoft son extensibles (Visual Basic 4.0 en el año 1996 ya lo era), lo que quiere decir que no tenemos que conformarnos con las funcionalidades que nos ofrecen sino que podemos complementarlos con nuevas funcionalidades de herramientas fabricadas por nosotros mismos o por terceros. Estas extensiones se integran perfectamente en cada entorno de desarrollo integrado (IDE, en adelante) a través de nuevos menús o barras de botones. En las versiones anteriores de Visual Basic, Microsoft sólo ofrecía una forma de extensibilidad, que eran los complementos (add-ins). En Visual Studio .NET no hay una sino tres formas de extensibilidad: • Macros: Por primera vez los desarrolladores de Visual Basic pueden grabar, editar y ejecutar macros en Visual Studio .NET, a través del editor de macros (menú “Herramientas”, “IDE de macros…”). Hay que indicar que la versión actual de Visual Studio .NET sólo admite Visual Basic .NET como lenguaje de programación de macros. • Complementos: Permiten una integración a alto nivel de nuevas funcionalidades proporcionadas por DLLs externas. Los complementos se pueden escribir en cualquier lenguaje de .NET, como Visual Basic .NET, C#, Visual J# o C++. • Paquetes del Visual Studio Integration Program (VSIP): Permiten una integración a bajo nivel de nuevas funcionalidades, editores especializados, nuevos lenguajes de programación, etc. Inicialmente sólo se permitía escribir estos paquetes en C++, pero más tarde Microsoft proporcionó VSIP Extras, que permiten crear estos paquetes en lenguajes como Visual Basic .NET o C# (no obstante la complejidad sigue siendo grande). En este artículo vamos a hablar de la forma de extensibilidad más común, los complementos. Al ser un componente compilado en una DLL, un complemento ofrece más protección de la propiedad intelectual que una macro y mejor rendimiento. El complemento “Hola mundo” En esencia, un complemento no es más que una DLL compilada que cumple 3 condiciones: • Su clase principal implementa ciertos interfaces para poder integrarse en el IDE. • Está registrada como componente COM (ActiveX). Debido a que Visual Studio .NET no es una aplicación .NET sino que sigue usando COM (una herencia del IDE de Visual Studio 6.0), sus complementos tienen que ser componentes COM. No obstante, podemos usar la interoperabilidad COM para hacer pasar a nuestra DLL .NET por un componente COM. ...vamos a hablar de la forma de extensibilidad más común,los complementos. Al ser un componente compilado en una DLL,un complemento ofrece más protección de la propiedad intelectual que una macro y mejor rendimiento << dnm.plataforma.net Figura 1. Para ir abriendo boca y antes de entrar en las farragosas explicaciones del registro de complementos, vamos a crear nuestro primer complemento “Hola mundo”. Para ello usaremos el asistente para creación de complementos que nos proporciona Visual Studio .NET. Se accede a dicho asistente pulsando el menú “Archivo”, “Nuevo”, “Proyecto…” seleccionando en el árbol de tipos de proyectos de la izquierda el nodo “Otros proyectos”, “Proyectos de extensibilidad”, y en la lista de la derecha la plantilla “Complemento de Visual Studio .NET”. Esto abre el asistente y en sus páginas iremos seleccionando como lenguaje de programación Visual Basic .NET, como aplicación de destino (host) a Microsoft Visual Studio .NET, le daremos un nombre (por ejemplo, MiAddin1) y una descripción, y dejaremos las siguientes opciones en sus valores por defecto. Al finalizar el asistente, éste nos habrá creado una solución con 2 proyectos: uno que generará la DLL de nuestro complemento y otro que generará un programa de instalación del mismo. Si nos fijamos en el proyecto de la DLL, veremos que tiene tres referencias que no nos sonarán tan familiares como las demás: son EnvDTE (contiene el modelo de objetos de la extensibilidad de Visual Studio .NET), Extensibility (contiene el interfaz que tienen que implementar todos los complementos) y Office (contiene el modelo de objetos de barras de menús, barras de botones, etc. que Visual Studio .NET toma prestado de Microsoft Office). Para familiarizarnos con el modelo de objetos de estos ensamblados, especialmente de EnvDTE , podemos usar el “Examinador de objetos”. La clase principal de este proyecto es Connect.vb. En esta clase: • Se declaran un atributo GUID y un atributo ProgId: como se mencionó anteriormente, necesitamos hacer pasar nuestra DLL por un componente COM, así que esos atributos especifican el GUID y ProgId de la clase del complemento. • Se implementa el interfaz Extensibility. IDTExtensibility2 . Esta interfaz contiene los métodos OnConnection , OnDisconnection , OnStartupComplete, etc. que a modo de eventos serán llamados por Visual Studio .NET cuando el complemento sea cargado o descargado. • Se declaran e inicializan las dos variables más importantes del complemento: La variable applicationObject representa el objeto raíz del entorno de desarrollo (del tipo EnvDTE.DTE) a partir de la cual tendremos acceso a los menús, documentos, soluciones, proyectos, ventanas, etc. del mismo. La variable addInInstance (del tipo EnvDTE.AddIn) representa esta instancia del complemento. Debido a que el interfaz IDTExtensibility2 sirve también para complementos que se usan en otros hosts (como Outlook, etc.) dicho método nos pasa las variables siendo del tipo Object y nosotros las convertimos a los tipos adecuados para poder usar Intellisense, early binding, etc. …no basta con que nuestra DLL implemente ciertos interfaces (en concreto Extensibility. IDTExtensibility2) para que se comporte como un complemento.Además hay que registrar la DLL como componente COM y como complemento de Visual Studio .NET El método OnConnection es el más importante de todos, y puede ser llamado en distintas situaciones. Visual Studio .NET nos informa del motivo mediante el parámetro connectMode. Cuando el complemento es cargado manualmente después de Visual Studio .NET, el valor que toma el parámetro connectMode es ext_ConnectMode. ext_cm_AfterStartup. Cuando el complemento es cargado automáticamente al inicio de Visual Studio .NET, el valor que se recibe es ext_ConnectMode. ext_cm_Startup. En este último caso, es posible que Visual Studio .NET no se haya inicializado por completo y no es recomendable acceder a sus propiedades, etc. por lo que cuando se ha completado la inicialización, Visual Studio .NET llama al método OnStartupComplete de nuestro com- <<dotNetManía • Está registrada como complemento de Visual Studio .NET, para que aparezca en la lista de complementos (menú “Herramientas”, “Administrador de complementos...”). Como podéis ver en dicha ventana, los complementos se pueden cargar y descargar en cualquier momento, y pueden ser marcados para ser cargados en el arranque de Visual Studio .NET (figura 1). 29 << dnm.plataforma.net plemento. Por tanto, la forma correcta de inicializar nuestro complemento es la siguiente (antes de ejecutar el complemento, añadiremos una referencia a System.Windows.Forms.dll, con su correspondiente línea Imports en el inicio del archivo, e incluiremos una caja de mensaje): el código fuente del mismo, y cuando vayamos a compilarlo nos dará un error porque no puede escribir la DLL ya que está en uso. En este punto no basta con ir al “Administrador de complementos” y descargar el complemento, ya que los dominios de aplicación (appdomains) no permiten descargar ensamblados y la Private applicationObject As EnvDTE.DTE Private addInInstance As EnvDTE.AddIn decir que cada vez que ejecutamos el complemento, sus clases públicas (en nuestro caso la clase Connect) son registradas como componentes COM. Conviene saber que también podemos registrar manualmente DLLs de .NET como componente COM usando la utilidad regasm.exe del .NET Framework, usando el flag /codebase: Regasm.exe /codebase miaddin.dll Y para desregistrarlo como componente COM usaríamos: Public Sub OnConnection(ByVal application As Object, _ ByVal connectMode As Extensibility.ext_ConnectMode, _ ByVal addInInst As Object, ByRef custom As System.Array) _ Implements Extensibility.IDTExtensibility2.OnConnection Regasm.exe /unregister miaddin.dll applicationObject = CType(application, EnvDTE.DTE) addInInstance = CType(addInInst, EnvDTE.AddIn) Select Case connectMode Case ext_ConnectMode.ext_cm_Startup ' No hacemos nada. VS.NET llamará a OnStartupComplete ' cuando esté inicializado Case ext_ConnectMode.ext_cm_AfterStartup OnStartupComplete(custom) End Select End Sub Public Sub OnStartupComplete(ByRef custom As System.Array) _ Implements Extensibility.IDTExtensibility2.OnStartupComplete MessageBox.Show("Hola mundo. Soy " & addInInstance.Name & _ " en " & applicationObject.Name) End Sub <<dotNetManía Fuente 1 30 Ahora ya podemos ejecutar y depurar nuestro complemento: ponemos un punto de ruptura en alguna línea del método OnConnection, pulsamos F5 y aparece una nueva instancia de Visual Studio .NET. En esta segunda instancia, vamos al “Administrador de complementos” y cargamos nuestro complemento MiAddIn1. Si todo ha ido bien, la ejecución se detendrá en el punto de ruptura que establecimos y al continuar la ejecución aparecerá una caja de mensaje con el texto “Hola mundo. Soy MiAddin1 en Microsoft Development Environment”. Para evitar tener que cargar manualmente el complemento en la segunda instancia de Visual Studio .NET, podemos marcarlo para que se cargue siempre al inicio de Visual Studio .NET, pero hay que tener en cuenta que en la siguiente sesión de Windows (al día siguiente, por ejemplo), el complemento se cargará en la primera instancia de Visual Studio .NET, la que tiene DLL seguirá en uso. Para solucionarlo hay que desmarcar el complemento para que no se cargue al inicio, cerrar Visual Studio .NET y volver a arrancarlo. En cualquier caso, para la versión final del complemento que queremos distribuir a nuestros usuarios, el programa de instalación del mismo deberá registrarlo como componente COM. Cuando el asistente creó nuestro proyecto también se encargó de crear unas entradas en el registro de Windows que permiten a Visual Studio .NET descubrir cuales son los complementos disponibles que mostrará en el “Administrador de complementos”. Visual Studio .NET lee los complementos disponibles de dos ramas distintas del registro de Windows: • HKEY_CURRENT_USER\Software\ Microsoft\VisualStudio\7.1\Addins\ <ProgId>. Se usa esta entrada para complementos que están disponibles sólo para el usuario que los instaló. • HKEY_LOCAL_MACHINE\SOFTWARE\ Registro de complementos Microsoft\VisualStudio\7.1\AddIns\ <ProgId>. Se usa esta entrada para Como dijimos al inicio, no basta con que nuestra DLL implemente ciertos interfaces (en concreto Extensibility. IDTExtensibility2) para que se comporte como un complemento. Además hay que registrar la DLL como componente COM y como complemento de Visual Studio .NET. ¿Cuándo hemos hecho esto en nuestro ejemplo anterior? La respuesta es que el asistente lo ha hecho por nosotros: Si vamos a la ventana de propiedades del proyecto del complemento, a la sección “Propiedades de configuración”, “Build”, veremos que la casilla de verificación “Registrar para interoperabilidad COM” está marcada. Esto quiere complementos que están disponibles para todos los usuarios. Para el caso de Visual Studio .NET 2002 las entradas usarían “7.0” en lugar de “7.1”. Como vemos, cada complemento queda identificado por su ProgId. Dado que este valor no es muy descriptivo, se usan unas entradas llamadas FriendlyName y Description para proporcionar un nombre y una descripción para nuestro complemento (estos son los valores que nos pidió el asistente en uno de los pasos). Se crean también otras entradas (CommandPreload, etc. que de momento ignoraremos). << dnm.plataforma.net IDE tienen por detrás un objeto comando (de la clase EnvDTE.Command). Podemos ver los comandos que pro- ¿Complicado tanto registro de complemento? Ciertamente. La buena noticia es que parece que en Visual Studio 2005 no será necesario ni registrar el complemento como componente COM ni usar el registro de Windows: un archivo XML en el directorio adecuado se encargará de todo, pero mientras tanto cuando vayamos a distribuir nuestro complemento a otras máquinas tendremos que hacer que nuestro programa de instalación cree dichos valores en el registro de Windows. Por tanto, combinando ambas formas de registro del complemento, el proceso de descubrimiento y carga resulta ser el siguiente: Visual Studio .NET muestra en el “Administrador de complementos” los nombres y descripciones que ha encontrado para cada ProgId que aparece en las ramas del registro HKEY_CURRENT_USER\Software\Microsoft\ VisualStudio\7.1\Addins\ y HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\7.1\AddIns. Cuando cargamos un complemento, Visual Studio .NET busca en la rama de registro HKEY_CLASSES_ROOT\<ProgId> (HKEY_CLASSES_ROOT\MiAddin1.Connect en nuestro caso) cual es el CLSID que corresponde a ese ProgId, y entonces busca la rama del registro HKEY_CLASSES_ROOT \CLSID\<CLSID>, cuyo valor InProcServer32\CodeBase contiene la ruta a la DLL del complemento. Se carga la DLL del complemento y como al menos una clase pública (la clase Connect) implementa el interfaz Extensibility.IDTExtensibility2, el complemento es cargado satisfactoriamente y Visual Studio .NET invoca el método OnConnection pasándonos las instancias del host y del complemento. porciona Visual Studio .NET pulsando el menú “Herramientas”, “Personalizar…” y en la ventana de diálogo que aparece pulsando en la ficha “Comandos”. Vemos que los comandos están agrupados en categorías, siendo una de ellas la categoría “Complementos”, que contiene los comandos externos al IDE, proporcionados por complementos como veremos más adelante. Cada comando está identificado de manera inequívoca por un GUID y un identificador ID. El GUID permite identificar al creador del comando (subsistema de Visual Studio .NET, un paquete VSIP o un complemento) y el ID permite al creador distinguir sus propios comandos entre sí. Como las propiedades GUID e ID de un comando no son muy amigables, cada comando tiene un caption, que es lo que se muestra en la interfaz de usuario, y un nombre. Podemos ver la lista de nombres de comandos en la ventana anterior, pulsando el botón “Teclado”. El nombre está formado por un prefijo y un nombre corto (por ejemplo, Build.Compile). En el caso de los complementos, el prefijo es el ProgId del complemento. Como el ProgId que genera el asistente es de la forma MiAddIn1.Connect, La buena noticia es que parece que en Visual Studio 2005 no será necesario ni registrar el complemento como componente COM ni usar el registro de Windows:un archivo XML en el directorio adecuado se encargará de todo A diferencia de versiones anteriores de Visual Basic, en Visual Studio .NET todos los menús y botones del Interacción con el IDE Un complemento puede interaccionar con el IDE de alguna de las siguientes maneras: • Respondiendo a eventos que se producen en el IDE con la solución, proyectos, documentos, etc. Para esto disponemos de distintas clases como DebuggerEvents, DocumentEvents, SolutionEvents, TaskLiskEvents, etc. El IDE nos proporciona una instancia de <<dotNetManía Introducción a los comandos los comandos de nuestro complemento tendrán nombres de la forma MiAddIn1.Connect.MiComando, lo cual no es muy estético; sería mejor que fueran de la forma MiAddIn1.MiComando, por lo que podemos cambiar el ProgId de nuestro complemento a simplemente MiAddIn1 (cambiando también, eso sí, las correspondientes entradas del registro del complemento y volviendo a registrar el complemento como componente COM para que el cambio tenga efecto). Por último, podemos obtener mediante código la lista de comandos usando la colección Commands de la clase EnvDTE.DTE. 31 << dnm.plataforma.net dichas clases mediante la propiedad Events de nuestro objeto del tipo EnvDTE.DTE. Por ejemplo, el siguiente complemento intercepta el evento DocumentOpened que se dispara cada vez que abrimos un documento: Private WithEvents eventosDocumento As EnvDTE.DocumentEvents Public Sub OnStartupComplete(ByRef custom As System.Array) _ Implements Extensibility.IDTExtensibility2.OnStartupComplete eventosDocumento = applicationObject.Events.DocumentEvents() End Sub Private Sub eventosDocumento_DocumentOpened( _ ByVal Document As EnvDTE.Document) _ Handles eventosDocumento.DocumentOpened MessageBox.Show("Has abierto el documento " & Document.Name) End Sub Fuente 2 • Interceptando la ejecución de un comando del IDE externo al complemento. A veces es muy interesante poder interceptar la ejecución de dichos comandos para realizar alguna acción antes o después de su ejecución. Por ejemplo, es muy habitual querer interceptar la ejecución del comando Build.BuildSolution, para realizar alguna acción antes de generar la solución. Para ello disponemos de la clase EnvDTE.CommandEvents, que nos proporciona los eventos BeforeExecute y AfterExecute. Para obtener una instancia de la clase EnvDTE.CommandEvents tenemos que usar la propiedad Events de nuestro objeto del tipo EnvDTE.DTE. Un complemento con esta funcionalidad quedaría como ve en el fuente 3. Hay que hacer notar un par de detalles: primero, que hay distintos comandos Build.XXX y este complemento sólo intercepta el que usa el menú “Generar”, “Generar solución” (“Build”, “Build Solution”); segundo, que existe también en el Private WithEvents eventosComando As EnvDTE.CommandEvents Public Sub OnStartupComplete(ByRef custom As System.Array) _ Implements Extensibility.IDTExtensibility2.OnStartupComplete Dim comandoBuildSolution As Command comandoBuildSolution = _ applicationObject.Commands.Item("Build.BuildSolution") eventosComando = _ applicationObject.Events.CommandEvents( _ comandoBuildSolution.Guid, comandoBuildSolution.ID) End Sub <<dotNetManía Private Sub eventosComando_BeforeExecute(ByVal Guid As String, _ ByVal ID As Integer, ByVal CustomIn As Object, _ ByVal CustomOut As Object, ByRef CancelDefault As Boolean) _ Handles eventosComando.BeforeExecute 32 If MessageBox.Show("¿Seguro que deseas compilar la solución?", _ "Pregunta", MessageBoxButtons.YesNo) = DialogResult.No Then CancelDefault = True End If End Sub Fuente 3 modelo de objetos una clase BuildEvents con eventos OnBuildBegin, OnBuildDone, etc. que podríamos usar como en el primer caso que hemos expuesto pero dichos eventos no permiten cancelar la acción. • Respondiendo a la ejecución de comandos del propio complemento (a través de sus botones y menús). Esto será lo más habitual en un complemento. Para ello, primero el complemento tiene que haber creado sus propios comandos. Creación de comandos Un complemento puede crear sus propios comandos usando el método AddNamedCommand de la colección Commands de nuestro objeto DTE. Dicha función recibe como parámetros la instancia del complemento (la que recibimos en el método OnConnection), el nombre corto del comando (el nombre largo llevará como prefijo el ProgId de nuestro complemento), el texto del comando (su caption en la interfaz de usuario), el texto de su tooltip, un valor booleano que indica si la imagen asociada al comando será una de las de Microsoft Office o una a medida diseñada por nosotros y el identificador de dicha imagen (más adelante comentaremos cómo asociar una imagen al comando). Podemos ignorar los otros parámetros opcionales restantes. Un aspecto importante a tener en cuenta es ¿cuándo debe crear un complemento sus comandos? Podríamos pensar que podría crearlos cada vez que es cargado y eliminarlos cada vez que es descargado. Sin embargo, esto no es muy conveniente, porque el usuario puede asociar un comando a una combinación de teclas y si hiciéramos eso el usuario perdería la asociación con su combinación de teclas preferida cada vez que descargara el complemento o cerrara Visual Studio .NET. Por tanto, aunque se pueden crear asociaciones con combinaciones de teclas por código mediante la propiedad Bindings de la clase Command, la respuesta correcta es que los complementos sólo deben crear comandos una vez, la primera vez que son cargados tras su instalación, y de igual manera sólo deben eliminarlos cuando son desinstalados de la máquina. Además, así se mejora el tiempo de carga de los complementos ya que no tienen que crear los comandos cada vez que son cargados (pensemos en complementos que proporcionan varias decenas de comandos, por ejemplo). Para facilitarnos la tarea de distinguir si es la primera vez que cargamos el complemento o no, el IDE nos proporciona el valor especial ext_ConnectMode.ext_cm_UISetup en el parámetro connectMode del método OnConnection. Solamente una vez recibiremos ese valor, y en ese momento deberemos crear los comandos del complemento. No obstante, si nuestro complemento tiene pocos comandos es más robusto comprobar cada vez que << dnm.plataforma.net complicado aún más, en especial para conseguir que la imagen tenga “transparencia” en lugar de un fon- Dim miComando As Command Try miComando=applicationObject.Commands.Item(addInInstance.ProgID & "." & "MiComando") Catch End Try If (miComando Is Nothing) Then miComando = applicationObject.Commands.AddNamedCommand( _ addInInstance, "MiComando", "Mi comando", "Mi comando", True, 59) End If Fuente 4 El programa de desinstalación tiene que encargarse de eliminar los comandos del complemento. Para ello, en una acción custom debe crear una instancia del ProgID “VisualStudio.DTE.7.1” (para Visual Studio .NET 2003) o “VisualStudio.DTE.7” (para Visual Studio .NET 2002) que será un objeto del tipo DTE, a partir del cual podemos acceder a su colección Commands y borrar los comandos de nuestro complemento con el método Delete de la clase Command. Imagen de un comando Para asociar una imagen a un comando de manera que cuando creemos botones en la interfaz de usuario a partir de dicho comando aparezca su imagen, tenemos dos opciones: • Usar una imagen ya existente en las barras de botones de Microsoft Office. En este caso, pasaríamos el valor True en el parámetro MSOButton del método AddNamedCommand y en el parámetro Bitmap pasaríamos el identificador de la imagen proporcionado por Office. Se pueden ver las imágenes disponibles en Office y sus identificadores como se explica en [3]. • Usar una imagen propia para nuestro comando. Usar imágenes propias en los botones de los complementos siempre ha sido complicado en la historia de Microsoft (antes había que usar el portapapeles de Windows, cuyo contenido se perdía si nuestro complemento no tenía la precaución de preservarlo). Por increíble que parezca, en el caso de Visual Studio .NET la cosa se ha do gris. Para llevarlo a cabo tenemos que crear una DLL satélite mediante un proyecto Win32 en Visual C++, añadir un recurso de tipo bitmap de 16x16 píxeles, pintar la imagen usando el color RGB 0,254,0 para las zonas transparentes (casi verde total, pero no el verde RGB 0,255,0 como indica erróneamente la documentación), colocar la DLL en una subcarpeta de nuestro complemento que tenga como nombre el código del locale (por ejemplo, 1033 para English US) y añadir unas entradas en el registro de Windows correspondientes a nuestro complemento con los nombres SatelliteDLLName (contiene el nombre de la DLL satélite) y SatelliteDLLPath (contiene la carpeta de la DLL, pero excluyen- Estado y ejecución de comandos Una vez que tenemos creados los comandos de nuestro complemento, podemos querer cambiar su estado (visible, invisible, habilitado, deshabilitado, etc.) en función del contexto, por ejemplo, dependiendo de si la ventana activa es una ventana de código o no. Y naturalmente, querremos recibir un evento cada vez que un comando es ejecutado para llevar a cabo la acción para la cual se creó. Para ambos propósitos Visual Studio .NET nos proporciona el interfaz EnvDTE.IDTCommandTarget, que debemos implementar en nuestro complemento. Dicho interfaz tiene sólo 2 métodos: • QueryStatus: Este método es llamado por el IDE cuando ha cambiado algo en el entorno de desarrollo y necesita saber el nuevo estado del comando. En este método recibimos el nombre del comando y tenemos que devolver una combinación de flags con el estado del comando. Si se trata de un comando de nuestro complemento, siempre tenemos que devolver como mínimo el valor vsCommandStatus. vsCommandStatusSupported. Si deseamos que el comando esté habilitado, combinaremos dicho valor con vsCommandStatus.vsCommandStatusEnab led, como se muestra en el fuente 5. Public Sub QueryStatus(ByVal CmdName As String, _ ByVal NeededText As EnvDTE.vsCommandStatusTextWanted, _ ByRef StatusOption As EnvDTE.vsCommandStatus, _ ByRef CommandText As Object) _ Implements EnvDTE.IDTCommandTarget.QueryStatus If CmdName = addInInstance.ProgID & "." & "MiComando" Then StatusOption = vsCommandStatus.vsCommandStatusSupported Or _ vsCommandStatus.vsCommandStatusEnabled End If End Sub Fuente 5 do la parte del locale, a pesar de lo que dice la documentación oficial). Finalmente, en nuestra llamada a la función AddNamedCommand, pasaríamos el valor False en el parámetro MSOButton y en el parámetro Bitmap pasaríamos el número de recurso del bitmap en nuestra DLL satélite. Para más información se puede consultar el artículo [4]. • Exec: Este método es llamado por el IDE cuando el usuario ha invocado nuestro comando. En este método llevaremos a cabo la acción deseada, como se muestra en el fuente 6. Creación de menús y botones El siguiente paso es crear elementos en la interfaz de usuario del IDE (boto- <<dotNetManía se carga el complemento si sus comandos están creados, y si no es así, crearlos como se muestra aquí: 33 << dnm.plataforma.net Public Sub Exec(ByVal CmdName As String, _ ByVal ExecuteOption As EnvDTE.vsCommandExecOption, _ ByRef VariantIn As Object, ByRef VariantOut As Object, _ ByRef handled As Boolean) Implements EnvDTE.IDTCommandTarget.Exec If CmdName = addInInstance.ProgID & "." & "MiComando" Then Handled = True MessageBox.Show("Has ejecutado MiComando.") End If End Sub Fuente 6 nes, menús, etc.) asociados a nuestro comando. Para crear un botón a partir de un comando se usa el método AddControl de la clase Command. Dicho método recibe como primer parámetro la barra de comandos (CommandBar) a la que se añadirá el botón. Como segundo parámetro se pasa la posición que tendrá el botón en dicha barra (si no se pasa un valor se asumirá que irá en la primera posición). Las posibilidades para añadir un botón son las siguientes: • Usar una barra de comandos ya existente: En este caso utilizaremos una de los objetos CommandBar que devuelve la colección CommandBars de nuestro objeto del tipo DTE. Cuando el complemento se descarga debemos eliminar dicho botón. Aquí se muestra cómo añadir o quitar nuestro comando de la barra de comandos “Herramientas” (“Tools”) de Visual Studio .NET (otra barra de comandos muy usada es el menú de contexto de las ventanas de código, cuyo nombre es “Code Window”): • Crear una barra de botones nueva: Esto sólo será necesario si nuestro complemento proporcionara tantos comandos que fuera mejor agruparlos en su propia barra, lo cual no es el caso de nuestro complemento de ejemplo, pero para ello emplearíamos el método Add de la colección CommandBars de nuestro objeto del tipo DTE. Dicho método nos devuelve un objeto del tipo CommandBar al que podemos añadir un botón como en el caso anterior. Conclusión En este artículo hemos visto lo básico para la creación de complementos para Visual Studio .NET. Con esto ya podemos centrarnos en la funcionalidad propia de nuestro complemento, como puede ser el manejo de ventanas y documentos, generación y manipulación de texto en nuestro código fuente, manipulación de formularios, navegación por la estructura de nuestro código fuente (namespaces, clases, métodos, etc.). En el siguiente apartado se proporcionan todos los recursos necesarios para seguir nuestra andadura. Recursos en la Web Existen multitud de recursos como documentación oficial, ejemplos, artículos, weblogs, foros y newsgroups, libros, etc. para los desarrolladores de complementos para Visual Studio .NET. Todos ellos están en inglés (incluso los que escribo yo) y están recogidos en la siguiente página de mi sitio Web: Private controlMiComandoEnMenuHerramientas As CommandBarControl Private Sub AñadirCommandoEnMenuHerramientas(ByVal comando As Command) Dim barra As CommandBar barra = applicationObject.CommandBars.Item("Tools") controlMiComandoEnMenuHerramientas = comando.AddControl(barra) controlMiComandoEnMenuHerramientas.Visible = True End Sub Public Sub OnDisconnection( _ ByVal RemoveMode As Extensibility.ext_DisconnectMode, _ ByRef custom As System.Array) Implements _ Extensibility.IDTExtensibility2.OnDisconnection If Not (controlMiComandoEnMenuHerramientas Is Nothing) Then controlMiComandoEnMenuHerramientas.Delete() End If End Sub <<dotNetManía Fuene 7 34 Si deseamos cambiar alguna propiedad del botón, por ejemplo su propiedad Style (para que muestre sólo el texto, o texto con imagen, etc.) o su propiedad BeginGroup (para que se muestre un separador), tendremos que convertir el objeto de tipo CommandBarControl en un objeto del tipo CommandBarButton mediante la instrucción CType (o DirectCast). Con el tipo CommandBarButton tendremos acceso a dichas propiedades que no están en el tipo CommandBarControl. http://www.mztools.com/resources_addin_developers.htm En especial cabe destacar los siguientes: [1] El libro “Inside Microsoft Visual Studio .NET 2003”, de Craig Skibo y otros: http://www.microsoft.com/mspress/books/6425.asp. Este libro es imprescindible para cualquier desarrollo serio en el tema de complementos para Visual Studio .NET y está escrito por uno de los miembros del equipo de extensibilidad de Microsoft Visual Studio .NET. [2] El foro de Yahoo para complementos de Visual Studio .NET. http://groups.yahoo.com/group/vsnetaddin. Tiene una historia de mensajes con preguntas y respuestas muy completa y una sección Files con muchos recursos. Yo mismo he pasado en este foro más de 3 años contestando preguntas sobre complementos para Visual Studio .NET. [3] “Finding Face ID Numbers for Your Microsoft Office 97 Toolbars”: http://msdn.microsoft.com/ library/default.asp?url=/library/en-us/ dno97ta/html/faceid.asp. [4] “Custom command bitmaps 101”: http://weblogs.asp.net/craigskibo/archive/2004/01/08/48814.aspx. dnm.inicio.fundamentos dnm.incio.fundamentos Guillermo “Guille” Som Interfaces Yo implemento, tu implementas,... ¡implementemos todos! En este primer artículo de esta nueva seccción explicamos las Interfaces. Las interfaces son de esos elementos de .NET Framework que juegan un papel bastante importante, pero que, a pesar de estar por todas partes, aparentemente pasan desapercibidas... << Y es cierto, tanto que juegan un parte importante como que pasan desapercibidas; de hecho las estamos usando continuamente y en muchos de los casos ni tan siquiera somos conscientes de ello. Esto es así, al menos en la mayoría de los casos, porque es el propio .NET el que juega ese papel de implementador de interfaces; nosotros simplemente las usamos, pero me atrevo a asegurar que en la mayoría de los casos no somos conscientes de que estamos trabajando codo a codo con las interfaces. Por tanto, ya va siendo hora de que sepamos que existen y cómo podemos aprovecharnos de su existencia... en el buen sentido de la palabra. Las interfaces son... Guillermo “Guille” Som es Microsoft MVP de Visual Basic desde 1997. Es redactor de dotNetManía, miembro de Ineta Speakers Bureau Latin America, mentor de Solid Quality Learning Iberoamérica y autor del libro Manual Imprescindible de Visual Basic .NET. http://www.elguille.info En su forma más simple, las interfaces son simplemente definiciones de buenas intenciones, es decir, sólo indican cómo deberían definirse ciertos miembros de nuestras clases y estructuras. Pero si lo examinamos un poco más a fondo, realmente son más que esas buenas intenciones, ya que, cuando entran en juego, no basta con tener buenas intenciones, sino que debemos seguir al pie de la letra lo que esas interfaces definen. Y este es el punto fuerte de las interfaces, no sólo definen cómo deberían ser las cosas, sino que nos obligan a que las cosas sean de una forma determinada. Seguramente estaremos hartos de leer que las interfaces son un contrato, es decir, son algo que cuando decidimos usarlas, debemos hacerlo al pie de la letra, no basta con tener la intención de..., sino debemos convertir esa intención en algo tangible. Como hemos comentado, el propio .NET Framework utiliza las interfaces cuando quiere ase- gurarse de que algo se puede hacer, por ejemplo, si queremos clasificar elementos en un array o una colección, (ver nº 7 de dotNetManía), esos elementos deben implementar la interfaz IComparable, de esta forma, el propio .NET se asegura de que esas clases clasificables se comportarán de una forma determinada, de modo que pueda utilizarse como está previsto que se utilicen. Esa seguridad que tiene .NET de hacer las cosas como está previsto se la da el hecho de que el programador que ha creado la clase usada para ser clasificada ha firmado un contrato, ese contrato le dice que debe utilizar los miembros de la interfaz correspondiente de la forma adecuada; en este ejemplo, debe implementar el método CompareTo para que coincida exactamente con la forma que está definido en la interfaz IComparable. Por tanto, si .NET se encuentra con una clase que define los miembros de esa interfaz, tiene la certeza de utilizarlos como está previsto. ¿Qué contiene una interfaz? Debido a la naturaleza propia de las interfaces, es decir, que solamente representan buenas intenciones, éstas no contienen código ejecutable, sólo definen qué código debe tener la clase o estructura que decida implementarla. Dicho esto, podemos concluir que las interfaces sólo definen los miembros, realmente la “firma” de los mismos, es decir, de qué tipo son, si reciben parámetros, cuántos y de qué tipo, y en el caso de las propiedades, además del tipo de las mismas, si éstas son de sólo lectura, predeterminadas (indizadores en C#), etc. Veamos un ejemplo para aclarar conceptos. En los fuentes 1 y 2 tenemos la definición de una interfaz, tanto para VB como para C#. << dnm.inicio.fundamentos Public Interface IPrueba Sub Mostrar(ByVal saludo As String) Property Nombre() As String Default ReadOnly Property Item(ByVal index As Integer) As String Function Total() As Integer Event DatosCambiados(ByVal mensaje As String) End Interface tipo) implementa dicha interfaz, lo haremos de la misma forma que al derivar la clase a partir de otra: usando dos puntos después del nombre del tipo, seguido con el nombre de la interfaz: public class Prueba : IPrueba {...} Fuente 1. Definición de una interfaz en Visual Basic Fuente 2. Definición de una interfaz en C# Como podemos comprobar, en las dos interfaces hemos definido todos los tipos de miembros que cualquier clase o estructura pueden tener: métodos, propiedades, indizadores (propiedades predeterminadas en VB) y eventos. En el caso de los eventos, la diferencia está en cómo se definen en VB y en C#, en este último, los eventos siempre están ligados con los delegados, mientras que en Visual Basic no tiene por qué hacerse esa asociación, aunque internamente sí que están bastantes ligados con los delegados, de hecho la declaración de la interfaz del fuente 1 la podemos hacer tal como mostramos en el fuente 3. Aunque en cualquier caso, siempre se podrán definir de la forma habitual (de VB), de hecho, cuando el propio IDE de Visual Studio crea la plantilla para implementar esta interfaz, lo hace de la misma forma que si hubiésemos usado la definición hecha en el fuente 1. ¿Cómo usar una interfaz? Tal como podemos comprobar en los fuentes 1 y 2, al definir una interfaz sólo indicamos la “firma” que tendrán los miembros sin indicar siquiera el ámbito de éstos, ya que siempre serán públicos, de hecho no tendía ningún sentido defi- Public Delegate Sub DatosCambiadosEventHandler(ByVal mensaje As String) Public Interface IPrueba ...resto de miembros... Event DatosCambiados As DatosCambiadosEventHandler End Interface Fuente 3. Definición de una interfaz de VB usando delegados [ El nombre de las interfaces Por definición, o convención, los nombres de las interfaces siempre empezarán con la letra I mayúscula seguida del nombre propiamente dicho. Aunque esto es sólo una sugerencia, ya que realmente el nombre de una interfaz puede ser cualquier nombre válido. ] nir miembros privados en una interfaz. Una vez que hemos definido el contenido de una interfaz y queremos usarla en una clase, estructura u otra interfaz, lo haremos de forma distinta dependiendo del lenguaje. En el caso de C#, para indicar que una clase (o Public Class Prueba Implements IPrueba ... End Class Si estamos usando Visual Studio como editor de nuestro código, éste puede crear las plantillas de los miembros de la interfaz automáticamente, de forma que nosotros sólo tengamos que escribir el código correspondiente a cada uno de estos miembros. La forma de definir esos miembros dependerá también del lenguaje que estemos utilizando, en el caso de C#, no hay que hacer nada especial, simplemente definir los miembros en la clase y asunto arreglado. Pero si el lenguaje usado es Visual Basic, esas definiciones hay que hacerlas de forma explícita, es decir, debemos indicar que las definiciones de esos miembros realmente son las definiciones de los miembros de la interfaz. Esto lo haremos usando, a continuación de la definición de cada uno de ellos, la instrucción Implements seguida del nombre de la interfaz y el miembro que implementa: Public Property Nombre() As String _ Implements IPrueba.Nombre Realmente esta forma de hacer de VB puede parecer, (de hecho lo es), una forma de rizar el rizo, pero la explicación o excusa que hay (con la que nos podemos consolar), es que en VB no tenemos porqué usar el mismo nombre indicado en la interfaz, por ejemplo, el método Mostrar lo podríamos definir de esta otra forma: Public Sub Imprimir(_ ByVal saludo As String)_ Implements IPrueba.Mostrar <<dotNetManía public delegate void DatosCambiadosEventHandler(string mensaje); public interface IPrueba { void Mostrar(string saludo); string Nombre{get; set;} string this[int index]{get;} int Total(); event DatosCambiadosEventHandler DatosCambiados; } En Visual Basic utilizaremos la instrucción Implements seguida del nombre de la interfaz: 37 << dnm.inicio.fundamentos En este caso, el método Imprimir de la clase Prueba realmente es la definición del método Mostrar de la interfaz IPrueba. Sobre esto, aunque está bien que podamos hacerlo, si queremos mantener nuestras mentes claras, sobre todo la de los que prefieren usar C#, deberíamos respetar siempre el nombre indicado en la interfaz. La primera, (que es la que usa el IDE de Visual Studio), es creando dos miembros para implementar cada uno de los de cada interfaz; por supuesto esos miembros deben tener nombres diferentes: Public Sub Mostrar(_ ByVal saludo As String) _ Implements IPrueba.Mostrar Múltiples interfaces en nuestros tipos .NET es un lenguaje de herencia simple, es decir, una clase de .NET no se puede derivar de más de una clase, (salvo con la excepción de la herencia implícita de la clase Object), pero en el caso de las interfaces, podemos decir que los lenguajes de .NET son de herencia múltiple. Esto es así porque una clase (o tipo) puede implementar más de una interfaz; por supuesto, en ese caso, siempre deberemos definir todos los miembros de todas las interfaces que implemente. Para indicar que una clase implementa más de una interfaz lo haremos de la siguiente forma. Para C#: public class Prueba2 : IPrueba, IPrueba2 {...} Public Sub Mostrar1(_ ByVal saludo As String) Implements IPrueba2.Mostrar La segunda es definiendo sólo un miembro e indicando que ese único miembro implementa las dos interfaces: Public Sub Mostrar(_ ByVal saludo As String) _ Implements IPrueba.Mostrar,_ IPrueba2.Mostrar Por supuesto, la forma que elijamos dependerá de cómo queramos implementar estos miembros, es decir, si queremos que compartan el mismo código o que ese código sea independiente para cada implementación. Y de esta otra para VB: Public Class Prueba2 Implements IPrueba, IPrueba2 ... End Class Múltiples interfaces con miembros idénticos <<dotNetManía Un problema con el que nos podemos encontrar es que dos interfaces distintas tengan miembros con la misma firma (y el mismo nombre). Bueno, problema, lo que se dice problema, no lo es, ya que la definición la haremos como de costumbre, si bien aquí volvemos a encontrarnos con la forma que tiene cada lenguaje de hacer frente a esa duplicidad. En el caso de C#, no tenemos que hacer nada en especial, sólo definir un miembro que cumpla con la firma correspondiente y ese mismo miembro lo podemos usar para las dos interfaces. 38 public void Mostrar(string saludo) { // Esta implementación servirá // para las dos interfaces En el caso de Visual Basic, podemos hacerlo de dos formas: Las interfaces sólo definen los miembros, realmente la “firma” de los mismos, es decir, de qué tipo son, si reciben parámetros, cuántos y de qué tipo, y en el caso de las propiedades, además del tipo de las mismas, si éstas son de sólo lectura, predeterminadas (indizadores en C#) Implementaciones privadas, ¿realmente son privadas? El problema con el que nos podemos encontrar es si esta misma forma de actuar, de tener definiciones diferentes para cada implementación, la queremos implementar en C#. Ya que este lenguaje no permite indicar que cada implementación es independiente una de la otra. Al menos si queremos que tanto una como otra sean públicas y queremos que ambas formen parte de la interfaz pública de la clase. << dnm.inicio.fundamentos public void Mostrar(string saludo) { // Esta implementación servirá para la interfaz IPrueba Console.WriteLine(saludo + ", " + Nombre); } void IPrueba2.Mostrar(string saludo) { // Esta implementación solo es para IPrueba2 Console.WriteLine("2: " + saludo + ", " + Nombre); } Fuente 4. Implementación privada en C# de los miembros de una interfaz Igualmente si sólo queremos que ambas implementaciones sean privadas, es decir, que no formen parte de la propia clase que las define, sino que sólo sean accedidas desde un objeto del tipo de la interfaz, las declaraciones las haremos usando la segunda forma mostrada en el fuente 4. En el caso de Visual Basic, como hemos visto, podemos hacerlo de las dos formas mostradas anteriormente, pero si queremos que tengan la misma funcionalidad “privada” que hemos visto en C#, podemos declarar esos miembros como privados, de forma que no formen parte de la interfaz pública de la clase, sino que sólo podamos usarlas desde objetos del mismo tipo que las interfaces. En el siguiente fuente podemos ver un ejemplo de esto que comentamos: Private Sub Mostrar1(ByVal saludo As String) _ Implements IPrueba2.Mostrar .NET es un lenguaje de herencia simple, es decir, una clase de .NET no se puede derivar de más de una clase, pero en el caso de las interfaces, podemos decir que los lenguajes de .NET son de herencia múltiple Como hemos comentado, aunque estos miembros estén definidos como privados, debemos saber que siempre formarán parte de la interfaz que implementa la clase, por tanto podremos acceder a ellos por medio de un objeto de la interfaz, tal como podemos ver en el código de los fuentes 5 y 6. Dim pr2 As New Prueba2 pr2.Nombre = "Pepe" pr2.Mostrar("Desde la clase Prueba2: Hola") Dim ipr1 As IPrueba Dim ipr2 As IPrueba2 ipr2 = pr2 ipr2.Mostrar("Desde la interfaz IPrueba2: Hola") ipr1 = pr2 ipr1.Mostrar("Desde la interfaz IPrueba: Hola") Fuente 5.Acceder a los miembros de una clase por medio de un objeto de la interfaz (VB) Prueba2 pr2 = new Prueba2(); pr2.Nombre = "Pepe"; pr2.Mostrar("Desde la clase Prueba2: Hola"); IPrueba ipr1; IPrueba2 ipr2; ipr2 = pr2; ipr2.Mostrar("Desde la interfaz IPrueba2: Hola"); ipr1 = pr2; ipr1.Mostrar("Desde la interfaz IPrueba: Hola"); Fuente 6.Acceder a los miembros de una clase por medio de un objeto de la interfaz (C#) Conclusión Como hemos podido comprobar en lo expuesto aquí, las interfaces son una de las formas que tienen los lenguajes para que nuestras clases puedan ofrecer cierta funcionalidad y que dicha funcionalidad pueda ser compartida por clases distintas. Debido a que las interfaces nos obligan a seguir unas normas o formas a la hora de definir ciertos miembros en nuestros tipos, podemos usar esta característica para asegurar que nuestras clases utilizan uno de los pilares de la programación orientada a objetos: el polimorfismo, ya que las interfaces le dan a nuestras clases una forma de utilización “medio-anónima”, al menos en el sentido de que si utilizamos una interfaz que nuestra clase implementa, podemos acceder a los miembros implementados por esa interfaz, sin necesidad de saber que estamos usando un objeto determinado de una clase en particular. En otra ocasión veremos de una forma algo más práctica cómo utilizar las interfaces y de paso algunos consejos que siempre vendrán bien para sacar el provecho de este tipo de datos que .NET pone a nuestra disposición. <<dotNetManía La solución es definir cada miembro independiente para que sólo puedan ser accedidos usando objetos del tipo de cada interfaz (o que uno sea parte de la clase y de una de las interfaces y el otro sólo lo sea de la otra interfaz). Esto lo podemos hacer definiendo estos miembros de la siguiente forma. En el fuente 4 se muestra cómo hacerlo para que la implementación de IPrueba sea parte de la clase y que la implementación de IPrueba2 sólo pueda ser accedida mediante un objeto del tipo de esa interfaz. 39 Suscríbase y llévese el CD Volumen 1 gratis AG OT AD O AG OT AD O Aún está a tiempo ❑ Nº3 Nº4 ❑ Nº5 ❑ Nº6 ❑ Nº 7 ❑ Nº8 ❑ Nº10 ❑ Nº11 ❑ Nº12 ❑ Nº13 ❑ Nº14 ❑ Nº15 Nº2 ❑ Nº9 Oferta válida sólo para España hasta el 30 de Junio de 2005 o hasta agotar existencias ✃❑ ❑ Deseo suscribirme a dotNetManía por un año (11 números) por un precio de 60,00€ IVA incluido y recibir el CD Volumen 1 con los 11 primeros ejemplares en formato PDF de alta calidad de forma gratuita. Deseo que me envíen los números atrasados marcados por un precio de 6,00€ IVA incluido cada uno. DATOS DE ENVÍO CIF/NIF. . . . . . . . . . . . . . . . . . . . Empresa . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Nombre y apellidos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Dirección . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Población . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Código Postal . . . . . . . . . . . . . . . . . . . Provincia . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Teléfono . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Fax . . . . . . . . . . . . . . . . . . . . . . . . . . . email . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . DATOS DE FACTURACIÓN (sólo si son distintos a los datos de envío) CIF/NIF. . . . . . . . . . . . . . . . . . . . Empresa . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Nombre y apellidos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Dirección . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Población . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Código Postal . . . . . . . . . . . . . . . . . . . Provincia . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Teléfono . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Fax . . . . . . . . . . . . . . . . . . . . . . . . . . . email . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Usted autoriza a la mecanización FORMA DE PAGO de estos datos. El responsable y ❑ Talón nominativo a nombre NETALIA, S.L. destinatario de éstos es Netalia, ❑ Transferencia bancaria a nombre de NETALIA, S.L. a: S.L. Usted tiene derecho a acceLa Caixa - Número de cuenta 2100 4315 48 2200014696 (Indique su nombre en la transferencia) der a sus datos, modificarlos y ❑ Domiciliación Bancaria (con renovación automática, previo aviso) cancelarlos cuando lo desee. Sus Indique su número de cuenta: datos no serán cedidos en ningu❑ Tarjeta de crédito na de las formas posibles a terceras partes y no se utilizarán más ❑ VISA ❑ MASTERCARD que para el buen funcionamienNúmero de su tarjeta: to de su suscripción a la revista Fecha de caducidad: / (imprescindible) Firma y/o sello a de Puede enviar sus datos por Fax al 91 499 13 64, o por teléfono al 91 666 74 77, o por email a la dirección [email protected], o también puede enviarlos por correo postal a la siguiente dirección: de 20 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 ❑ Netalia, S.L. C/ Robledal, 135 28529- Rivas Vaciamadrid (Madrid) dnm.arquitectura Daniel Mazzini Herencia ¿To be or not to be? En este artículo se demuestra por medio de patrones cuando la herencia es una buena opción y algunos síntomas que nos pueden indicar cuando usarla se puede convertir en un problema y cómo resolverlo. todo esto explicado por dos patrones de diseño y con ejemplos sacados de la plataforma .NET y otros propios. Primero veremos cuando no utilizarla, veremos algunos de sus inconvenientes para luego hacer de esos inconvenientes, virtudes. Por último unas conclusiones salomónicas. Los patrones que seleccione se conocen como Pattern of Patterns, es decir patrones de diseño que son muy básicos y están por debajo de los patrones que se definen en otros libros como GoF o Fowler03. Patrón delegado Resumen Mejorar el diseño por medio de composición cuando la herencia da más problemas que soluciones. Se ruega no confundirse con delegate. Objetivo En algunas situaciones usar herencia para extender clases no es una decisión acertada. La delegación sigue un propósito más general para extender funcionalidad. Contexto de uso Daniel Mazzini colabora habitualmente con dotNetManía. Es Arquitecto de Sistemas de Información en Insert Sistemas. Imparte cursos tanto de C# como de Visual Basic.NET para Aula DAT y colabora en los talleres MSDN de Microsoft Ibérica. La herencia es el modo más común de extender funcionalidad, si se usa correctamente para los casos “es un”. Recalcaría el “un” debido a que en .NET no soporta herencia múltiple. En algunos sistemas, un usuario juega distintos roles. Por ejemplo, en un sistema de conferencias para hoteles un congresista puede ser un empleado del hotel o una persona externa, teniendo tratamientos diferentes, ya que un congresista externo factura sus horas mientras que el empleado no. También en otros entornos donde no se soporta herencia (yo la he usado en VB 6) se imita por medio de la delegación. No debemos mezclar las clases referentes al dominio de la aplicación con las clases de utilidades. Cuando desarrollamos clases de utilidades o herramientas, por ejemplo un manejador de XML, es normal ver cómo una clase delega la creación del XML a la herramienta. Este patrón sigue una de las máximas que se encuentra en GoF: es mejor la colaboración entre clases que la herencia. Esto se debe a que la herencia define su estructura en tiempo de diseño sin posibilidad de cambiar la clase base en tiempo de ejecución. El ocultar métodos o propiedades de una clase base es un indicador de que no es buena idea heredar de esa clase. Lo mismo sucede con las interfaces; si vemos que tenemos una interfaz de tres métodos, la implementamos en diez clases, en ocho de las diez clases uno de los tres métodos está devolviendo un nulo, es porque debemos separar la interfaz y dejar ese método en una segunda interfaz. Y, sobretodo, el uso inapropiado de la herencia puede que nos lleve a crear un AntiPatron como puede ser una clase Dios. Una clase Dios es aquella clase que lo hace todo, donde todo el sistema gira alrededor de esta clase, logrando una gran dependencia hacia ella. Ventajas de este patrón • La herencia es una relación estática mientras que la delegación es dinámica. Podemos hacer lo mis- <<dotNetManía << Veremos distintas motivaciones para usar o no herencia, 41 << dnm.arquitectura mo que con herencia pero cambiando la clase que resuelve el problema en tiempo de ejecución. • Las clases relacionadas al dominio de la aplicación no deben heredar de clases de utilidades. Además de ser una mala decisión de diseño, una vez terminada la clase expondría los métodos públicos de la clase de utilidad, rompiendo su encapsulación. • Proliferación de clases hijas. Ejemplo: tenemos dos clases, empleado y colaborador. Luego sabemos que un empleado puede llegar a ser un colaborador, las dos clases heredan de persona. Habría que crear una clase uniendo las dos posibilidades. Si en lugar de tener una combinación entre 2, lo hacemos entre 5, el número crece radicalmente. • Mejora con interfaces. Se puede mejorar más la colaboración entre clases si el delegado implementa una interfaz. Esto daría la posibilidad de tener más de una clase que pueda servirnos como delegado. Desventajas de este patrón • Más código: Se requiere escribir más código en algunas situaciones. • Comportamiento: Se pueden dar casos donde el comportamiento de la clase cambie, por ejemplo se espera un tipo de error y se recibe otro. Roles Delegado: Clase en que se confía una responsabilidad. Delegador: Clase que le pide al delegado que le resuelva su problema. determinado. Internamente, cuando se cambia la propiedad ListViewItemSorter también se ejecuta el método Sort. Para ordenar un vector, la clase System.Array en una sobrecarga del método Sort permite que le pasemos el vector a ordenar y una clase que implemente la interfaz IComparer. Ejemplo Durante la primera etapa de un desarrollo podemos llegar a conclusiones apresuradas. Por ejemplo, que una ventana es un tipo de rectángulo. Como la relación es del tipo “es un”, creamos la clase base rectángulo capaz de calcular su superficie en m2 y luego la clase ventana que heredara de rectángulo. Todo funciona correctamente, hasta que, bajo un nuevo requerimiento, el cliente nos indica que las ventanas pueden tener distintas formas y que también necesita calcular la superficie. Debemos cambiar el diseño porque no podemos cambiar la clase base de ventana. Debemos delegar en una clase u otra el calculo basándose en el tipo de forma que tiene la ventana. Para que pueda ser más de una clase hacemos una interfaz llamada ISuper ficie, con el método CalcularArea. El fuente 1 muestra el Figura 2. Grafico del apartado de ejemplo - Diseño inicial código que resuelve esta situación. Figura 1. Roles del patrón delegado <<dotNetManía Dentro de .NET 42 Existen gran cantidad de casos dentro de las librerías bases de la plataforma donde podemos ver el uso de delegados. Paso a ejemplificar dos, ambos relacionados con la ordenación de objetos. Cuando hay que ordenar un control ListView se consulta a la propiedad ListViewItemSorter, que es de tipo IComparer si tiene un ordenador asignado. Si la propiedad ListViewItemSorter está nula, crea el ordenador pre- Figura 3. Diseño final. Patrones relaciones Al igual que en la plataforma .NET, muchos patrones utilizan la delegación, los casos mas claros son el Proxy y el Decorador. << dnm.arquitectura #region Miembros de ISuperficie public Double CalcularArea() { return _lado1 * _lado2; } #endregion } /// <summary> /// La clase circulo es uno de los delegados /// </summary> public class Circulo:ISuperficie { public Circulo(double radio) { _radio=radio; } double _radio; #region Miembros de ISuperficie public Double CalcularArea() { return (Math.PI * (Math.Pow(_radio,2))); } #endregion } /// <summary> /// La clase ventana es el delegador /// </summary> public class Ventana { ISuperficie _sup; public Ventana(double lado1,double lado2) { _sup= new Rectangulo(lado1,lado2); } public Ventana(double radio) { _sup= new Circulo(radio); } public double ObtenerArea() { return _sup.CalcularArea(); } } /// <summary> /// Aplicacion de prueba /// </summary> public class Test { [STAThread] static void Main(string[] args) { Ventana v1 = new Ventana(5,5); Ventana v2 = new Ventana(2.5); Console.WriteLine(v1.ObtenerArea()); Console.WriteLine(v2.ObtenerArea()); Console.WriteLine(); Console.WriteLine("Presione cualquier tecla para continuar"); Console.ReadLine(); } } } Fuente 1 Patrón Superclase Abstracta Resumen Asegurar consistencia para encapsular clases conceptualmente relacionadas por medio de una clase superclase abstracta. Contexto Tenemos que crear un conjunto de colecciones para un sistema con información crítica, nos han pedido que no se pueda quitar un objeto de la lista y que podamos ocultar la información lo más que podamos. No quieren que usemos ArrayList.ReadOnly por las dudas que nos olvidemos de usarlo en una de las clases. Nosotros hemos decidido que al llamarse a Remote o RemoteAt, que siga con la documentación de .NET, que dice que debe elevar una excepción del tipo NotSupportedException. Si usamos la clase ColeccionBase nos encontramos que ya viene con este método escrito pero sin posibilidad de sobrescribirlo. Tenemos que usar la interfaz IList. Llegado este punto tenemos dos posibilidades: • Implementar en cada clase concreta la interfaz IList y tener n veces repetido el mismo código que eleva la excepción en los métodos Remote o RemoveAt. • Crear una clase abstracta que resuelva cómo usar el método Remote y RemoveAt para todas las clases hijas. Muchas veces tenemos la posibilidad de elegir entre dos maneras de solucionar un problema, y pocas veces son las que unimos las dos soluciones en una mejor solución, sino que generalmente optamos por una y descartamos la otra. ¿Vacaciones en la playa o en la montaña? ¿Por qué no las dos juntas?. Es el caso de interfaz y clase abstracta: la interfaz nos garantiza indireccionamiento, que el cliente sabrá lo mínimo sobre el servicio que usa, mientras que la clase abstracta nos da un comportamiento común. Si unimos los dos, podremos encontrarnos que tendremos un sistema donde el cliente sólo verá una interfaz (IList), las clases se ocultarán y tendrán un comportamiento homogéneo ya que unos métodos los resuelve la propia clase abstracta y otros métodos quedan abstractos para que los resuelva la clase concreta porque éstos sí son diferentes en cada clase concreta. Ventajas de usar este patrón • Asegurar que un conjunto de clases relacionadas se implementan en forma consistente. • No desea escribir de más. • Facilidad a la hora de mantenerlo. • Facilidad en caso de agregar una clase nueva. <<dotNetManía using System; namespace Delegado { /// <summary> /// Interfaz para comunicar mejor el delegador con el delegado /// </summary> public interface ISuperficie { Double CalcularArea(); } /// <summary> /// La clase rectangulo es uno de los delegados /// </summary> public class Rectangulo:ISuperficie { public Rectangulo(double lado1,double lado2) { _lado1=lado1; _lado2=lado2; } double _lado1; double _lado2; 43 << dnm.arquitectura using System; using System.Collections; • Pruebas: Si un método se implementa en la superclase, y se prueba satisfactoriamente, sabremos que todos los hijos también pasarán esa prueba. namespace SuperClaseAbstracta { public abstract class BaseColeccion:IList { private ArrayList _lista; Desventajas protected BaseColeccion(ICollection coleccion) { _lista= new ArrayList(coleccion); } #region Miembros de IList public bool IsReadOnly { get{return true;} } public object this[int index] { get{return _lista[index];} set{throw new NotSupportedException("La colección es de solo lectura");} } public void RemoveAt(int index) { throw new NotSupportedException("La colección es de solo lectura"); } public void Insert(int index, object value) { throw new NotSupportedException("La colección es de solo lectura"); } public void Remove(object value) { throw new NotSupportedException("La colección es de solo lectura"); } public bool Contains(object value) { return _lista.Contains(value); } public void Clear() { throw new NotSupportedException("La colección es de solo lectura"); } public int IndexOf(object value) { return _lista.IndexOf(value); } • La dependencia que crea la clase abstracta (en el patrón anterior se explicó en detalle este problema). - El hecho de agregarle responsabilidad que no debe tener. Cuando desarrollamos solemos agregar más y más funcionalidad hacia las clases base. El problema es que en ciertas veces, no todas las veces, se necesita esta funcionalidad en todas las clases hijas. Roles • Interfaz: Métodos genéricos que se desean ejecutar desde el cliente. • SuperClase abstracta: Clase encargada de encapsular la lógica común para un conjunto de clases relacionadas que son sus clases hijas. Los métodos con lógica diferente se dejan como abstract, asegurando que cada subclase concreta lo implementa a su manera. • Clases concretas: Las clases concretas son clases relacionadas entre sí, por ejemplo, que están en la misma capa de la aplicación, y que se desea que los métodos que tienen código igual pase a formar parte de una clase base. public int Add(object value) { throw new NotSupportedException("La colección es de solo lectura"); } public bool IsFixedSize { get{return true;} } #endregion #region Miembros de ICollection <<dotNetManía public bool IsSynchronized { get{return _lista.IsSynchronized;} } 44 Figura 4. Roles del patrón superclase abstracta Dentro de .NET public int Count { get {return _lista.Count;} } public void CopyTo(Array array, int index) { Fuente 2 (...sigue) En las colecciones se ven mucho estos casos. Tenemos la interfaz ICollection, la clase abstracta CollectionBase, que implementa ICollection y más de 20 clases que heredan de CollectionBase. << dnm.arquitectura _lista.CopyTo(array,index); arAuto[1]=a2; arAuto[2]=a3; ColeccionAuto col = new ColeccionAuto(arAuto); } public object SyncRoot { get{return _lista.SyncRoot;} } try { col.Add(new Auto("Z","z")); } catch(NotSupportedException nse) { Console.WriteLine(nse.Message); } try { col.Insert(2,new Auto("Z","z")); } catch(NotSupportedException nse) { Console.WriteLine(nse.Message); } try { col.Clear(); } catch(NotSupportedException nse) { Console.WriteLine(nse.Message); } try { col.Remove(a1); } catch(NotSupportedException nse) { Console.WriteLine(nse.Message); } try { col.RemoveAt(0); } catch(NotSupportedException nse) { Console.WriteLine(nse.Message); } #endregion #region Miembros de IEnumerable public IEnumerator GetEnumerator() { return _lista.GetEnumerator(); } #endregion } public class ColeccionAuto:BaseColeccion { public ColeccionAuto(ICollection col):base(col) {} } public class Auto { public Auto(string marca,string modelo) { Marca=marca; Modelo=modelo; } public string Marca; public string Modelo; } /// <summary> /// Aplicacion de prueba /// </summary> public class Test { [STAThread] static void Main(string[] args) { Auto a1 = new Auto("A","a"); Auto a2 = new Auto("B","b"); Auto a3 = new Auto("C","c"); Console.WriteLine(); Console.WriteLine( "Presione cualquier tecla para continuar"); Console.ReadLine(); } } Auto[] arAuto = new Auto[3]; arAuto[0]=a1; } (...cotinuación) Fuente 2 Ejemplo Voy a seguir con el ejemplo que puse al principio, en el apartado de Contexto. Vea el fuente 2. Patrones relacionados • Composite: Utilizado para representar relaciones jerárquicas. Todas las jerarquías tienen un grupo de información común que nos permite movernos entre las jerarquías. • Bridge: Se definen dos interfaces que se comunican entre sí, luego se crean clases abstractas y concretas a partir de estas dos interfaces. Por ejemplo, un IMusico toca un IInstrumento, hasta llegar a que un guitarrista, que es un músico de cuerda, toca una guitarra que es un instrumento de cuerda. • Visitor: Un caso especial de Bridge, donde se extiende funcionalidad indirectamente. Para asociarlo con algo conocido, el ToolTip es un control que con sólo soltarse sobre el formulario hace que cada uno de los otros controles que están en el mismo formulario se le agregue una nueva propiedad que es el texto que mostrará el ToolTip. <<dotNetManía Otro caso lo tenemos en los DataAdapter. Está la interfaz IDataAdapter, con los métodos básicos Fill y Update; la clase abstracta DataAdapter, que implementa IDataAdapter, dejando los metodos Fill y Update como abstractos; luego la clase abstracta DBDataAdapter, que hereda de DataAdapter y le agrega propiedades relacionadas con las bases de datos, como SelectCommand, dejando Fill y Update como métodos que se pueden sobrescribir; y, por último, las clases concretas según cada motor de bases de datos, como SQLDataAdapter, que están marcadas como no heredables para que nadie sobrescriba ningún método. 45 << dnm.arquitectura using System; namespace Mixto { /// <summary> /// Clase base de las entidades /// </summary> public abstract class BaseBE { public BaseBE() { } public void Cargar(System.Data.IDataReader dr) { //TODO Hacer la carga por Reflection } } /// <summary> /// Log que se hace sobre una entidad /// </summary> public class Signatura:BaseBE { public DateTime FechaHoraCreacion; public DateTime FechaHoraUltimaModificacion; public string Creador; public string Modificador; } /// <summary> /// Clase base para quien use una firma /// </summary> public abstract class BaseFirmado:BaseBE { public Signatura Firma; } En estos casos, debemos: • Juntar un conjunto de responsabilidad que creemos que está relacionada. • Crear una clase con esa responsabilidad. • Agregarlo como propiedad a una buena clase base. • Hacer que quienes tengan que tener esa responsabilidad hereden de la nueva clase base. En la figura 5 se ven estos pasos, primero se crea la clase Signatura. Luego se crea la clase abstracta BaseFirmado que a diferencia de la clase BaseEntidades tiene la propiedad Firma de tipo Signatura. Todas las clases que no necesitan firma heredarán directamente de BaseEntidades, mientras que aquellas que necesiten una firma lo hacen de BaseFirmado e indirectamente continuarán heredando de BaseEntidades. /// <summary> /// Clase concretaque usa firma /// </summary> public class Comercial:BaseFirmado { public int IdComercial; public string Nombre; } Figura 5. /// <summary> /// Clase que no usa firma /// </summary> public class Mensaje:BaseBE { public string Creador; public string Destinatario; public DateTime FechaHoraEmicion; public DateTime FechaHoraLeido; public int Prioridad; } } <<dotNetManía Fuente 3 46 De esta manera hemos unido los dos patrones, primero por medio de la SuperClase abstracta al crear una interfaz y clase abstracta para tener un comportamiento común, y después el patrón delegado creando un clase asignándole una responsabilidad muy concreta, y que los demás delegan esa responsabilidad en esta nueva clase. En el fuente 3 puede ver el código del ejemplo anterior. ¿To be and not to be?,¿por qué no? Conclusiones Una de las afirmaciones que hice es que a veces tenemos dos soluciones posibles y optamos por una o por la otra, cuando si unimos podemos mejorar aún más el diseño. ¿Se puede unir herencia y delegación? Un pequeño ejemplo: Cuando se desarrollan entidades de negocios por medio de clases, se suele colocar una clase base y seguir el patrón SuperClase abstracta. Una vez me encontré frente a un caso donde las clases de entidad tenían que tener un log, pero luego resultó que no todas las clases debían tener ese log porque eran invariables, es decir, que después que se creaban no se podían modificar, por ejemplo, los mensajes que se enviaban entre usuarios del sistema. Siempre me gusta decir una frase que está en “Analisys Pattern”, de Martin Fowler: "Los diseños no son malos o buenos, sino más o menos provechosos". Expuse en la primera parte los problemas de la herencia para que sepamos de antemano, si la usamos, con qué nos podemos topar, y si el camino lo vemos libre, pues usarla y si no está tan claro, mejor tirar hacia delegación. Lo que es malo de la herencia es lo que la hace fuerte, la dependencia que tiene una clase hija hacia la clase base es la que nos permite escribir código en la clase base, probarlo y saber que funcionará para todas sus hijas. Por otro lado, si no hemos entendido bien el dominio de aplicación del cliente podemos suponer ciertas cosas que no lo son y quedarnos con un diseño poco provechoso. << dnm.mvp.online Jorge Serrano Aviso para navegantes La amplitud de movimiento de los MVP permite, en muchos casos, divulgar la tecnología Microsoft a rincones insospechados a través de los medios disponibles hoy día. El artículo de la sección MVP Online de este mes trata de mostrar cómo la radio puede llegar a ser una buena prueba de la divulgación tecnológica. Alejandro Curquejo, MVP de Windows, es un fiel ejemplo de esto que comento. << El título no es ningún aviso para el lector; es el nombre del pro- Jorge Serrano es redactor de dotNetManía. Es Ingeniero Informático y MVP de VB y de .NET. Es Webmaster de PortalVB.com y autor de diferentes libros y artículos técnicos. Jorge está entre los mejores profesores y conferenciantes sobre la tecnología .NET de nuestro país. grama en el que participa Alejandro todos los martes en la segunda parte del programa. Este programa radiofónico se emite de lunes a viernes a partir de las 21 horas a través del Canal Sur Radio, una de las tres emisoras de radio de la RTV Autonómica Andaluza o RTVA. Como esta revista llega a ser leída incluso por algunos privilegiados fuera de nuestro país, comentaré brevemente, que Andalucía es una de las regiones de España, situada al sur del país. “Aviso para navegantes” es un programa que lleva en antena muchos años. Se trata de un programa sobre Internet y las nuevas tecnologías, y donde el objetivo que se persigue, es el de informar y hacer reflexionar sobre la nueva era digital, siempre desde un punto de vista del usuario no especializado. En este programa se abordan diferentes apartados, todos ellos dentro de secciones de noticias, ocio electrónico, seguridad en la red, administración electrónica, software libre como Linux, y software propietario como Windows. Sobre la emisora Canal Sur Radio, diremos de ella que es según el EGM (Estudio General de Medios), una de las emisoras más escuchadas en la región de Andalucía. En el programa, Alejandro dispone de 10 minutos para hablar de la tecnología Windows XP. El buen ambiente reinante y la genial transferencia de los conocimientos por parte de Alejandro, hace que el director del programa deje pasar de largo esos 10 minutos y éstos se extiendan a veces hasta los 25 ó 30 minutos incluso. Ojos que no ven... Cuando le toca a Alejandro el turno de participar en el programa, el director le introduce en el tema del día, a partir del cuál se desarrolla la plática. Quizás la mayor dificultad del medio radiofónico para hablar de un tema de carácter tan práctico y técnico como la informática, es encontrar las palabras justas y adecuadas para describir el tema que se quiere abordar. El espacio en el que participa Alejandro está enfocado a los usuarios no expertos, con grandes dosis de entusiasmo por aprender. Por todo esto, un usuario experto puede entender en un momento dado lo que Alejandro podría querer explicar en un momento dado, pero para un usuario novel, las explicaciones deben estar muy preparadas y pensadas para que no haya dudas y todo resulte ameno, didáctico y útil. La informática no come a nadie El espacio en el que colabora Alejandro, trata de llevar la informática a todos los usuarios, ayudándolos a comprender las tareas más comunes y habituales. En este programa, se les explica a los usuarios tanto tareas comunes como tareas un poco más complejas, y aunque a algunos oyentes puedan resultarles algunas de las tareas bastante obvias y sencillas, para un gran número de usuarios y aficionados a la informática son tareas muy interesantes y útiles. Entre algunas de las tareas mencionadas por Alejandro en el programa radiofónico en el que participa, podemos citar por ejemplo, la explicación a los usuarios de cómo instalar un sistema operativo, cómo se formatea un disco, cómo se crean particiones, como realizar una instalación dual, las acciones generales del mantenimiento de un equipo o una explicación de las diferencias entre el software y el hardware. De todos los modos, Alejandro aborda a veces en el programa una sección específica que se parece a algo como “hágalo usted mismo”. En esta sección, se le anima al oyente a abrir su ordenador y conocer los entresijos de éste. En esta investigación, se le anima, enseña << dnm.mvp.online Sobre Alejandro Curquejo “Aviso para navegantes” es un programa que lleva en antena muchos años. Se trata de un programa sobre Internet y las nuevas tecnologías, y donde el objetivo que se persigue, es el de informar y hacer reflexionar sobre la nueva era digital y explica al oyente cómo realizar una limpieza de polvo del ordenador, cómo instalar un segundo disco duro, cómo mejorar el uso del sistema operativo Windows XP y a usar herramientas fundamentales como por ejemplo, el programa anti-spyware de Microsoft. Aún y así, en el programa no se pasa por el olvido tampoco tratar temas relacionados con la seguridad. El usuario debe conocer la importancia de la seguridad y por eso se le enseña a que se familiarice con ella y con sus términos. Por todo esto, al usuario y por lo tanto al oyente, se le educa a que actualice su sistema operativo con regularidad y se le explica el porqué de la importancia de las actualizaciones. De hecho, se hace especial hincapié en el Service Pack 2 de Windows XP y se indica que no es una simple actualización o una simple mejora del sistema operativo de Microsoft. Indudablemente, para contar todos estos temas, es necesario utilizar un lenguaje llano, no purista ni lleno de tecnicismos. El oyente debe encontrarse completamente identificado para sentirse cómodo. Conclusión Es interesante saber que hay diferentes medios de comunicación para informar y divulgar una tecnología como la informática, pero es muy curioso observar como uno de los medios de comunicación más antiguos de la historia moderna, es el utilizado para divulgar en este caso, algo tan actual como Internet, la tecnología y Windows XP. La tarea más compleja en el caso de usar un medio radiofónico, es sin duda el transmitir el mensaje para que llegue al oyente de forma clara y concisa. Al contrario de una conversación telefónica, no existe emisor y receptor que interactúen entre sí, y por lo tanto, sabiendo los temas que se abordan, la complejidad en la comunicación es muy alta. Alejandro Curquejo es MVP de Windows XP desde Abril de 2003, y es conocido en los grupos de noticias de Windows XP como Alezito. En su periplo por los bit y bytes, entra en el mundillo informático en los años 80 de la mano de una Casio PB-100 para pasar posteriorAlejandro Curquejo mente al nostálgico Spectrum 48K y más adelante a un QL de Sinclair; todo ello mientras realizaba estudios sobre Electrónica de Comunicaciones. Desde aquel mismo instante, la informática, que hasta ese momento sólo era privilegio de algunas empresas, comenzaba a llegar a los usuarios y ocuparía un lugar importante entre sus aficiones y el mundo laboral hasta el día de hoy. Alezito es y ha sido colaborador habitual de los grupos de noticias de Windows 98, Windows ME y Windows XP en castellano, siendo uno de los miembros más activos del grupo de noticias, con cerca de 10.000 intervenciones al año. Además de participar en los foros de noticias, también es probador de versiones beta de aplicaciones Microsoft, participando en muchas de ellas como en el programa beta de Windows XP SP2 y Longhorn. En lo que compete a su perfil profesional, Alezito trabaja para un importante medio de telecomunicaciones, y comparte su trabajo y dedicación como MVP en los foros, a formar a compañeros y empleados de su misma empresa y a escribir numerosos artículos técnicos y trucos relacionados con Windows XP, además de colaborar en Canal Sur Radio. Puede recoger más información de las actividades realizadas por Alezito en los grupos de noticias, o en la web: http://www.multingles.net/tutexpertos.htm#ALE Para otros asuntos o inquietudes, podrás contactar con él en la dirección de e-mail [email protected]. Si quieres saber más sobre el programa MVP puedes consultar la página oficial de Microsoft en: http://mvp.support.microsoft.com Programación de la emisora http://www.canalsur.es/PROGRAMAS/radio/index_radio.html Sintonización de la emisora por Internet (con Real Player) http://www.canalsur.es/Informativos/EmisionesDirecto/canalsurradio.ram Sintonización por el Satélite ASTRA Nombre de Servicio: ANDALUCÍA RADIO Dial Digital+: 224 Satélite: Astra 2C Transponder: 1056 Frecuencia Downlink: 10.818 MHz Polarización: V Symbol rate: 22 Mbaudios FEC: 5/6 Codificación (acceso condicionado): Mediaguard Network ID: 1 TS ID: 1056 Service ID: 29969 http://www.canalsur.es/PROGRAMAS/radio/programas/aviso_navegantes/index_aviso_navegantes_jorge_gonzalez.htm Para descargarse emisiones anteriores en MP3 <<dotNetManía Diales de Canal Sur Radio 49 dnm.comunidad.net << dnm.comunidad.net El sitio de “El Guille” Un sitio con más de ocho años de historia El sitio de “El Guille” ha crecido mucho desde que nació en 1996.Y no por “viejo” está anticuado. Como él mismo dice, en el sitio de el Guille hay mucha información y de la buena sobre .NET Framework. Guillermo Som es redactor de dotNetManía, mentor asociado de Solid Quality Learning y miembro de INETA Speaker Latin America por lo que se recorre el mundo dando conferencias << Hace unos días que Paco Marín, el editor de esta revista, me pidió que escribiera algo sobre mi sitio, realmente me dijo: "...cuenta un poco la historia –o la prehistoria casi– de tu sitio, qué es lo que se pretende con él, para qué puede ser útil, etc." Al principio, lo de prehistoria me hizo gracia, (todavía me la hace), y la verdad es que no anda muy desencaminado, ya que en estos tiempos que corren y tratándose de un sitio de programación, ocho años sí que se puede considerar prehistoria... Pero no te preocupes que no te voy a contar las batallitas que he tenido que mantener durante estos últimos ocho años -realmente ocho años y medio- para mantener vivo y activo mi sitio. Pero como tengo que enrollarme un poco, pues algo sí que te contaré de todo este tiempo que llevo en la red. <<dotNetManía Al principio fue... 50 Todo comenzó casi por casualidad, en aquellas fechas, noviembre de 1996, yo mantenía un sitio dedicado a noticias sobre Nerja y alrededores. El servidor que alojaba ese sitio lo gestionaba un amigo mío, y este caballero me comentó si quería tener un sitio para que yo pusiera lo que quisiera en él. Le dije que sí, así me serviría para practicar más todo eso de crear páginas Web y demás “novedades”, al menos para mí, sobre escribir código HTML, ya que en esas fechas, prácticamente casi todas las páginas había que hacerlas a mano, que eso de tener un editor de HTML no era tan común como lo es ahora. Así que rebusqué entre las cosillas que tenía en mi disco duro, creo que en aquella época era uno de 100 megas, (sí, megas, no gigas), y empecé publicando algunos trucos de Visual Basic. En enero del 97 me apunté a una lista de distribución de Visual Basic, (vb-es), ade- más de empezar a visitar algunos grupos de noticias públicos de Microsoft, no sólo de Visual Basic, sino también otros relacionados con la programación HTML y lenguajes scripts, ya que lo que yo iba descubriendo me servía para “orientar” a otros que estaban más perdidos que yo. Así fue como poco a poco mi sitio fue creciendo, cuatro trucos por aquí, cuatro por allá; por suerte la gente también empezó a colaborar con sus propios trucos, (creo que la primera colaboración que recibí fue de David A. Garza), hasta que en pocos meses era casi un sitio en el que había que pararse para encontrar algo sobre Visual Basic y en español, ya que en inglés sí que había otros sitios, pero, si ya cuesta trabajo leer... tener que hacerlo en inglés, pues como que costaba más, y si además del idioma le añadías que todo era gratis y que encontrabas un montón de código, pues mejor... sobre todo para muchos que lo que necesitaban era precisamente esa “rutinilla” que andaban buscando y que acababan por solucionarle algunos quebraderos de cabeza. En el mes de febrero de 1997 empecé a publicar artículos traducidos del inglés de, por aquél entonces, un gran sitio dedicado a Visual Basic: VBOnline. En esa labor de traducción, en la que el primer número me tocó traducirlo todo a mí, colaboraron un montón de gente que iban rotando, entre ellos mi buen amigo Joe LeVasseur, el yankee menos yankee de todos los yankees. Esos artículos traducidos no estaban en mi sitio, sino en uno independiente, aunque al cabo de poco tiempo, acabó como un directorio de mi sitio, ya que no seguimos con las traducciones porque al final casi todo el contenido de la versión USA era “semi” comercial y lo que realmente interesaba era publicar temas relacionados con el “código” y no traducir anuncios. En todo este tiempo, el sitio de el Guille ha cambiado varias veces de ubicación, aunque hasta finales de 2003 siempre en el servidor de mi amigo Manolo: Web Costasol. Incluso en los primeros meses ni tan siquiera se llamaba “guille”, sino “guiller”, (con “r” al final), ya que mi colega Manolo me llamaba así y así me “bautizó”. La verdad es que en todos estos años, en más de una ocasión mi sitio tuvo sus momentos críticos, al menos << dnm.comunidad.net consumo de ancho de banda, de hecho ese consumo es ilimitado, así que... el único problema para que la cosa deje de funcionar es que todos los años por el mes de marzo no tenga en mi cuenta el importe del pago anual. ¿Que hay en el sitio de el Guille? Después de la batallita sobre la vida desde la “prehistoria” hasta nuestros tiempos de mi sitio, ya va siendo hora de que te cuente qué es lo que puedes encontrar en él y cuales son mis intenciones o, las razones para que el sitio exista. Como te he contado antes, el sitio lo empecé para publicar “cuatro truquillos” que tenía, trucos que pensaba que a otros les podía ser de interés, después empecé a escribir “tutoriales” (o entregas) sobre temas que a muchos les interesaba, como la forma de crear un fichero de ayuda e incluso un curso de programación con Visual Basic. Curso que empecé en abril del 97 y que casi todas las semanas iba actualizando, pero conforme pasaba el tiempo y al recibir más visitas, también recibía más consultas, tuve que ir alargando los plazos de entrega, ya que en ocasiones el responder a todas esas consultas me llevaba incluso más de ocho horas diarias, sí..., parece una locura y de hecho era una locura dedicar todo ese tiempo “por la cara” a responder consultas, consultas que en ocasiones se convertían hasta en peticiones, (y en algunos casos, exigencias), de que les hiciera el programa completo... era como se suele decir que uno le daba la mano y acababan queriendo el brazo completo, así que... casi tuve que cortarlo de raíz, de esa forma podía dedicarle más tiempo a publicar cosas nuevas, además de que la programación con Visual Basic se iba complicando cada vez más y necesitaba dedicar más tiempo a investigar que a responder a consultas, la mayoría de las cuales ya tenían respuesta en lo que había publicado en mi sitio. Y es que algunos no llegaban a entender que todo eso lo hacía, (y lo sigo haciendo), sin recibir ninguna compensación económica, es decir, mantener el sitio no es un trabajo remunerado, vamos, que no hay ninguna empresa que diga: “Guille tu dedícate a esto que yo El Guille 1987-2005 te pago tus gastos, el alquiler de tu casa y te doy de comer”, y para más INRI, ni siquiera me dedico a la programación profesional, al menos en el sentido de que no vendo programas. Afortunadamente no sólo era yo el que publicaba nuevas cosas, y de forma altruista, sino que el número de colaboradores también crecía casi a diario, incluso en la actualidad son los colaboradores los que se llevan todo el peso del contenido de mi sitio, si no fuese por ellos no habría tantas cosas nuevas casi a diario. Cosas que en los últimos años están más enfocadas a la programación con .NET, y no sólo dedicado al lenguaje Visual Basic, que aunque es el que a más gente atrae a mi sitio, realmente hay muchas cosas publicadas sobre C# y en general sobre todo lo que .NET Framework ofrece, ya que hay que estar al loro con lo que la gente demanda, y hoy por hoy, la gente quiere saber más y mejor sobre .NET, y aunque no esté bien decirlo, e incluso hay gente que todavía no lo sabe, el sitio de el Guille tiene mucho contenido, y del bueno, sobre .NET Framework, de hecho en mi caso particular, todo lo que publico lo hago siempre en los dos lenguajes principales de .NET: Visual Basic y C#; y en lo que respecta a los colaboradores, siempre encontrarás autores que utilizan uno u otro lenguaje, así que... si aún no sabes dónde encontrar información sobre cómo hacer las cosas en .NET, ya sea en Visual Basic o en C#, ya sea para trabajar con acceso a datos mediante ADO.NET o para crear sitios Web con ASP.NET o para crear y utilizar servicios Web o para saber cómo trabajar con encriptación, gráficos GDI+ o con cualquier cosa que te interese de punto NET, sólo tienes que darte una vuelta por mi sitio: http://www.elGuille.info. ¡Te espero! Guillero “El Guille” Som <<dotNetManía en lo referente a su permanencia, ya que conforme pasaba el tiempo el sitio era más popular y consumía más ancho de banda, y como no reportaba beneficios, (todo siempre ha sido gratis), pues mis peleas me costaba para que no desapareciera; no culpo a la gente de Costasol, ya que para ellos era un gasto que crecía día a día y durante demasiado tiempo soportaron esos gastos, siete años para ser precisos. Incluso llegué a buscar sitios gratuitos en geocities e incluso en un servidor francés, (que exigía que el contenido estuviese en idioma de Asterix), por si esas conversaciones algún día se terminaban por convertir en discusiones. De hecho en marzo del 2003 la gente de BusiNet me ofreció espacio gratuito y así fue como apareció MundoProgramación, un sitio “espejo” con el que aseguraba la existencia del sitio de “el Guille”. Fue a principios de diciembre de ese mismo año cuando “de pronto” el sitio que tenía en Costasol dejó de existir, básicamente porque mi colega ya no estaba a cargo de los servidores Web y no podía seguir cubriéndome las espaldas, por tanto, tuve que buscar otro sitio nuevo donde alojar las muchas cosas que ya tenía publicadas, así es como nació elguille.info. Toda esta movida, y realmente las últimas que tuve antes de esa fecha, estaba siempre motivada principalmente por el consumo tan grande de ancho de banda, es más, en abril de 2004 tuve que mudarme de nuevo, (aunque seguí conservando el mismo nombre), ya que en el mes de marzo ese consumo se disparó (y eso que tenía 40GB contratados), y “la broma” me costó una pasta... aunque el problema no fue realmente el dinero, sino la forma “no clara” de calcular el importe extra que debía pagar, así que... agarré los bártulos y me mudé nuevamente, y hasta la fecha sigo en el mismo sitio, un sitio en el que el límite sólo lo tengo en el espacio que ocupe, y por suerte, no lo que la gente “consuma”, ya que en el año que llevo en el nuevo servidor, prácticamente todos los meses se supera, y con creces, el consumo de ancho de banda del mes anterior y hasta ahora no ha habido ninguna queja ni tampoco nuevos “cargos extras” en los importes pagados. Por supuesto, esto es así porque el tipo de alojamiento que tengo contratado no es el más económico, sino uno que me asegurara que no tendría problemas con el “famoso” 51 dnm.todotnet.qa Dino Esposito Acceso a datos y contenedores de datos << En estos años hemos visto varios modelos de programación Dino Esposito es redactor de dotNetManía. Formador, consultor y escritor afincado en Roma. Miembro del equipo de Wintellect, Dino está especializado en ASP.NET y ADO.NET. Puede enviarle sus consultas a [email protected] para bases de datos en SQL Server, que se sucedían uno a otro sin descanso. Las características suministradas por el Sistema de Gestión de Bases de Datos subyacente (el DBMS), cambiaban con el tiempo dando solución a los requerimientos de los usuarios, y cumpliendo el objetivo de conseguir, cada vez, un producto más poderoso y exitoso. De forma paralela, los modelos de acceso a datos, evolucionaban para incorporar las novedades, mientras mantenían un adecuado nivel de sencillez de uso de las, cada vez, más complejas características internas ofrecidas por los servidores, tanto para el desarrollador como para el administrador, de cara a construir la capa de acceso a datos. Hoy, los desarrolladores pueden utilizar objetos contenedores de alto nivel para almacenar y manipular datos. En un próximo futuro –en una predicción evidente–, nos encontraremos utilizando objetos de negocio que implementen cualquier tipo de manipulación de datos de una forma fácil y conveniente. De esta forma, un viejo sueño de los desarrolladores se hará realidad: usar objetos en lugar de registros. En ese día, la base de datos, que ahora es parte constituyente del API se convertirá –con todos los predicamentos– en una herramienta más. Nos guste o no, esto nos lleva al siguiente paso de un proceso que, iniciado hace una década con ODBC, parece ahora despegar hacia el modelo de enlaces Objeto/Relación (O/R). La abandonada iniciativa Object Spaces. –que inicialmente era parte integrante de .NET Framework 2.0– se muestra como un signo más del camino a seguir. Todo esto nos conduce a la primera pregunta de este mes. ¿Cuál es la diferencia entre ODBC y ADO.NET y por qué Microsoft sintió la necesidad de crear un modelo de objetos totalmente nuevo como ADO.NET? ¿No bastaba con ADO? Trabajé en mi primer proyecto Windows a principios de los 90. Nuestra aplicación necesitaba algún tipo de soporte de bases de datos, aunque ésta no era una de sus partes críticas. No había razón ninguna para escoger entre Access, Paradox o quizás SQLServer. Adoptamos ODBC, que para la época era el estándar emergente en conectividad de bases de datos. Era una elección perfecta para nosotros, por que lo conocíamos suficientemente. El API de ODBC, de hecho, se diseñó para programadores de C/C++. ODBC fue el primer intento de normalizar el acceso a toda una serie de sistemas DBMS a través de un API común. Antes de esto, los programadores no tenían más remedio que adentrarse en las particularidades propias de cada sistema de base de datos. Además, resultaba imprescindible mantenerse al día de las novedades de cada dialecto SQL y la arquitectura subyacente a él. Aunque no era perfecto en sí mismo, ODBC mostraba la forma correcta de hacer las cosas. ODBC se diseñó como un API orientada a C pero el advenimiento de COM y los entornos RAD como Visual Basic planteó de inmediato la necesidad de una alternativa basada en COM. Más o menos al mismo tiempo, los desarrolladores de Access y Visual Basic disfrutaban del modelo de objetos DAO incluido en Microsoft Access y controlado por el motor de datos JET. DAO fue mejorado para permitir el acceso a SQL Server y Oracle vía ODBC. Básicamente, DAO actuaba como un proxy entre nuestro código y el API de ODBC. Este modelo, sin embargo, introdujo cierta sobrecarga, debido a que los resultados tenían que ser reconvertidos al modelo de DAO, para poderse utilizar realmente. Para soslayar esta dificultad, Microsoft introdujo RDO y, después, ODBCDirect. Los Objetos de Datos Remotos (RDO) son un modelo de objetos COM que expone las funcionalidades del modelo ODBC. No tiene más posibilidades o es más potente que el modelo ODBC; es sencillamente, un “envoltorio” COM para ODBC diseñado para hacer ODBC accesible desde un fichero de script, la Web, o aplicaciones Visual Basic. ODBCDirect, sin embargo, se creó para acelerar las aplicaciones existentes que accedían a SQL Server. ODBCdirect es una especie de modo de trabajo DAO. Cuando se habilita, utiliza RDO y ODBC en lugar de JET para leer y escribir datos en las bases de datos SQL Server. No obstante, la primera innovación significativa en el acceso a datos tras ODBC fue OLE-DB. OLE-DB se introdujo por primera vez en 1998 como parte de la ¿ ¿Cuál es la diferencia entre ODBC y ADO.NET y por qué Microsoft creó un modelo de datos totalmente nuevo como ADO.NET? ? << dnm.todotnet.qa y se ha sustituido por el proveedor de datos administrado. Además, en .NET, se pueden llamar a los proveedores de OLE-DB directamente, sin la intervención de ADO. ADO.NET es un conjunto de clases que expone servicios de acceso a datos a las aplicaciones .NET. Existen varias diferencias sintácticas entre los modelos de ADO y ADO.NET. A pesar de todo, las funcionalidades de ADO y ADO.NET se parecen bastante debido a que Microsoft hizo lo posible para que la similitud entre la sintaxis de ambos modelos fuera máxima. De esta forma, los desarrolladores no necesitan familiarizarse con demasiados conceptos nuevos para utilizar ADO.NET y pueden migrar aplicaciones mediante una curva de aprendizaje relativamente suave. Con ADO.NET, probablemente, no podrás reutilizar mucho del código existente, pero, ciertamente, podrás reutilizar todos tus conocimientos de ADO. ADO.NET consiste en dos bloques de alto nivel: contenedores y proveedores de datos. Las clases contenedoras de datos forman una especie de modelo de bases de datos en memoria. Clases como DataSet, DataTable y DataView son clases tipo array y pueden ser rellenadas con cualquier dato, incluyendo datos leídos de una base de datos. Además, las clases suministran características avanzadas que soportan un modelo de base de datos desconectado, basado en memoria, con características avanzadas tales como tablas, relaciones, restricciones y claves primarias. Son la contrapartida de los proveedores OLE-DB. Los proveedores administrados acceden a los sistemas DBMS, y en general a los almacenamientos de datos, exponiendo sus funcionalidades a través de una interfaz común de programación y contenedores de datos. Los proveedores administrados se diferencian de los proveedores OLE-DB al menos en dos aspectos: son objetos administrados (en oposición a los objetos COM) y son más sencillos (implementando un conjunto más compacto de interfaces). Otra clara ventaja de los proveedores administrados es que devuelven datos utilizando objetos específicos del framework de alto nivel, haciendo innecesaria cualquier otra conversión (como el Recordset de ADO) a contenedores más manejables. Esas son las razones por las que Microsoft abandonó ADO y OLE-DB en favor de un nuevo modelo: ADO.NET Hay tantas clases de colecciones en el .NET Framework que uno se confunde fácilmente. Pero, afortunadamente, usted puede ayudarnos ¿no? Exacto. Mi labor aquí es (tratar de) ayudar y arrojar algo de luz sobre los puntos oscuros. ¿Te quejas del número de colecciones en la versión 1.1 de .NET Framework? Pues tienes que echar un vistazo a los generics en .NET Framework 2.0. Generics dobla el número de opciones disponibles. Al más alto nivel de abstracción, una colección sirve de contenedor para instancias de otras clases. Todas las clases de colección implementan la interfaz ICollection, que, a su vez, implementa la interfaz IEnumerable. Como resultado, todas las colecciones suministran las siguientes funcionalidades básicas: Disponen de una propiedad Count que devuelve el número de ítems en memoria; tienen también un método CopyTo() para copiar sus elementos (todos o en parte) a un array externo; contienen un método GerEnumerator() que instancia un objeto enumerador para recorrer sus elementos. Este es el método que permite que posteriormente, puedan recorrerse los objetos que implementan esta interfaz mediante bucles tipo foreach (C#) /For…Each (VB.NET). ¿ Hay tantas clases de colecciones en el .NET Framework que uno se confunde fácilmente. Pero, afortunadamente, usted puede ayudarnos ¿no? IList e IDictionary son dos interfaces que extienden ICollection otorgando una definición más precisa a las clases colectivas resultantes. ICollection sólo suministra la funcionalidad mínima y básica. Por ejemplo, en la interfaz no existen métodos para añadir o quitar elementos. Esta función es justamente la que suministra la interfaz IList. En la interfaz IList, los métodos Add() e Insert() aña- ? <<dotNetManía plataforma de Visual Studio 6.0. OLEDB era desde el punto de vista del desarrollo, lo que se dio en llamar visión UDA (Universal Data Access). La idea inspiradora de UDA era que cualquier tipo de almacenamiento de datos fuera accesible a través de un conjunto común de interfaces COM. Básicamente, es el mismo principio rector de ODBC, pero retocado y refinado para integrarse en la más popular y exitosa plataforma de desarrollo del momento: el Modelo de Objetos de Componentes (COM). De nuevo, el modelo –en sus inicios– tenía ciertas imperfecciones. Totalmente basado en COM, el modelo consumidor/proveedor de OLE-DB era relativamente fácil de implementar en aplicaciones C++, pero demostró su extrema dificultad para aplicaciones Visual Basic y ASP. Ambos, los componentes de VB y ASP carecen de la posibilidad de trabajar con interfaces COM de bajo nivel, por no mencionar que la generalidad del modelo de programación, era sofisticado y requiere bastante trabajo para implementar incluso las operaciones más simples. ActiveX Data Objects (ADO) es la librería COM creada para hacer accesible el modelo OLE-DB a todos los entornos de programación. Como RDO y ODBC, se sitúa entre la aplicación y las API de acceso a datos de bajo nivel y sirve de mediador entre las operaciones garantizando que los datos traspasados entre ésta y el sistema DBMS se expongan a los usuarios potenciales en forma apropiada y conveniente. ADO es la elección primaria –a menudo la única razonable– para construir una capa de acceso a datos en COM, ASP y aplicaciones VB6. También ha sido incorporado y resulta fácil de llamar desde otras herramientas RAD no Microsoft, tales como Delphi o PowerBuilder. ¿Y qué sucede si creamos aplicaciones .NET? Lo primero, debido a que ADO es un objeto COM no existe ninguna contraindicación por su arquitectura para que sea llamado desde una aplicación .NET. Dicho esto, sin embargo, la utilización de ADO en .NET no es –generalmente– una buena idea. En .NET Framework, una gran parte de las funcionalidades de ADO han sido incorporadas en el nuevo framework de ADO.NET. El proveedor OLE-DB ya no es el modo preferido de acceso a datos, 53 54 [email protected] [email protected] <<dotNetManía << dnm.todotnet.qa den elementos al final o en una posición concreta de la colección. Los métodos Remove() y RemoveAt() borran elementos, mientras el método Clear() vacía totalmente la colección. Finalmente, Contains() verifica si un ítem con un valor dado pertenece a la colección e IndexOf() devuelve el índice de un ítem especificado. La interfaz IDictionary define un API que representa una colección de pares clave/valor. La interfaz expone métodos similares a IList, pero con diferentes signaturas. Las clases Dictionary también muestran propiedades tales como Keys y Values. Ambos devuelven las colecciones respectivas de Claves y Valores del diccionario. Algunos ejemplos típicos de estas clases son ListDictionary, HashTable y SortedList. Basados en las interfaces implementadas, podemos reconocer tres tipos de colecciones en .NET Framework: colecciones simples, listas y diccionarios. Las primeras son clases secuenciales como Queue y Stack que típicamente, consumen ítems tras leerlos. Estas clases implementan ICollection solamente. Las listas (Lists) son clases que implementan IList (que, a su vez, hereda de ICollection). Finalmente, los diccionarios implementan IDictionary e implícitamente ICollection. En algunos casos, lo único que se necesita es una colección particular de items de cierto tipo o una colección que añada un conjunto de nuevas características a la colección base. En .NET Framework, se suministran unas pocas colecciones fundamentales, como el sustrato para construir, a partir de ellas, nuevas colecciones a medida. Las clases base abstractas son CollectionBase DictionaryBase ReadonlyCollectionBase y NameObject CollectionBase. Si necesitas una colección con un comportamiento específico, no tienes que reinventar la rueda, sino que puedes partir de una de esas colecciones bien conocidas. La interfaz de programación de las clases base ya suministra todos los métodos y propiedades que se necesitan para sobrescribir nuestra propia clase de colección. Las colecciones de propósito general son modificables. Hay algunas, sin embargo, específicas a un contexto dado, cuyos ítems son de sólo lectura. Un ejemplo de una colección de sólo lectura es la clase ProcessModule Collection en el espacio de nombres System.Diagnostics. La clase ReadonlyCollectionBase suministra un sustrato sobre el que construir colecciones no modificables. ¿Cuál es la colección adecuada para tu propia aplicación? La regla de oro es no usar colecciones con características que no se necesiten. Para aplicar esta regla, comienza tu examen y valoración desde abajo, o sea, desde las clases más simples de la jerarquía. Considera la utilización de Queue y Stack sólo si necesitas eliminar elementos tras leerlos. Si necesitas ejecutar más de una lectura sobre el mismo elemento, piensa en otras opciones. ¿Los arrays serían apropiados? Los arrays específicos de los lenguajes son los más apropiados, en especial si se trata de arrays unidimensionales. De hecho, en este caso, los compiladores de los lengua- Los proveedores administrados se diferencian de los proveedores OLE-DB al menos en dos aspectos: son objetos administrados (en oposición a los objetos COM) y son más sencillos jes pueden usar intrucciones ad hoc para procesarlos. Sin embargo, los arrays son de dimensión fija. ¿Necesitas un objeto que pueda crecer? En tal caso, ArrayList es la mejor opción. Muchas otras clases de colecciones usan objetos ArrayList internamente para “cachear” datos que después son mostrados en interfaces más avanzadas. En la mayoría de los casos un ArrayList es perfecto y guarda el equilibrio entre eficiencia y facilidad de uso. ¿En qué casos no resulta apropiado ArrayList? Por ejemplo, si vas a rellenarlo con cadenas (strings). En ese caso, utiliza StringCollection. ArrayList sólo soporta acceso indexado a los ítems, pero no soporta ordenación o inversión de índices. ¡No es una lista ordenada, sin embargo! Un objeto que reordena sus items tras realizar cambios, es –normalmente– mucho más pesado que aquellos que sólo ordenan a petición. Ten bien clara esta distinción a la hora de escoger. Si necesitas acceso basado en claves, en lugar de índices, entonces decide entre una clase HashTable y un ListDictionary basándote en el número de ítems que prevés manejar. Cuando son pocos items, lo apropiado es un ListDictionary. ¿Pero, qué hacer si el número de items puede crecer indiscriminadamente dependiendo de factores del tiempo de ejecución? En lugar de controlar el número de items en la lista y entonces cambiar a una tabla hash cuando se exceda cierto límite, puedes usar más eficientemente la clase HybridDictionary que hace justo esta tarea. Se trata de una colección adecuada cuando el tamaño del diccionario es desconocido. La clase se cambia automáticamente a HashTable cuando hay más de 15 items almacenados, y siempre mantiene un aceptable nivel de rendimiento. Si sabes que sólo vas a manejar cadenas, String Dictionary es una mejor opción que HashTable. Sin embargo, si vas a manejar muchas cadenas duplicadas considera la utilización de la clase System.Xml.NameTable, que suministra un almacenamiento altamente optimizado y un mecanismo de búsqueda basado en referencias de cadenas, en vez de ordinales de cadenas. Las clases más lentas son SortedList y NameValueCollection, debido a razones estructurales: son las más complejas y ricas de las clases de colección. Deberías considerar su uso sólo si necesitas al mismo tiempo acceso indexado y basado en claves. Traducción por Marino Posadas publireportaje << publireportaje El eLearning al servicio del desarrollador El Máster Alhambra-Eidos en Tecnologías Avanzadas para el Desarrollo de Software << No es fácil para los profesionales del desa- Alhambra-Eidos aporta, como desde hace muchos años viene haciendo, su Máster en Tecnologías Avanzadas para el Desarrollo de Software, uno de los más sólidos programas formativos al que pueden acceder los desarrolladores para alcanzar el nivel de conocimiento que las complicadas arquitecturas tecnológicas actuales les exigen Luis Miguel Blanco y Guido Peterssen (de izquierda a derecha) ¿A qué achacas el éxito y el prestigio de la versión virtual de vuestro Máster? Guido Peterssen: Bueno, yo creo que hay varios factores: • El primero es la seriedad. El Máster en su versión presencial se está impartiendo desde el año 1993 y la versión virtual simplemente ha heredado la experiencia y buenas prácticas de su hermano mayor. • El segundo es la experiencia. En la convocatoria de 2005-2006 entramos en el octavo año de impartición virtual, lo que hace al alumno consciente que no somos alguien que improvisa algunas cosas por Internet y usando el correo electrónico para contactar con el tutor, monta un curso. • El tercero es el rigor y la organización. Quien ha estudiado con nosotros sabe que se encuentra con un itinerario absolutamente reglamentado de trabajo, con tutorías semanales planificadas, con miles de páginas de material y dece- <<dotNetManía rrollo de software mantenerse al día en sus conocimientos y habilidades en un entorno tan dinámico y cambiante como el nuestro. AlhambraEidos aporta, como desde hace muchos años viene haciendo, su Máster en Tecnologías Avanzadas para el Desarrollo de Software, uno de los más sólidos programas formativos al que pueden acceder los desarrolladores para alcanzar el nivel de conocimiento que las complicadas arquitecturas tecnológicas actuales les exigen. Este año, los responsables de dicho plan formativo nos hablan de la versión virtual del mismo, una de las más usadas por los desarrolladores que no tienen tiempo para acceder a los mucho más densos programas presenciales. Guido Peterssen, responsable del área de eLearning de Alhambra-Eidos y Luis Miguel Blanco, coordinador de la versión virtual de del Máster contestan nuestras preguntas. 55 << publireportaje <<dotNetManía La verdad es que estamos muy orgullosos de las continuas felicitaciones que recibimos de los alumnos que terminan su proceso de estudio con nosotros 56 nas de videoconferencias. En fin, con un entorno de enseñanza garantizado que genera cada año un buen número de titulados. ¿Cómo es el proceso de tutorización que se realiza por parte del profesorado? Luis Miguel Blanco: Yo me ocupo de la coordinación general del Máster y además tutorizo alguno de sus módulos. Los profesores procuramos estar siempre encima de las necesidades del alumno. Participamos en los foros de debate sobre las distintas temáticas, atendemos las consultas de los alumnos y, además, tenemos todas las semanas tutorías planificadas con ellos, donde atendemos de modo síncrono cualquier duda y orientamos el proceso de estudio. La verdad es que estamos muy orgullosos de las continuas felicitaciones que recibimos de los alumnos que terminan su proceso de estudio con nosotros. De vuestro Máster destaca la absoluta actualización tecnológica de sus contenidos. ¿Cómo lo hacéis? Guido Peterssen: Invertimos cada año mucho dinero en diseñar nuevos contenidos. Nunca ha habido una edición del Máster igual a la del año anterior. Por ejemplo, este año comenzamos ya con la introducción al alumno a SQL Server 2005 y Visual Studio 2005, aunque aún los productos no están en la calle nosotros tenemos ya módulos que orientan al alumno sobre el futuro uso de los mismos. Decís que vuestro Máster sirve para obtener la certificación MCAD, ¿cómo es esto? Luis Miguel Blanco: El Máster tiene muchos más contenidos de los que se exigen para obtener la certificación MCAD, pero existe una parte del mismo que se ciñe absolutamente a los contenidos oficiales de Microsoft para la obtención de dicha titulación. No en vano somos el centro de formación oficial de Microsoft que más titulados MCAD genera cada año. Nuestra especialidad es el desarrollo de software y sabemos perfectamente qué es lo que tiene que conocer un desarrollador para afrontar con éxito el proceso de certificación. << dnm.biblioteca.net dnm.biblioteca.net ADO.NET and System.Xml 2.0 Alex Homer, Dave Sussman y Mark Fussel Editorial: Addison-Wesley ISBN: 0321247124 Páginas: 560 Publicado: Enero, 2005 (2ª edición) Autores populares en el mundo de los eventos de desarrollo Microsoft, Alex Homer se dio a conocer con su popular “XML IE5”, ya en los primeros estadios de implantación del soporte XML en el navegador de Microsoft. C# 2.0: Practical Guide for Programmers Michel de Champlain y Brian Patrick Editorial: Morgan Kaufmann ISBN: 0121674517 Páginas: 271 Publicado: Febrero, 2005 Autores, previamente, de “Java jumpstart: using object concepts and UML”, Champlain y Patrick, abordan este proyecto desde un punto de vista muy práctico, cubriendo las características del lenguaje, pero dejando claros ejemplos de los fundamentos y de cómo esos fundamentos han variado en algunos casos para esta nueva versión del lenguaje. Todas las novedades están claramente remarcadas, y acompañadas por pequeños ejercicios (snippets) que pueden usarse con facilidad para la probatura del código. Además, las características están organizadas según los fundamentos de la OOP y sus características principales, de forma que la experiencia didáctica sea más clara. <<dotNetManía << En esta obra, junto a Sussman y Fussel, recorren las novedades de desarrollo de ADO.NET 2.0, junto a las muchas novedades del namespace System.Xml, en lo relativo a la programación asíncrona, transacciones, integración con SQL Server 2005 (por ejemplo, su utilización como base de datos XML), personalización de la seriación de datos XML y consideraciones de rendimiento. Mereció los elogios de los propios autores de la herramienta. 57 << dnm.desvan noticias.noticias Marino Posadas Singularity:Un nuevo sistema operativo para investigación escrito en C# Dos investigadores de Microsoft Research, Jim Larus y Galen Hunt, han dirigido un curioso proyecto de construcción de un sistema operativo denominado Singularity, con propósitos de investigación, que, según sus autores tiene por objeto la construcción de sistemas fiables a través de la innovación en areas de sistemas, lenguajes y herramientas. Para más información, el proyecto tiene una Web propia: http://research.microsoft.com/os/singularity. ¿Cómo (y cuándo) será Office 12 en la realidad? Una vez más recurrimos a Paul Thurrot y su Windows SuperSite para leer de sus muy próximas fuentes que Office 12 saldrá después de Longhorn (del que siguen afirmando que estará RTM (Ready To Manufacture) en mayo de 2006. Según el cronista, Office 12 no verá la luz hasta octubre de 2006, con una primera beta pública a primeros de ese año. Algunas de las características más notables de esa versión, tienen que ver con la productividad empresarial. Desde un gran número de posibilidades de reutilización de documentos, hasta las búsquedas rápidas de materiales, propiciadas por la tecnología subyacente en Longhorn. Office 12 será más gráfico, favoreciendo la conversión de textos en imágenes de todo tipo y la colaboración, búsqueda y recopilación analítica y sintética de información serán pilares de la nueva versión. Respecto a los requisitos de máquina, serán más o menos los normales de ahora, ejecutándose tanto en Windows XP SP2 como en Longhorn (cliente). Documentos en la Red Enterprise 1.0 Hands-On-Labs: http://www.microsoft.com/ downloads/details.aspx?FamilyID=b9bff619-236c-4bbb9aa1-2e7bc562c7f5&DisplayLang=en Este es el sitio de descarga de las prácticas de laboratorio para la Patterns&Practices Enterprise Library. Incluye 8 laboratorios distintos en VB.NET y C#. Implementing Manage code in SQL Server 2005: Por Jagadish Chaterjee, gran experto en bases de datos y asiduo contribuidor de ASPFree, publica en http://www.aspfree.com/c/a/MS-SQLServer/Implementing-Managed-code-in-SQL-Server-2005using-Visual-Studio-NET-2005/ un documento introductorio a las características de uso del CLR desde la nueva versión de SQL Server. <<dotNetManía Implicaciones y repercusiones de las clases parciales en .NET Framework 2.0: Gran artículo de nuestro colabo- 58 rador Dino Esposito en DevX, que recorre las implicaciones arquitectónicas que las nuevas clases parciales tienen en el desarrollo. Disponible en http://www.devx.com/codemag/Article/27819?trk=DXRSS_LATEST. A Jaime, un lanzamiento más del 2005.Alberto, todo un padre para los MVP españoles, ya tiene un MVP, digo un niño, más que mimar. ¡Suerte Jaime!