Visual Basic.NET - Tecnología, Tips de Programación … · ben teniendo el formato de cuaderno...

60
dotNetManía nº15 mayo 2005 • 6,00 (España) Visual Basic.NET • C# • Delphi • ASP.NET • ADO.NET • .NET Framework • Windows Server System Opinión dotNetManía www.dotnetmania.com Dedicada a los profesionales de la plataforma .NET La perspectiva del cliente Difíciles decisiones, pero decisiones al fin ToDotNet Q&A Emitir código JavaScript desde WebForms y controles Web personalizados • Regulando nuestras expresiones • Refactoring en Visual Studio 2005 • Testeo unitario con NUnit Reflection.Editor Una biblioteca para programar la edición de ensamblados .NET Entrevista a Rick LaPlante General Manager Visual Studio Team System Universidad.net Final de la Imagine Cup española Laboratorio.net VIASCAPE WHOIS, PING for .NET, edtFTPnet, Smilla NNTP

Transcript of Visual Basic.NET - Tecnología, Tips de Programación … · ben teniendo el formato de cuaderno...

Page 1: Visual Basic.NET - Tecnología, Tips de Programación … · ben teniendo el formato de cuaderno técnico, ... olvidamos que el producto de nuestro trabajo no es un fin en sí mismo

dotNetManíanº

15 m

ayo

2005

• 6

,00

€(E

spañ

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

Opinión

dotNetManíawww.dotnetmania.com Dedicada a los profesionales de la plataforma .NET

La perspectiva del cliente

Difíciles decisiones, pero decisiones al finToDotNet Q&A

Emitir códigoJavaScript desde

WebForms y controles Webpersonalizados • Regulando nuestras

expresiones • Refactoring en VisualStudio 2005 • Testeo unitario con NUnit

Reflection.EditorUna biblioteca para programar la edición de ensamblados .NET

Entrevista a Rick LaPlanteGeneral Manager Visual Studio Team System

Universidad.netFinal de la Imagine Cup española

Laboratorio.netVIASCAPE WHOIS, PING for .NET,edtFTPnet, Smilla NNTP

Page 2: Visual Basic.NET - Tecnología, Tips de Programación … · ben teniendo el formato de cuaderno técnico, ... olvidamos que el producto de nuestro trabajo no es un fin en sí mismo
Page 3: Visual Basic.NET - Tecnología, Tips de Programación … · ben teniendo el formato de cuaderno técnico, ... olvidamos que el producto de nuestro trabajo no es un fin en sí mismo

Bienvenidos al número 15 dedotNetManía de mayo de 2005.

La esperada noticia del lanzamien-to de la beta 2 de Visual Studio 2005 seha producido por fin. Al final aparacióel 49 de marzo, no el 38 de marzo comopronosticaba Eric Rudder en el pasa-do VS Live! ¡Cuestión de fechas!

Y ésta es una gran noticia para cual-quier dotnetmaníaco que se precie porque esta nueva beta, junto con la nue-va versión de SQL Server 2005, laCTP de abril, son totalmente operati-vas y pueden trabajar juntas. Ademáscon licencia Go-Live que nos permi-tirá empezar ya a tener nuestros desa-rrollos en producción.

Son, sin duda, el comienzo del findel desarrollo de ambas, aunque que-dan aún unos meses, pero con ellas ycon los recursos de formación que cadavez aparecen más, podemos estar per-fectamente preparados para cuandopodamos comprar “la caja”.

En este número hemos tenido la suer-te de entrevistar a Rick LaPlante, GeneralManager de Visual Studio Team System enMicrosof quien pasó por Madrid conmotivo del XII Forum de Arquitectos deSoftware que organizó Microsoft Ibéricadedicado a Visual Studio Team System.Muy recomendable.

Como podrá comprobar han termi-nado los artículos seriados que publica-

mos anteriormente. Aunque pueda noparecerlo, la línea editorial que segui-mos es la de publicar artículos divididosen series sólo cuando sea imprescindi-ble. Los temas que merezcan un trata-miento más extenso, posiblemente aca-ben teniendo el formato de cuadernotécnico, independiente de la revista.

A destacar, el magnífico artículo delGrupo Weboo que presenta la biblio-teca Reflection.Editor, que permite modi-ficar ensamblados sin tener que dispo-ner del código fuente.

También a tener en cuenta el artí-culo de Luis Miguel Blanco “Emitircódigo JavaScript desde WebForms ycontroles Web personalizados”, porquenos veníamos olvidando del lado delcliente.

El artículo sobre NUnit, deRodrigo Corral, significa el comienzode una nueva manera de enfocar los artí-culos de arquitectura. Para próximosnúmeros hablaremos de Patrones,Integración Continua, Visual StudioTeam System, etc.

Los artículos sobre Expresionesreguladas, como le gusta traducir aJorge Serrano las Regular Expressions,y sobre Refactoring, una nueva carac-terística de Visual Studio 2005, deFernando Nogueras, completan estenúmero.

Espero que le guste.do

tNet

Man

ía<<

3

Habemus BetadotNetManía

Dedicada a los profesionales de la plataforma .NET

Vol. II •Número 15 • Mayo 2005Precio: 6€ (España)

EditorPaco Marín

([email protected])

AdministraciónPilar Pérez

([email protected])

Asesor Técnico/CoordinaciónMarino Posadas

([email protected])

RedactoresAntonio Quirós, Dino Esposito, Guillermo

'guille' Som, Jorge Serrano, José ManuelAlarcón, Luis Miguel Blanco, MiguelKatrib (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,

Manuel Imaz, Miguel Egea, OctavioHernández, Pablo Abbate, Pepe Hevia,

Rodrigo Corral y Salvador Ramos.

Edición y Suscripciones.netalia

c/ Robledal, 13528529 Rivas-Vaciamadrid (Madrid)

Tf. (34) 91 666 74 77Fax (34) 91 499 13 64

PublicidadMediadev

Sophie Mancini ([email protected])Tf. 93 426 22 57 - 670 99 74 64

Fax. 93 423 11 40

ImprimeGráficas Vallehermoso

www.graficasvallehermoso.com

ISSN1698-5451

Depósito LegalM-3.075-2004

<<

dnm.editorial

Page 4: Visual Basic.NET - Tecnología, Tips de Programación … · ben teniendo el formato de cuaderno técnico, ... olvidamos que el producto de nuestro trabajo no es un fin en sí mismo

15dnm.sumario

dnm

.sum

ario

La perspectiva del cliente 8-9No lo he hecho, quizá algún día lo haga, pero estoy seguro (y pido perdón anticipado poresta soberbia intelectual) de que si hiciera una encuesta obtendría los resultados que espero.¿De qué estoy hablando? Simple, de hasta qué punto los desarrolladores de softwareolvidamos que el producto de nuestro trabajo no es un fin en sí mismo sino un medio paraayudar a nuestros clientes en sus respectivos negocios.

Entrevista a Rick LaPlante 10-13Con motivo del XII Forum de Arquitectos de Software que organizó Microsoft Ibéricadedicado a Visual Studio Team System en Madrid, nos visitó Rick LaPlante, GeneralManager de Visual Studio Team System, al que entrevistamos en una reunión dondecontamos con la colaboración de Carlos Oramas, .NET Architect Advisor de Microsofty Rodrigo Corral, MVP en Visual C++, colaborador habitual de dotNetmanía.

Emitir código JavaScript desde WebForms y controles Web personalizados 14-23A pesar de la profusión de novedades y mejoras aportadas por ASP.NET, existen situacionescuya resolución sigue siendo aconsejable realizar utilizando rutinas de script en el navegadorcliente. En el presente artículo explicamos cómo abordar este tipo de escenarios desdeASP.NET.

Regulando nuestras expresiones 24-29Las Expresiones Reguladas, son una de las características y posibilidades que ofreceun lenguaje de programación y que por alguna oscura razón, hace que el programadorsienta miedo al enfrentarse a ellas. En realidad no voy a descubrir nada diciendo quesu dominio requiere tiempo y dedicación; el resumen de esto es que no es lo quedefiniríamos como sencillo, pero no nos asustemos, no deja de ser en cierta maneraun mito y prueba de ello es lo que vamos a ver a partir de ahora: Qué son lasExpresiones Reguladas, para qué sirven y cómo usarlas en .NET.

Reflection.Editor, una biblioteca para programar la edición deensamblados .NET 30-38

En este trabajo se presenta la biblioteca Reflection.Editor que nos permite lograr efectostan atractivos como cambiar nombres de tipos, métodos, quitar miembros de un ensamblado,añadir nuevos miembros, pasar miembros de un ensamblado a otro, poner atributos, yotros más, y todo ello, claro, sin tener que disponer del código fuente. Se presenta ademásla herramienta IL_Lego desarrollada sobre esta biblioteca nos da la posibilidad de hacerinteractivamente modificaciones de esta naturaleza.

Refactoring en Visual Studio 2005 40-43Creo que todos estaríamos de acuerdo al afirmar que lo difícil del código que desarrollamosdía tras día, no es que sepa entenderlo nuestra máquina, sino que sepa comprenderlo uncerebro humano. Pongamos, por ejemplo, el de un pobre compañero al que le ha tocadocambiar ciertas funcionalidades de una aplicación en la que estuvimos trabajando hacetiempo. En una sola frase, podríamos decir que el buen código es aquel que transmite entodo momento lo que está haciendo.

Testeo unitario con NUnit 44-48Sin duda el testeo unitario es una de las técnicas relacionadas con la calidad del softwareque mayores beneficios aporta al proceso de desarrollo. Aunque es una técnica clásica, enlos últimos tiempos se ha popularizado de la mano de las metodologías ágiles de desarrollode software y gracias a la aparición de herramientas que facilitan la escritura, ejecucióne integración de los test en el proceso de desarrollo.

dnm.todotnet.qa 52-54Difíciles decisiones, pero decisiones al fin.

dnm.laboratorio.net 55-56VIASCAPE WHOIS, PING for .NET, edtFTPnet, Smilla NNTP

dnm.biblioteca.net 57Writing secure code –2ª Edición– (Michael Howard y David LeBlanc)Code Complete –2ª Edición– (Steve McConnell)

dnm.desvan 58

Page 5: Visual Basic.NET - Tecnología, Tips de Programación … · ben teniendo el formato de cuaderno técnico, ... olvidamos que el producto de nuestro trabajo no es un fin en sí mismo
Page 6: Visual Basic.NET - Tecnología, Tips de Programación … · ben teniendo el formato de cuaderno técnico, ... olvidamos que el producto de nuestro trabajo no es un fin en sí mismo

dotN

etM

anía

<<

6

dnm.noticias<<dnm.noticias

Disponible la Beta 2 de Visual Studio 2005

no

ticia

s.n

oti

cia

s.n

oti

cia

s.n

oti

cia

s.n

oti

cia

s.n

oti

cia

s

Microsoft ha liberado la Beta 2 de Visual Studio 2005,así como la Beta2 de.NET Framework 2.0, y la versión CTP de abril de SQL Server 2005.

Con la aparición de estas versio-nes, Visual Studio 2005 y SQL Server2005 entran en su larga recta final dedesarrollo. Como todos sabrán, ambosproductos saldrán a la venta conjunta-mente, en lo que será una integracióndel entorno de desarrollo con un sis-tema gestor de base de datos, sin pre-

cedentes.Especialmente la

aparición de la beta 2de Visual Studio 2005y .NET Framework2.0 tienen una gran

importancia para lacomunidad de desarrolla-

dores de la plataforma .NET. Primeroporque es la primera beta pública, nosólo para suscriptores a MSDN y abetatesters, sino para cualquiera quequiera descargarla; segundo porque esla primera que traerá un acuerdo delicencia (EULA) que permitirá la ins-talación y despliegue de aplicacionesen producción con ella (llamada licen-cia Go-Live), con lo que ya podemosusarla y tener nuestros trabajos y cono-cimientos al día; y tercero, cómo se des-prende del punto anterior, porque tie-ne la estabilidad y funcionalidades sufi-cientes como para empezar nuestro

aprendizaje y familiarizarnos con todaslas novedades.

La licencia Go-Live permitirá dis-tribuir aplicaciones ASP.NET,Windows Forms, Visual Studio Toolsfor Office y .NET CompactFramework para dispositivos quesoporten Windows Mobile. Esta licen-cia abarca tanto a Visual Studio 2005,como a .NET Framework 2.0 y a SQLServer 2005.

Para más información sobre estaliciencia puede visitar la página:http://msdn.microsoft.com/vs2005/golive.

Con la aparición de la versión SQLServer 2005 CTP de abril, Microsofttambién ha anunciado que adoptaráeste tipo de versiones hasta el final desu ciclo de desarrollo, ya que así losclientes pueden recibir nuevas versio-nes cada poco, de forma que puedan irconociendo sus novedades sin necesi-dad de esperar el tiempo que transcu-rre entre betas. Según Paul Flessner,senior vice president of applications serversen Microsoft, la calidad de estas ver-siones CTP se han mejorado sustan-cialmente y han recibido buenas opi-niones acerca de ellas de buenos clien-tes y partner que ya han desplegadoaplicaciones con ellas.

Por último, Microsoft aportará a losclientes recursos y herramientas de apre-dizaje como apoyo al lanzamiento deestas versiones. Concretamente ofrece-rá un libro online de Microsoft Press gra-tuitamente a los clientes que registren subeta 2. Asimismo, apoyará con títulos deMicrosoft E-Learning que están plani-ficados para el verano, y se continuará elsoporte con oportunidades de aprendi-zaje, tales como libros en la caja, ense-ñanza a distancia gratuita con MicrosoftE-Learning o descuentos en exámenes.

El objetivo de Microsoft Learninges, pues, el de aportar libros, módulos e-learning, cursos y certificaciones, paraque los clientes de Visual Studio 2005 ySQL Server 2005 aprendan lo antes posi-ble las nuevas tecnologías. Para másinformación sobre esto puede visitarhttp://lab.msdn.microsoft.com/vs2005/resources/learning/default.aspx

Desde dotNetManía enviaremosun CD con Visual Studio 2005 beta 2edición standard en castellano, con elpróximo número, por gentileza deMicrosoft Ibérica.

En número de julio-agosto, dondepublicaremos un monográfico de SQLServer 2005, irá incluida también la últi-ma versión de SQL Server 2005.

Opciones para conseguir su Beta¿Y cómo conseguir nuestra ansiada beta? Pues tiene varios

caminos a elegir. Dependiendo de la edición que elija:

• Visual Studio 2005 Express Editions: Se pueden des-cargar de la Web de Miscrosoft Ibérica o recibir las cin-co herramientas (dos de ellas, Visual Basic Express yVisual Web Developer, en español) más SQL ExpressCTP, así como contenido de formación, tutoriales, docu-mentación, etc. en castellano con el número de junio dela revista PC Actual.

• Visual Studio 2005 Standard (en castellano): Lo reci-birán los asistentes al DevDays 2005, así como todos lossuscriptores de dotNetManía en el próximo número.

• Visual Studio 2005 Team System (en inglés): Seentregará a los asistentes a eventos para arquitectos e

ISV durante el mes de junio, ytambién podrá pedirse vía Web a tra-vés de la página Beta Experience enhttp://www.microsoft.com/emea/msdn/betaexperience, queha comenzado su andadura el 25 de abril y que da ser-vicio para Europa.

Habrá una página similar a esta última en español, conrecursos en nuestro idioma, pero al cierre de esta edición noestaba aún en funcionamiento. Puede visitar la página de MSDNOnline en castellano en: http://www.microsoft.com/spanish/msdn/spain, donde se anunciará en cuanto esté disponible.

Más información (internacional) en: http://lab.msdn.micro-soft.com/vs2005.

Page 7: Visual Basic.NET - Tecnología, Tips de Programación … · ben teniendo el formato de cuaderno técnico, ... olvidamos que el producto de nuestro trabajo no es un fin en sí mismo

Microsoft Ibérica organiza, como cadaaño, el Microsoft Developer Day, el mayorevento que se realiza en España para los

desarrolladores .NET. Seesperan alrededor de 1.200asistentes que escucharán lasponencias centradas mono-gráficamente en los nuevosVisual Studio 2005 y SQLServer 2005.

Las conferencias que seimpartirán son: • Dispositivos móviles en

Visual Studio 2005• Novedades en el entorno de ejecución

.NET 2.0• Desarrollo de clientes inteligentes:

Windows Forms 2.0 y Visual StudioTools for Office

• Novedades en el desarrollo de aplicacio-nes web ASP.NET 2.0

• SQL Server 2005 para desarrolladores• Gestión del ciclo de vida completo de un

proyecto software: Visual Studio TeamSystem

• Caso práctico: desarrollo de la aplicaciónMSDN Video

• Y un invitado sorpresa.

Lugar de celebraciónKinepolis, Pozuelo de Alarcón (Madrid)

Fecha17 de mayo de mayo 2005

PrecioGratuito

Dirección en Internethttp://www.microsoft.com/spanish/msdn/Spain/eventos/devday

dnm.noticias<<

dnm.noticias

dotN

etM

anía

<<

7

Microsoft Developer Day 2005El 17 de mayo en Madrid se celebrará el mayor eventolocal para desarrolladores de la plataforma .NET

DotNetSolidario

DotNetSolidario llega a unacuerdo con Microsoft para ofrecer

a las ONG licenciasde Visual Studio

.NET 2003 y semi-narios de formación

en desarrollo de formagratuita.

Para que las ONG puedan con-seguir estas licencias gratuitas y pue-dan asistir a los seminarios debenestar registradas en DOTNETSO-LIDARIO y estar ubicadas enEspaña. Así se pretende ayudar a lasONG a darse a conocer en Internet,promover sus proyectos en la red deredes y encontrar benefactores quequieran contribuir a sus nobles cau-sas.

Puede encontrar mas informa-ción al respecto en la web de DOT-NETSOLIDARIO, http://www.dot-netsolidario.com

Microsoft y DotNetSolidario

Microsoft reducirá el precio estimado deventa de Visual Studio 2005 ProfessionalEdition al tiempo que ofrece un precio espe-cial a los actuales suscriptores de MSDN paraobtener Visual Studio 2005 Team System.

Además, los usuarios de Visual Studiopodrán beneficiarse de un descuento promo-cional si adquieren una suscripción MSDNahora, con la ventaja añadida de que les per-mitirá recibir Visual Studio 2005 en cuanto sealanzado, durante el segundo semestre de esteaño.

El precio de venta estimado de las versio-nes Standard y Professional del nuevo VisualStudio 2005 en retail es:

• Visual Studio 2005 ProfessionalEdition: 679€ (actualización: 469€)

• Visual Studio 2005 Tools for theMicrosoft Office System: 679€ (actua-lización: 469€)

• Visual Studio 2005 Standard Edition:259€ (actualización: 169€)

• Visual Studio 2005 Express Editions:40€ (promocionalmente se ofrecerán sincoste)

Visual Studio 2005 Team System y SuscripcionesMSDN para nuevos clientes

La gama de productos basados en rolesde Visual Studio Team System incluye VisualStudio Team Edition para Arquitectos deSoftware, Visual Studio Team Edition paraDesarrolladores, y Visual Studio TeamEdition para Testers. La nueva línea VisualStudio Team System también incluye VisualStudio Team Suite, que contiene los tres pro-ductos basados en estos roles, y el nuevoVisual Studio Team Foundation Server, parauna colaboración en equipo mucho más efi-ciente.

Los clientes pueden elegir un nivel deSuscripción MSDN y recibir licencias de desa-rrollo y prueba de aplicaciones y servidores deMicrosoft junto con un producto Visual Studio.Con Visual Studio Team System, los clientescontinuarán recibiendo los beneficios de lasantiguas suscripciones MSDN dentro de unanueva línea de suscripciones que complemen-tan la gama de producto Visual Studio 2005.

La nueva oferta de suscripciones quedacompuesta por (precios orientativos por año

en retail; precios en contratos de volumenincluyendo Software Assurance desde 2600€):

• Visual Studio 2005 Team Suite con sus-cripción MSDN Premium: 9299€ (reno-vación: 3899€)

• Visual Studio 2005 Team Edition paraArquitectos con suscripción MSDNPremium: 4649€ (renovación: 1949€)

• Visual Studio 2005 Team Edition paraDesarrolladores con suscripciónMSDN Premium: 4649€ (renovación:1949€)

• Visual Studio 2005 Team Edition paraTesters con suscripción MSDNPremium: 4649€ (renovación: 1949€)

• Visual Studio 2005 Professional Editioncon suscripción MSDN Premium:2119€ (renovación: 1699€)

• Visual Studio 2005 Professional Editioncon suscripción MSDN Professional:1019€ (renovación: 679€)

• Suscripción MSDN OperatingSystems: 599€ (renovación: 419€)

• Suscripción MSDN Library: 169€

(renovación: 89€)

Microsoft da a conocer el precio de Visual Studio 2005 ysimplifica el modelo de suscripciones MSDN

Page 8: Visual Basic.NET - Tecnología, Tips de Programación … · ben teniendo el formato de cuaderno técnico, ... olvidamos que el producto de nuestro trabajo no es un fin en sí mismo

La perspectiva del cliente

No lo he hecho, quizá algún día lo haga, pero estoy seguro (y pido perdón anticipadopor esta soberbia intelectual) de que si hiciera una encuesta obtendría los resultadosque espero. ¿De qué estoy hablando? Simple, de hasta qué punto los desarrolladoresde software olvidamos que el producto de nuestro trabajo no es un fin en sí mismosino un medio para ayudar a nuestros clientes en sus respectivos negocios.

que nos movemos las más de lasveces en nuestra visión de las cosas y olvidamos laperspectiva del cliente, ese esencial elemento quedebería guiar la totalidad de nuestro trabajo y querara vez lo hace.

¿Somos capaces de imaginarnos un constructorque al encargarle una casa a medida comience aponer cosas de su cosecha? Y donde nosotros le diji-mos que pusiera una ventana él deje un muro o, acambio, ponga una puerta, dándonos como razo-nes que le era más fácil hacerlo así e incluso inten-tando convencernos de que somos unos imbécilespor desear una ventana donde la lógica y el senti-do común apuntan a que debería ir una puerta.Bueno, quizá sí seamos capaces de imaginarnos alconstructor de turno. Al fin y al cabo no hay dosoficios que se parezcan más que la construcción decasas y la construcción de software.

Así somos. Quizá sea un último reducto de aque-lla época en que inflados en la burbuja tecnológicaéramos los dioses de un universo que se arrodilla-ba reverente ante nuestro infinito conocimiento ysabiduría. Pero, amigo, los tiempos están cambiandoy hay que adaptarse.

Algunos remedios caseros desde la boticadel líder

De todos es sabido que Microsoft es el líder enla cosa del desarrollo de software y, desde luego,esto no es producto de la casualidad sino de unapolítica bien definida de cara a satisfacer de formaomnímoda las necesidades de sus usuarios. Lo hace

y, además, nos dice cómo hacerlo. ¿Dónde? Pues,dónde va a ser, sino en Microsoft Solutions Framework,su metodología de trabajo recomendada para hacerque los proyectos de desarrollo de software culmi-nen con éxito. Revisemos a continuación algunosde los elementos presentes en MSF que nos ayu-dan a andar este camino de conversión intelectualy humildad tecnológica.

Una visión compartida del proyectoLa visión que sobre el proyecto tienen usuarios

y desarrolladores suele tener matices diferenciales.Sobre todo cuando el equipo de desarrollo no hatrabajado con demasiado rigor a la hora de tomarrequisitos y especificaciones funcionales. Si algo noestá escrito y pactado con el cliente se tiende a laimprovisación en lugar de a la consulta. Olvidamosque el software tiene una relevancia fundamentalpara el negocio de nuestro cliente y que no estáconcebido para nuestro lucimiento tecnológico.Interpretar las necesidades del cliente es el mejorcamino para equivocarse.

Por ello el documento de visión compartida esbásico. No se trata de un análisis funcional com-pleto, eso vendrá más tarde y desarrollará muchomás este documento inicial, pero en él debemosescribir con claridad lo que el cliente desea y espe-ra del software a desarrollar y el alcance que hemosnegociado para el proyecto. Es decir, no sólo lo queel cliente quiere sino lo que compra porque tam-bién en ocasiones existe cierta discordancia entresus deseos y lo que está dispuesto a pagar por con-

Antonio Quirós

dnm.opinion

<< O lo que es lo mismo,

Antonio Quirós es redactor de dotNetManía.

Co-fundador de las revistasclippeRManía, FOXManía yAlgoritmo.Actualmente es General Area Manager en

Alhambra-Eidos

Page 9: Visual Basic.NET - Tecnología, Tips de Programación … · ben teniendo el formato de cuaderno técnico, ... olvidamos que el producto de nuestro trabajo no es un fin en sí mismo

seguirlos. Este documento debe ser conocido enprofundidad por todos (usuarios, responsables deproyecto, analistas,p r o g r a m a d o r e s ,implantadores, etc.).Su conocimiento nosevitará muchos proble-mas de interpretaciónpor parte de los pro-gramadores a la horade construir los dife-rentes procesos de queuna aplicación se com-pone.

La función del Product ManagerMSF distingue con claridad las funciones de

gestión de proyecto y gestión de producto. A tra-vés de la primera nos ocupamos de desarrollar losproyectos con el método adecuado y en el tiempoy forma previstos. A través de la segunda garanti-zamos que el producto a obtener cumple con losrequisitos expuestos para el mismo y no se desvíade las expectativas que quienes lo han concebidohan puesto en el mismo.

En la compañía en que trabajo realizamos ensu día en cierto enfoque metodológico y tratamos

de ser pragmáticos a la hora de escoger lo que con-siderábamos más adecuado de cada una de las meto-dologías que conocíamos. Es lo que para nosotroses nuestra metodología Canon v. 1.0 con la quedesarrollamos nuestros proyectos de desarrollo desoftware. De MSF tomamos muchas cosas, una deellas es el contenido que Microsoft da al rol deProduct Manager. Realmente en Canon, que nohabla de roles, sino de funciones, la labor de serabogado de los usuarios se circunscribe a lo quedenominamos la función de Diseño Funcional, perotratamos de que esta idea transite a través de todaslas funciones y vigilamos fuertemente los proyec-tos para que se cumpa. ¡Y cuántos disgustos noscuesta por los conflictos entre quienes construyensoftware y quienes permanecen atentos para quelo construido respete en todo momento la visióndel mismo que los usuarios tienen!

El foco en el valor del negocio

El tiempo que gastemos en fomentar este prin-cipio en la totalidad de las personas de nuestra orga-nización que se dedican al desarrollo de softwarenunca será tiempo perdido. Hay dos frases que mesuelen dar dolor de estómago cada vez que un desa-rrollador de mi equipo las pronuncia. Una es “Perosi en mi equipo funciona” y la otra “Los usuariosno saben lo que quieren”. La primera es mala y sepuede cargar un proyecto, pero la segunda es horri-ble y hará que nuestra empresa no funcione. Losusuarios son los que saben lo que quieren. Ellosconocen su negocio y saben qué herramientas nece-sitan para gestionarlo bien. Nosotros no somos másque recursos a su disposición para que nuestrocliente mejore su negocio gracias al software quepara él construimos.

Tras revisar estos tres importantísimos princi-pios de MSF sólo anotar una última máxima:Resolver los problemas técnicos es un medio paraconseguir un fin, pero no un fin en sí mismo. Elfin es sólo uno, que el software que desarrollemossea capaz de aumentar el valor del negocio de nues-tros clientes.

dotN

etM

anía

<<

9

dnm.opinion<<

…el producto de nuestro trabajo noes un fin en sí mismo sino un mediopara ayudar a nuestros clientes en

sus respectivos negocios.

Olvidamos que el software tiene una relevancia funda-mental para el negocio de nuestro cliente y que no está

concebido para nuestro lucimiento tecnológico.

Page 10: Visual Basic.NET - Tecnología, Tips de Programación … · ben teniendo el formato de cuaderno técnico, ... olvidamos que el producto de nuestro trabajo no es un fin en sí mismo

Entrevista a Rick LaPlante

Con motivo del XII Forum de Arquitectos de Software que organizó Microsoft Ibéricadedicado a Visual Studio Team System en Madrid, nos visitó Rick LaPlante, GeneralManager de Visual Studio Team System, al que entrevistamos en una reunión donde con-tamos con la colaboración de Carlos Oramas, .NET Architect Advisor de Microsoft yRodrigo Corral,MVP en Visual C++, colaborador habitual de dotNetmanía.

managers a cargo de la producción de VSTS.¿Puedes explicar a nuestros lectores qué es exactamen-te Visual Studio Team System?

Claro. VSTS es una suite de herramientas enca-minadas a dar solución a dos problemas específicos:el primero es una solución para el equipo de ingenie-ros de desarrollo. Continuamos progresando en lafacilidad de uso, la integración, etc., incluso de formaque no sea necesario un consultor para que se puedaprogresar en su utilización; la segunda tiene muchoque ver con el control de la aplicación a lo largo delflujo de desarrollo.

¿Dejan las nuevas características de VSTS fuerade juego a Visio?

Realmente no se trata de hacer obsoleto un pro-ducto, ya que Visio está destinado a la creación demodelos UML, y vamos a continuar vendiéndolocomo parte de la edición Visual Studio EnterpriseArchitects. Vamos a garantizar que sigue siendo fun-cional para las nuevas versiones de los lenguajes. Sinembargo, estamos añadiendo nuevas capacidades dediseño gráfico en VSTS –en forma de dominios delenguajes específicos– que suponen un añadidoimportante a lo que Visio ofrece.

Marino Posadas

dnm.directo.entrevistas

Marino Posadas esasesor técnico y

redactor dedotNetManía, MVP de

C# y formador deAlhambra-Eidos

<< Eres uno de los

Rick LaPlante

Page 11: Visual Basic.NET - Tecnología, Tips de Programación … · ben teniendo el formato de cuaderno técnico, ... olvidamos que el producto de nuestro trabajo no es un fin en sí mismo

Carlos Oramas: Pero estáis reem-plazando cierta funcionalidad de Visio…

Solamente una, concretamente, eldiseñador de clases. Quizá con el tiem-po incluyamos algunos de los diseña-dores más importantes, como los deDiagramas de Secuencia, los Diagramasde Actividad, etc. Cada uno dentro deldominio del lenguaje que le competa.

Muchos desarrolladores –al menosen España– son muy reticentes a la horade utilizar herramientas de diseño, porque piensan que –al final– se lo tieneque hacer uno a mano, como siempre.Por otro lado, uno de los puntos fuer-tes de este producto es la sincronizacióndel código con el esquema. ¿Qué nospuedes decir al respecto?

Bueno, yo comencé en Microsoftcomo perteneciente al equipo de com-piladores. Por lo tanto, era reticente aaceptar que los diseñadores puedieranfuncionar de forma perfecta. Y he sidodurante mucho tiempo escéptico acer-ca de lo que las herramientas CASEpueden hacer. Una de las cosas impres-cindibles para hacer esto viable es dis-poner de un mapa semántico exacto.Una vez que existe un mapa exacto entremodelo y código, la traducción no es tal,sino simplemente, otra forma de ver lodiseñado. Todos los diseñadores quetenemos ahora se basan en un motor dediseño reutilizable y aplicable enmuchos contextos, incluido, por ejem-plo el diseñador de BizTalk 2004. Noexiste, pues un modelo arbitrario, quedebamos traducir en cada caso. Y aho-ra mismo, este nuevo modelo está fun-cionando extraordinariamente.

Rodrigo Corral: Hemos estadohablando antes sobre Visio. Hay unas

cuantas herramientas que la gente estáusando ahora, como NDoc, NUnit,SourceSafe, etc. ¿Existirá una vía clarade migración desde estas herramientasa VSTS?

Para algunas cosas específicas, porsupuesto. Por ejemplo, para SourceSafe.En los casos de NUnit y NCover, no.Nuestro objetivo principal ha sido sumi-nistrar una vía de migración paraSourceSafe y también para ClearCase.

El año pasado en el Tech-Ed vimosuna demo impresionante que implica-ba varios equipos para crear una aplica-ción en n capas. ¿Significa eso que VSTSes solamente para grandes proyectos engrandes compañías?

Pensamos que no. La mayor partede las compañías con las que me he reu-nido en mi estancia en Europa son com-pañías medias que buscan mejoras muyespecíficas en el control de la aplicacióny su ciclo de vida y metodología. Perosirve para cualquier tamaño de empre-sa y aplicación. En la próxima beta 2,veremos esto claramente, ejecutandotodo el código de servidores en unamáquina y todo el de clientes en otra.Pensamos que los clientes pequeños uti-

lizarán metodologías ágiles para la opti-mización del proceso igual que los clien-tes grandes.

Rodrigo Corral: ¿Existe un tama-ño mínimo para que un equipo puedautilizar el VSTS?

Una pregunta interesante. Por ejem-plo, un equipo de 2/3 personas no vana necesitar todas las herramientas decolaboración, pero seguramente nece-sitarán las herramientas de productivi-dad, testeo y rendimiento. Para el casode las grandes empresas, independien-temente de esto, buscarán cómo refor-zar las metodologías, la integración delproyecto, etc. Quizá podríamos decirque, para equipos inferiores a 5 perso-nas, SourceSafe seguiría siendo la solu-ción. Más allá iríamos a la parte de cola-boración de VSTS.

Profundizando un poco en el con-cepto de generación de código, ¿se uti-lizan las reglas conocidas como “buenasprácticas” en la generación de código?

Después de la salida del producto, exis-tirá un add-on, que cubrirá toda esa parte

de “mejores prácticas y guías en el desa-rrollo”. De forma que estamos trabajan-do con el equipo de desarrollo de esas guí-as de manera que sea posible consultaresas prácticas desde el VSTS. Hablaremosmás en detalle sobre eso, a medida que seacerque la fecha de salida.

La gente está comenzando a acos-tumbrarse a las especificaciones deUML. ¿Sigue VSTS dichos estándares?

Es una pregunta compleja por quetenemos que considerar varios factores.Por un lado, ¿a cuál de los estándaresnos referimos? Podemos estar hablan-do de la versión 1.4 de UML o de la 2.0,en cuya construcción estuvieron impli-cados varios de los integrantes de miequipo. De forma que, podemos decir

dotN

etM

anía

<<

11

dnm.directo.entrevistas<<

De Izquierda a derecha: Rodrigo Corral, Rick LaPlante y Carlos Oramás

Todos los diseñadores que tenemos ahora se basan en unmotor de diseño reutilizable y aplicable en muchos contextos,

incluido, por ejemplo el diseñador de BizTalk 2004

Page 12: Visual Basic.NET - Tecnología, Tips de Programación … · ben teniendo el formato de cuaderno técnico, ... olvidamos que el producto de nuestro trabajo no es un fin en sí mismo

que, de cara a ciertos diseñadores, síhemos seguido fundamentalmente esospatrones, con ciertos añadidos y mejo-ras, para adaptarnos mejor a los len-guajes específicos.

Por otro lado está, la forma de des-cribir un modelo de integración don-de, de cierta forma divergimos delmundo UML. Existe un estándarinventado por la UniversidadCarnegie-Mellon (Pennsylvania), lla-mado Domain specific languages, dondela noción es que si vas a construirmodelos que correspondan exacta-mente con la semántica subyacente delsistema, esos modelos deben ser preci-sos. No pueden consistir en abstrac-ciones de algún modelo preexistenteque tú utilices a tal efecto. Como dije,tenemos varios consultores senior quehan estado implicados en la construc-ción de UML 2.0, pero tras ello, hemosdecidido que la mejor manera de imple-mentar un sistema óptimo, adecuado acada dominio específico de lenguaje,era basarnos en la otra especificacióncitada, principalmente. Los usuarios,finalmente, utilizarán ambas, depen-diendo de la tarea a realizar.

Y, ¿qué puedes anticiparnos respec-to a la instalación del producto y el núme-ro de máquinas necesarias para ello?

Hoy, en el estado actual de la releaseexistente (una CTP, o CommunityTechnology Preview), requiere dos servi-dores al menos. Uno para la capa de datosy otro para la capa intermedia. Pero enla beta 2, ya será posible la realización deuna única instalación de servidor.

¿Esperáis una amplia adopción deVSTS considerando las dificultadesiniciales asociadas a la curva de apren-dizaje?

Lo primero que quiero significaraquí es que se trata de herramientasmuchísimo más fáciles de utilizar de loque pueda parecer en principio, espe-cialmente si las comparamos con lasherramientas existentes hoy en día.Uno de nuestros objetivos era que lagente pudiera ser productiva desde elprimer día.

Respecto a la adopción del produc-to a gran escala, sí, absolutamente.Estamos siguiendo una serie de pro-yectos piloto con nuestros clientes, paracomprobar qué tal se adaptan al nuevosistema, y los resultados son muy satis-factorios.

Rodrigo Corral: ¿Está Microsoftutilizando esta misma herramienta ensus propios desarrollos?

En muchos casos las implementa-ciones que se encuentran en VSTS hanestado utilizándose en Microsoft duran-te años, incluso las hemos ido modifi-cando desde hace 10 años en ocasiones.Pero no podemos aplicarlo exactamen-te en su totalidad, debido a que tene-mos requisitos que –probablemente– no

se encuentran en ninguna otra empre-sa, como la integración de código pro-veniente de varios miles de personas enun mismo proyecto, con implicacionesde escalabilidad, etc. No obstante, espe-ramos alcanzar esos niveles en la próxi-ma versión, así que migraremos partede los equipos para que trabajen –en loposible– con este nuevo sistema.

La otra cuestión es la forma en quenosotros abordamos los ciclos de vida delos proyectos, que varían dependiendo deque se trate del equipo de ingenieros, per-sonal de IT, etc., pero que se basan prin-cipalmente en la metodología MSF, conciertas variantes.

¿Cómo encaja VSTS en solucionesque implican integración de entornos dife-rentes, y –de paso– qué va a suceder conel soporte de los proyectos de BizTalk?

Respecto a la primera pregunta, porun lado existen herramientas que sontotalmente específicas de un lenguaje oplataforma, y otras que lo son de la inte-gración. Por tanto, respecto a las pri-meras, como los compiladores, los pro-filers, o las herramientas de testeo uni-tario, como son específicas de lenguajey plataforma, y no podrían funcionar enun proyecto de desarrollo entre plata-

formas diferentes. Sin embargo, existenherramientas que no dependen de la pla-taforma, como las herramientas de tes-teo de bajo nivel. Tampoco es que seaexpresamente un problema de VSTS,ya que hoy día esperamos que la comu-nicación entre plataformas distintas ten-ga lugar a través de Servicios Web.Sabemos que Borland y algunos otrospartners van a producir herramientaspara escenarios muy específicos, que

dotN

etM

anía

<<

12

dnm.directo.entrevistas<<

Existe un estándar inventado por la Universidad Carnegie-Mellon (Pennsylvania), llamado Domain specific

languages, donde la noción es que si vas a construir modelos que correspondan exactamente con la semánticasubyacente del sistema, esos modelos deben ser precisos

...tenemos varios consultores senior que han estado implicados en la construcción de UML 2.0, pero tras ello,hemos decidido que la mejor manera de implementar un sistema óptimo, adecuado a cada dominio específico de lenguaje, era basarnos en la otra especificación citada

Page 13: Visual Basic.NET - Tecnología, Tips de Programación … · ben teniendo el formato de cuaderno técnico, ... olvidamos que el producto de nuestro trabajo no es un fin en sí mismo

podrán usarse para complementarVSTS en situaciones especiales.

Respecto a lo de BizTalk, proba-blemente no se va a ver una integra-ción completa en la primera release delproducto, pero –en el momentoactual– no puedo comentar muchomás al respecto.

¿Cuáles dirías que son las caracte-rísticas más esperadas, las que te gusta-ría remarcar en esta versión?

Bueno se trata de una herramientatan grande, que, probablemente, depen-derá de los clientes, pero, creo que lasherramientas de integración, el nuevosistema que sustituye a SourceSafe va asignificar una aportación de muchovalor para los usuarios. La facilidad deuso de la parte servidora, va a marcaruna diferencia importante, igual que elsistema de generación de informes, lavisibilidad del proyecto, etc.

Y luego, hay 3 características espe-cíficas que me gustaría resaltar: La pri-mera son los diseñadores –en la versiónArchitect, del producto–, y la forma enque se sincroniza todo el diseño con elcódigo fuente; la segunda son las herra-mientas de testeo de bajo nivel; y la ter-cera es la herramienta de análisis decódigo estático.

Rodrigo Corral: Por lo que vemos,van a existir muchas novedades en laoferta de VSTS, pero, ¿qué hay de lageneración o producción de documen-tación, así como de la gestión de requi-sitos de la aplicación?

Podría decirse que esta última par-te, (Gestión de Requisitos) sería la opues-ta a la pregunta anterior, pero no erauna de las peticiones prioritarias. En el

caso de que necesites ese nivel específi-co de control del proceso de produc-ción, varios partners –como ya hecomentado– van a sacar productos paracubrir esas necesidades puntuales. Encuanto a la producción de documenta-ción, es algo que probablemente podre-mos ver en la próxima versión, ya que

hemos decidido posponerlo en esta, ytrabajarlo con más detalle.

Grady Booch, de IBM Rationalargumenta que su implementación esmejor porque ellos usan algo denomi-nado Rational Unified Process [RUP].¿Supondrá eso un handicap para VSTSo persiguen en establecimiento de unnuevo estándar de facto?

Una gran pregunta. Lo primero, nocreo que se pueda decir que RUP sea unestándar. No existe tal estándar en laindustria. De haberlo, sería CMMI (verhttp://www.sei.cmu.edu/cmmi), y es lo quenos ha servido de inspiración en variosaspectos. Sin embargo, Booch tiene razónen que es muy importante, en este con-texto, adoptar una metodología. Lo queno funciona de todo eso es que un con-junto de documentos, plantillas y guías notiene un impacto real en las herramien-tas. Eso no configura la forma en que sedeben comportar las herramientas. Esotienes que hacerlo tú mismo.

Nuestra metodología no es simple-mente documentación, ni siquiera losdocumentos XML que configuran laforma en que se comporta la herra-mienta. De hecho nosotros hemos lle-gado a un acuerdo para la implementa-ción de la metodología descrita enCMMI. De forma que el proceso esimportante, pero la adaptación de la

herramienta a ese proceso lo es mástodavía.

Rodrigo Corral: ¿Cómo se combi-nan VSTS y MSF?

Existen profundas conexiones enmuchos aspectos. Lo primero, es imposi-ble seleccionar un proyecto nuevo enVSTS sin elegir una plantilla metodoló-gica. Lo que se verá en la implementacióndel producto son, en realidad, dos solu-ciones, una de metodología ágil (AgileMethodology, ver http://agilemanifesto.org)y otra, asociada con la mejora de proce-sos al estilo de lo establecido por CMMI.Incluso te puedes descargar una plantillabasada en Test Driven Delopment (TDD,ver http://www.agiledata.org/essays/tdd.html)ya que la comunidad de usuarios de TDDestá construyendo plantillas metodológi-cas para VSTS. Y están configuradas deforma que presentan los modelos esta-blecidos también por MSF en cuanto aquién, y con qué características de riesgo,se realiza la aplicación. De hecho, una vezestablecidas esas premisas iniciales, segenera un sitio de SharePoint asociado alproyecto, que no estará vacía, sino que yacontendrá muchas de las plantillas y docu-mentos asociados a lo establecido por lametodología. De forma que la herra-mienta va a contar, desde el principio, conmuchas de esas plantillas. Creo que hemoshecho una implementación muy prácti-ca, configurable y totalmente integrada,basada en la experiencia de los usuarios ysus necesidades, y que nos permite poner-nos manos a la obra desde el primermomento.

Rodrigo Corral ¿En qué formaVSTS va a ayudar en la gestión de pro-yectos de código no administrado (tipoC++)?

En varias formas, ya que disponemosde un conjunto de herramientas llamadasNative Profiling Tools, que nosotros hemosestado utilizando constantemente y mejo-rando, y que construimos a propósito porque no existía nada así en el mercado. Esoserá claramente una ventaja para los cons-tructores de aplicaciones de alto rendi-miento. Y luego, la herramienta de análi-sis estático para código nativo, que estáintegrada con el compilador, de forma quepodamos hacer cosas, análisis de flujos dedatos, etc. No existirá una diferencia nota-ble en la forma de tratar proyectos admi-nistrados y no administrados.

dotN

etM

anía

<<

13

dnm.directo.entrevistas<<

Hay 3 características específicas que me gustaría resaltar:La primera son los diseñadores –en la versión Architect,del producto–, y la forma en que se sincroniza todo el

diseño con el código fuente; la segunda son lasherramientas de testeo de bajo nivel; y la tercera es la

herramienta de análisis de código estático

Page 14: Visual Basic.NET - Tecnología, Tips de Programación … · ben teniendo el formato de cuaderno técnico, ... olvidamos que el producto de nuestro trabajo no es un fin en sí mismo

Emitir código JavaScript desde WebForms ycontroles Web personalizados

A pesar de la profusión de novedades y mejoras aportadas por ASP.NET,existen situa-ciones cuya resolución sigue siendo aconsejable realizar utilizando rutinas de script enel navegador cliente. En el presente artículo explicamos cómo abordar este tipo deescenarios desde ASP.NET.

<<La llegada de ASP.NET al mundo del desarrollo

de aplicaciones para Internet ha supuesto una consi-derable mejora con respecto al modelo de programa-ción ofrecido por ASP 3 (también conocido como ASPclásico), que imperaba anteriormente.

Los cambios en dicho modelo han sido cuantio-sos y profundos, contribuyendo entre otros muchosaspectos a la consecución de un código más efectivoen un menor espacio de tiempo.

No cabe duda de que el paradigma de desarrollopropuesto por ASP.NET es a todas luces más óptimoque el disponible con la anterior versión de la plata-forma de desarrollo Web de Microsoft, residiendouno de sus puntos destacables en el conjunto de con-troles Web, los cuales ofrecen un abanico de posibi-lidades de programación más amplio y rico en méto-dos, propiedades y eventos que los tradicionales con-troles HTML de ASP clásico; no obstante, como todossabemos, también podemos seguir utilizando estosúltimos en formularios ASP.NET.

Podemos programar gran parte del comporta-miento y funcionalidad de los nuevos controles Webdesde el lado del servidor, dado que su arquitecturaestá diseñada para ser gestionada en esta parte del flu-jo de proceso de la aplicación, lo que ofrece una poten-cia inusitada con respecto a la programación Webempleando ASP clásico.

Sin embargo, el hecho de que ahora tengamos unamayor capacidad de control del lado servidor en nues-tras aplicaciones, no quiere decir que esto sea la pana-cea que vaya a resolver todos nuestros problemas dedesarrollo, ni tampoco resulta conveniente su uso des-

mesurado, ya que seguirán existiendo operacionescuyo tratamiento sea más adecuado efectuarlo en ellado cliente, dado que su gestión en el servidor pro-vocaría una pérdida de rendimiento.

Es por ello que derivar la ejecución de ciertas tare-as para que se procesen en el navegador cliente siguesiendo un factor primordial en aras de conseguir unaaplicación equilibrada en lo que al consumo de recur-sos se refiere, y ágil en cuanto a su ejecución. De estamanera se descarga en muchos casos al servidor de unimportante número de operaciones que de otro modotendría que soportar, o que en determinadas situa-ciones ni siquiera sería viable su ejecución en el ser-vidor por cuestiones de eficacia de la aplicación.

Por este motivo, tal y como reza el título del artí-culo, vamos a describir los mecanismos con los quecuenta ASP.NET para la generación de código descript en el navegador cliente, y más concretamenteJavaScript, ya que representa el lenguaje de script másampliamente utilizado en el desarrollo de aplicacio-nes para Internet. Como navegador Web empleadoen la demostración de los diversos ejemplos utiliza-remos Internet Explorer.

También haremos un repaso de las técnicas utili-zadas para asociar el código JavaScript que generemoscon los eventos de los controles de nuestros formula-rios Web, y un pequeño truco para facilitar la genera-ción de este tipo de código desde el servidor.

Dado que este es un artículo que versa sobre cómoaplicar JavaScript, se asume por parte del lector unconocimiento al menos básico de este lenguaje.

Todos los casos tratados se ilustrarán a través deejemplos repartidos en dos soluciones de Visual

Luis Miguel Blanco

dnm.asp.net

Luis Miguel Blancoes redactor de dotNetManía. Es

consultor en Alhambra-Eidos.Haescrito varios libros y decenas de

artículos sobre la plataforma.NET (lalibreriadigital.com)

La dependencia del lado cliente

Page 15: Visual Basic.NET - Tecnología, Tips de Programación … · ben teniendo el formato de cuaderno técnico, ... olvidamos que el producto de nuestro trabajo no es un fin en sí mismo

Studio .NET, que el lector puede descargar, comomaterial de apoyo para este artículo, desde la direc-ción www.dotnetmania.com.

Comencemos pues por la primera de estas solu-ciones, EjArticASPNETJS, en la que podemos encon-trar un proyecto de igual nombre con variosWebForms, que ilustran algunos de los ejemplos delos próximos apartados.

El formulario de entrada de este proyecto,Inicio.aspx, dispone de varios botones que nos daránpaso a cada uno de los WebForm de ejemplo.

Al estilo antiguoSi nos encontramos en la situación de ser un pro-

gramador de ASP clásico que necesita migrar haciaASP.NET, debemos saber que la creación de códigoJavaScript podemos seguir realizándola en el modo alque ya estamos acostumbrados, lo que facilita la curvade aprendizaje en lo que a este particular respecta.

Para ello crearemos el formulario WebForm1, y enmodo de diseño situaremos dos controles Input detipo texto, cuya finalidad será la de comprobar la can-tidad de caracteres que hemos escrito en uno de loscontroles, mostrando dicho número en el otro.

Seguidamente accederemos al código HTML delformulario y entre las etiquetas <head></head> escri-biremos nuestro código JavaScript, utilizando, natu-ralmente, las etiquetas <script></script>. Este códi-go consistirá en una función que será llamada al pro-ducirse el evento onblur en uno de los controles, y queefectuará el cálculo anteriormente mencionado, comovemos en el fuente 1.

Terminada la creación de este formulario, lo eje-cutaremos, comprobando cómo el código cliente quehemos escrito se ejecuta al desencadenarse el eventocorrespondiente.

Puede darse también el caso de que tengamos unelevado número de funciones en JavaScript, parte delas cuales son de propósito general, que necesitare-mos reutilizar en la mayoría de los formularios de laaplicación.

Para no tener que volver a repetir esas funcionesen todos los formularios, podemos crear un archivoque contenga este código JavaScript de uso general,y referirnos a él usando el atributo src de la etiqueta<script>, como hacemos en el formulario WebForm2del proyecto. Véase el fuente 2.

Lo que hemos hecho aquí ha sido añadir el archi-vo FuncionesVarias.js al proyecto, y escribir en él lasfunciones PasarMayusculas() y CambiarColor(), paradespués conectarlas mediante el evento onblur de loscontroles del formulario txtNombre y txtCiudad.

Generación de código script al estiloASP.NET

Dejando a un lado ya la antigua técnica de gene-ración de JavaScript, pasemos a describir los meca-nismos de que dispone ASP.NET para realizar todoel proceso de emisión de este tipo de código desde ellado servidor.

Partiendo del hecho de que vamos a trabajar concontroles Web, debido a las múltiples ventajas quepresentan, no es posible, dada la naturaleza de estos

dotN

etM

anía

<<

15

dnm.asp.net<<

<HEAD>........<script language="javascript">function CalcularLongitud(){

var sCadena = new String();sCadena = document.Form1.txtCadena.value;document.Form1.txtLongitud.value = sCadena.length;

}</script>

</HEAD><body>

<form id="Form1" method="post" runat="server">Escribir texto: <INPUT id="txtCadena" type="text"

onblur="CalcularLongitud()"><br>Longitud texto: <INPUT id="txtLongitud" type="text"

size="2"></form>

</body>

Fuente 1

//----- archivo FuncionesVarias.js ---------------function PasarMayusculas(oTextBox){

var sTextoControl = new String();sTextoControl = oTextBox.value;oTextBox.value = sTextoControl.toUpperCase();

}//---------------------function CambiarColor(oTextBox){

oTextBox.style.backgroundColor="#66ff99";}<!-- código HTML de WebForm2 -->....<HEAD>

....<script language="javascript" src="FuncionesVarias.js"></script>

</HEAD><body>

<form id="Form1" method="post" runat="server">Nombre:<INPUT id="txtNombre" type="text"

onblur="PasarMayusculas(this)"><br>Ciudad:<INPUT id="txtCiudad" type="text" onblur="CambiarColor(this)"><br>Provincia:<INPUT type="text">

</form></body>....

Fuente 2

Page 16: Visual Basic.NET - Tecnología, Tips de Programación … · ben teniendo el formato de cuaderno técnico, ... olvidamos que el producto de nuestro trabajo no es un fin en sí mismo

controles, efectuar la conexión entreuna función JavaScript y un evento delcontrol de la misma forma que veíamosen el apartado anterior con los con-troles HTML. Ahora debemos utilizarun mecanismo distinto, consistente enescribir el código JavaScript en el code-behind del WebForm, procediendo a suemisión hacia el navegador medianteel método RegisterClientScriptBlockde la clase Page, que tiene la siguientesintaxis:

Page.RegisterClientScriptBlock(Clave,CodigoScript)

A continuación describimos losparámetros de este método:

• Clave: Cadena que identifica demodo unívoco al bloque de códigoJavaScript que estamos registran-do/generando para el formulario.Esto nos permite poder utilizarvarias veces este método para regis-trar diferentes bloques de códigoscript, cada uno con su correspon-diente identificador.

• CodigoScript: Cadena que contie-ne el bloque de código JavaScriptque vamos a registrar/enviar alnavegador Web desde el code-behind.

Como ejemplo de esta técnica de cre-ación de código en el cliente Web, el for-mulario WebForm3 de nuestro proyecto deprueba contiene, en su método Load, lasinstrucciones para generar nuestro códi-go de script pertinente y registrarlo conRegisterClientScriptBlock, como vemosen el fuente 3.

Al ejecutar este WebForm, si acce-demos a la opción “Ver código fuente”en el navegador, comprobaremos comoallí aparece el código script que hemosemitido desde el code-behind de la pági-na, todo ello sin necesidad de habermanipulado directamente el HTML delWebForm.

La única pega que podríamos acha-car a este resultado sería que el códigoJavaScript generado se dispone en unalínea única, lo que dificulta su lecturaen el navegador, y lo que es más grave,cuando existe una gran cantidad de estecódigo se pueden producir errores ensu ejecución.

Para remediar este inconvenientetan sólo hemos de añadir, desde el code-behind, un salto de línea de forma explí-cita a cada una de las líneas del script,utilizando la enumeración/miembroControlChars.CrLf, como vemos en elfuente 4.

Para añadir saltos de línea tambiénpodemos utilizar la clase/propiedadEnvironment.NewLine, que devuelveuna cadena con los caracteres de nue-va línea para la plataforma de ejecu-ción actual.

Las operaciones que acabamos depracticar simplemente crean código descript y lo depositan en el navegadorWeb, no ejecutan por sí mismas una deestas funciones JavaScript que hemosgenerado en el navegador. Nos quedapendiente pues una parte muy impor-

tante del proceso: conectar una funciónde script con el evento del control quedeberá ejecutarla.

Para lograr este objetivo debemostomar el control Web que necesitamosconectar con el código JavaScript, y aña-

dotN

etM

anía

<<

16

dnm.asp.net<<

Private Sub Page_Load(....) Handles MyBase.Load....Dim sJS As StringsJS = "<script language=""javascript"">"sJS &= "function CambiarMayMin()"sJS &= "{"sJS &= "var sTexto = new String();"sJS &= "sTexto = document.Form1.txtNombre.value;"sJS &= "if (sTexto.length > 0)"sJS &= "{"sJS &= "if (document.Form1.chkMayMin.checked)"sJS &= "{"sJS &= "document.Form1.txtNombre.value = sTexto.toLocaleUpperCase();"sJS &= "}"sJS &= "else"sJS &= "{"sJS &= "document.Form1.txtNombre.value = sTexto.toLowerCase();"sJS &= "}"sJS &= "}"sJS &= "else"sJS &= "{"sJS &= "alert(""No hay texto para convertir"");"sJS &= "}"sJS &= "}"sJS &= ""sJS &= "function ContarCaracteres()"sJS &= "{"sJS &= "var sTexto = new String();"sJS &= "sTexto = document.Form1.txtNombre.value;"sJS &= "document.Form1.txtNumCaracteres.value = sTexto.length;"sJS &= "}"sJS &= "</script>"' generar el código de script en el navegador WebMe.RegisterClientScriptBlock("CodJS", sJS)....

Fuente 3

....sJS = "<script language=""javascript"">" & ControlChars.CrLfsJS &= "function CambiarMayMin()" & ControlChars.CrLfsJS &= "{" & ControlChars.CrLfsJS &= "var sTexto = new String();" & ControlChars.CrLfsJS &= "sTexto = document.Form1.txtNombre.value;" & ControlChars.CrLfsJS &= "if (sTexto.length > 0)" & ControlChars.CrLfsJS &= "{" & ControlChars.CrLf....

Fuente 4

Page 17: Visual Basic.NET - Tecnología, Tips de Programación … · ben teniendo el formato de cuaderno técnico, ... olvidamos que el producto de nuestro trabajo no es un fin en sí mismo

dir a su colección de atributos el nombre del evento y lafunción de script que actuará como manipulador de dichoevento cuando sea desencadenado. El fuente 5, que tam-bién escribiremos en el evento Load del formulario, ilus-tra el modo de llevar a cabo esta acción.

La colección Attributes, disponible para todos loscontroles Web, permite que al ser creado en el nave-gador el código HTML correspondiente al control,se generen también, dentro de las etiquetas del con-trol, determinados atributos que no están disponiblesa través de las propiedades de la clase del control.Como puede comprobar el lector, en este caso, emple-amos la mencionada colección para producir el códi-go HTML que asigna a un evento del control una fun-ción del script. Para el CheckBox chkMayMin de nuestrapágina, el HTML resultante sería el siguiente:

<input id="chkMayMin" type="checkbox" name="chkMayMin"onclick="CambiarMayMin()" />

De esta forma, cuando ejecutemos la páginaWebForm3, cada vez que marquemos o desmarquemosel CheckBox, se ejecutará la función CambiarMayMin enrespuesta al evento onclick de este control.

Si a pesar de lo anterior, seguimos prefiriendoescribir nuestro código de script dentro del HTMLdel formulario, es totalmente factible hacerlo (aunqueno sea la práctica recomendada), ya que la colecciónAttributes de los controles Web no distingue si elcódigo JavaScript ha sido escrito directamente en elHTML del WebForm o desde su code-behind.

Depurando nuestrocódigo JavaScript

Si necesitamos sabercon una mayor exactitudcuándo se ejecuta nuestrocódigo de script en elnavegador Web, podemoshacer que el depurador deVisual Studio .NETsupervise dicho código en

tiempo de ejecución; para ello debemos seguir unossencillos pasos que explicamos a continuación.

En primer lugar abriremos Internet Explorer,seleccionando su opción de menú “Herramientas” +“Opciones de Internet”. A continuación haremos clicen la pestaña “Opciones avanzadas”, y dentro de ésta,desmarcaremos la casilla con el título “Deshabilitardepuración de secuencias de comandos”, como vemosen la figura 1.

Tras aceptar este cuadro de diálogo pasaremos ala función que necesitemos depurar de nuestro blo-que de script, y dentro de su código situaremos la ins-trucción debugger, sin finalizar la línea con punto ycoma, como vemos en el fuente 6.

Al cargarse ahora en el navegador la página quecontiene esta función, cuando la misma sea ejecutadase producirá una parada en el flujo de ejecución,entrando en acción el depurador de igual forma que

dotN

etM

anía

<<

17

dnm.asp.net<<

Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) HandlesMyBase.Load

'....' generar el código de script en el navegador WebMe.RegisterClientScriptBlock("CodJS", sJS)' conectar los eventos de los controles con las funciones de scriptMe.chkMayMin.Attributes.Add("onclick", "CambiarMayMin()")Me.txtNombre.Attributes.Add("onkeyup", "ContarCaracteres()")

End Sub

Fuente 5

Figura 1

....sJS = "<script language=""javascript"">" & ControlChars.CrLfsJS &= "function CambiarMayMin()" & ControlChars.CrLfsJS &= "{" & ControlChars.CrLfsJS &= "debugger" & ControlChars.CrLfsJS &= "var sTexto = new String();" & ControlChars.CrLf....

Fuente 6

En función del punto en el que necesitemos generar el código de

script: tras la etiqueta de apertura delformulario, o bien, antes de la etiqueta

de cierre del mismo, deberemos usar respectivamente los métodosRegisterClientScriptBlock o

RegisterStartupScript][

Page 18: Visual Basic.NET - Tecnología, Tips de Programación … · ben teniendo el formato de cuaderno técnico, ... olvidamos que el producto de nuestro trabajo no es un fin en sí mismo

si estuviéramos depurando el code-behindde una página ASPX. Dentro de estecontexto podremos evaluar expresiones,visualizar el contenido de variables, pro-piedades de controles, etc. La figura 2muestra un ejemplo de esta situación.

Ejecutando un bloque descript durante la carga de lapágina

Durante el proceso de creación delWebForm podemos emitir un bloquede código de script para que sea ejecu-tado durante esta fase inicial de creaciónde la página. Todo lo que tenemos quehacer es escribir dicho bloque sin quese encuentre contenido dentro de unafunción JavaScript, como vemos en elfuente 7.

Esta práctica sufre empero de uninconveniente. Supongamos que nosencontramos diseñando un formularioque tiene un control DropDownList conla lista de meses del año, y queremosque al comenzar la ejecución de dichoformulario se compruebe cuál es el mescorrespondiente a la fecha actual,

dejándolo como elemento selecciona-do en la lista antes de presentar la pági-na al usuario.

Ante estos requerimientos hemosde tener presente que el métodoPage.RegisterClientScriptBlock

genera el JavaScript justamente des-

pués de la etiqueta HTML de aper-tura del WebForm: <form>, lo quieredecir que si usamos este método para

incluir un bloque de código que inten-te manipular uno de los controles delformulario, se producirá un error por-que al ser ejecutado el script todavíano se habrán creado los controles delWebForm.

La solución a este problema laencontramos en el método Page.Regis-terStartupScript, que también emitecódigo de script al navegador, perosituándolo en este caso justo antes de laetiqueta HTML que cierra elWebForm: </form>.

El modo de uso de este método esigual que RegisterClientScriptBlock,es decir, debemos pasar al método unacadena que será el identificador úni-co del bloque de código, y otra cade-na conteniendo el código JavaScript.Veamos este método en acción dentrodel evento Load de la página WebForm4(fuente 8).

dotN

etM

anía

<<

18

dnm.asp.net<<

Figura 2

Private Sub Page_Load( ByVal sender As System.Object, _ByVal e As System.EventArgs) Handles MyBase.Load

Dim sJS As StringsJS = "<script language=""javascript"">" & ControlChars.CrLfsJS &= "alert('comenzamos a ejecutar el WebForm');"sJS &= "</script>"Me.RegisterClientScriptBlock("CodJS", sJS)

End Sub

Fuente 7

Me.ddlMeses.Items.Add("Enero")Me.ddlMeses.Items.Add("Febrero")Me.ddlMeses.Items.Add("Marzo")Me.ddlMeses.Items.Add("Abril")Me.ddlMeses.Items.Add("Mayo")Me.ddlMeses.Items.Add("Junio")Me.ddlMeses.Items.Add("Julio")Me.ddlMeses.Items.Add("Agosto")Me.ddlMeses.Items.Add("Septiembre")Me.ddlMeses.Items.Add("Octubre")Me.ddlMeses.Items.Add("Noviembre")Me.ddlMeses.Items.Add("Diciembre")

Dim sJS As StringsJS = "<script language=""javascript"">" & ControlChars.CrLfsJS &= "var dtFecha = new Date();" & ControlChars.CrLfsJS &= "var nMes = dtFecha.getMonth();" & ControlChars.CrLfsJS &= "document.Form1.ddlMeses.selectedIndex=nMes;" & ControlChars.CrLfsJS &= "</script>"

Me.RegisterStartupScript("CodJS", sJS)

Fuente 8

Para depurar el códigoJavaScript que generemos en elnavegador, tan sólo debemosincluir en dicho código la ins-trucción "debugger"; esto nos

permitirá realizar un seguimien-to de lo que ocurre en el códi-go cliente desde el entorno de

Visual Studio .NET][

Page 19: Visual Basic.NET - Tecnología, Tips de Programación … · ben teniendo el formato de cuaderno técnico, ... olvidamos que el producto de nuestro trabajo no es un fin en sí mismo

Ahora ya no se producirán errores en este senti-do, puesto que al ser ejecutado el JavaScript, los con-troles del formulario ya estarán creados, como vemosa continuación, en el código HTML de la página acce-sible desde el navegador (fuente 9).

Generación de código JavaScript desdecontroles Web personalizados

Cuando desarrollamos controles Web propios, enla gran mayoría de casos también necesitaremos quelos mismos emitan código de script para el navegadorWeb en el que tengan que ejecutarse. Es por ello, quelas capacidades de creación de JavaScript en ASP.NETestán disponibles para ser usadas tanto desdeWebForms como desde controles Web.

Como ejemplo para este tipo de casos usaremos lasolución EjArticCtlASPNETJS, que también podemosdescargar de www.dotnetmania.com. Esta solución lacompone el proyecto MisControlesWeb, que consisteen una librería de clases conteniendo un par de con-troles Web para las diversas pruebas de generación descripts, y un proyecto con el mismo nombre de la solu-ción, que usaremos como banco de pruebas de los con-troles personalizados.

El primer control con el que vamos a tratar seráCajaNúmero, una clase que hereda de WebControl, y queen tiempo de ejecución crea un TextBox que sólo per-mite escribir números. Como es natural, dadas lascaracterísticas de nuestro artículo, el elemento de este

control que va a comprobar si su contenido es exclu-sivamente numérico será un bloque de códigoJavaScript.

Un control no puede, por sí mismo, emitir el códi-go de script que necesite depositar en el navegador,es decir, carece de los métodos RegisterXXX que veía-mos en ejemplos anteriores.

Sin embargo, un control sí dispone de la propie-dad Page, que representa al WebForm que lo contie-ne, y por mediación de esta propiedad puede accedera los métodos RegisterXXX de su formulario para cre-ar los bloques de código de script que necesite.Podemos realizar esta tarea reemplazando el métodoOnPreRender en la clase de nuestro control, como vemosen el fuente 10.

El objeto oCaja representa al TextBox que mostraránuestro control personalizado, y actúa como controlconstituyente del control Web principal. Para instanciar

dotN

etM

anía

<<

19

dnm.asp.net<<

<form name="Form1" method="post" action="WebForm4.aspx" id="Form1">

....

....<select name="ddlMeses" id="ddlMeses">

<option value="Enero">Enero</option><option value="Febrero">Febrero</option><option value="Marzo">Marzo</option><option value="Abril">Abril</option><option value="Mayo">Mayo</option><option value="Junio">Junio</option><option value="Julio">Julio</option><option value="Agosto">Agosto</option><option value="Septiembre">Septiembre</option><option value="Octubre">Octubre</option><option value="Noviembre">Noviembre</option><option value="Diciembre">Diciembre</option>

</select>

<script language="javascript">var dtFecha = new Date();var nMes = dtFecha.getMonth();document.Form1.ddlMeses.selectedIndex=nMes;

</script></form>

Fuente 9

Protected Overrides Sub OnPreRender(ByVal e As System.EventArgs)Dim sJS As String

MyBase.OnPreRender(e)Me.EnsureChildControls()

sJS = "<script language=""javascript"">" & ControlChars.CrLfsJS &= "function CompruebaCampo()" & ControlChars.CrLfsJS &= "{" & ControlChars.CrLfsJS &= "if (! (event.keyCode >= 48 && event.keyCode <= 57))" & _

ControlChars.CrLfsJS &= "{" & ControlChars.CrLfsJS &= "event.returnValue = false;" & ControlChars.CrLfsJS &= "}" & ControlChars.CrLfsJS &= "}" & ControlChars.CrLfsJS &= "</script>"' registrar el bloque de código script ' en la página que contiene al controlMe.Page.RegisterClientScriptBlock("CodJSCajaNumero", sJS)

' oCaja contiene el objeto TextBox,' asociar el evento del TextBox con la función JavaScript Me.oCaja.Attributes.Add("onkeypress", "CompruebaCampo()")

End Sub

Fuente 10

Un control Web personalizado no puedegenerar directamente código JavaScript;

utiliza su propiedad Page, que le proporcio-na acceso al objeto WebForm,y por consi-guiente a los métodos y propiedades de

este último para crear el código de script. ][

Page 20: Visual Basic.NET - Tecnología, Tips de Programación … · ben teniendo el formato de cuaderno técnico, ... olvidamos que el producto de nuestro trabajo no es un fin en sí mismo

y generar este TextBox, debemos reem-plazar los método CreateChildControls yRender, respectivamente, añadiendo elcódigo que se ocupe de dichas tareas,como vemos en el fuente 11.

De esta forma ya podemos utilizarel control en el WebForm de pruebas,donde veremos que sólo nos permitiráintroducir números.

Comprobar si un bloque decódigo script ya ha sido registrado

Como ya sabemos, el primer pará-metro de los métodos Page.RegisterXXXconsiste en una cadena que funciona comoidentificador del bloque de código queestamos generando en el navegador, loque impide que registremos en más de unaocasión un bloque de código script con elmismo identificador. Pongamos comoejemplo el fuente 12.

Cuando este code-behind sea ejecuta-do, el código JavaScript generado en elnavegador sólo corresponderá a la fun-ción Primera(), ya que al intentar regis-trar el siguiente bloque de script, comotambién estamos utilizando el identifi-cador “CodJS”, ASP.NET detectará queya ha sido registrado un script con el mis-mo identificador, ignorando este últimointento de registro.

En este preciso momento se estarápreguntando, estimado lector, acerca dela utilidad de lo que acabamos de explicar,

y ciertamente, observada desde el con-texto de un WebForm, esta situación noreviste mayores problemas si simplemen-te registramos todo nuestro códigoJavaScript con una única llamada a cadauno de los métodos RegisterXXX.

Donde realmente este escenariocobra importancia es cuando nos encon-tramos desarrollando nuestros propioscontroles Web, sobre todo aquellos quepueden necesitar una considerable can-tidad de código de script.

Debemos tener presente que si aña-dimos a un WebForm varias copias denuestro control, cada una de estas instan-cias pasará por las líneas de código quegeneran el bloque de JavaScript, pero sóloserá en la primera ocasión en que se eje-cuten, cuando se emita el consabido códi-go de script hacia el navegador, mientrasque en el resto de ocasiones en que el flu-jo de la aplicación pase por este mismopunto, la llamada a los métodosRegisterXXX no tendrá resultado alguno,consumiendo inútilmente un preciosotiempo de proceso y recursos.

Para optimizar esta situación, la clasePage proporciona los métodos IsClient-ScriptBlockRegistered e IsStartup-ScriptRegistered, que sirven para confir-mar si un bloque de código script ya hasido registrado utilizando los métodosRegisterClientScriptBlock o Register-StartupScript respectivamente.

Ambos métodos reciben como pará-metro una cadena que representa alidentificador del bloque de código acomprobar, y devuelven un valor lógi-co que indica si ya existe en la página unscript con ese identificador.

Aplicando esta técnica al controlCajaNumero, deberemos modificar lige-ramente el método OnPreRender delmodo que muestra el fuente 13.

Empleando macros para auto-matizar la preparación delcódigo JavaScript

Como hemos mencionado en un apar-tado anterior, cuando necesitamos añadir

dotN

etM

anía

<<

20

dnm.asp.net<<

Dim sJS1 As String

sJS1 = "<script language=""javascript"">"sJS1 &= "function Primera()"sJS1 &= "{"sJS1 &= "alert('esta es la función Primera')"sJS1 &= "}"sJS1 &= "</script>"

Me.RegisterClientScriptBlock("CodJS", sJS1)

Dim sJS2 As StringsJS2 = "<script language=""javascript"">"sJS2 &= "function Segunda()"sJS2 &= "{"sJS2 &= "alert('esta es la función Segunda')"sJS2 &= "}"sJS2 &= "</script>"

' atención, vamos a usar el mismo identificador' de bloque de código que en la anterior ocasiónMe.RegisterClientScriptBlock("CodJS", sJS2)

Fuente 12

Protected Overrides Sub OnPreRender(ByVal e As System.EventArgs)'....If Not (Me.Page.IsClientScriptBlockRegistered("CodJSCajaNumero")) Then

sJS = "<script language=""javascript"">" & ControlChars.CrLfsJS &= "function CompruebaCampo()" & ControlChars.CrLf'....Me.Page.RegisterClientScriptBlock("CodJSCajaNumero", sJS)

End If'....Me.oCaja.Attributes.Add("onkeypress", "CompruebaCampo()")

End Sub

Fuente 13

'....Private oCaja As WebControls.TextBox

'....Protected Overrides Sub CreateChildControls()

' limpiar la colección de controles constituyentes de este controlMe.Controls.Clear()' crear el TextBox contenido en este controlMe.oCaja = New WebControls.TextBox

End Sub

Protected Overrides Sub Render(ByVal output As System.Web.UI.HtmlTextWriter)' generar el control incluyendo ‘el TextBox constituyenteMyBase.Render(output)

Me.oCaja.RenderControl(output)

End Sub

'....

Fuente 11

Page 21: Visual Basic.NET - Tecnología, Tips de Programación … · ben teniendo el formato de cuaderno técnico, ... olvidamos que el producto de nuestro trabajo no es un fin en sí mismo

una gran cantidad de código de script a un WebFormpodemos escribirlo en un archivo .JS aparte, y estable-cer una referencia al mismo desde el HTML del for-mulario, utilizando el atributo srcde la etiqueta <script>.

Esta práctica puede resultar un problema cuando elcódigo JavaScript a generar pertenece a un control Webpersonalizado, ya que en ese caso, además del ensam-blado que contiene el control, debemos proporcionar elarchivo con su código de script asociado. En resumen,se trata de un modo de trabajo poco efectivo.

Cuando diseñamos y desarrollamos un control pro-pio debemos procurar que su funcionamiento sea lo másautónomo posible; esto quiere decir que si debe generarcódigo de script, tiene que hacerlo el propio control des-de el interior de su clase utilizando los métodosRegisterXXX, lo cual puede llegar a resultar un tanto farra-goso por la conveniencia, ya explicada en anteriores ejem-plos, de concatenar las líneas de código en una variabley añadir los correspondientes saltos de línea.

¿No sería estupendo poder escribir el códigoJavaScript de igual modo que lo hacemos con el códi-go “normal” del control, es decir, sin tener que con-catenar cada línea a una variable que lo contenga niañadirle el salto de línea final?.

Pues bien, esto es posible si recurrimos a unapotente herramienta que nos proporciona el entornode Visual Studio .NET: las macros. Gracias a unamacro, el programador puede dedicarse a escribirexclusivamente el código de script, y encomendar a lamacro el trabajo pesado de concatenar todo ese códi-go en una variable, y añadir los caracteres especialesde salto de línea. Procedamos pues.

Primeramente añadiremos al proyecto un nuevocontrol con el nombre CajaColor, que consistirá enuna caja de texto, cuyo color de fondo y contenidocambiará en base a determinadas circunstancias.

A continuación también agregaremos al proyectoun archivo con el nombre GeneracionCodigoJS.js, enel que escribiremos las funciones JavaScript que conec-taremos con los eventos del control. El fuente 14 mues-tra una función encargada de cambiar el color de fon-do de la caja, según la cantidad de caracteres que estacontenga.

El siguiente paso consiste en seleccionar el menúde Visual Studio .NET “Herramientas” + “Macros” +

“Explorador” de macros, que abrirá la ventana“Explorador de macros”, dentro de la cual expandire-mos sus nodos de la siguiente forma: “Macros” +“MyMacros” + “Module1”. Ver la figura 3.

Haciendo clic derecho sobre el nodo Module1,seleccionaremos la opción “Editar”, con la que entra-remos en el entorno de desarrollo de macros (IDE)de VS.NET, quedando situados dentro del editor decódigo de macros, en el que escribiremos la macroTransfCodigoJSEnBloque, que no es otra cosa que unprocedimiento Sub que se ejecuta bajo un contextomuy particular dentro del entorno de desarrollo.

El objetivo de esta macro consiste precisamente enrealizar el trabajo que antes hacíamos manualmente, esdecir, tomar el código de script y concatenarlo a unavariable, incluyendo los caracteres especiales de salto delínea. Debido a que un tratamiento exhaustivo de lasmacros es algo que queda fuera del ámbito de este artí-culo, hemos proporcionado las oportunas explicacionesdentro del código para que el lector sepa lo que está ocu-rriendo en cada momento. Prometemos abordar el inte-resante tema de las macros en un próximo artículo, vea-mos ahora el contenido de la macro en el fuente 15.

Finalizada la creación de la macro volveremos alproyecto de los controles Web, y nos situaremos enel código de la función JavaScript CambiarColor. Desdeaquí podemos ver en la ventana “Explorador demacros” la macro TransfCodigoJSEnBloque recién cre-ada; haciendo doble clic sobre la misma se ejecutará,aplicando la transformación sobre nuestro código descript que vemos en el fuente 16.

A continuación tomaremos el código resultantetras la ejecución de la macro y lo situaremos como unmétodo del control, al que llamaremos en el momen-

dotN

etM

anía

<<

21

dnm.asp.net<<

function CambiarColor(obj){

if (obj.value.length > 4){

obj.style.backgroundColor = "PaleGreen";}else{

obj.style.backgroundColor = "White";}

}

Fuente 14

Figura 3

Para comprobar si un bloque de código descript ya ha sido registrado en el WebFormdisponemos en la clase Page de los méto-dos IsClientScriptBlockRegistered e

IsStartupScriptRegistered. ][

Page 22: Visual Basic.NET - Tecnología, Tips de Programación … · ben teniendo el formato de cuaderno técnico, ... olvidamos que el producto de nuestro trabajo no es un fin en sí mismo

dotN

etM

anía

<<

22

dnm.asp.net<<

Sub TransfCodigoJSEnBloque()Dim sLineaCodigo As String' situarnos al final del documento de códigoDTE.ActiveDocument.Selection.EndOfDocument()' añadir dos líneas en blancoDTE.ActiveDocument.Selection.NewLine(2)' situarnos al comienzo de línea y añadir una' cadena que usaremos como marca que indica que' hemos llegado al final del código a manipularDTE.ActiveDocument.Selection.StartOfLine(vsStartOfLineOptions.vsStartOfLineOptionsFirstColumn)DTE.ActiveDocument.Selection.Text = "****%%%%****"DTE.ActiveDocument.Selection.NewLine()' situarnos al comienzo del códigoDTE.ActiveDocument.Selection.StartOfDocument()' añadir una línea de código que creará un StringBuilder' en el que se irán agregando las líneas de scriptDTE.ActiveDocument.Selection.Text = "Dim sb As New System.Text.StringBuilder"DTE.ActiveDocument.Selection.NewLine()

' recorrer y transformar cada línea de código scriptWhile True

' seleccionar la línea de código y asignar a una variableDTE.ActiveDocument.Selection.StartOfLine(vsStartOfLineOptions.vsStartOfLineOptionsFirstColumn)DTE.ActiveDocument.Selection.EndOfLine(True)sLineaCodigo = DTE.ActiveDocument.Selection.Text' añadir comillas dobles en donde sea necesario' para evitar errores en la composición de cadenassLineaCodigo = sLineaCodigo.Replace("""", """""")' añadir la línea de código transformadaDTE.ActiveDocument.Selection.Text = "sb.Append(""" & sLineaCodigo & """ & ControlChars.CrLf)"' comprobar si hemos llegado al final del código a transformarDTE.ActiveDocument.Selection.LineDown()DTE.ActiveDocument.Selection.StartOfLine(vsStartOfLineOptions.vsStartOfLineOptionsFirstText)DTE.ActiveDocument.Selection.EndOfLine(True)If CType(DTE.ActiveDocument.Selection, TextSelection).Text = "****%%%%****" Then

' si hemos llegado a la marca de final de código' borrarla y salir del bucleDTE.ActiveDocument.Selection.Delete()Exit While

ElseDTE.ActiveDocument.Selection.StartOfLine(vsStartOfLineOptions.vsStartOfLineOptionsFirstText)

End IfEnd While

' añadir la línea de código que devuelve el StringBuilder' que contiene el script adecuadamente transformadoDTE.ActiveDocument.Selection.LineDown()DTE.ActiveDocument.Selection.StartOfLine(vsStartOfLineOptions.vsStartOfLineOptionsFirstText)DTE.ActiveDocument.Selection.Text = "Return sb.ToString()"

End Sub

Fuente 15

Dim sb As New System.Text.StringBuildersb.Append("function CambiarColor(obj)" & ControlChars.CrLf)sb.Append("{" & ControlChars.CrLf)sb.Append(" if (obj.value.length > 4)" & ControlChars.CrLf)sb.Append(" {" & ControlChars.CrLf)sb.Append(" obj.style.backgroundColor = ""PaleGreen""; " & ControlChars.CrLf)sb.Append(" }" & ControlChars.CrLf)sb.Append(" else" & ControlChars.CrLf)sb.Append(" {" & ControlChars.CrLf)sb.Append(" obj.style.backgroundColor = ""White""; " & ControlChars.CrLf)sb.Append(" }" & ControlChars.CrLf)sb.Append("}" & ControlChars.CrLf)sb.Append("" & ControlChars.CrLf)sb.Append("" & ControlChars.CrLf)

Return sb.ToString()

Fuente 16

Page 23: Visual Basic.NET - Tecnología, Tips de Programación … · ben teniendo el formato de cuaderno técnico, ... olvidamos que el producto de nuestro trabajo no es un fin en sí mismo

to de registrar los bloques de código de script, lo cual,en nuestro ejemplo, hacemos desde el métodoOnPreRender, como vemos en el fuente 17.

Una de las ventajas en el empleo de esta técnica con-siste en que mantenemos fácilmente la indentación delcódigo de script generado, lo que facilita su lectura des-de la opción de visualizar código del navegador.

Conectando eventos y código JavaScriptdesde el método AddAttributesToRender

Como punto final a este artículo, para conectar loseventos cliente de nuestro control CajaColor con lasfunciones JavaScript, vamos a utilizar una nueva téc-nica de trabajo que consiste en reemplazar el métodoAddAttributesToRender, el cual es llamado durante la cre-ación del control.

En este método podemos centralizar todas las ins-trucciones relacionadas con la creación de atributos parael control, es decir, la conexión entre los diferentes even-tos desencadenados en el lado cliente por el control, y

las funciones de script que se ejecutarán en respuesta adichos eventos. El fuente 18 muestra un ejemplo de usode este método.

AddAttributesToRender recibe un parámetro de tipoHtmlTextWriter, que usaremos para asociar los eventos yel código de script llamando a su método AddAttribute.

AddAttribute, por otra parte, recibe dos parámetros:el primero lo utilizamos para especificar el nombre delevento a tratar, bien como una cadena de caracteres omediante uno de los miembros de la enumeraciónHtmlTextWriterAttribute; el segundo parámetro es unacadena con el nombre de la función de script que actua-rá como manipulador del evento.

<script> Finalizamos </script>Nuestro periplo termina aquí, no sin antes agrade-

cer al lector la atención que nos haya dedicado, con-fiando en que todas las experiencias aquí vertidas pue-dan serle útiles en su quehacer diario como noble arte-sano del código.

dotN

etM

anía

<<

23

dnm.asp.net<<

Private Function GeneraJSCambiarColor() As String' genera el código javascript que cambia el color de la caja de textoDim sb As New System.Text.StringBuildersb.Append("" & ControlChars.CrLf)sb.Append("function CambiarColor(obj)" & ControlChars.CrLf)sb.Append("{" & ControlChars.CrLf)sb.Append(" if (obj.value.length > 4)" & ControlChars.CrLf)sb.Append(" {" & ControlChars.CrLf)sb.Append(" obj.style.backgroundColor = ""PaleGreen""; " & ControlChars.CrLf)sb.Append(" }" & ControlChars.CrLf)sb.Append(" else" & ControlChars.CrLf)sb.Append(" {" & ControlChars.CrLf)sb.Append(" obj.style.backgroundColor = ""White""; " & ControlChars.CrLf)sb.Append(" }" & ControlChars.CrLf)sb.Append("}" & ControlChars.CrLf)sb.Append("" & ControlChars.CrLf)

Return sb.ToString()End Function'-------------------------------------------------------Protected Overrides Sub OnPreRender(ByVal e As System.EventArgs)

Dim sJS As StringMyBase.OnPreRender(e)

If Not (Me.Page.IsClientScriptBlockRegistered("CodJSCajaColor")) ThensJS = "<script language=""javascript"">" & ControlChars.CrLfsJS &= Me.GeneraJSCambiarColor()sJS &= Me.GeneraJSManipulaContenido()sJS &= "</script>"' registrar el bloque de código javascript que usará el controlMe.Page.RegisterClientScriptBlock("CodJSCajaColor", sJS)

End IfEnd Sub

Fuente 17

Protected Overrides Sub AddAttributesToRender(ByVal writer As System.Web.UI.HtmlTextWriter)' conectar los eventos del control' con el código/funciones de javascript correspondienteswriter.AddAttribute(HtmlTextWriterAttribute.Onchange, "alert('Se ha cambiado el control');")writer.AddAttribute("onkeyup", "CambiarColor(this)")writer.AddAttribute("onblur", "ManipulaContenido(this)")

End Sub

Fuente 18

Page 24: Visual Basic.NET - Tecnología, Tips de Programación … · ben teniendo el formato de cuaderno técnico, ... olvidamos que el producto de nuestro trabajo no es un fin en sí mismo

Regulando nuestras expresiones

Las Expresiones Reguladas, son una de las características y posibilidades que ofrece unlenguaje de programación y que por alguna oscura razón, hace que el programadorsienta miedo al enfrentarse a ellas. En realidad no voy a descubrir nada diciendo quesu dominio requiere tiempo y dedicación;el resumen de esto es que no es lo que defi-niríamos como sencillo, pero no nos asustemos, no deja de ser en cierta manera unmito y prueba de ello es lo que vamos a ver a partir de ahora:Qué son las ExpresionesReguladas, para qué sirven y cómo usarlas en .NET.

<< una breve introducción idiomática sobre eltérmino inglés Regular Expressions, y es que no me gus-taría perder la oportunidad de hablar de este tema sinreivindicar algo a favor de nuestra, a veces, torpedea-da lengua. Extrayendo de este término inglés la pala-bra “regular” que proviene del latín “regulare” y queen castellano tiene el significado de “reglar”, el cuál asu vez significa “medir” o “componer las acciones con-forme a regla”, o el significado mismo de “regular”,que significa entre otras acepciones “ajustado y con-forme a regla”, podríamos afirmar entonces que el tér-mino Regular Expressions es común y erróneamente tra-ducido como Expresiones Regulares (me sumo a esas per-sonas que lo han traducido mal alguna vez), y por lotanto, deberíamos quizás traducirlo como ExpresionesReguladas o Expresiones Regladas, aunque me quedo conla primera de ellas, y que cerca de convertirse en unatraducción más exacta del término, nos ayudaría aentender aún más su significado en .NET y en otroslenguajes de desarrollo.

Por esa razón y a partir de ahora, cuando me quie-ra referir a Regular Expressions, me referiré en caste-llano a Expresiones Reguladas.

Breve historia de las Expresiones ReguladasLas cosas no surjen de la nada, todo lo que existe

tiene un origen, y lo mismo sucede con las ExpresionesReguladas.

El origen del estudio de lo que se conoce comoExpresiones Reguladas, tiene su embrión en el estudio delas teorías autómatas con reglas matemáticas de tuning yotras barbaridades ingeniosas, en la que se mezcla ade-más de las propias matemáticas, la lógica y la potencia decálculo que proporciona la informática. Se trata de un

tema muy interesante y apasionante que da como resul-tado el estudio de una cadena de texto o expresión, paradeterminar si cumple una determinada regla sintáctica.

Sin duda, en todos estos estudios e investigaciones,se sucede una lista de nombres de personas que colabo-ran una tras otra en la evolución humana, y casi siempresin saberlo, como ha ocurrido con tantísimos otros des-cubrimientos e inventos. Por citar algunos nombres paraalmacenarlos en el justo juicio del recuerdo (siempre seolvida algunos nombres desgraciadamente), nombraréa Warren McCulloch y Walter Pitts por su impor-tancia en el estudio de los autómatas, Stephen Kleenepor la descripción de los modelos de notación matemá-tica, y Ken Thompson que aplicándolo sobre sistemasUnix, estableció estos estudios de forma clara a lo quehoy día conocemos como Expresiones Reguladas.

Una bonita historia con un final feliz, y cuyas apli-caciones e importantes usos se vieron a prueba en apli-caciones y lenguajes de desarrollo como awk, Emacs,vim, lex y Perl.

Sin embargo, digamos que si hoy día es tan impor-tante el uso de las Expresiones Reguladas, es en buenaculpa por el lenguaje de programación Perl, lenguajeideal para trabajar con cadenas de texto permitiendouna rapidez y potencia de tratamiento realmente incre-íble. Este lenguaje nació de la mano de Larry Wallaproximadamente en el año 1986, aunque la primeraversión que vió la luz data del 1987. Quizás encontre-mos referencias en Internet a este lenguaje como B-News, Pearl y por supuesto el mismo Perl, y que con-forman los diferentes nombres que ha tenido este len-guaje. Este lenguaje, sin embargo, ha sufrido diferen-tes cambios y evoluciones a lo largo de su existencia, yentre ellos, el que tiene que ver con las ExpresionesReguladas, las cuáles fueron añadidas al lenguaje en la

Jorge Serrano

dnm.plataforma.net

Permítame hacer

Jorge Serranoes redactor de dotNetManía. EsIngeniero Informático y MVP deVB y de .NET. Es Webmaster de

PortalVB.com y autor dediferentes libros y artículos

técnicos. Jorge está entre losmejores profesores y

conferenciantes sobre latecnología .NET de nuestro país.

Page 25: Visual Basic.NET - Tecnología, Tips de Programación … · ben teniendo el formato de cuaderno técnico, ... olvidamos que el producto de nuestro trabajo no es un fin en sí mismo

versión 2.0 (1988), teniendo buena cul-pa de esto Harry Spencer.

Del trabajo de Harry Spencer, sur-gió PCRE que significa Perl Com-patible Regular Expressions, y que no esotra cosa, que una librería escrita porPhilip Hazel y que es comúnmenteusada por muchos lenguajes de desa-rrollo para trabajar con ExpresionesReguladas.

Las Expresiones Reguladas son utili-zadas de forma general hoy día por lacasi totalidad de lenguajes de desarro-llo para el tratamiento de cadenas parasu formateo, análisis y validación.

Por último y para finalizar esta pre-ciosa historia de las Expresiones Reguladas,me gustaría indicar que quizás vea enalgunos sitios que Regular Expressions seindica de forma abreviada como regex,regexp o regxp, aunque la forma abrevia-da más extendida y conocida es quizásregex.

Expresándonos en .NET¿Qué haría .NET sin las Expresiones

Reguladas?. Seguro que muchas cosasademás de poder simularlas, pero ¿quéharía un desarrollador de .NET sinExpresiones Reguladas?. Indudablemente,las Expresiones Reguladas nos facilitan eninnumerables ocasiones, ahorrarnos unagran parte del trabajo y si no las tuvié-ramos en .NET, tendríamos que recu-rrir a librerías externas o a construirnuestras propias rutinas de tratamientonosotros mismos. Por suerte, en .NETse añadieron las clases necesarias paratrabajar con Expresiones Reguladas, algoque veremos a continuación.

El espacio de nombres encargado detrabajar con Expresiones Reguladas, esSystem.Text.RegularExpressions, el cuálutilizando la orientación a objetos, nospermitirá trabajar eficientemente conExpresiones Reguladas. Puesto que lasinfluencias de las Expresiones Reguladastienen su embrión en el lenguaje Perlcomo ya hemos indicado, este espaciode nombres tiene, como no podía sermenos, claros parecidos con la sintaxisutilizada en Perl 5.

¿Y cómo trabajan las ExpresionesReguladas?. En realidad lo hace de unaforma muy simple. A una cadena decaracteres determinada, se la compara

con un patrón que efectúa una valida-ción sobre la cadena de texto, permi-tiendo validar dicha cadena para quecumpla todas las normas impuestas enel patrón.

Gramática y sintaxis de lasExpresiones Reguladas

El espacio de nombres System.Text.RegularExpressions es tan sólo la envol-tura de lo que esconden las ExpresionesReguladas. Entre otras cosas, existe un con-junto de reglas, aplicadas según la gramá-tica y sintaxis, que nos permitirá utilizareficientemente nuestras ExpresionesReguladas. A continuación veremosmuchas de ellas, aunque normalmente yen la mayoría de los casos, utilizaremostan solo un subconjunto de todas estas.Aún así, conviene conocer al menos, lasmás generales.

Sintaxis:Opciones de las ExpresionesReguladas

Cuando ejecutamos una ExpresiónRegulada, debemos hacerlo en algunaocasión, teniendo en cuenta las opcio-nes que podemos utilizar para ello. Acontinuación y en la siguiente tabla,encontraremos esta equivalencia:

Sintaxis:Caracteres de salida

Muy a tener en cuenta en el trata-miento de Expresiones Reguladas, son loscaracteres de salida. Éstos pueden obser-varse en la siguiente tabla:

Sintaxis:Conjunto de caracteres a uti-lizar en las Expresiones Reguladas

Para poder utilizar las ExpresionesReguladas, conviene conocer con qué

dotN

etM

anía

<<

25

dnm.plataforma.net<<

Sintaxis Descripción

i No sensitivo al texto

mModo multilínea, correspondenciascon el principio y fin de cada líneade texto

nCaptura explícitamente gruposnumerados o nombrados

rHace búsquedas de derecha aizquierda

sModo línea simple, corresponden-cias carácter a carácter

xElimina del patrón espacios enblanco

Sintaxis Descripción

\numNum identifica el carácter ASCIIdado como valor octal (\059)

\xnumNum identifica el carácterASCII dado como valor hexa-decimal (\x73)

\a Timbre o alarma (el típico beep)

\b Retroceso

\e Escape

\f Sacar por impresora

\n Nueva línea de texto

\non-escape Carácter no escape

\r Retorno de carro

\t Tabulador horizontal

\v Tabulador vertical

\unumNum identifica el carácterASCII dado como valor hexa-decimal Unicode (\u0067)

\0 Valor nulo (null)

Las Expresiones Reguladas son utilizadas de forma general hoydía por la casi totalidad de lenguajes de desarrollo para el

tratamiento de cadenas para su formateo, análisis y validación

Page 26: Visual Basic.NET - Tecnología, Tips de Programación … · ben teniendo el formato de cuaderno técnico, ... olvidamos que el producto de nuestro trabajo no es un fin en sí mismo

dotN

etM

anía

<<

26

dnm.plataforma.net<<

juego de caracteres podemos jugar.Estos son identificados según se detallaen la siguiente tabla:

Sintaxis:Sustitución de cadenas

Una interesante cualidad de lasExpresiones Reguladas, es la que tieneque ver con la sustitución de cadenasde texto. En la siguiente tabla, veremoslas instrucciones de sustitución másempleadas:

Hemos visto hasta ahora algunasdefiniciones de sintaxis sobre Expre-siones Reguladas. A continuación vere-mos más, pero para abrir boca, escri-biremos un pequeño ejemplo de códi-go, que emplee algunas de las sintaxisanteriormente vistas.

En este ejemplo, sustituiremos unafecha de tipo MM-DD-YYYY como porejemplo 12-25-2004 por la correspon-diente DD/MM/YYYY que daría como resul-tado 25/12/2004. Este ejemplo enVB.NET sería el que se detalla en elfuente 1.

En primer lugar, observamos enel ejemplo, el uso de la clase Regex,donde indicaremos la expresión a eva-luar. Dentro de esa expresión hemosutilizado como conjunto de caracte-res (\w). De esta manera, estaremostrabajando con un conjunto de carac-teres que están comprendidos entrea-z, A-Z ó 0-9. También vemos comoen esta transformación, usamos lasustitución de caracteres utilizadamediante el carácter $ seguido de laposición.

Sintaxis:Cuantificadores o repetidores

Los cuantificadores es una de laspartes más destacables e interesantes atener en cuenta cuando trabajamos conExpresiones Reguladas, ya que nos per-mitirá realizar acciones adicionales muyvaliosas para nosotros. En la siguientetabla, podemos ver la lista de cuantifi-cadores a usar:

Sintaxis:Posicionamiento

Si lo que queremos es situar nues-tra cadena o restos de nuestra cadenaen algún lugar determinado, podemos

Sintaxis Descripción

.Busca correspondencias concualquier carácter excepto conel carácter \n

\dBusca correspondencias consímbolos numéricos decima-les que oscilan entre 0-9

\DBusca correspondencias concualquier carácter NO numé-rico

\p{texto}Realiza correspondencias concualquier carácter indicado entexto

\P{texto}Realiza correspondencias concualquier carácter NO indi-cado en texto

\sBusca correspondencias conun espacio en blanco, queequivale a \n\r\t\f

\SBusca correspondencias concualquier carácter que NOsea un espacio en blanco

\wBusca correspondencias concualquier carácter compren-dido entre a-z, A-Z ó 0-9

\WBusca correspondencias concualquier carácter que NOsea a-z, A-Z ó 0-9

[lista_de_caracteres]

Busca correspondencias conlos caracteres indicados enlista_de_caracteres, comopor ejemplo [abcde]

[^lista_de_caracteres]

Busca correspondencias conlos caracteres NO indicadosen lista_de_caracteres

[carácter_1-carácter_2]

Busca correspondencias conlos caracteres indicados entrecarácter_1 y carácter_2

Sintaxis Descripción

$numNum identifica y sustituye el grupode caracteres a sustituir ($2)

${num}Num identifica y sustituye el grupode caracteres a sustituir por ?<num>

Imports System.Text.RegularExpressions[...]Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)_

Handles Button1.ClickDim strTextoEjemplo As String = "12-25-2004"Dim MiRegEx As New Regex("(\w+)-(\w+)-(\w+)")strTextoEjemplo = MiRegEx.Replace(strTextoEjemplo, "$2/$1/$3")MessageBox.Show(strTextoEjemplo)

End Sub

Sintaxis Descripción

*Indica 0 ó más correspon-dencias

+Indica 1 ó más correspon-dencias

? Indica 0 ó 1 correspondencia

*?Busca la primera correspon-dencia con el mínimo derepeticiones

+?Busca el mínimo de repeti-ciones, con la salvedad de queal menos, debe repetirse 1 vez

?? Busca 0 ó ninguna repetición

{n}Busca el número exacto decorrespondencias indicadasen n, como por ejemplo \d{2}

{n,}Busca que el número decorrespondencias sea comomínimo, el indicado en n

{n,m}Busca que las corresponden-cias estén situadas entre n y m

{n}?Indica justo el número derepeticiones indicadas en n

{n,}

Indica justo el mínimo derepeticiones, obligando a quesean como mínimo las indi-cadas en n

{n,m}Indica el número de repeti-ciones, situadas entre n y m

Fuente 1

Page 27: Visual Basic.NET - Tecnología, Tips de Programación … · ben teniendo el formato de cuaderno técnico, ... olvidamos que el producto de nuestro trabajo no es un fin en sí mismo

usar la sintaxis de posicionamiento.En la siguiente tabla, podemos ver lalista que corresponde con la sintaxisde posicionamiento. Viendo esta tabla,entenderemos mucho más como fun-ciona:

Sintaxis:Agrupaciones o grupos

Otra sintaxis de las ExpresionesReguladas es la que tiene que ver con lasagrupaciones. Se trata de una sintaxisun poco más avanzada a la que hemosvisto con anterioridad, pero igualmen-te potente e interesante:

Sintaxis:Referencias reversibles

Otra de las características de lasExpresiones Reguladas, es la de hacer refe-rencias reversibles o hacia atrás, comovemos en la siguiente tabla:

Sintaxis:Alternancia

La alternancia es otra característicamás en el trabajo con ExpresionesReguladas. En la tabla adjunta, puedeverse las correspondencias de esta sin-taxis:

Sintaxis:Otras reglas sintácticas

Existen más reglas sintácticas parautilizar con nuestras Expresiones Reguladas.Aquí veremos el resto de ellas, las cualesno hemos visto aún:

Regulando validaciones en .NET

Todo lo que hemos visto, forma par-te de la teoría de las Expresiones Reguladas.Ahora bien, ¿cómo aplicamos esta sinta-xis a nuestras aplicaciones?. Sin duda eltrabajo con Expresiones Reguladas, requie-re que conjuguemos y mezclemos la sin-taxis vista aquí para dar lugar a una regla.Un ejemplo de esto que cuento es el códi-

dotN

etM

anía

<<

27

dnm.plataforma.net<<

Sintaxis Descripción

$ Indica el final de la línea

^ Indica el comienzo de la línea

\A Indica el comienzo de la cadena

\bIndica dentro del límite de unapalabra

\BIndica que NO está dentro dellímite de una palabra

\G Indica el lugar dónde comienza

\zIndica exactamente el final de lacadena

\Z Indica el final de la línea o cadena

Sintaxis Descripción

( )Captura la correspondencia a lasubcadena

(?<texto>)Captura la correspondencia deltexto indicado en texto

(?<num>)Captura la correspondencia deltexto indicado en num, dónde numes el número de caracteres

(?: ) No captura ninguna agrupación

(?= )Continúa haciendo correspon-dencias si la expresión corres-ponde con la parte derecha

(?! )

Continúa haciendo corres-pondencias si la expresión NOcorresponde con la partederecha

(?<= )

Continúa haciendo corres-pondencias si la expresióncorresponde con la parteizquierda

(?<! )

Continúa haciendo corres-pondencias si la expresión NOcorresponde con la parteizquierda

(?> )La subexpresión se corres-ponde una vez, pero no ensentido inverso

(?<name_1-name_2>)

Almacena el intervalo y gru-po en name_1 si name_2 esindefinido, haciendo lascorrespondencias en sentidoinverso

{n,}

Indica justo el mínimo derepeticiones, obligando a quesean como mínimo las indica-das en n

{n,m}Indica el número de repeti-ciones, situadas entre n y m

(?imnsx-imnsx: )

Aplica o deshabilita las opcio-nes de correspondencia

A una cadena de caracteresdeterminada, se la comparacon un patrón que efectúa

una validación sobre la cadena de texto, permitiendovalidar dicha cadena para que

cumpla todas las normasimpuestas en el patrón

Sintaxis Descripción

\countCuenta el número de referenciasreversibles

\k<name> Nombra las referencias reversibles

Sintaxis Descripción

| Indica la aplicación lógica OR

(?(name)yes|no)

Corresponde como yes si el textoo cadena en name tiene algunacorrespondencia. En caso contra-rio, indica no

(?(expresión)yes|no)

Corresponde como yes si la expre-sión en expresión tiene algunacorrespondencia. En caso contra-rio, indica no

Sintaxis Descripción

(?imnsx-imnsx)

Establece o deshabilita opciones enla mitad del patrón

# Comentario

(?# ) Comentario en línea

Page 28: Visual Basic.NET - Tecnología, Tips de Programación … · ben teniendo el formato de cuaderno técnico, ... olvidamos que el producto de nuestro trabajo no es un fin en sí mismo

go del fuente 2 que evalua la expresión“^\s*$”.

Analizando el código anterior, obser-vamos que la Expresión Regulada dada“^\s*$” indica que la cadena completa, ^(indica comienzo) y $ (fin), debe estarcompuesta por cero ó más de un carácteren blanco, indicados por \s*. De estamanera y con esta expresión, somos capa-ces de detectar rápidamente si una cade-na de texto contiene caracteres diferentesde los espacios en blanco o simplementeuna cadena sin caracteres.

Otra validación que podemos haceres utilizando la clase Match. En este casopodemos utilizar la propiedad Match.Success para determinar la posición de laprimera correspondencia (ver fuente 3).

Esta instrucción nos dará comoresultado la posición en la cuál se haencontrado la correspondencia.

Indudablemente, la aplicación deExpresiones Reguladas es tremendamenteamplia. El uso más habitual de éstas es paraaplicar validaciones a una cadena o expre-sión dada. Pero podemos trabajar tambiéncon grupos y colecciones, como veremosa continuación de forma práctica.

Regulando reemplazamientos en.NET

Otra de las singularidades de lasExpresiones Reguladas que ya hemos vistoal principio en otro ejemplo, es la capaci-dad que tiene de reemplazar caracteres ocadenas de texto de forma tremendamenteeficiente. Esto es lo que veremos en elejemplo de código del fuente 4.

Este ejemplo en ejecución reemplazalos caracteres “e”, “m” o “t” por un carác-ter “.”. Como vemos, trabajar y manipu-

lar cadenas de texto en las ExpresionesReguladas es extremadamente sencillo.

Regulando colecciones en .NET

El uso de colecciones con ExpresionesReguladas, vienen de la mano de la claseMatchCollection. Para que veamos cómomanejar este objeto, lo mejor es practicarcon él. El ejemplo del fuente 5, nos mues-tra uno de sus usos más frecuentes.

Este ejemplo dará como resultado eltexto “Me Como Las Naranjas”. LaExpresión Regulada “\b[A-Z][a-z]+\b” nosindica que nuestra cadena de texto busca-da, corresponderá con un comienzo enletra mayúscula seguida de un texto enminúsculas. De hecho, hay que tener encuenta que una cadena de texto del tipo

“A mí Me gusta Como son Las frutasNaranjas” daría como resultado de salidael mismo texto “Me Como Las Naranjas”.

Regulando grupos en .NET

Los grupos son útiles para estable-cer un conjunto de correspondencias

dentro de una cadena de texto. Un ejem-plo práctico que nos ayude a aclarar losconceptos teóricos, sería el que se deta-lla en el fuente 6.

Este ejemplo nos permite extraeruna parte del grupo de una cadena de

texto, que cumple la expresión“(?<Fabricante>(\w+))\s(¿<Modelo>(w+-?\d+))”. Pero aún así, podemoscomplicar un poco más el uso deExpresiones Reguladas combinandoalguna de las técnicas que hemos visto.

Regulando colecciones y grupos en.NET

Lo que haremos a continuación, serácombinar el uso de colecciones y gru-pos para que veamos otra de las posibi-lidades que nos ofrece el uso de expre-siones complejas.

dotN

etM

anía

<<

28

dnm.plataforma.net<<

Dim strTextoEjemplo As String = " "Dim MiRegEx As New Regex("^\s*$")MessageBox.Show(IIf(MiRegEx.IsMatch(strTextoEjemplo), "Cadena Vacía", strTextoEjemplo))

Dim MiRegEx As New Regex("/")Dim MiMatch As Match = MiRegEx.Match("12/25/2004")If MiMatch.Success Then

MessageBox.Show("Encontrado en la posición " & MiMatch.Index.ToString())End If

Dim strTextoEjemplo As String = "Esto es un ejemplo de texto."Dim MiRegEx As New Regex("[emt]")MessageBox.Show("Complete la frase: " & MiRegEx.Replace(strTextoEjemplo, "."))

Dim strTextoEjemplo As String = "Me gusta Como son Las frutas Naranjas"Dim MiRegEx As New Regex("\b[A-Z][a-z]+\b")Dim MiMatchColl As MatchCollection = MiRegEx.Matches(strTextoEjemplo)Dim strTextoSalida As String = ""Dim MiMatch As MatchFor Each MiMatch In MiMatchColl

strTextoSalida = strTextoSalida & MiMatch.Value() & " "NextstrTextoSalida = strTextoSalida.TrimMessageBox.Show(strTextoSalida)

Fuente 2

Fuente 3

Fuente 4

Fuente 5

Dim strTextoEjemplo As String = "Airbus A-320"Dim Expresion As String = "(?<Fabricante>(\w+))\s(?<Modelo>(\w+-?\d+))"Dim MiRegEx As RegexMessageBox.Show(MiRegEx.Match(strTextoEjemplo, Expresion).Groups("Modelo").ToString())

Fuente 6

Page 29: Visual Basic.NET - Tecnología, Tips de Programación … · ben teniendo el formato de cuaderno técnico, ... olvidamos que el producto de nuestro trabajo no es un fin en sí mismo

En el ejemplo del fuente 7, lo queveremos es cómo extraer los modelosde todos los aviones dados. La cadenade entrada será en este caso “Airbus A-320, Airbus A-332, Airbus B-441”.Nuestro objetivo será por lo tanto,extraer los modelos de estos aviones, queson A-320, A-332 y B-441, como vere-mos en el ejemplo del fuente 7.

Analizando este ejemplo, observare-mos que es casi un calco completo delanterior, con la salvedad de que en estecaso, lo que estamos haciendo es utilizaruna colección de los valores de un grupopara manipularlos posteriormente comodeseemos dentro de nuestra aplicación.

Regulando la captura de colecciones.NET

Otra posibilidad de las ExpresionesReguladas, es la capacidad que tienen depoder trabajar con colecciones capturán-dolas y utilizándolas una a una. Un ejem-plo práctico de esto que comento, es elque podemos ver en el fuente 8.

La captura de colecciones nos per-mite trabajar con las correspondenciascomo si fueran colecciones de expre-siones que cumplen el patrón.

Regulando con comentarios en .NET

Otra de las características de lasExpresiones Reguladas, es la de permitirnosel uso de comentarios dentro de nuestrasexpresiones. Todos sabemos que cuandonos ponemos a desarrollar aplicaciones,al principio está todo controlado (o debe-ría estarlo), pero a medida que pasa eltiempo, aquel recuerdo termina por desa-

parecer y muchas veces cuando regresa-mos a nuestra aplicación, no estamos com-pletamente seguros de ciertas cosas.

Los comentarios dentro de la aplica-ción ayudan a aclarar algunos conceptos.La documentación de la aplicación tam-bién. Pero además de estas posibilidades,las Expresiones Reguladas, nos permitentambién añadir comentarios dentro de lapropia expresión.

En el ejemplo del fuente 9, nos ense-ña cómo usar comentarios en ExpresionesReguladas. Se trata de un ejemplo muy sen-cillo para que lo comprendamos perfec-tamente.

Como podemos observar, los comen-tarios en Expresiones Reguladas, los hemosescrito como (?#Comentario).

Aunque pueda resultarnos un pococomplejo comprender los comentariosde nuestras expresiones, a veces puederesultar especialmente útil. No es, detodas maneras, muy habitual encon-trarnos con comentarios dentro de lasexpresiones, pero sirva este punto, paraque sepamos que podemos utilizarlo silo deseamos.

ConclusionesComo hemos podido ver en este

artículo, el espacio de nombresSystem.Text.RegularExpressions nosofrece la posibilidad de trabajar conExpresiones Reguladas en nuestras apli-caciones .NET.

Para usar estas expresiones es, sinembargo, necesario conocer algunasparticularidades que nos permitiránsacarle el máximo provecho y enten-der cómo se construyen. La sintaxisde uso de las expresiones es funda-mental. Dominar estas expresiones escomplicado, pero con la práctica ter-minará al menos, controlando en granparte su uso. También es necesarioconocer la extensibilidad del espaciode nombres dado, ya que aquí sólohemos visto algunas de sus implica-ciones, quizás las más habituales. Porello, le invito a investigar y ampliar

sus conocimientos, estudiando en pro-fundidad el espacio de nombresSystem.Text.RegularExpressions.

Por último, me gustaría indicarle unadirección Web dónde usuarios de todo elmundo, han contribuido con susExpresiones Reguladas personales, com-partiéndolas con todos nosotros. Si nece-sita en algún momento, ejecutar una vali-dación determinada, quizás el punto ini-cial sea este sitio Web. Se trata de la lis-ta no oficial de Expresiones Reguladas:http://www.regexlib.com.

dotN

etM

anía

<<

29

dnm.plataforma.net<<

Dim strTextoEjemplo As String = "Airbus A-320, Airbus A-332, Airbus B-441"Dim MiRegEx As New Regex("(?<Fabricante>(\w+))\s(?<Modelo>(\w+-?\d+))")Dim MiMatchColl As MatchCollection = MiRegEx.Matches(strTextoEjemplo)Dim MiMatch As MatchDim strTextoSalida As String = ""For Each MiMatch In MiMatchColl

strTextoSalida = strTextoSalida & MiMatch.Groups("Modelo").ToString() & " "NextMessageBox.Show(strTextoSalida)

Fuente 7

Dim MiRegEx As New Regex("(\d[/]\d)+")Dim MiMatch As Match = MiRegEx.Match("12/25/2004")Dim MiCaptColl As CaptureCollectionDim MiGroupColl As GroupCollectionMiGroupColl = MiMatch.GroupsDim I As IntegerDim J As IntegerDim Contador As IntegerFor I = 0 To MiGroupColl.Count - 1

MiCaptColl = MiGroupColl(I).CapturesContador = MiCaptColl.CountFor J = 0 To Contador - 1

MessageBox.Show(MiCaptColl(J).ToString() & vbCrLf & MiCaptColl(J).Index.ToString())Next

Next

Fuente 8

Dim strTextoEjemplo As String = " "Dim MiRegEx As New Regex("^\s*$")MessageBox.Show(IIf(MiRegEx.IsMatch(strTextoEjemplo), "Cadena Vacía", strTextoEjemplo))

Fuente 9

Page 30: Visual Basic.NET - Tecnología, Tips de Programación … · ben teniendo el formato de cuaderno técnico, ... olvidamos que el producto de nuestro trabajo no es un fin en sí mismo

Reflection.Editor,una biblioteca para programar la edición de ensamblados .NET

En este trabajo se presenta la biblioteca Reflection.Editor que nos permite lograr efec-tos tan atractivos como cambiar nombres de tipos, métodos, quitar miembros de unensamblado,añadir nuevos miembros,pasar miembros de un ensamblado a otro,poneratributos, y otros mas, y todo ello claro sin tener que disponer del código fuente. Sepresenta además la herramienta IL_Lego desarrollada sobre esta biblioteca nos da laposibilidad de hacer interactivamente modificaciones de esta naturaleza.

<<Uno de los mitos fundamentalistas es que hay que

tener acceso al código fuente. ¿Para qué querríamos el código fuente? ¿Para saber

dónde y cómo se puede usar dicho código? Si se tie-ne una buena documentación, un buen diseño orien-tado a objetos, y se dispone además de la capacidadde integrar metadatos junto con el código ejecutable(como hacen los ensamblados .NET), entonces no estan necesario tener que disponer del fuente.

¿Para qué querríamos el código fuente? ¿Para ase-gurarnos de que un programador malévolo no ocultaen el código final acciones que nos pueden hacer daño?Si el asunto es de desconfianza, entonces habría quedesconfiar también de un posible compilador malicio-so que pudiera colocar sus espías en el código ejecuta-ble que genere, aún cuando el código fuente parezcainocente. La capacidad que tiene .NET de hacer refle-xión del código IL nos aumenta la confianza porquecon ello podemos inspeccionar el código IL lo cual estámás cercano a lo que realmente se ejecutará.

¿Para qué querríamos el código fuente? ¿Para ente-rarnos de los intríngulis de los algoritmos y del knowhow no documentado escondido en la implementa-ción de los métodos? Bueno, éste sí que es un temapolíticamente discutible: qué se protege de la pro-piedad intelectual y qué no, cuál conocimiento se com-parte y cuál no, qué se da gratuito y qué no, pero cual-quiera sea su posición no debe perder de vista en cómoestimular hoy la generación de nuevas ideas y pro-ductos para el mañana. Recomendamos la lectura de“Adversus Linux”, un buen artículo sobre este temapublicado por dotNetManía [1]. Pero esta cara del

asunto no tiene que ver propiamente con .NET y sesale del marco de este trabajo.

¿Qué aparente razón queda entonces para quererel fuente? Poder hacer modificaciones y adaptacionesal software, reclaman algunos. ¿Pero la solución paraesto es dar el fuente? ¿Y si el programador mete susgarras y cambia lo que no debiera? Un buen diseño, unbuen lenguaje y una buena programación orientada aobjetos es más deseable, aunque no se disponga delfuente, que tener un código fuente críptico e indesci-frable1. Para ser “abierto” a cambios y adaptaciones elsoftware no debe dejar de ser “cerrado”2. .NET es unabuena tecnología para reafirmarnos en este principioque se conoce como “abierto” y “cerrado”.

Sin embargo no todo es alcanzable en .NET. Sin elcódigo fuente, ¿cómo lograr algo tan simple como cam-biarle el nombre a una clase o a un método?, ¿cómo eli-minar de un ensamblado un tipo o un método que se hanvuelto obsoletos?, ¿cómo insertar un tipo en un ensam-blado o cómo fusionar dos tipos en uno?, ¿cómo indicarque un tipo de un ensamblado implementa un tipo inter-face, porque sabemos que tiene esta funcionalidad, si estono se concibió en el diseño y en la compilación original?Y algo más ambicioso: ¿cómo introducir modificacionesen el propio código IL de los métodos?

De momento en .NET no hay soporte para res-ponder a las preguntas anteriores. En el artículo “Copia,Corta y Pega de ensamblados .NET” [4] vimos lo quese podría hacer con el nuevo tipo MethodBody que traeVisual Studio 2005 para tener acceso al código IL de unmétodo y bajo qué limitadas situaciones se podría lograralgo como cambiar el nombre de algunos miembros. Sin

Erick Bacallao

dnm.plataforma.net

¿Necesito el código fuente?

Erick Bacallao yYoelvis ParodiSon estudiantes y programadores

del grupo WEBOO delDepartamento de Ciencia de laComputación de la Universidad

de la Habana.

Miguel KatribEs Dr. y Catedrático del Depar-

tamento de Ciencia de laComputación de la Universidad

de La Habana y jefe del grupoWEBOO.Es un especialista en

lenguajes de programación yentusiasta de la tecnología .NET y

el lenguaje C#.

Miguel Katrib Yoelvis Parodi

1 Como ocurre con algunos códigos en C puro y duro2 Sobre esto escribimos hace tiempo (ver [2,3]), aún antes de la aparición de .NET

Page 31: Visual Basic.NET - Tecnología, Tips de Programación … · ben teniendo el formato de cuaderno técnico, ... olvidamos que el producto de nuestro trabajo no es un fin en sí mismo

embargo, en este mismo trabajo vimos laslimitaciones para lograr el efecto de una“edición” más especializada del ensam-blado. En “El Poder de la Reflexión en.NET” [5] se vio cómo generar dinámi-camente intermediarios (proxy) para lograrel efecto de tratar a un objeto como siimplementara un tipo interface aún cuan-do en el código fuente no se dijo que eltipo del objeto implementa dicha inter-face. En “Aspectos e Intercepción deMétodos en .NET” [6] se vio cómo, uti-lizando atributos y las capacidades deintercepción de llamadas, lograr el efectofuncional de una suerte de “entretejido”de códigos.

En este artículo se presentará el espa-cio de nombres Reflection.Editor en elcual se incluyen los tipos y métodos nece-sarios para programáticamente hacer estas“ediciones” de un ensamblado, sin tenerque disponer del fuente que le dio origeny sin tener que generar intermediarios. Elenfoque aplicado por Reflection.Editorconsiste en hacer una “copia especial enmemoria” de un ensamblado (expresadamediante el tipo EditionAssembly) y sobreesta copia realizar la edición a través deoperaciones como renombrado, elimina-ción, inserción y edición de tipos, y demiembros dentro de un tipo. Cuando esteensamblado en edición se salve hacia unfichero se obtendrá un ensamblado .NETequivalente al original pero con las modi-ficaciones realizadas. Por último, se pre-senta una herramienta visual (IL_Lego)que facilita hacer estas ediciones interac-tivamente.

Edition AssemblyEn el espacio de nombres

Reflection.Editor un EditionAssembly

es una analogía de un AssemblyBuilderdel espacio de nombres System.Reflection y que hace de marco de tra-bajo para producir un ensamblado a par-tir de otro. De tal modo que este nue-vo ensamblado pueda interpretarsecomo si estuviésemos haciendo opera-ciones de edición y modificación sobreel original pero los resultados se vanreflejando en el EditionAssembly. Luegoal salvar este EditionAssembly hacia unfichero, se guardará como un nuevoensamblado que “equivale” a la ediciónque se ha realizado.

El proceso, entonces, es obtener unensamblado ya existente usando losrecursos de la reflexión:

Assembly sourceAssembly =Assembly.LoadFrom("AssemblyA.dll");

Crear un EditionAssembly a partirde éste:

EditionAssembly editingAssembly = new EditionAssembly(sourceAssembly);

El EditionAssembly creado ante-riormente contiene los mismos miem-bros que el ensamblado original. A esteEditionAssembly se le pueden quitar,modificar o añadir miembros.

Finalmente este editingAssemblydebe ser salvado con la operación:

editingAssembly.Save("NewAssemblyA.dll");

Aunque la orientación fundamentalde Reflection.Editor es para obtenerun nuevo ensamblado a partir de unoque existe, también puede comenzar aeditar un ensamblado desde cero, esdecir, no partiendo de ningún ensam-blado original usando la sobrecarga delconstructor:

EditionAssembly newAssembly = new EditionAssembly();

Si no hacemos ninguna operaciónsobre el ensamblado en edición, con elsiguiente patrón podemos hacer fácil-mente una copia o clone de un ensam-blado:

Assembly sourceAssembly = Assembly.LoadFrom("...AssemblyA.dll");

EditionAssembly targetAssembly = new EditionAssembly(sourceAssembly);

targetAssembly.Save("NewAssemblyA.dll");

En elf i c h e r o

NewAssemblyA.dll

queda un ensambladoque tiene lamisma fun-

cionalidad queel que está en el

fichero AssemblyA.dll, esdecir, con la misma fun-

cionalidad que si se hubiesecopiado y luego renombrado el fichero ori-ginal con el explorador de Windows, aun-que no tienen que ser físicamente iguales.

Obtener los módulos de unEditionAssembly

A un EditionAssembly se le puedenpedir los módulos de manera similar acomo esto se hace en la reflexión.

El método:

EditionModule[] GetModules()

Devuelve un array con todos losmódulos que hay en el EditionAssembly.

Edition ModulePara mantener la analogía con el

modelo de ensamblados de .NET y lareflexión en Reflection.Editor se tienetambién el concepto de EditionModule.Recuerde que en .NET un ensambladoestá compuesto por módulos (en generalpor un solo módulo cuando el ensambla-do corresponde a un proyecto generadopor el IDE Visual Studio 2003).

Obtener los tipos de EditionModule

A un EditionModule le podemospedir los tipos que hay en el módulo conel método:

EditionType[] GetTypes()

Este método nos devuelve todos lostipos que estaban en el módulo originalpero transformados hacia EditionTypede forma que puedan ser editados.También nos devuelve los nuevos tiposque se pudieron definir dentro de unEditionModule. El EditionType seráexplicado más adelante.

dotN

etM

anía

<<

31

dnm.plataforma.net<<

Page 32: Visual Basic.NET - Tecnología, Tips de Programación … · ben teniendo el formato de cuaderno técnico, ... olvidamos que el producto de nuestro trabajo no es un fin en sí mismo

De igual forma se puede obtener un tipo específicocontenido en un EditionModule mediante:

EditionType GetType(string typeFullName)

Eliminar un Tipo de un Módulo

Se puede eliminar un tipo de un módulo con elmétodo aplicado al EditionModule correspondiente:

void RemoveType(EditionType t)

O con:

void RemoveType(string typeFullName)

El código del fuente 1 muestra cómo de un ensam-blado A generar un ensamblado NuevoA con los mis-mos miembros que A pero del que se ha eliminado eltipo T porque éste ha quedado obsoleto:

//Posible fuente del ensamblado Anamespace Test{//Tipo obsoleto que se quiere eliminarpublic class T{...

}...

}

Normalmente un desarrollador tendría que dis-poner del código fuente de A para eliminar el tipo Tcon el editor y recompilar entonces el ensamblado.

Definir una Clase en un Módulo

Se pueden adicionar tipos a un EditionModule conel método DefineType que consta de las sobrecargassiguientes:

1.EditionType DefineType(string typeFullName)En este caso, el resto de las especificaciones queintervienen en la definición de una clase (atri-butos, tipo base, etc.) serán puestas por defec-to del mismo modo en que lo hace el compila-dor de C# cuando una clase se escribe classExample{...}.

2.EditionType DefineType(string typeFullName,TypeAttributes attribs)

Igual que en el anterior pero el usuario está especi-ficando atributos para la clase como la visibilidad.

3.EditionType DefineType(string typeFullName,TypeAttributes attribs, Type parentType)

Ídem a 2 pero indicando que la clase hereda deparentType.

4.EditionType DefineType(string typeFullName,TypeAttributes attribs, Type[] interfaceTypes)

Ídem a 2 pero indicando que la clase implementalas interfaces interfaceTypes

5.EditionType DefineType(string typeFullName,TypeAttributes attribs, Type parentType, Type[]

interfaceTypes)

Ídem a 4 pero indicando que la clase además here-da de parentType.

Cada una de estas sobrecargas retorna una ins-tancia de EditionType. Como este EditionType es deri-vado de Type se puede usar entonces a su vez paraincorporarle nuevos miembros durante la edición, opara si luego se quiere definir como tipo de una varia-ble, tipo de retorno de un método o tipo de paráme-tro de un método.

El código del fuente 2 crea, a partir de un ensam-blado A, un nuevo ensamblado NuevoA al que se le haañadido una nueva clase C.

public class C{}

Esta clase ahora es una clase vacía que no tienenada. Más adelante veremos cómo se introducenmiembros dentro de una clase.

Definir un delegado dentro de un Módulo

Para esto contamos con el método:

EditionType DefineDelegate(string delegateFullName, TypeAttributes attributes, ParameterInfo[] parameters, Type returnType)

El primer parámetro es el nombre del delegado,el segundo describe sus atributos (visibilidad), el ter-cero los parámetros y el cuarto su tipo de retorno.

dotN

etM

anía

<<

32

dnm.plataforma.net<<

Assembly a = Assembly.LoadFrom("A.dll");EditionAssembly eAssembly = new EditionAssembly(a);EditionModule eModule = eAssembly.GetModules()[0];eModule.RemoveType("Test.T");eAssembly.Save("NuevoA.dll");

Fuente 1. Eliminar un tipo de un ensamblado

Assembly a = Assembly.LoadFrom("A.dll");EditionAssembly eAssembly = new EditionAssembly(a);EditionModule eModule = eAssembly.GetModules()[0];EditionType tipoC = eModule.DefineType("C",

TypeAttributes.Public);//Posibles acciones para insertar miembros dentro del tipoeAssembly.Save("NuevoA.dll");

Fuente 2. Introducir una clase a un ensamblado

Page 33: Visual Basic.NET - Tecnología, Tips de Programación … · ben teniendo el formato de cuaderno técnico, ... olvidamos que el producto de nuestro trabajo no es un fin en sí mismo

Definir un enum dentro de un Módulo

Para definir un enumerativo se tiene el método:

EditionType DefineEnum(string enumFullName, TypeAttributes attributes, Type enumType)

Sus parámetros son: el nombre que se le va a daral enumerador, los atributos y el tipo sobre el que sebasa el enum (int, long, etc.).

Cómo ponerle los campos a un enum lo veremosmas adelante cuando expliquemos cómo definir unavariable en un EditionType.

Copiar un tipo hacia un Módulo

El método EditionType PasteType(Type typeToPaste)inserta en el módulo en edición a typeToPaste y lo devuel-ve como EditionType de modo que puede ser modifica-do. El código del fuente 3 nos muestra cómo lograr elefecto de "editar" un ensamblado A al que se le han aña-dido todos los tipos que existen en otro ensamblado B.El ensamblado resultante de la edición se salva con elnombre C.

Edition TypeUn EditionType es un tipo del Reflection.Editor

que es derivado de Type y que sirve para representara los tipos que forman parte de un EditionModule (olo que es lo mismo los tipos que forman parte de unensamblado). Los tipos existentes en un módulo enedición se obtienen con los métodos GetTypes y GetTypeque vimos anteriormente.

Los objetos de tipo EditionType son únicos, esdecir, cualquier aplicación por segunda vez de algu-nos de los métodos GetTypes y GetType volverá a darlos mismos objetos (con las modificaciones que sehayan hecho sobre ellos).

El tipo Type tiene las propiedades (properties) Name,Attribute, BaseType de modo que éstas serán hereda-das en EditionType. Sin embargo, en Type son de sólolectura y no tienen parte set en Type3. De modo quepara que en un EditionType se puedan cambiar estaspropiedades se cuenta con los métodos SetName,

SetAttributes, SetBaseType, con los cuales se puedeentonces modificar el nombre de un tipo, los atribu-tos y su clase base. Se introduce además el métodoSetInterfaces para indicar las interfaces que este tipoimplementa. Todos estos cambios quedarán persis-tentes al salvar el ensamblado en edición.

El fuente 4 nos ilustra cómo cambiarle el nombrey la visibilidad a un tipo.

De nombre Test.LinkedList que tenemos compi-lado en un ensamblado Utils.dll y que queremos que-de ahora con nombre Test.ListaEnlazada y en unensamblado con nuevo nombre Utilitarios.dll.

EditionMember

El tipo EditionMember es un tipo interface que emu-la las principales funcionalidades del tipo MemberInfodel System.Reflection. Los tipos EditionMethod,EditionField, EditionProperty, EditionConstructor,EditionEvent y EditionType son implementaciones con-cretas de esta interface y que a su vez derivan de los res-pectivos tipos MethodInfo, FieldInfo, PropertyInfo,ConstructorInfo, EventInfo y Type derivados deMemberInfo en el System.Reflection.

A un EditionMember se le puede consultar el nom-bre con la propiedad Name.

Para modificar el nombre de un miembro se usa elmétodo SetName. Esto no se aplica en el caso de unEditionMember que sea un EditionConstructor ya que losconstructores en .NET tienen el nombre fijo .ctor., demodo que por generalidad el método SetName se ha deja-do en la clase base EditionMember, pero éste es redefini-do en la clase derivada EditionConstructor para que dis-pare una excepción si se intenta usar.

Obtener miembros de un EditionType

El método:

MemberInfo[] GetMembers()

Nos devuelve todos los miembros de un EditionType.Realmente éste es un array de tipos concretos para cadamiembro que heredan de MemberInfo y que a su vez imple-mentan la interface EditionMember. De este modo comoEditionType hereda de Type hay que mantener la mismasignatura de GetMembers en Type y por eso el método está-ticamente se dice que devuelve un MemberInfo[].

dotN

etM

anía

<<

33

dnm.plataforma.net<<

Assembly b = Assembly.LoadFrom("B.dll");Assembly a = Assembly.LoadFrom("A.dll");EditionAssembly eAssembly = new EditionAssembly(a);EditionModule eModule = eAssembly.GetModules()[0];//Recorre los tipos de Bforeach(Type t in b.GetTypes())//inserta los tipos de B en el EditionModule de AeModule.PasteType(t);

//Salva con el nuevo nombre C el ensamblado editadoeAssembly.Save("C.dll");

Fuente 3. Unir dos ensamblados en uno

Assembly a = Assembly.LoadFrom("Utils.dll");EditionAssembly eAssembly = new EditionAssembly(a);EditionType eTypeLinkedList =

eAssembly.GetModules()[0].GetType("Test.LinkedList");eTypeLinkedList.SetAttributes(TypeAttributes.Public);eTypeLinkedList.SetName("ListaEnlazada");eAssembly.Save("Utilitarios.dll");

Fuente 4. Cambiar el nombre y la visibilidad de un tipo

3 En el .NET Framework 2.0 podemos heredar de Type y añadirle parte set a una propiedad.

Page 34: Visual Basic.NET - Tecnología, Tips de Programación … · ben teniendo el formato de cuaderno técnico, ... olvidamos que el producto de nuestro trabajo no es un fin en sí mismo

Por la razón anterior, el método:

MethodInfo[] GetMethods();

Devuelve un array con los MethodInfo de todos losmétodos de un EditionType. Realmente estos MethodInfoson de tipo EditionMethod y por tanto sujetos a ser edi-tados si se le hace el cast correspondiente a EditionMethod.

Por lo mismo, los métodos:

MethodInfo GetMethod(string methodName) yMethodInfo GetMethod(string methodName,

Type[] parameterType)

Devuelven un MethodInfo que realmente dinámi-camente es un EditionMethod (ver en el fuente 5 cómose aplica la operación de cast).

Los siguientes métodos nos permiten obtenermiembros concretos de un EditionType según lasdiferentes categorías GetFields, GetField,GetConstructors, GetConstructor, GetEvents,GetEvent, GetProperties, GetProperty,GetNestedTypes y GetNestedType que devuelven res-pectivamente sus miembros específicos en modoedición.

El código del fuente 5 ilustra cómo pasar al espa-ñol los nombres de todos los métodos del tipoMatemathics que se da a continuación:

namespace Utils{class Mathematics{public static bool IsEven(int k){return ((k%2)==0);

}public static int Factorial(int k){if (k==0) return 1;else return k*Factorial(k-1);

}public static float Square(float x){return x*x;

}}

}

Eliminar un miembro de un EditionType

Mediante el método:

void RemoveMember(EditionMember memberToRemove)

Se puede eliminar cualquier miembro de un tipo.La eliminación de un miembro puede dejar al tipo enestado erróneo (por ejemplo, si se elimina un métodoy hay otros métodos que hacen invocaciones a él). Estecomportamiento no puede ser reportado como error alaplicar este método porque una edición posterior pue-de subsanarlo (por ejemplo, eliminar todos los méto-dos que se referían a éste o sustituir las llamadas a éstepor llamadas a otro método). Desde una herramientacomo IL_Lego, se puede invocar a la aplicaciónPEVerify4 para comprobar la corrección y consistenciade un ensamblado en edición una vez que se haya deci-dido salvar éste hacia un archivo. Por ahora elReflection.Editor no tiene integrada una funcionali-dad similar a la de del PEVerify5 para hacer estas verifi-caciones a la par de la propia edición. De modo que laresponsabilidad de no formar un ensamblado inconsis-tente queda a cargo del programador.

namespace Test{public class T{public void F(){...}...

}}

Análogamente existen los métodosRemoveConstructor, RemoveField, RemoveEvent yRemoveProperty, RemoveType.

Definir un método dentro de un EditionType

Se pueden definir métodos dentro de un tipo enedición. Para definir un nuevo método se dispone delos siguientes métodos:

EditionMethod DefineMethod(string methodName)

Se agrega un método public, void, sin parámetrosy sin funcionalidad (es decir, un método que no hacenada y que tiene como única instrucción un ret):

dotN

etM

anía

<<

34

dnm.plataforma.net<<

Assembly a = Assembly.LoadFrom("Mathematics.dll"); EditionAssembly eAssembly = new EditionAssembly(a);EditionModule eModulo = eAssembly.GetModules()[0];EditionType tipoM = eModule.GetType("Utils.Mathematics");tipoM.SetName("Matematica");((EditionMethod)tipoM.GetMethod("IsEven")).SetName("EsImpar");((EditionMethod)tipoM.GetMethod("Square")).SetName("ElevaAlCuadrado");eAssembly.Save("Matematica.dll");

Fuente 5.Cambiar al español los nombres de los miembros del tipo Mathematics

Assembly a = Assembly.LoadFrom("A.dll");EditionAssembly eAssembly = new EditionAssembly(a);EditionModule eModule = eAssembly.GetModules()[0];EditionType tipoT = eModule.GetType("Test.T");EditionMethod metodoF = (EditionMethod)tipoT.GetMethod("F");tipoT.RemoveMethod(metodoF);eAssembly.Save("NuevoA.dll");

Fuente 6. Eliminarle un método a un tipo

4 PEVerify se distribuye con el .Net Framework SDK5 La implementación de una tal capacidad está en estudio por nuestro grupo.

Page 35: Visual Basic.NET - Tecnología, Tips de Programación … · ben teniendo el formato de cuaderno técnico, ... olvidamos que el producto de nuestro trabajo no es un fin en sí mismo

EditionMethod DefineMethod(string methodName,ILSnippet code)

Igual al caso 1 anterior, pero en estecaso, el parámetro code especifica el códi-go IL que define el cuerpo del método.Para trabajar y hacer modificaciones en elcódigo IL de los métodos se ha definidoel tipo ILSnippet. Un ILSnippet es unasuerte de representación interna del códi-go IL que hace de cuerpo de un método.Reflection.Editorofrece funcionalidadespara inyectar código dentro del cuerpo deun método siguiendo diferentes patronesde entretejido de código. Por razones deespacio este tema no será visto ahora y setratará en un próximo artículo dedotNetManía.

EditionMethod DefineMethod(string methodName, MethodAttributes attr,ILSnippet code)

Igual al anterior pero el parámetroMethodAttributes attr indica las especi-ficaciones de visibilidad del método:

EditionMethod DefineMethod(string methodName,MethodAttributes attr,Type returnType,ILSnippet code)

Igual al caso anterior pero el pará-metro returnType indica el tipo de retor-no del método:

EditionMethod DefineMethod(string methodName, MethodAttributes attr, Type returnType, ParameterInfo[] paramsInfo, ILSnippet code)

Igual al caso 4 pero el array paramsInfonos da los tipos de los parámetros.

Definir una propiedad dentro de unEditionType

EditionProperty DefineProperty(string name, PropertyAttributes,Type propertyType, EditionMethod getMethod, EditionMethod setMethod)

Note que a nivel de ensambladouna propiedad (property) es sólo unaidentificación en los metadatos querelaciona a dos métodos. El parámetrogetMethod hace de parte get y tiene queser un EditionMethod que provenga deun método que sea de la forma T F()

(si el valor de este parámetro es nullsignifica que la propiedad no tiene par-te get). El parámetro setMethod hacede parte set y tiene entonces que pro-venir de un método de la forma voidH(T value) (si es null significa que notiene parte set). Son los lenguajes fuen-tes como C#, VB .NET los que usu-fructúan esa característica para dar unmejor azúcar sintáctico a través de unamejor interfaz.

Definir un constructor dentro de unEditionType

De manera similar a la definición demétodos se tienen los correspondientesmétodos DefineConstructor para defi-nir constructores. Se eliminan de lasobrecarga el parámetro methodName y elparámetro returnType (los constructo-res no tienen nombre ni retornan nin-gún valor).

Definir los parámetros de un método

Para poder formar el arrayParameterInfo[] que se pasa como pará-metro en la definición de un método(indica los parámetros del método) seintroduce el tipo EditionParameter. Estetipo es derivado directo de la claseSystem.Reflection.ParameterInfo, y sebrinda para poder crear instancias direc-tamente de parámetros.

El constructor de EditionParameterqueda entonces:

EditionParameter(string paramName,Type paramType,ParameterAttributes attribs,object constant)

Definir una Variable dentro de unEditionType

Una variable se añade dentro de untipo, para ello se utiliza el método:DefineField. Todas las sobrecargas deDefineField devuelven un EditionField,que hereda de FieldInfo.

EditionField DefineField(string fieldName, Type fieldType)

El primer parámetro es el nombreque la variable va a tener y el segundo eltipo de la variable. En este caso la varia-ble se define pública por defecto:

EditionField DefineField(string fieldName, Type fieldType,FieldAttributes fieldAttr)

Igual al anterior pero el último pará-metro dice los atributos de la variableque se está definiendo:EditionField DefineField(

string fieldName, Type fieldType,F i e l d A t t r i b u t e s

fieldAttr,object constant)

Igual al anterior pero con el últi-mo parámetro se da la posibilidad deasignar un literal a la variable.

Habiendo definido el EditionTypecorrespondiente a un enumerativo por

dotN

etM

anía

<<

35

dnm.plataforma.net<<

Reflection.Editor incluye los tipos y métodos necesarios paraprogramar aplicaciones que puedan hacer "ediciones" de unensamblado, sin tener que disponer del código fuente que le

dio origen y sin tener que generar intermediarios.

Page 36: Visual Basic.NET - Tecnología, Tips de Programación … · ben teniendo el formato de cuaderno técnico, ... olvidamos que el producto de nuestro trabajo no es un fin en sí mismo

medio de un DefineEnum, entonces, usando estosmétodos podemos definir los valores de un enum. Porejemplo, si semana es el EditionType correspondien-te a un enumerativo definido para los días de la sema-na, entonces podemos ponerle valores mediante:

DefineField("Lunes", typeof(int),

FieldAttributes.Public |

FieldAttributes.Literal, 1)

Copiar Miembros hacia un EditionType

Podemos copiar miembros, ya existentes en otroType, hacia dentro de un EditionType:

EditionMember PasteMember(MemberInfo memberToPaste)

El parámetro memberToPaste es de tipoMemberInfo, es decir, puede ser un EditionMemberde un tipo en edición o simplemente un MemberInfodel System.Reflection. Con ello se puede copiarcualquier miembro (método, propiedad, variable,tipo anidado, evento) de un Type (EditionType)hacia un EditionType.

Por lo general, la copia de miembros de un tipohacia otro deberá ir acompañada de la copia de otrosmiembros (porque por lo general un miembro tra-baja ligado a otros). El código del fuente 7 muestrala fusión de dos tipos en uno que correspondería aunir el tipo T1 del ensamblado A1.dll con el tipo T2del ensamblado A2.dll para lograr un equivalente alo que sería el tipo T12.

namespace A1{class T1{int k1;public void F1(){ ...código que usa la variable k1...}string s1;public void H1(){ ...código que usa la variable s1...}//...otros miembros

}}namespace A2{class T2{int k2;public void F2(){ ...código que usa la variable k2...}string s2;public void H2(){ ...código que usa la variable s2...}//...otros miembros

}}

Nuevo tipo fusionado en A2namespace A2{class T12{int k1;public void F1(){ ...código que usa la variable k1...}string s1;public void H1(){ ...código que usa la variable s1...}int k2;public void F2(){ ...código que usa la variable k2...}string s2;public void H2(){ ...código que usa la variable s2...}//...otros miembros

}}

EditionCustomAttribute

La capacidad de poner atributos personaliza-dos (custom attributes) a diferentes recursos en unensamblado es una de las características más rele-vantes de .NET en comparación con otras tecno-logías anteriores de componentes [6]. Como resul-tado de la compilación, la información de los atri-butos que se han escrito en el código fuente que-da de forma persistente dentro de un ensamblado.Luego una aplicación puede consultar estos atri-butos en forma de objetos desde el ensambladomediante la reflexión, pero cualquier modificaciónque se haga sobre estos objetos no vuelve a per-sistir como atributos en el ensamblado.

En cambio, con Reflection.Editor tenemos laposibilidad de editar los atributos de un ensam-blado que tengamos como EditionAssembly y tam-bién podemos colocar nuevos atributos en el mis-mo. Esto sería una opción muy útil para lograr elefecto de “colocar” metainformación que no fueincluida cuando se compiló el código fuente delensamblado.

dotN

etM

anía

<<

36

dnm.plataforma.net<<

Assembly a1 = Assembly.LoadFrom("A1.dll");Assembly a2 = Assembly.LoadFrom("A2.dll");EditionAssembly eAssembly = new EditionAssembly(a2);EditionType tipoT2 = eAssembly.GetModules()[0].GetType("A2.T2");Type tipoT1 = a1.GetType("A1.T1");foreach(MemberInfo mInfo in tipoT1.GetMember()){tipoT2.PasteMember(mInfo);

}tipoT2.SetName("T12");eAssembly.Save("A12.dll");

Fuente 7.Código que realiza la fusión de los tipos T1 y T2 en un tipo T12

Page 37: Visual Basic.NET - Tecnología, Tips de Programación … · ben teniendo el formato de cuaderno técnico, ... olvidamos que el producto de nuestro trabajo no es un fin en sí mismo

El tipo EditionType tiene los méto-dos:

EditionCustomAttribute[]GetCustomAttributes()

EditionCustomAttribute[]GetCustomAttributes(

Type attributeType)

El primero nos devuelve todos losEditionCustomAttributes de los atribu-tos asociados al EditionType, el segun-do sólo retorna aquellos que sean deltipo attributeType. Similarmente se tie-nen estos métodos para el resto de losEditionMember así como paraEditionParameter, EditionModule yEditionAssembly.

En .NET un atributo queda dentrode un ensamblado como la informaciónnecesaria para crear la instancia corres-pondiente de System.Attribute e ini-cializar algunos de sus campos.

En este sentido un Edition

CustomAttribute tiene las propiedadessiguientes:

public ConstructorInfo Constructor { get{...} set{...}}

public object[] ConstructorArgs { get{...} set{...}}

public FieldInfo[] Fields { get{...} set{...}}

public object[] FieldValues { get{...} set{...}}

public PropertyInfo[] Properties { get{...} set{...}}

public object[] PropertyValues { get{...} set{...}}

Mediante las cuales podemos editarun atributo personalizado.

Para la creación de un EditionCustomAttribute tenemos el constructor:

public EditionCustomAttributes(ConstructorInfo constructor, object[] constructorArgs,

PropertyInfo[] properties, object[] propertyValues, FieldInfo[] fields, object[] fieldValues){...}

El parámetro constructor tiene queser el ConstructorInfo que permite cre-ar el atributo, los valores del arrayconstructorArgs tienen que correspon-der a los tipos de los argumentos dedicho constructor. Los valores del arraypropertyValues tienen que correspon-der con las PropertyInfo del array pro-

perties y análogamente fieldValuescon fields.

Una vez que se disponga de unEditionCustomAttribute, se le puedecolocar a una instancia en edición(tipo, método, etc) que correspondaal tipo de destino al que se le quiereponer el atributo.

Podemos añadirle un atributo a unEditionAssembly ya que éste tiene tam-bién el método:

public EditionCustomAttribute AddCustomAttribute(EditionCustomAttribute attribute)

O quitarle un atributo con:

public void RemoveCustomAttribute(EditionCustomAttribute attribute)

De manera similar, existen losmismos métodos para ponerle o qui-tarle atributos a un EditionMember,EditionParameter, EditionModule yEditionAssembly.

El código del fuente 8 le coloca el atri-buto [ModifiedBy(WEBOO)] al tipo Test.Ade un ensamblado.

La herramienta visual IL_Lego

IL_Lego es una herramienta visualque trata de simplificar la aplicación dealgunas de las funcionalidades que ofreceel espacio de nombres Reflection.Editorpara hacer la edición de ensamblados.

La figura 1 nos muestra el resulta-do de abrir el ensamblado mathema-tics.dll en el cual tenemos dos clasesMathematics_I y Mathematics_II. Lafigura 2 nos muestra como se ha cam-biado el nombre de Mathematics_I porMatematica_I y cómo a través de un ins-pector de propiedades se está cambia-do el nombre del método IsEven porEsPar.

La figura 3 muestra cómo se va a cor-tar un método Max de la claseMathematics_II. La figura 4 nos muestracomo queda la clase Matematica_I luegode habérsele pegado el método Max que seha quitado de la clase Mathematis_II, paraluego salvar este ensamblado en el archi-vo utilidades.dll.

dotN

etM

anía

<<

37

dnm.plataforma.net<<

public class ModifiedBy: System.Attribute{

public ModifiedBy(string modifier){}}

static void Main(string[] args){Assembly a = Assembly.LoadFrom("SourceAssembly.dll");EditionAssembly eAssembly = new EditionAssembly(a);EditionCustomAttribute cusAtt = new EditionCustomAttribute(typeof(ModifiedBy).GetConstructors()[0]

, new object[1]{"WEBOO"}, null, null, null, null);eAssembly.GetType("Test.A").AddCustomAttribute(cusAtt);eAssembly.Save("newAssembly");

}

Fuente 8. Poniéndole un atributo a un tipo

Tenemos ahora la posibilidad de editar los atributos que tengamos en un ensamblado y también podemos

colocar nuevos atributos en el mismo

Page 38: Visual Basic.NET - Tecnología, Tips de Programación … · ben teniendo el formato de cuaderno técnico, ... olvidamos que el producto de nuestro trabajo no es un fin en sí mismo

ConclusionesEl espacio de nombres Reflection.Editor satisfa-

ce una necesidad de poder interactuar sobre un ensam-blado, en el mismo estilo en que hacemos introspec-ción con la reflexión, pero pudiendo hacer “cambios”en lo inspeccionado sin necesidad de tener acceso alcódigo fuente. La herramienta IL_Lego desarrolladasobre este espacio de nombres (y puesta a disposiciónde los lectores de dotNetManía) nos permite hacerde modo interactivo esta edición.

En un próximo artículo veremos cómoReflection.Editor nos da también la posibilidad deinsertar y modificar incluso el propio código IL de losmétodos. Con ello se darán las bases para el desarro-llo de herramientas dirigidas a soportar en .NET lasideas de la Programación Orientada a Aspectos y el entre-tejido de código.

AgradecimientosLos autores agradecen a Oscar Luis Vera, Sandro

Vega y Eddy Gonzalo, miembros del grupoWEBOO, por el desarrollo e implementación de laherramienta visual IL_Lego.

dotN

etM

anía

<<

38

dnm.plataforma.net<<

Figura 1.Abriendo un ensamblado para edición

Figura 2. Se le ha cambiado el nombre a la clase Mathematics_Iy se la va a cambiar el nombre al método IsEven

Figura 3 Se va a quitar un método de la clase Mathematics_II

Figura 4 El método se ha copiado en la clase Mathematics_I

Referencias

[1] Quirós Antonio, Adversus Linux, dotNet-manía No 6, España Julio-Agosto 2004

[2]Katrib Miguel, Principio Abierto CerradoC++ vs Eiffel round 1, Soluciones Avanzadas,No 7, México 1994.

[3]Katrib Miguel, Principio Abierto CerradoC++ vs Eiffel round 2 y 3, SolucionesAvanzadas, No 8, México 1994.

[4]

Bacallao Erick, Katrib Miguel, ParodiYoelvis, Copia, corta y pega en ensambla-dos .NET. ¿Hasta dónde se puede llegar conla reflexión en el próximo .NET Framework2.0? dotNetmanía No 11, España Enero2005

[5]Katrib Miguel, del Valle Mario, El poderde la reflexión en .NET, dotNetmanía No 3,España Abril 2004

[6]Hernández Yamil, Katrib Miguel,Aspectos e Intercepción de Métodos en.NET, dotNetmanía No 10, EspañaDiciembre 2004

Page 39: Visual Basic.NET - Tecnología, Tips de Programación … · ben teniendo el formato de cuaderno técnico, ... olvidamos que el producto de nuestro trabajo no es un fin en sí mismo
Page 40: Visual Basic.NET - Tecnología, Tips de Programación … · ben teniendo el formato de cuaderno técnico, ... olvidamos que el producto de nuestro trabajo no es un fin en sí mismo

Refactoring en Visual Studio 2005Creo que todos estaríamos de acuerdo al afirmar que lo difícil del código que desa-rrollamos día tras día,no es que sepa entenderlo nuestra máquina, sino que sepa com-prenderlo un cerebro humano. Pongamos, por ejemplo, el de un pobre compañero alque le ha tocado cambiar ciertas funcionalidades de una aplicación en la que estuvimostrabajando hace tiempo.En una sola frase,podríamos decir que el buen código es aquelque transmite en todo momento lo que está haciendo.

<< todos hemos ido concienciándonos de esto yhan ido surgiendo diversas técnicas o paradigmas,como por ejemplo la AOP (Aspect OrientedProgramming) o la más conocida OOP (Object OrientedProgramming) que entre sus muchas bondades nospermite encapsular y entender el código de forma másnatural para nuestro cerebro.

¿En que consiste la técnica deRefactoring?

La técnica de Refactoring nace con el objetivo demejorar nuestro código, pero no en el sentido de laeficiencia o el rendimiento, sino en simplificarlo omejorarlo haciendo que éste quede más limpio, ele-gante y comprensible para los humanos.

Parece simple, pero todo esto conlleva cambiar unpoco el chip y cierta organización para que, lo que apriori se pretende que sea una mejora, no conviertanuestro código en un caos o en algo que antes fun-cionaba y ahora “por culpa del reafactoring este...”deje de hacerlo.

Programar se convierte entonces en un ciclo comoel que sigue:

1.Codificar.2.Buscar Bad smells o malos olores (lo explicaremos

a continuación).3.Refactorizar.4.Pasar tests de unidad (unit test)para asegurarse que

todo sigue funcionando.

Esta técnica ha encajado muy bien en la llamadaXP (eXtreme Programming) convirtiéndose en uno delos puntos fuertes de este modelo de desarrollo.

También va cogida de la mano de los test de unidad,y casi podríamos decir que obligatoriamente de los test

de unidad automatizados, con herramientas como porejemplo nUnit (si le interesa, puede leer el siguiente artí-culo sobre testeo unitario con nUnit de Rodrigo Corral).

Algunas refactorizaciones son obvias y nos recuer-dan a mejoras que ya hemos hecho muchas veces a lolargo de nuestra vida laboral. Pero la verdadera poten-cia de Refactoring no son las modificaciones en sí delcódigo, sino el hecho de que alguien las haya especi-ficado formalmente y creado un proceso paso a pasopara realizar cada una de ellas. Y, a mi entender, lomás importante es que están surgiendo en el merca-do herramientas automatizadas que es lo que de ver-dad da auge a este tipo de cosas.

Bad SmellsQue traducido al castellano significa “malos olo-

res”, y no, no es que sufra del estómago mientras escri-bo estas líneas. Bad smells digamos que es como uncatálogo de malos olores o “cosas feas” que puedehaber en nuestro código y que nos va a ayudar a sabercuándo hay que refactorizar y qué refactorizaciónescoger en un determinado caso de “mal olor”.

Pongamos, por ejemplo, uno de los bad smells máscomunes que pueden existir en nuestro código: Duplicatedcode. Este consiste en que existe el mismo trozo de códi-go en más de un sitio de nuestro programa. Aunque nofuese el mismo código exactamente línea a línea, al menosrealiza la misma funcionalidad.

En este caso, lo mejor es aplicar una refactoriza-ción que se llama Extract Method y que consiste en lle-varse este código común a un nuevo método y reem-plazar los dos o más trozos de código existentes porsendas llamadas al nuevo método creado.

Esto puede parecer simple y obvio a primera vista,pero puede acarrearnos problemas en un programa de

Fernando Nogueras

dnm.plataforma.net

Con el tiempo,

Fernando Noguerases colaborador habitual dedotNetManía. Es Ingeniero

técnico en informática y MCAD.Es autor de numerosos artículos

y colabora habitualmente enproyectos Open Source.

Page 41: Visual Basic.NET - Tecnología, Tips de Programación … · ben teniendo el formato de cuaderno técnico, ... olvidamos que el producto de nuestro trabajo no es un fin en sí mismo

miles de líneas y dejarnos de funcionardespués de aplicar este cambio.

Otra cosa que no debemos olvidares pasar los procedentes test de unidaduna vez que hemos completado la refac-torización, lo cual nos garantizará quela funcionalidad del programa no se havisto afectada.

Refactoring en Visual Studio2005

En sus primeros tiempos de exis-tencia, Refactoring era una técnica quese tenía que aplicar a mano, es decir, elprogramador identifica el código quequiere modificar, y después de unoscuantos copy, paste, find, replace..., se podíatestear y si todo estaba OK, dar la ope-ración por concluida.

Como es de suponer esto da lugar amuchos errores y quebraderos de cabe-za e incluso puede dar lugar al pensa-miento típico de “para qué me pondríayo a complicarme la vida si mi códigoal fin y al cabo funcionaba bien”.

Afortunadamente, empezaron a salirherramientas que nos ayudaban a reali-zar estos cambios a modo de wizard conlo cual nos sentimos más seguros, aho-rramos tiempo y todo funciona mejor.Esto empezó a ocurrir en el mundo deJava con JRefactory.

Luego salió la plataforma .NET yparece que Microsoft quiere añadir estafuncionalidad a su nueva herramientade desarrollo, Visual Studio 2005.

En Visual Studio 2005 Beta 1 pode-mos acceder a la opción de Refactoringdesde diversos sitios, a saber, desde elmenú contextual del botón derechohaciendo clic encima del código que que-remos aplicar la refactorizacion, o biendesde la opción “Refactor” del menú quenos aparece siempre que tenemos activa-da la zona del editor de código fuente.

En Visual Studio 2005 Beta 1 lasopciones de refactorización que nos apa-recen son las que se muestran en la tabla1 o en la figura 1. En este artículo tra-taremos de hablar de las principales deellas, introduciendo al lector en el mun-do del Refactoring.

Extract MethodComo hemos comentado en la tabla

1, la opción “Extract Method” nos va aproveer una manera de crear un nuevométodo utilizando código existente.

Esta es una de las refactorizacionesmás comunes que podemos utilizar, bienpor separado o bien como parte de unarefactorización más grande.

Pongamos que detectamos en nues-tro código un mal olor, por ejemplo, elllamado Comment, es decir, comentariosen el código. ¿Cómo que comentarios?¿pero es que ahora está mal comentar elcódigo? Pero, ¡si nos han dicho toda lavida que los buenos programadores escri-ben comentarios explicando que hace elcódigo! Pues bien, señores, ya no.

La idea es que, como dijimos al prin-cipio, el código sea autoexplicativo. Estono significa que no podamos poner nin-gun comentario, puesto que hay vecesque tenemos que meter código que nose refiere únicamente al problema denegocio en cuestión. Por ejemplo, vaciarun búfer o hacer alguna reconexión conalgún origen de datos o algo así, y estoes bueno comentarlo explicando por quése hace. Pero, por norma general, la ideaes que antes de poner un comentarioque afecta a una porción de código,antes intentes refactorizar esa porciónde código.

El caso más común es que pongamosun comentario explicando las 5 ó 6 líne-as que vienen a continuación. En ese casolo que se nos aconseja es realizar la refac-torización Extract Method y poner un nom-bre al nuevo método parecido a lo que íba-mos a expresar en nuestro comentario.

En el caso de que nuestros comenta-rios estén en un método existente, expli-cando lo que éste hace, quizás deberíamosplantearnos la refactorización RenameMethod y darle un nuevo nombre más des-criptivo. Esto lo hacemos mediante laopción “Rename”.

O quizás lo que queremos hacer connuestro comentario es establecer algunascondiciones sobre el estado del sistema,entonces lo mejor es la refactorizaciónIntroduce Assertion, que dejo como tareade investigación al lector para no exten-der demasiado este artículo.

Como ejemplo de Extract Methodveamos el código del fuente 1, que loúnico que hace es teniendo un array

dotN

etM

anía

<<

41

dnm.plataforma.net<<

Refactorización Significado

Extract MethodNos permite crear un nuevo método a partir de la porción de códigoseleccionada.

Encapsulate FieldCambia una variable que hemos declarado como public a una propertyde .NET.

Extract Interface Crea una nueva Interfaz basada en los miembros de una clase existente.

Reorder Parameters Reordena argumentos de un miembro.

Remove Parameters Nos ayuda a eliminar argumentos de un miembro.

Rename Facilita la tarea de renombrar un método, propiedad, variable, etc…

Promote LocalVariable to Parameter

Mueve una variable local de un método para convertirla en un pará-metro de dicho método.

Figura 1.Menú Refactoring de VS2005 Beta 1.

Tabla 1. Refactorizaciones en Visual Studio 2005 Beta 1.

public void procesaEmpleados() {double comisionBase = 5000;Empleado empleado;IEnumerator it = empleados.GetEnumerator();

// Actualizamoswhile (it.MoveNext()) {empleado = (Empleado)it.Current;empleado.setSueldo(empleado.getSueldo()+

comisionBase);}

// Imprimimosit.Reset();while (it.MoveNext()) {empleado = (Empleado)it.Current;Console.WriteLine(empleado.ToString());

}}

Fuente 1. Ejemplo de Extract Method.

Page 42: Visual Basic.NET - Tecnología, Tips de Programación … · ben teniendo el formato de cuaderno técnico, ... olvidamos que el producto de nuestro trabajo no es un fin en sí mismo

de empleados, primero lo recorre y actualiza sussueldos, y posteriormente lo vuelve a recorrer paraimprimirlos.

Vamos a aplicar la refactorización citada anterior-mente y sacamos en un nuevo método la parte que sededica a imprimir por pantalla los datos del empleado.

En el fuente 2 vemos el método que nos ha resulta-do después de refactorizar. Vemos cómo el métododevuelve un objeto empleado, cosa que no necesitamospara la función del mismo, ya que lo único que vamos ahacer es imprimir por pantalla y únicamente hemos uti-lizado la variable empleado como almacén temporal paraaclarar el código. Por lo tanto, después de unos peque-ños arreglitos todo quedaría como se ve en el fuente 3.

Vemos como el mismo asistente de refactoriza-ción nos ha generado la llamada al método, junto conlos parámetros que necesita.

Como norma general, el asistente crea el métodoprivate y static, y además es prototipado según elcontexto del mismo. Aunque hay veces que tenemosque retocar alguna cosilla como en este caso, por loque, en mi opinión, sería deseable que en la versióndefinitiva de VS2005 este asistente venga más confi-gurable para moldear el futuro método.

La refactorización Extract Method es muy últil enmuchos casos, más además del citado anteriormente, porejemplo, cuando tenemos el mal olor llamado Long

Method, y que a todos nos ha pasado alguna vez cuandovemos que un método es demasiado largo o realiza dema-siadas tareas y queremos descomponerlo en varios méto-dos que estructuren mejor la funcionalidad.

RenameEsta opción del menú “Refactor” es muy útil, pues

nos permite cambiar el nombre a cualquier método,variable, namespace, parámetro, etc…, sin tener quepreocuparnos de tener que explorar el resto del códi-go en busca de alguna referencia al antiguo nombre,ya que VS2005 va a hacerlo por nosotros y a actuali-zar dicha referencia con el nuevo nombre.

Imaginemos que queremos renombrar el nombre deun método llamado MetodoCualquiera por un nombreun poco más descriptivo. Para ello simplemente tene-mos que seleccionar el nombre del método y luego selec-cionamos la citada opción del menú “Refactor”.

dotN

etM

anía

<<

42

dnm.plataforma.net<<

private static Empleado ImprimirEmpleados(IEnumerator it){

Empleado empleado;// Imprimimosit.Reset();while (it.MoveNext()){

empleado = (Empleado)it.Current;Console.WriteLine(empleado.ToString());

}return empleado;

}

Fuente 2. Método resultante.

Figura 2.Asistente de Extract Method.

public void procesaEmpleados() {double comisionBase = 5000;Empleado empleado;IEnumerator it = empleados.GetEnumerator();

// Actualizamoswhile (it.MoveNext()) {

empleado = (Empleado)it.Current;empleado.setSueldo(empleado.getSueldo()+ comisionBase);

}

ImprimirEmpleados(it);}

private static void ImprimirEmpleados(IEnumerator it){

Empleado empleado;

it.Reset();while (it.MoveNext()){

empleado = (Empleado)it.Current;Console.WriteLine(empleado.ToString());

}return;

}

Fuente 3. Código final.

Figura 3.Asistente de Rename.

Page 43: Visual Basic.NET - Tecnología, Tips de Programación … · ben teniendo el formato de cuaderno técnico, ... olvidamos que el producto de nuestro trabajo no es un fin en sí mismo

No deberíamos olvidarnos de mar-car todas las opciones para que nos hagalos cambios en todas las zonas de nues-tro código.

Extract InterfaceMuchas veces nos encontramos con

que tenemos clases que poseen varios méto-dos en común y que tienen una funciónsimilar o que están relacionados. A veces,dichos métodos representan un compor-tamiento concreto de dichas clases y tienesentido separarlos en una interfaz que des-pués podremos utilizar para referenciar lasclases de una manera genérica.

Podemos ver en la figura 4 un dia-grama UML que nos aclara un poco estasituación.

En este caso, es recomendable cre-ar una nueva interfaz que contenga losmiembros comúnes y luego “decir” queambas clases implementan dicha inter-faz, con ello ganamos en flexibilidad,polimorfismo y además hacemos el códi-go más legible.

Vamos a ver un ejemplo ilustrativo ysu manera de proceder en VS2005.Imaginemos que tenemos las clases de lafigura 5. Está claro que en ambas clases

hay un método comer y otrodormir, que son inherentes a laentidad Persona. Por ello.vamos a crear una interfazIPersona que los contenga yharemos que ambas clasesimplementen la misma.

Vamos a aplicar dicharefactorización a la claseProfesor. Para ello hacemosclic con el botón derechoencima de cualquier lugar deleditor de código y seleccio-namos “Refactor/ExtractInterface…” y nos aparecerá el diálogode la figura 6. Cambiamos el nombre de

la interfaz aIPersona y selec-cionamos losmiembros de laclase que quere-mos incluir en lamisma.

En este mo-mento ya tene-mos nuestra in-terfaz creada yademás, nuestra

clase Profesor ya imple-menta la misma.

El problema es queVS2005, hasta el momento,en su version Beta1 nosoporta el hecho de quepodamos seleccionar dos ovarias clases y a partir de ahísacar una interfaz en común,con lo cual tenemos queintroducir a mano el hechode que la clase Alumno imple-

mente IPersona. El diagrama de clasesresultante quedaría como aparece en lafigura 7.

ConclusiónPara empezar, y esto es un opinión

personal, creo que es una maravilla queMicrosoft apueste por estas técnicasmodernas de desarrollo, que en el mun-do Java ya llevan varios años de ventajapero que antes de la aparición de la pla-taforma .NET se nos caía la baba a losprogramadores de Visual Basic y pare-cía como algo restringido sólo a la gen-te que trabajaba con Java.

ReferenciasPara empe-

zar, si queréisprofundizar enRefactoring, esde obligada lec-tura el libro“ R e f a c t o r i n g :Improving theDesign ofExisting Code”

(Addison Wesley, 1999) de MartinFowler, que es el padre del refacto-ring. Ahí se explican todas y cada unade las refactorizaciones a nivel teóri-co. Mientras compras el libro puedesir visitando la página www.refacto-ring.com.

También son interesantes:- www.refactoring.be, muy buena, con

explicaciones gráficas.- http :// c2. com/cgi/wiki?WhatIs

Refactoring- http://www.industriallogic.com/xp/

refactoring, interesante libro.

dotN

etM

anía

<<

43

dnm.plataforma.net<<

Figura 4. Diagrama UML de Extract Interface.

Figura 5. Clases de ejemplo.

Figura 6.Asistente de Extract Interface.

Figura 7. Resultado final al aplicar EstractInterface.

Page 44: Visual Basic.NET - Tecnología, Tips de Programación … · ben teniendo el formato de cuaderno técnico, ... olvidamos que el producto de nuestro trabajo no es un fin en sí mismo

Testeo unitario con NUnitSin duda el testeo unitario es una de las técnicas relacionadas con la calidad del soft-ware que mayores beneficios aporta al proceso de desarrollo.Aunque es una técnicaclásica, en los últimos tiempos se ha popularizado de la mano de las metodologías ági-les de desarrollo de software y gracias a la aparición de herramientas que facilitan laescritura, ejecución e integración de los test en el proceso de desarrollo.

<<¿Qué es el testeo unitario? A mi me gusta defi-

nir el testeo unitario como escribir código que ponea prueba otro código de manera que podamos rea-lizar pruebas de forma automatizada. Un test deunidad es código que comprueba que el comporta-miento de otro código es acorde a las especifica-ciones. Los test de unidad deben centrarse en pro-bar que el código se ejecuta sin errores inespera-dos, que el código es seguro, que el rendimientodel código es correcto y que el código se compor-ta de acuerdo a las especificaciones del software queestamos construyendo.

Las ventajas de utilizar testeo unitario en nuestroproceso de desarrollo son muchas, de hecho son tantasque si tuviese que elegir una única técnica relacionadacon la calidad del software que llevar a cabo en mis pro-yectos, ésta sería el testeo unitario. Entre las múltiplesventajas cabe citar:

• Escribir test de unidad obliga a tener en cuenta lacalidad: La calidad de software es lo primero que tira-mos por la ventana los desarrolladores cuando esta-mos apurados de tiempo (que es siempre), abando-nar la preocupación por la calidad parece una ganan-cia de tiempo, pero sólo lo es corto plazo. Si estamosobligados a escribir test de unidad, nunca nos olvi-daremos de la calidad.

• Escribir test de unidad ayuda a mantener la calidad:Es mucho menos costoso mantener la calidad delsoftware, que una vez que ésta se ha degradado, vol-ver a parámetros aceptables de calidad. Los tests uni-tarios ayudan a mantener la calidad por que permi-ten en cualquier momento comprobar de manerarápida y fácil que el código sigue comportándose deacuerdo a la especificaciones, y que el nuevo códigoañadido al sistema no ha estropeado el comporta-miento del antiguo.

• El testeo unitario ayuda a soportar otras buenas prác-ticas de desarrollo, como las construcciones diariasy los tests de humo: Construyendo a diario nuestrosistema y realizando “test de humo” (probar lo esen-cial del software una vez construido cada día) ase-guramos que los problemas de integración se corri-gen pronto. Si antes de realizar el test de humo, pasa-mos los tests unitarios, aseguramos que podremoshacer unas mínimas pruebas del sistema. La inte-gración continua es mucho más sencilla si tenemostests unitarios.

• El testo unitario permite mejorar nuestra base decódigo sin temor a que éste deje de funcionar: Amenudo los desarrolladores evitamos mejorar códi-go para hacerlo más eficiente o más legible por eltemor a introducir errores (“si funciona no lotoques”), si tenemos tests de unidad para el códigoque pretendemos mejorar, esto asegurara que su com-portamiento seguirá siendo el correcto.

• Los tests de unidad detectan tempranamente pro-blemas de rendimiento: Es habitual que en ocasio-nes nuevo código degrade de manera significativa elrendimiento de nuestro software por errores de pro-gramación o incluso de arquitectura. Una batería detest que ayer tardaba en ejecutarse dos minutos y hoytarda quince minutos puede ponernos en la pista deque algo pasa con el código añadido al sistema.

• Los tests de unidad documentan el sistema: A menu-do es mucho más fácil deducir cuáles son las res-ponsabilidades de una clase observando sus test deunidad que leyendo su código fuente.

• Los tests de unidad facilitan la portabilidad del soft-ware: Una vez portado el software a la nueva plata-forma, es sencillo comprobar que el comportamientoes el correcto ejecutando las baterías de test.

• Los tests de unidad incrementan la modularidad y

Rodrigo Corral

dnm.arquitectura

Testeo unitario

Rodrigo Corralcolabora habitualmente con

dotNetManía. Es Microsoft MVPy analista de Sisteplant, empresa

líder en el sector de lasaplicaciones de gestión industrial

Page 45: Visual Basic.NET - Tecnología, Tips de Programación … · ben teniendo el formato de cuaderno técnico, ... olvidamos que el producto de nuestro trabajo no es un fin en sí mismo

evitan el acoplamiento: Los tests prue-ban unidades (clases, librerías, com-ponentes, etc.) y para que sea sencilloescribir test y ejecutarles, las clasesdeben ser lo más autónomas posible,de manera que no sea necesario mon-tar una compleja infraestructura paracorrer el test de una determinada uni-dad.

• Los tests de unidad ayudan a mejorarel soporte al usuario: A menudo es unabuena táctica enviar al usuario unabatería de test para diagnosticar unproblema; es fácil utilizar los tests deunidad como una herramienta dediagnóstico. Esta técnica funcionaespecialmente bien si se tiene la disci-plina de escribir un test de unidad queasegure la corrección de errores ante-riormente reportados por los usuarios.Es condición necesaria que los testsde unidad, una vez terminada su eje-cución, dejen el sistema en el estadoen el que se encontraba.

Como véis, existen motivos más quesuficientes para escribir test de unidad,aún así, el principal inconveniente con elque me he encontrado a la hora de utili-zar testeo unitario en los proyectos enlos que he participado, es la reticenciapor parte de los miembros del equipo dedesarrollo. En principio, el uso de test deunidad se ve como “escribir el doble decódigo”, el hecho es que sí suponen escri-bir algo más de código, pero nunca eldoble. Estimo que el tamaño del códigode testeo rara vez es más del 20% deltamaño del código a probar, y ya hemosvisto las importantes ventajas de ese códi-go adicional. También tengo que decirque una vez vencida esa reticencia ini-cial, en algunos casos muy fuerte, nuncanadie ha propuesto abandonar la escri-tura de test de unidad. Por lo que con-cluyo que las reticencias iniciales siem-pre se deben a la ignorancia de las ven-tajas que esta técnica aporta.

Testeo unitario en .NET conNUnit

Ya he comentado que uno de los fac-tores que han popularizado la adopciónde los tests de unidad es la aparición deframeworks y herramientas que permitenescribirlos y ejecutarlos. En el caso de la

dotN

etM

anía

<<

45

dnm.arqutiectura<<

using System;

namespace TesteoUnitario{

/// <summary>/// Clase simple que representa una cuenta corriente/// </summary>public class CuentaCorriente{

private uint _Id;public CuentaCorriente(uint Id){_Id = Id;

}

/// <summary>/// Devuelve el identificador de la cuenta/// </summary>public uint Id{get { return _Id; }

}

private int _Saldo;

/// <summary>/// Devuelve el saldo de la cuenta/// </summary>public int Saldo{get { return _Saldo; }

}

/// <summary>/// Incrementa el saldo de la cuenta/// </summary>/// <param name=”cantidad”>Cantidad en la que se incrementa el saldo</param>public void RealizarAbono(int cantidad){_Saldo += cantidad;

}

/// <summary>/// Decrementa el saldo de la cuenta/// </summary>/// <param name=”cantidad”>Cantidad en la que se decrementa el saldo</param>public void RealizarCargo(int cantidad){_Saldo -= cantidad;

}

/// <summary>/// Realiza una tranferencia desde la propia cuenta/// </summary>/// <param name=”cantidad”>Cantidad a trasferir</param>/// <param name=”destino”>Cuenta de destino</param>public void RealizarTransferencia(int cantidad, CuentaCorriente destino){if (this.Id == destino.Id)

throw new ApplicationException(“No se pueden realizar tranferencias sobre la misma cuenta”);

this.RealizarCargo(cantidad);destino.RealizarAbono(cantidad);

}}

}

Fuente 1.

Page 46: Visual Basic.NET - Tecnología, Tips de Programación … · ben teniendo el formato de cuaderno técnico, ... olvidamos que el producto de nuestro trabajo no es un fin en sí mismo

plataforma .NET, la herramienta por excelencia esNUnit. Esta herramienta, utilizando características avan-zadas de .NET como atributos y reflexión, ha converti-do el escribir y ejecutar test de unidad en un tarea sim-ple. Podemos descargar NUnit desde www.nunit.org. Suinstalación es muy simple.

Una vez instalado NUnit tenemos a nuestra dispo-sición una serie de librerías que nos permitirán escribirtest unitarios de una manera simple y elegante.

Escribir un test unitarioVamos a crear una simple clase que representa una

cuenta bancaria. No es un ejemplo muy original ya losé, pero sí que es uno útil y simple. Esta clase presentalos siguientes miembros:

• Una propiedad Saldo que devuelve el saldo de lacuenta.

• Una propiedad Id que devuelve el identificador dela cuenta. Se establece en el constructor.

• Un método RealizarAbono que añade una canti-dad al saldo de la cuenta.

• Un método RealizarCargo que quita una cantidadal saldo de la cuenta.

• Un método RealizarTransferencia que transfiereuna cantidad a otra cuenta. Este método lanzará unaexcepción cuando intentemos realizar una transfe-rencia que tenga como destino la propia cuenta.

El código de esta clase es el del fuente 1.Conocidos estos datos, ya podríamos saber qué

puntos debería comprobar un test de unidad que com-probase el correcto funcionamiento de esta clase:

• Que RealizarAbono incrementa el saldo en el valorcorrecto.

• Que RealizarCargo decrementa el saldo en valorcorrecto.

• Que RealizarTransferencia disminuye el saldo dela cuenta origen y aumenta el de la cuenta desti-no y que el balance permanece correcto.

• Que RealizarTransferencia lanza una excepciónsi la cuenta de origen es la misma que la destino.

Empezaremos creando una nueva librería de clasesque contendrá nuestros tests de unidad y añadiendo unareferencia a la librería de test de NUnit, NUnit.Frameworklo que pondrá a nuestra disposición los atributos que uti-liza NUnit para distinguir los conjuntos de test y cadatest unitario, así como las clases que nos permiten com-probar el adecuado funcionamiento de nuestro código.Las clases y atributos que utilizaremos para escribir testde unidad se encuentran en el espacio de nombresNUnit.Framework.

El atributo TestFixtureAttribute nos permite mar-car una clase como contenedor de un conjunto de testde unidad. Cada uno de los tests de unidad se imple-menta como un método de esa clase y se identifica

mediante el atributo TestAttribute. Estos atributospermiten a NUnit detectar los tests y ejecutarlos.

NUnit marcará como test fallido todo test del quereciba una excepción, siempre y cuando el propio testno la controle. Si queremos comprobar que bajo ciertascondiciones un método lanza una determinada excep-ción (por ejemplo el método RealizarTransferenciacuando se especifica la propia cuenta como destino) tene-mos que utilizar el atributo ExpectedExceptionAttribute,especificando como parámetro del mismo el tipo de laexcepción esperada.

Los tests de unidad no sólo están orientados a queno se produzcan excepciones o que éstas sean con-troladas o esperadas, además deben asegurar el buenfuncionamiento de nuestra clase en el sentido de querealice el trabajo para el que está diseñada (por ejem-

dotN

etM

anía

<<

46

dnm.arquitectura<<

using System;using NUnit.Framework;

namespace TesteoUnitario{

/// <summary>/// Tests de la clase cuenta corriente/// </summary>[TestFixture]public class CuentaCorrienteTest{

/// <summary>/// Test del método RealizarAbono/// </summary>[Test]public void RalizarAbonoTest(){/* Código que prueba el método RealizarAbono */}

}}

Fuente 2. Ejemplo de cómo se usan los atributos para definir un test

using System;using NUnit.Framework;

namespace TesteoUnitario{

/// <summary>/// Tests de la clase cuenta corriente/// </summary>[TestFixture]public class CuentaCorrienteTest{

[Test][ExpectedException(typeof(ApplicationException))]public void RealizarTransferencia(){

/*Código que prueba el método RealizarTransferencia*/}

}}

Fuente 3. Ejemplo de ExpectedExceptionAttribute

Page 47: Visual Basic.NET - Tecnología, Tips de Programación … · ben teniendo el formato de cuaderno técnico, ... olvidamos que el producto de nuestro trabajo no es un fin en sí mismo

plo, que el método RealizarCargo disminuya el saldode la cuenta en la cantidad especificada). La claseAssert de NUnit proporciona una serie de métodosque permiten escribir comprobaciones de ese tipo, verla tabla 1, “Métodos de la clase Assert”.

Existen además otros atributos que nos permitenagrupar conceptualmente tests o incluso especificarcódigo que se ejecute antes (por ejemplo, para prepa-rar el entorno para la realización de los tests) o des-pués de un grupo de tests (típicamente utilizado paradevolver el entorno a su estado inicial), ver la tabla 2,“Atributos de NUnit”.

Cómo organizar nuestros tests

Voy a comentar aquí cómo acostumbro a organi-zar los tests unitarios de los proyectos en los que tra-bajo. Supongo que existirán otras formas de hacerloy que algunas incluso sean mejores, no lo sé, pero loque si sé es que ésta me es cómoda.

La técnica que utilizo consiste en generar porcada assembly, un assembly paralelo que contienelos tests unitarios. Es decir, si tengo un assembly lla-mado, MyAssembly genero otro llamado MyAssembly.Test y ambos los añado a la misma solución. Paracada una de las clases contenidas en MyAssembly, lla-mémosla MyClass, y supongamos que está conteni-da en el namespace MyAssembly.MyNamespace, gene-ró una clase paralela en MyAssembly.Test, con nom-bre MyClassTest y ubicada en el namespaceMyAsembly.MyNamepace.Test.

Siguiendo estas pequeñas reglas me es sumamen-te fácil encontrar los tests de una clase y clase a la quecorresponde un determinado test.

A la hora de nombrar las funciones que imple-menta un test de una función, simplemente nom-bro la función que realiza el test como la función atestear, seguida del subfijo test; así para la funciónMyFunction el test se llamará MyFunctionTest. En

dotN

etM

anía

<<

47

dnm.arqutiectura<<

Tabla 1. Metodos de la clase Assert

Método Descripción

AreEqual

Verifica que dos valores numéricos o dos objetos soniguales. Los objetos se comparan utilizando su méto-do Equals. Si son diferentes lanza una excepciónAssertionException.

AreSameVerifica que dos objetos son referencias al mis-mo objeto. Si no lo son, lanza una excepciónAssertionException.

FailLanza una excepción AssertionException con elmensaje que le pasamos. Generalmente no se usade manera directa.

IsFalseComprueba que una condición es falsa. Si la condición es verdadera lanza una excepciónAssertionException.

IsTrueComprueba que una condición es verdadera. Sila condición es falsa, lanza una excepciónAssertionException.

IsNotNullComprueba que un objeto no es nulo. Si el objeto esnulo, lanza una excepción AssertionException.

IsNullComprueba que un objeto es nulo. Si el objeto no esnulo, lanza una excepción AssertionException.

/// <summary>/// Test del método RealizarAbono/// </summary>[Test]public void RalizarAbonoTest(){

CuentaCorriente cc = new CuentaCorriente(1);int saldoInicial = cc.Saldo;/*Realizamos un abono*/const int cantidad = 1000;cc.RealizarAbono(catidad);/*Comprobamos que el saldo se ha incrementado*/Assert.IsTrue(cc.Saldo == saldoInicial + cantidad,

"No se realizo correctamente el abono");}

Fuente 4. Ejemplo de cómo se utiliza la clase Assert

Tabla 2.Atributos de NUnit

Atributo Descripción

TestFixtureAttributeEs el atributo con el que se marcan aquellasclases que contienen un conjunto de tests.

TestAttribute

Este atributo se aplica a aquellos método deuna clase marcada con el atributoTestFixtureAttribute para indicar que elmétodo es un test unitario. El método debeser público y devolver void.

TestFixtureSetUpAttribute

Este atributo marca una función de la claseque implementa el conjunto de tests demanera que será ejecutada previamente a lostests del conjunto.

TestFixtureTearDownAttribute

Este atributo marca una función de la claseque implementa el conjunto de tests de mane-ra que será ejecutada posteriormente a los testsdel conjunto.

IgnoreAttributePodemos aplicar este atributo a un test deter-minado para evitar, de manera provisional, quesea ejecutado al correr los tests.

CategoryPermite agrupar en categorías tests que esténrelacionados entre sí.

ExpectedExceptionAttribute

Este atributo permite especificar que un deter-minado test debe lanzar una excepción de undeterminado tipo para que el test se conside-re como pasado.

Page 48: Visual Basic.NET - Tecnología, Tips de Programación … · ben teniendo el formato de cuaderno técnico, ... olvidamos que el producto de nuestro trabajo no es un fin en sí mismo

bastantes ocasiones, una única funciónno es suficiente para probar a fondouna función de una clase; en esos casosañado un número correlativo a la fun-ción de prueba, MyFucntionTest1,MyFucntionTest2,...

A veces es conveniente asociar testscon bugs, para asegurar que estos no sevuelven a introducir en el código. Si tusistema de bug tracking es capaz de hacerlos bugs accesibles mediante una URL, esuna buena práctica poner ésta en la sec-ción <remarks>de la documentación XMLdel método de prueba, si no, añadir unsufijo al nombre de la función que iden-tifique el bug, MyFunctionTestBug123.También puede ser útil utilizar ambas téc-nicas a la vez.

Por último, recordar que las clasesque implementan los tests siguen sien-do clases, y que por tanto, permiten usartodas las técnicas de la programaciónorientada a objetos, como la herenciapara reutilizar funcionalidad de un testen otro.

Cómo correr y depurar nues-tros tests

Una vez construidos nuestros teststenemos que poder correrlos. Para elloNUnit provee dos herramientas quepermiten cargar y correr tests, Nunit-console, que como su nombre indicaes una aplicación en consola y Nunit-gui que es una aplicación de ventana.Nunit-console es muy útil para auto-matizar e integrar la ejecución de lostests en el proceso de construcción denuestro proyecto.

Aquí me centraré enNunit-gui. Para correrun test unitario conNunit-gui simplementetenemos que cargarloutilizando la opción“Open” del menú“File”, y seleccionandoel assembly que contie-ne los tests. Hemos deasegurarnos de que esteassembly tiene accesibleel assembly que contie-ne la clases a probar, loque básicamente impli-ca que ambos estén enel mismo directorio.

Una vez hecho esto,un árbol muestra lostests que tenemos dis-ponibles, y podemos uti-lizar [F5] para iniciarlos.Una vez los tests hanterminado, NUnit pre-sentará los resultados delos mismos mediante uncódigo de colores.

Los tests que hayan fallado, apa-recerán en rojo y podremos obtenermás información sobre el fallo en elpanel de la derecha haciendo clic sobrelos mismos en el árbol.

Podemos utilizar NUnit para depu-rar los tests y las clases que los tests prue-ban. Para ello simplemente deberemos,antes de iniciar los tests, y con ellos car-gados, asociar el depurar al proceso Nunit-gui.exe, teniendo la solución que contie-ne las clases y sus tests cargada. Una vezhecho esto, cualquier punto de rupturaque pongamos en las clases o los tests seráreconocido por el depurador.

El futuro, testeo unitario enVisual Studio 2005

Parece que Microsoft también a des-cubierto la importancia del testeo unita-rio y, a partir de la nueva versión de VisualStudio, el testeo unitario va a estar total-mente integrado dentro de esta herra-mienta de desarrollo.

Contaremos con nuevos tipos de pro-yecto y plantillas de clase orientadas aescribir test y además podremos correrestos tests sin salir del entorno. Esta posi-bilidad en Visual Studio 2003 existe gra-cias a addins como TestDriven.Net(http://sourceforge.net/projects/nunitaddin).

Además parece ser que se van a poderimportar los tests escritospara NUnit, y que estosserán convertidos demanera automática a testde Visual Studio.

Entre los diferentestipos de tests con los quecontaremos en VisualStudio 2005 se encentranlos tests unitarios, tests decarga o tests de Web, ade-más de plantillas para des-cribir tests a realizarmanualmente.

dotN

etM

anía

<<

48

dnm.arquitectura<<

Page 49: Visual Basic.NET - Tecnología, Tips de Programación … · ben teniendo el formato de cuaderno técnico, ... olvidamos que el producto de nuestro trabajo no es un fin en sí mismo

dotN

etM

anía

<<

49

es la “copa de la imagina-ción”, un concurso universitario quepremia a los proyectos más imaginati-vos y talentosos realizados bajo la pla-taforma .NET.

Éste es un concurso internacionaldonde participan universidades de 100países y un total de 10.000 estudiantes.Los premios de la gran final son 25.000,15.000 y 10.000 dólares para primer,segundo y tercer equipo clasificado, res-pectivamente.

Acabamos de asistir a la final españo-la que nos ha dado el proyecto que seránuestro representante en la final deYokohama (Japón) a finales de julio: laUniversidad de Deusto, con el equipo for-mado por Daniel García Gómez, IvánGarcía Cossío y Javier FernándezGonzález, que participarán con el pro-yecto Environment Mobile IntelligentInteraction (EMI²).

EMI² es una plataforma que permi-tirá a los creadores de programas infor-máticos poner en práctica de forma sen-cilla y segura diversas aplicaciones, talescomo servicios de subtítulos y traduc-ciones, información sobre horarios deautobuses, pago de parquímetros a tra-vés de dispositivos móviles, etc.

La plataforma dispone de una serie deherramientas de ayuda, basadas en ele-mentos gráficos, que facilitan a los dise-ñadores de programas la creación y eje-cución de las diferentes aplicaciones. Lassoluciones pueden ser ejecutadas tanto endispositivos móviles (Pocket PC,Smartphone, Tablet PC y PCs portátiles),como en ordenadores de sobremesa.

EMI² fue elegido por un jurado deuniversitarios, periodistas y personal deMicrosoft, después de una dura pugna

entre otros cuatro proyectos más quellegaron a la final con un nivel realmentebueno.

Proyectos finalistasEl segundo premio fue a parar al

excelente SmartMarkt de la UniversidadPontificia de Salamanca (Campus deMadrid) del equipo compuesto porCarlos Delgado Brillas, CarlosFernández de la Reguera Mantilla yMiguel Muñoz Royo.

SmartMarkt supone una apuesta tec-nológica que busca poner fin a las colasde espera en los supermercados y otrasgrandes superficies, así como gestionarun sistema de ofertas a clientes total-mente personalizado.

A través de un dispositivo móvil ygracias a las posibilidades de la tec-nología Wi-Fi, el usuario puede rea-lizar sus compras mientras recibeinformación sobre los diferentes pro-ductos, realiza pagos vía serviciosWeb, etc. Al mismo tiempo, los res-ponsables del establecimiento man-

tienen actualizada subase de datos con histo-riales sobre clientes ystock de productos.

El tercer puesto fue arecaer en el proyecto BonAppétit de la Universidadde Sevilla, con el equipocompuesto por MiguelÁngel Ramos Barroso yJuan María Leó Ramos.

Bon Appétit trata deevitar los problemas desalud debidos a unamala alimentación y al

considerable aumento de la poblaciónalérgica a distintos alimentos. Este sis-tema aconseja al usuario sobre aque-llos alimentos que debe tomar, en fun-ción de los síntomas y dolencias quepadezca.

Uno de los grandes atractivos de lasolución es que dispone de un sistema pro-pio de búsqueda online que nos permiti-rá acceder a un amplio rango de recetas,información sobre los ingredientes quecomponen diferentes platos, etc. Todo elloa través de un dispositivo Pocket PC, lige-ro y fácil de utilizar, del que podremoshacer uso durante nuestros viajes y des-plazamientos.

Los otros dos finalistas fueronMercaFácil de la Universidad de Oviedopor Carlos García Gutiérrez, Dae SungKim Park y Rafael del RiegoFernández-Nespral y OneWeek de laUniversidad de Sevilla por DavidGutiérrez de Solana Torres, JavierCantón Ferrero, Jorge Cantón Ferreroy Javier Fernández Rodríguez.

La información completa puedeencontrarla en www.dotnetmania.com.

Final de la Imagine Cup 2005 en EspañaEl proyecto EMI², de la Universidad de Deusto, ganador de la final

española de la copa Imagine Cup 2005 de Microsoft

<< Imagine Cup

Los creadores de EMI2, ganadores de la edición de este año

dnm.universidad.net

Page 50: Visual Basic.NET - Tecnología, Tips de Programación … · ben teniendo el formato de cuaderno técnico, ... olvidamos que el producto de nuestro trabajo no es un fin en sí mismo

IMPORTES VÁLIDOS HASTA NUEVA OFERTA

DATOS DE FACTURACIÓN

CIF/NIF . . . . . . . . . . . . . . . . . . . . .Empresa . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Nombre y apellidos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Dirección . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Población . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Código Postal . . . . . . . . . . . . . . . . . . . Provincia . . . . . . . . . . . . . . . . . . . . . . . . .Teléfono . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Fax . . . . . . . . . . . . . . . . . . . . . . . . . . . email . . . . . . . . . . . . . . . . . . . . . . . . . . . .

DATOS DE ENVÍO (sólo si son distintos de los datos de facturación)

CIF/NIF . . . . . . . . . . . . . . . . . . . . .Empresa . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Nombre y apellidos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Dirección . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Población . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Código Postal . . . . . . . . . . . . . . . . . . . Provincia . . . . . . . . . . . . . . . . . . . . . . . . .Teléfono . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Fax . . . . . . . . . . . . . . . . . . . . . . . . . . . email . . . . . . . . . . . . . . . . . . . . . . . . . . . .

FORMA DE PAGO

❑ Talón nominativo a nombre NETALIA, S.L.❑ Transferencia bancaria a nombre de NETALIA, S.L. a:

La Caixa - Número de cuenta 2100 4315 48 2200014696 (Indique su nombre en la transferencia)

❑ Domiciliación Bancaria (con renovación automática, previo aviso)Indique su número de cuenta:

❑ Tarjeta de crédito❑ VISA ❑ MASTERCARDNúmero de su tarjeta: Fecha de caducidad: / (imprescindible)

Firma y/o sello

a de de 200

Suscripción a dotNetManía

Usted autoriza a la mecanizaciónde estos datos. El responsable ydestinatario de éstos es Netalia,S.L. Usted tiene derecho a acce-der a sus datos, modificarlos ycancelarlos cuando lo desee. Susdatos no serán cedidos en nin-guna de las formas posibles a ter-ceras partes y no se utilizaránmás que para el buen funciona-miento de su suscripción a larevista dotNetManía y parainformarle de las actividadescomerciales que realice la edito-rial Netalia, S.L. Si no desearecibir información comercial dedotNetManía marque la casillasiguiente ❑

❑ Nº9 ❑ Nº11 ❑ Nº12

Puede enviar los datos al email [email protected],al FAX (34) 91 499 13 64 o al teléfono (34) 91 666 74 77.

También puede enviarlo por correo postal a la siguiente dirección:

Netalia, S.LC/ Robledal, 13528529 - Rivas VaciamadridMadrid (España)

❑ Deseo suscribirme a dotNetManía por un año (11 ejemplares) y beneficiarme de la oferta del 10% dedescuento por un importe total de 60 € para España; o por 120€ para el resto del mundo (envío poravión) (IVA incluido).

❑ Nº13 ❑ Nº14❑ Nº8

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

❑ Nº10

Page 51: Visual Basic.NET - Tecnología, Tips de Programación … · ben teniendo el formato de cuaderno técnico, ... olvidamos que el producto de nuestro trabajo no es un fin en sí mismo
Page 52: Visual Basic.NET - Tecnología, Tips de Programación … · ben teniendo el formato de cuaderno técnico, ... olvidamos que el producto de nuestro trabajo no es un fin en sí mismo

una materia unívoca. Dos opciones opues-tas pueden ser, ambas, válidas, dependiendo del contex-to, y unos pocos detalles que marcan la diferencia. Sinembargo, esos –así llamados– pequeños detalles, puedenser importantes para el éxito de la aplicación y no pode-mos dejarlos al azar.

En este artículo, responderé a algunas preguntas rela-cionadas con elecciones difíciles de tomar que me hanpasado los lectores. Permítaseme decir, ante todo, que,probablemente, no pueda encontrar una respuesta defi-nitiva para todas las preguntas que siguen. E, incluso sipudiera, algunos de ustedes podrían razonablementeestar en desacuerdo o mostrar un brillante contra-ejem-plo. De forma que, en definitiva, ¿cuál es el propósito deestas respuestas? Simplemente, aclarar los conceptos,arrojar algo de luz, ilustrar los conceptos de fondo, ydejarle la libertad de tomar las decisiones difíciles, perocon un poco más de información. Comencemos con unejemplo clásico de decisiones difíciles.

A la hora de crear una jerarquía de componentes,¿debería decidirme por clases base o por interfaces?

¿Qué es una interfaz? Una interfaz es una colecciónde miembros relacionados lógicamente y agrupados bajoun único nombre. Colectivamente, una interfaz se refie-re a cierta funcionalidad y comportamiento. Nos refe-rimos a menudo a los interfaces como a contratos. Enrealidad, la interfaz no es un contrato en sí, sino el pro-pósito del acuerdo. Una vez que la otra parte acuerdaeso, se establece un contrato entre la clase que llama yla que es llamada. Una interfaz no es una clase. No con-tiene código y sólo permite la definición de algunosmiembros: propiedades, métodos y eventos. Como ejem-plo, consideremos la interfaz ICollection:

public interface ICollection : IEnumerable {

void CopyTo(Array array, int index);

int Count { get; }bool IsSynchronized { get; }object SyncRoot { get; }

}

La sintaxis es similar a la de una clase, excepto que nose especifica ningún código. También existe algún tipo deherencia para las interfaces, tal y como demuestra el códi-go fuente anterior. Una interfaz puede heredar las “cláu-sulas” del contrato definido por otras interfaces. En par-ticular, ICollection hereda todos los miembros deIEnumerable. Para implementar ICollection, de hecho,tenemos que implementar los miembros de ambos con-juntos. Cuando declaramos interfaces, no tenemos quemarcar los miembros con modificadores como protec-ted, private o, quizás, internal (friend, en Visual Basic.NET). Todos los miembros de una interfaz son siempreconsiderados como public y virtual (overridable).

Las interfaces no existen sin una clase o estructura.Las clases y estructuras, de hecho, pueden implementaruna o varias interfaces para definirse a sí mismas y expo-ner comportamientos bien conocidos, tales como losdefinidos en el contrato.

Una clase que implementa una interfaz, está obliga-da a sobrescribir todos los miembros definidos en ladeclaración de la interfaz. Como hemos mencionado,dichos miembros, sólo pueden ser públicos y virtuales.¿Significa esto que cada clase que implementa una inter-faz dada adquiere un montón de métodos (a veces nodeseados) para sobrescribir? Es justamente lo que suce-

Difíciles decisiones,pero decisiones al fin

Dino Esposito

dnm.todotnet.qa

<< El software no es

Dino Esposito es redactor de dotNetManía.

Formador, consultor y escritorafincado en Roma.Miembro

del equipo de Wintellect,Dino está especializado en

ASP.NET y ADO.NET. Puedeenviarle sus consultas a

[email protected]

Es sobradamente conocido que la vida nos pone a veces en el trance de tomar decisionesdifíciles: BMW ó Mercedes, café o té,Atlético o Real, etc. En la vida real, el contexto, a vecesinfluye decisivamente en esa toma decisiones. Otras veces, son circunstancias aparentemen-te no relacionadas las que influyen.Pero,¿qué sucede con el software? Imagine que es un arqui-tecto a cargo del desarrollo de una aplicación. ¿Se consideraría un buen profesional si toma-se decisiones dependiendo de, por ejemplo, lo que ha tomado para desayunar?

A la hora de crear una jerarquía decomponentes, ¿debería decidirmepor clases base o por interfaces?

¿ ?

Page 53: Visual Basic.NET - Tecnología, Tips de Programación … · ben teniendo el formato de cuaderno técnico, ... olvidamos que el producto de nuestro trabajo no es un fin en sí mismo

de a no ser que tomemos ciertas contra-medidas.

En Visual Basic .NET, la implemen-tación de un método de una interfaz vie-ne a expresarse mediante el siguientecódigo:

Sub CopyTo( ByVal a As Array, _ByVal index as Integer) _

Implements ICollection.CopyTo:

End Sub

La palabra clave Implements, vincu-la explícitamente el código del métodocon su método correspondiente de lainterfaz. Sin embargo, en el modo ope-rativo usual, los compiladores no expo-nen éste método de forma pública y vir-tual. El método está ahí, pero sólo estádisponible para los que lo llaman a tra-vés de la interfaz. En C#, las cosas fun-cionan de manera algo distinta.Podemos implementar una interfazmediante la simple adición del códigosiguiente:

public void CopyTo(Array a, int index){

:}

No obstante, si lo hacemos así, sim-plemente añadimos un método público ala clase que puede ser accedido o no, a tra-vés de la interfaz. Para obtener el mismocomportamiento que en Visual Basic,deberíamos modificar el código de lasiguiente forma:

public void ICollection.CopyTo(Arraya, int index){

:}

En términos de elegancia y eficiencia,la segunda aproximación parece muchomás recomendable. Es curioso notar, sinembargo, que ése no es el tipo de códigoque Visual Studio 2003 añade al editorcuando crea las plantillas de código de unadeterminada interfaz.

En .NET Framework, una interfaz esconsiderada como un tipo. Más concre-tamente, es una descripción parcial de untipo, que, potencialmente, múltiples cla-ses pueden soportar. Cuando vamos a defi-nir un comportamiento común a un con-junto de clases, las interfaces son, cierta-mente, una aproximación viable. ¿Pero,

qué sucede con las clases base que contie-nen miembros abstractos?

Una clase base es aquella que defineun comportamiento común a un conjun-to de clases derivadas. Cuando necesita-mos definir una clase que implemente uncierto comportamiento, podemos obrarde dos formas:

• Que la clase implemente un interfazdado.

• Que la clase herede de otra clase base.

¿Cuál es mejor? En general, las clasesson mucho más flexibles que las interfa-ces. Para empezar, las clases contienencódigo y pueden implementar múltiplesinterfaces. Aunque esta característica nolas hace necesariamente las ganadoras deldebate, sí que es cierto que las capacitancomo herramienta más poderosa.

Pero aún hay más. Pensemos, porejemplo, en las versiones. Si añadimos unmétodo a la versión 2.0 de una clase, cual-quier clase que derive de ella siguenfuncionando sin cambios, siempreque el nuevo método no esté decla-rado como abstracto (abstract). Lamisma situación no funciona paralos interfaces. Estos módulos hansido escritos acorde con un “con-trato” previo, y en el momento enque cambie éste, los módulos estánrompiendo las reglas.

En resumen, mi sugerencia esutilizar clases base en lugar deinterfaces siempre que sea posi-ble. Si prevé que un cierto aspecto deuna clase puede personalizarse median-te clases derivadas, defina esa funciónparticular mediante un método virtualy protegido, de forma que las clases deri-vadas puedan sobrescribirlo con facili-dad, sin afectar al código existente. Encambio, deberíamos utilizar interfacescuando un conjunto de clases no rela-cionadas deban de soportar un proto-colo común, o, en general, cuando latécnica de la agregación no resulta apro-piada. Para reforzar esta idea, es un pla-cer remitirme a los propios arquitectosde ASP.NET 2.0. En la versión alfa deASP.NET 2.0 (del PDC 2003), la mayo-ría de las relaciones de pertenencia secodificaban mediante interfaces. En laBeta 1 (y posteriores), esto ha sido remo-dificado mediante clases base.

Mi jefe ha tomado la decisión deque nuestra aplicación utilice múlti-

ples subprocesos de ejecución para lle-var a cabo tareas potencialmente lar-gas. En mi código lanzo un nuevo sub-proceso en la forma en que recomien-dan los manuales, a través de la claseThread. No obstante, he visto en losforos una sugerencia respecto al usode agrupaciones de subprocesos (ThreadPools). ¿Qué me recomienda?

El subproceso (thread) es la unidadfundamental de ejecución en Windows.Y fíjese que digo Windows, no sóloCLR o .NET. Todas las aplicacionesadministradas o no, comienzan en unsubproceso simple, y pueden añadírse-le subprocesos adicionales a medida quese necesiten. Los subprocesos que se eje-cutan concurrentemente, compartentiempo de CPU y recursos, de acuerdocon los algoritmos empleados por el sis-tema operativo. Y lo que es más impor-tante, el CLR no interviene directamen-te en la gestión de subprocesos.

Por último, los subprocesos trabajanen modo de tiempo compartido a no serque se disponga de más de una CPU. Laventaja real de la utilización de procesosen máquinas de una sola CPU, es el podercontar con múltiples tareas que progre-san simultáneamente. En realidad, no setrata de un paralelismo real ya que los sub-procesos avanzan intercalando pequeñosfragmentos de código entre sí. La técni-ca es ventajosa cuando están implicadossubprocesos largos, pero no debiera deconsiderársela como la “garantía cierta”de mejora del rendimiento de las aplica-ciones. A menudo, ¡es justo lo contrario!

Otro escenario donde los subproce-sos son de gran ayuda es cuando uno delos subprocesos funciona en una máqui-na distinta, como por ejemplo, en las lla-madas a servicios Web o en comandos demanejo de bases de datos. En una aplica-ción .NET, cuando lanzamos un nuevo do

tNet

Man

ía<<

53

dnm.todotnet.qa<<

Lanzo un nuevo subproceso através de la clase Thread.No obs-

tante, he visto una sugerenciarespecto al uso de Thread Pools.

¿Qué me recomienda?

¿?

Page 54: Visual Basic.NET - Tecnología, Tips de Programación … · ben teniendo el formato de cuaderno técnico, ... olvidamos que el producto de nuestro trabajo no es un fin en sí mismo

subproceso mediante la forma recomendada, el métodoThread.Start, se crea un nuevo subproceso en el siste-ma operativo. En otras palabras, Thread.Start es total-mente equivalente a una llamada al API de Win32CreateThread. Si, puntualmente, la aplicación necesitacrear un subproceso, Thread.Start es una buena opción.Si estás escribiendo una aplicación de servidor que gene-ra varios procesos de forma regular y se necesita sincro-nizarlos, entonces podrás comprobar cómo la CPU cam-bia a menudo de contextos, con la consecuente pérdidade rendimiento, sobre todo al escalar la solución. En estecaso una agrupación de aubprocesos puede ayudar muchí-simo.

La agrupación de subprocesos, permite al sistema opti-mizar las “rodajas de tiempo” asignadas a cada sub-proceso teniendo en cuenta todos los procesos acti-vos en el equipo. Si tenemos un cierto número de tare-as cortas que requieren más de un subproceso, el usode la clase ThreadPool es fácil y efectivo al mismo tiem-po. El propio .NET Framework utiliza subprocesosagrupados en tareas tales como las llamadas asíncro-nas, conexiones mediante sockets, y finalización deoperaciones asincrónicas de E/S. El CLR administraun grupo de procesos y los expone a través de la claseSystem.Threading.ThreadPool. El grupo es único por cadainstancia del CLR en ejecución. La implementación dellamadas asíncronas a través de la interfaz recomendada.NET, también funciona a través de un grupo de sub-procesos. Bien, pero, ¿qué es exactamente un grupo desubprocesos? Una colección de subprocesos preexisten-tes, creados, manejados y dependientes del CLR.Enviamos tareas al grupo y se nos atiende tan prontocomo un subproceso está disponible.

Dicho esto, hay que subrayar que una agrupación desubprocesos no es ideal en todos los casos. Por ejemplo,no deberíamos utilizarlos si tenemos tareas prioritariasa tener en cuenta, o modelos sofisticados de sincroniza-ción. Para este caso concreto, las novedades que nos lle-gan de Whidbey son atractivas. Resumiendo en pocaspalabras, las llamadas repetidas a Thread.Start son laaproximación menos eficiente para crear aplicacionesmultiproceso. Puede estar bien para tareas puntuales;pero no para una aplicación de servidor seria, como ser-vidores Web, o gestores de recursos.

Voy a invertir en inmobiliarias. Pero tengo dudasentre las Granjas de Servidores y los Jardines deServidores…

Supongo que es broma… si de verdad se refiere ainmobiliarias, probablemente lo mejor es que busquerespuesta en otro lado… Pero, por otra parte, si estamoshablando de “inmobiliarias Web”, el punto es razona-ble y merece una buena respuesta.

Un Jardín de Servidores Web (Web Garden) es un mode-lo de procesos que aprovecha la implantación de múlti-ples CPU's en la misma máquina. El modelo es benefi-cioso cuando se dispone de un servidor de datos lento ollamadas a componentes COM. Incluso más, en gene-

ral, se trata de un modelo provechoso siempre que hayadependencias externas. Dentro de un jardín Web cadaCPU asociada, ejecutará su propia copia del proceso detrabajo y dispondrá de su propia copia del estado de laaplicación, de la sesión y del objeto caché. Un algorit-mo de enrutamiento cíclico es utilizado para el balancede la carga de trabajo en los procesos participantes. Cadapetición de entrada es automáticamente redirigida alsiguiente proceso de CPU disponible. Si disponemos deun jardín Web con 5 procesadores habilitados, cada unode ellos recibirá solicitudes de proceso una vez por cada5 peticiones. En general, un jardín Web es una forma demejorar la eficiencia, si bien no hay garantía de que estosuceda. Las pruebas de rendimiento son las únicas capa-ces de garantizarlo.

Las Granjas de Servidores Web son algo totalmentedistinto. Consisten en múltiples equipos conectados yconfigurados para comportarse como una única máqui-na de cara al mundo exterior. Cada vez que llega unapetición, es recogida y procesada por una de las máqui-nas disponibles. El modelo consigue una excelente esca-labilidad, pero requiere algún trabajo adicional de con-figuración, en lo referente a las aplicaciones ASP.NET.Por ejemplo, se necesita sincronizar la gestión de losobjetos viewstate así como de la autenticación, median-te la definición de claves de codificación/descodificacióna un valor común y explícito para todos los ficherosWeb.Configde la granja. Y, además, si gestionamos el esta-do de sesión, tenemos que recurrir a un modelo exter-no (out-of-process) para garantizar que todas las máqui-nas pueden acceder al medio de almacenamiento.

¿Cuál es mejor? Esa es la pregunta del millón dedólares, o mejor, del millón de euros. Las granjas Webson una solución clásica y efectiva para grandes sitiosWeb con escalabilidad y requisitos estrictos. Un jar-dín Web tiene un ámbito más reducido, tal y como yolo veo. Simplemente, sirven para mejorar el rendi-miento de una única máquina, dividiendo el trabajoentre varias CPU. Las granjas son más fáciles de con-figurar y garantizan un mayor porcentaje de éxito. Porotra parte, si lo que se busca es mejorar el rendimien-to de una solución ya implantada, como podría seruna aplicación de Intranet, el jardín Web parece elcamino a seguir. Son cosas distintas, y resultan difíci-les de comparar, si no es a altos niveles de abstracción.Sí, como naranjas y manzanas.

dotN

etM

anía

<<

54

dnm.todotnet.qa<<

To

do

tNet.

qa@

do

tnetm

an

ia.c

om

To

do

tNet.

qa@

do

tnetm

an

ia.c

om

Traducción por Marino Posadas

Voy a invertir en inmobiliarias. Perotengo dudas entre las Granjas de

Servidores y los Jardines deServidores…

¿ ?

Page 55: Visual Basic.NET - Tecnología, Tips de Programación … · ben teniendo el formato de cuaderno técnico, ... olvidamos que el producto de nuestro trabajo no es un fin en sí mismo

dotN

etM

anía

<<

55

VIASCAPE WHOIS es un componente que nospermite conocer información de un dominio. Esta infor-mación acerca de un dominio se obtiene a través delprotocolo Whois, y en concreto utiliza la recomenda-ción RFC-954 para el protocolo Whois.

La información que podemos obtener del dominioes sobre todo referida al registro del mismo, así pode-mos ver entre otros datos:

• La dirección de los servidores DNS a los queapunta.

• La fecha de creación del dominio.• La fecha que expira el dominio.• La empresa en la que se registró.• Los datos de quien registró el dominio y del con-

tacto técnico y el contacto administrativo.

Este componente nos permite realizar consultas sín-cronas o asíncronas, estas últimas permiten llamar a unmétodo cuando finalizan. Además, el componente tam-bién implementa un control de excepciones para posi-bles errores en las comunicaciones.

Podemos ver a continuación un ejemplo con códi-go de cómo obtener la información de un dominio através de una llamada síncrona.

Viascape.Net.WhoIs.WhoIs oWhoIs = new Viascape.Net.WhoIs.WhoIs();

oWhoIs.WhoIsServer = "whois.opensrs.net";oWhoIs.Port = 43;oWhoIs.Lookup("dotnetmania.com");

Para aprender a utilizar este componente dis-ponemos de un fichero de ayuda donde explicatodas las propiedades y métodos, aunque un pocobreve, es suficiente para conocer toda la funciona-lidad. Además incluye un ejemplo de cómo utili-zarlo, que nos permitirá fácilmente hacernos a laidea de lo sencilla que es su programación.

Pedro Pozo

dnm.laboratorio.net

VIASCAPE WHOIS

Pedro Pozoes redactor de dotNetManía. Es

es consultor e-Bussines.Ingeniero Técnico Informático

de Sistemas y Webmaster del portal para desarrolladores

.NET Framework Clikear.com

Ficha técnicaNombre Viascape WhoisVersión 1.1Fabricante Xceed

Webhttp://www.componentspot.com/products/index.aspx?Categories=2007

Categoría ComunicacionesPrecio GRATISValoración

Ping for .NET no se trata de un compo-nente en el sentido estricto, es más bien unejemplo de cómo crear una clase para poderhacer Ping desde una aplicación .NET.

Está programado por completo en C#,y podemos descargarnos el código fuente así comouna pequeña aplicación de prueba que nos explicacómo utilizar esta clase para hacer Ping desde nues-tros desarrollos.

Al disponer del código fuente, que por cierto estámuy bien estructurado y comentado, siempre tenemosla posibilidad de estudiarlo y modificarlo, para adaptar-lo a nuestras necesidades.

A continuación podemos ver un ejemplo de lo sen-cillo que es hacer Ping utilizando este componente.

PING for .NET

Ficha técnicaNombre Ping for .NETVersión 1.0

Fabricante Data idee

Web http://www.dataidee.com/ping/ping.htm

Categoría ComunicacionesPrecio GRATIS

Valoración

<<

<< Ping oPing = new Ping();oPing.Open();TimeSpan span = oPing.Send("192.168.0.0",

new TimeSpan(0,0,10));oPing.Close();

Hemos analizado cuatro componentes que nos permitirán utilizar algunos de los protocolos de comunicaciones más habituales, en concreto WHOIS, FTP,NNTP y PING.Aunque

hay multitud de componentes para trabajar con estos protocolos, hemos elegido estos cuatropor su funcionalidad, su facilidad de manejo y por su relación calidad-precio.

Page 56: Visual Basic.NET - Tecnología, Tips de Programación … · ben teniendo el formato de cuaderno técnico, ... olvidamos que el producto de nuestro trabajo no es un fin en sí mismo

Este componente le sorprenderá muy gratamen-te, ya que tiene todas las características que nos gus-tan a los desarrolladores. Se trata de un componen-te gratuito, disponemos del código fuente, es senci-llo de utilizar, viene bien documentado, tiene ejem-plos con código y nos ofrece toda la funcionalidadnecesaria para realizar FTP.

Incluso dispone de una página Web con un foropúblico, donde poder intercambiar conocimientoscon otros usuarios. Además, sigue la recomendaciónRFC959, lo que nos asegura un funcionamiento están-dar y fiable.

edtFTPnet nos permite realizar FTP en modoactivo o en modo pasivo, también dispone de even-tos para realizar un seguimiento del envío de fiche-ros y así poder monitorizar en qué estado están encada momento.

Y una cualidad muy interesante de este componen-te es la posibilidad de reanudar el envío de ficheros bina-rios después de una interrupción en las comunicacio-nes. Si por ejemplo, estamos enviando un fichero degran tamaño y se corta la conexión cuando íbamos porla mitad del envío, podemos reanudarlo por el mismopunto que lo habíamos dejado.

A continuación podemos ver un ejemplo de cómoenviar un fichero llamado readme.txt a un servidor FTPcuya dirección es ftp.dotnetmania.com.

FTPClient ftp = new FTPClient("ftp.dotnetmania.com");

ftp.Login("miusuario", "mipassword");ftp.ConnectMode = FTPConnectMode.PASV;ftp.TransferType = FTPTransferType.ASCII;ftp.Put("readme.txt", "readme.txt");ftp.Quit();

También existe una versión edtFTPnet Pro (nogratuita) que implementa transferencia segura de datoscon SSL para los desarrollos que requieran de unaseguridad máxima y SOCKS Proxy para las conexio-nes FTP a través de un Firewall.

Sin duda edtFTPnet es un muy buen componen-te, desarrollado de una forma muy profesional que gus-tara incluso a los desarrolladores más exigentes.

<< dnm.laboratorio.net

56

<<do

tNet

Man

ía

Ficha técnicaNombre edtFTPnetVersión 1.1.5Fabricante Enterprise Distributed Technologies

Webhttp://www.enterprisedt.com/products/edtftpnet

Categoría ComunicacionesPrecio GRATISValoración

Smilla NNTP nos permite acceder a foros de dis-cusión a través del protocolo NNTP. Este componen-te de código abierto viene acompañado además de unaaplicación de ejemplo, que consiste en un lector deNEWS, que nos servirá para aprender a utilizar estecomponente.

También trae una documentación de ayuda paraconocer todos los métodos y propiedades de los quedispone. Aunque la documentación es quizá dema-siado breve, junto con el componente viene unaaplicación de ejemplo bastante completa que nosservirá para conocer el funcionamiento de este com-ponente.

Cabe destacar que el componente tiene una bue-na distribución en clases, que nos servirán parapoder abarcar toda la funcionalidad que se le pue-de pedir a un componente para utilizar el protoco-lo NNTP.

A continuación puede ver un ejemplo de cómodescargar los artículos publicados en un grupo de noti-cias. Para el ejemplo hemos conectado al servidornews.microsoft.com, que es el servidor de NEWS públi-co de Microsoft. Y nos hemos descargado los 10 últi-mos artículos enviados al grupo de noticiasmicrosoft.public.es.dotnet.aspnet.

string cabeceras;Session session = new Session("msnews.microsoft.com");NewsGroup grupo = session.GetNewsGroup(

"microsoft.public.es.dotnet.aspnet");ArticleCollection articles =

grupo.GetArticles(true, 10);for(int cont=9;cont>=0;cont--){

cabeceras = articles[cont].Header.Subject;}session.Disconnect();

Smilla NNTP está un poco escaso de documen-tación que aclare un poco más cómo poder utilizarloen nuestros desarrollos, pero si se le dedica tiempopodemos descubrir que se trata de un componenteque nos ofrece una amplia funcionalidad para traba-jar con el protocolo NNTP.

Smilla NNTP

Ficha técnicaNombre Smilla NNTPVersión 1.0Fabricante Smilla GroupWeb http://www.smilla.ruCategoría ComunicacionesPrecio GRATISValoración

<<

<<

edtFTPnet

Page 57: Visual Basic.NET - Tecnología, Tips de Programación … · ben teniendo el formato de cuaderno técnico, ... olvidamos que el producto de nuestro trabajo no es un fin en sí mismo

dotN

etM

anía

<<

57

<<

Writing secure code (2ª Edición)Michael Howard y David LeBlanc

Editorial: Microsoft PressISBN: 0735617228Páginas: 650Publicado: Diciembre, 2002

Howard dirige la sección de seguridad de código en el equipo de Windows X,LeBlanc forma parte del Microsoft's Information Technology Group. Ya la primera edi-ción se había convertido rápidamente en un clásico en su género, hasta el punto deque Microsoft exigió su lectura a todos los arquitectos de software bajo su cargo.

En esta segunda edición, se han incrementado los aspectos relacionados con el desa-rrollo seguro bajo .NET. Modelos de amenazas, procesos de diseño seguro, pro-blemas con el sistema de ficheros, globalización, adición de privacidad y revisiónsegura del código. Añade al final unas –más que recomendables– listas de compro-bación para desarrolladores, equipos de pruebas y analistas.

Code Complete (2ª Edición)Steve McConnell

Editorial: Microsoft PressISBN: 0735619670Páginas: 960Publicado: Junio, 2004

Para muchos, se trata de una de las mejores obras acerca del proceso de la cons-trucción de software (lo que ahora llamamos “ciclo de vida”), y su implementaciónfinal. La primera edición ya era considerada como un clásico.

Ahora, en esta nueva revisión, recoge aspectos de diseño, gestión de activida-des de desarrollo, aplicación de las técnicas correctas de construcción de soft-ware, eliminación de errores, planificación y un montón de aspectos impres-cindibles de cara al Analista, Diseñador y Jefe de Proyectos. Además, ésta ver-sión incluye aspectos específicos del desarrollo Web y ejemplos de código fuen-te (correctos e incorrectos) en varios lenguajes: C++, Visual Basic, C#, Java, etc.De obligado cumplimiento.

dnm.biblioteca.net<<

dnm.biblioteca.net

Page 58: Visual Basic.NET - Tecnología, Tips de Programación … · ben teniendo el formato de cuaderno técnico, ... olvidamos que el producto de nuestro trabajo no es un fin en sí mismo

RSS Reader 1.0.88.0: Es la últimaversión del popular lector XMLy RSS, que incluye más de 400 mejoras según sus autores, res-pecto a la versión anterior de hace 4 meses. Está disponibleen la dirección: http://www.rssreader.com.

MSN Search Toolbar Beta: Ya está disponible la réplica deMicrosoft a la herramienta de búsqueda de

escritorio de Google. En la página de des-carga (http://beta.toolbar.msn.com) pue-den además leerse las características prin-cipales de funcionamiento, así como seguirun “tour” guiado sobre las nuevas capaci-dades de la herramienta, entre las que se

pretende incluir la posibilidad de la navegaciónmultipágina.

Extractor de Favoritos de Internet Explorer: Una curiosa uti-lidad, que permite guardar y recuperar los favo-ritos en varios formatos: XML, texto plano yHTML. Está disponible en BelkaSoft(http://belkasoft.com).

XSL-FO Debugger: Una notable herra-mienta que sirve para depurar hojasde estilo extendidas (XSL), ateniéndose rigurosamente al están-dar definido por la W3C. Es gratuito y puede descargarse dehttp://alt-soft.com/products_xsl-fo_debugger.jsp.

Jim Alchin da a conocer nuevas características de Longhorn

El máximo responsable de Windowspor más de una década, Jim Alchin,mostraba hace unos días en una reu-nión particular concedida a DavidKirkpatrick (Fortune), algunas nue-vas características del sistema.Longhorn, del que ahora se dice queverá la luz a finales de 2006, tendrácaracterísticas como la realización de

defragmentación automática y silenciosa del disco duro,reconocimiento de contenidos multimedia y auto adapta-ción a distintos entornos de producción. La búsqueda deelementos del sistema será mucho más fácil y rápida (con-firmando la presencia de WinFS en el sistema local, queapuntábamos en esta columna hace unos meses, y que par-te de la prensa se apresuró a desgajar de la versión defini-tiva), e incluirá la característica de poder ver la primerapágina de los documentos como parte su icono. Se esperaconocer muchos más detalles en la próxima edición del

WinHEC, que tendrá lugar pocos días después de la pre-paración de estas líneas.

Lanzamiento del SP1 de Windows Server 2003

Microsoft ha anuncia-do el lanzamiento deWindows Server 2003

Service Pack 1, que proporcionará a los clientes mejoras enseguridad, fiabilidad y rendimiento. El SP 1 está construidosobre una amplia recopilación de actualizaciones de seguri-dad, y da respuesta a importantes asuntos de seguridad adi-cionales al proporcionar a los clientes una menor superficiede ataque, servicios del sistema mejor protegidos con opcio-nes por defecto más fuertes y privilegios reducidos.

Puede descargarlo desde: http://www.microsoft.com/down-loads/details.aspx?FamilyId=22CFC239-337C-4D81-8354-72593B1C1F43

Asimismo, se ha anunciado el lanzamiento de la versiónRTM de las ediciones Windows Server 2003 x64 y WindowsXP Professional x64, que estarán disponibles a través de variospartners a finales de abril.

dotN

etM

anía

<<

58

no

ticia

s.n

oti

cia

s

Tech-Interviews: Un curioso sitio donde se recogen pre-guntas típicas que surgen en las entrevistas de trabajo paraprogramadores (incluyendo preguntas sobre .NET).Disponible en http://www.techinterviews.com.

DotNetFreaks: Desde aplicaciones completas, tutoriales yejemplos, hasta componentesy controles Windows y Webpueden encontrarse en estecompleto sitio: http://www.dot-netfreaks.com.

dnm.desvan<<

Marino Posadas

Lista de “bugs” corregidos por el Service Pack 2 de SQL-2000 Reporting Services: La reciente aparición del SP2de Reporting Services ha despertado la curiosidad desus ya muchos usuarios por el contenido de correccio-nes. Microsoft ha publicado la página http://support.micro-soft.com/?kbid=889640 con una lista exhaustiva de “bugs”y sus explicaciones individuales.

Documentos en la Red

Enlaces del mes

Utilidades recomendadas

Page 59: Visual Basic.NET - Tecnología, Tips de Programación … · ben teniendo el formato de cuaderno técnico, ... olvidamos que el producto de nuestro trabajo no es un fin en sí mismo
Page 60: Visual Basic.NET - Tecnología, Tips de Programación … · ben teniendo el formato de cuaderno técnico, ... olvidamos que el producto de nuestro trabajo no es un fin en sí mismo