Webs muy recomendadas: (1)

CABECERA POST
DANBA
icono 3 Qué es: en la región tibetana de Danba cuenta una vieja leyenda que los padres construían unas torres de vigilancia para proteger las almas de sus hijos de los malos espíritus hasta que eran  mayores de edad. Este es el origen de este sistema de vigilancia para menores.
Existen muchos sistemas para controlar el uso de Internet en los niños, unos más polémicos que otros: los filtros, los bloqueos por contraseña o, como en el caso de Danba, la monitorización de la navegación.

  http://vimeo.com/moogaloop.swf?clip_id=3142388&server=vimeo.com&show_title=1&show_byline=1&show_portrait=0&color=&fullscreen=1

icono 2 Úsala para realizar un seguimiento, en segundo plano y de forma transparente al usuario, de la navegación por Internet. Al contratar el servicio instalas un software que registra las webs que visitan los menores. Si se accede a webs inapropiadas, los padres reciben un SMS o un email de aviso.

icono 4 Su mejor característica es que esta labor de vigilancia se acompaña de un asesoramiento de profesionales, que aconsejan a los padres cómo actuar si descubren que sus hijos visitan webs pornográficas o de bulimia o anorexia.

icono 1  Mi opinión es; una web muy interesante para incluir un sistema de seguimiento y control parental en aquellos ordenadores a los que los menores tienen acceso. En cualquier caso, al tratarse de un sistema de vigilancia de pago, se echa en falta una demo o versión de demostración accesible al usuario para tener una experiencia previa que le permita contratar los servicios que se ofrecen en ésta web con la garantía de conocer qué se está pagando.

icono_direccion  www.danba.es

 

JPG FUN
icono 3 Qué es: los editores fotográficos online están de moda. Su éxito se debe a una conjunción de razones: el “boom” de la fotografía digital, la facilidad de uso y los divertidos resultados. JPG Fun es uno de los más populares.

Dibujo1

icono 2 Úsala para aplicar originales efectos y preparar diversas composiciones utilizando tus propias fotos, que previamente tendrás que subir a la página web. Hay decorados muy interesantes, como los carteles de “Se busca”, o las portadas de revistas como Time a la que puedes añadir tu foto.

icono 4 Su mejor característica es la gran cantidad de opciones y los buenos resultados que se obtiene.

icono 1  Mi opinión es; Al tratarse de una web en inglés y que no cuenta con la opción de elegir el castellano, seguramente esté muy limitado su uso para aquellos usuarios que descartan automáticamente las páginas que no estén en su idioma, sin embargo siempre es posible usar un traductor on-line de webs que nos permitirá usar las principales características que nos ofrece jpg fun.

icono_direccion  http://jpgfun.com 

 

DRAGONBALL AL CINE
icono 3 Qué es: la serie japonesa Dragonball, causó un efecto similar en los años 80 y 90 al que produjo Mazinger Z en los 70. El pasado 8 de abril se estrenó en España la primera película de la serie realizada con actores reales. Un filme que presenta muchas dudas sobre su calidad debido a los problemas de rodaje y a los rumores que anunciaron su cancelación por culpa de las malas sensaciones de las proyecciones privadas. En cualquier caso, si eres fan de la serie y tienes curiosidad por la película, en esta web en castellano encontrarás todo lo que necesitas.

Dibujo2

icono 2 Úsala para echar un vistazo al estreno cinematográfico. Sorprende el gran desglose del mismo, con apartados dedicados a los actores, los aspectos técnicos, las audiciones, los extras, la banda sonora o los inevitables videojuegos que se lanzarán con el estreno de la película.

icono 4 Su mejor característica es la traducción de las entrevistas en inglés que han dado los protagonistas, así como el subtitulado de los tráilers para que los fans que no saben idiomas puedan disfrutar de ellos.

icono 1  Mi opinión es; un sitio muy interesante para estar al día sobre ésta película y además cuenta con su propio foro en el que los usuarios se comunican y expresan su opinión acerca del filme. También se incluyen multitud de enlaces con información sobre la mítica serie de TV. ¡Échale un vistazo para disfrutar con Bola de Dragón!.

icono_direccion  www.dragonballalcine.com

 

SPEED.IO
icono 3 Qué es: existen muchos test en línea que realizan un diagnóstico de tu conexión a Internet, pero pocos son tan completos  descriptivos como Speed.io. Además, pese a que no lo indica en ningún sitio, el test por defecto está en castellano.

Dibujo3

icono 2 Úsala para realizar un chequeo de tu conexión a Internet. Simplemente tienes que pulsar el botón “Comienzo SpeedTest”. Tras unos minutos de prueba, obtendrás una gran cantidad de información útil: el nombre de tu proveedor, tu dirección IP, la velocidad real de subida, la de bajada y datos muy importantes para jugar online o realizar videoconferencias, como el número de conexiones por minuto y el ping.

icono 4 Su mejor característica es su acierto para mostrar toda esta información, de forma gráfica, mediante una representación que simula el salpicadero de un coche.

icono 1  Mi opinión es; Al tratarse de valores que nos indican la descarga y subida que tenemos disponible con nuestra conexión a Internet, siempre hay que realizar los test, cerrando cualquier programa que consuma conexión. De todas formas el resultado del test, es orientativo y debe ser el ISP el que facilite un enlace para realizar un test de velocidad interno.

icono_direccion  www.speed.io

 

WEB PENÉLOPE
icono 3 Qué es: Penélope Cruz ha entrado en la historia al ser la primera actriz española en ganar un Oscar, el de Mejor Actriz de Reparto, por la película de Woody Allen “Vicky Cristina Barcelona”. No dispone de web oficial, pero existen páginas no oficiales, como Web Penélope, que te permitirán conocer la vida y obra de una de las “chicas Almodóvar” más populares.

Dibujo4

icono 2 Úsala para seguir las noticias de Penélope Cruz, leer su biografía, conocer su filmografía, así como sus últimos proyectos. No faltan las inevitables secciones multimedia, como una galería fotográfica, y diversos vídeos: desde su aparición en el vídeo de Mecano “La fuerza del Destino” hasta el de la entrega del Oscar.

icono 4 Su mejor característica es la constante actualización con noticias sobre la actriz, centradas en su faceta profesional y no en su vida privada, como suele ocurrir en este tipo de webs.

icono 1  Mi opinión es; para los fans de ésta actriz, seguramente ésta página sea una referencia de obligada lectura para conocer aspectos más concretos de una mujer espectacular. Destacar que algunos de los vides que incluyen en la web, y que han sido incrustados desde YouTube, no están disponibles, a causa de tratarse de una web no oficial de Penélope Cruz.

icono_direccion  www.webpenelope.com

 

KIDREX
icono 3 Qué es: ahora que Internet está implantada en todos los ámbitos de la sociedad y es de uso cotidiano entre los niños, resulta incomprensible que no existan mecanismos por defecto para proteger a los menores. Por suerte, hay iniciativas que se preocupan por ofrecer entornos seguros a los más pequeños, en donde pueden navegar sin problemas. KidRex es una de ellas.

Dibujo5

icono 2 Úsala para que los mas pequeños puedan buscar páginas web, en un ambiente divertido. KidRex es un buscador que utiliza Google como motor de búsqueda, pero con la protección Google SafeSearch activada, filtrando webs con contenido sexual, violento y otros temas no aptos para menores. Además, KidRex realiza sus propios análisis para perfeccionar aún más esta protección.

icono 4 Su mejor característica es la interfaz, que simula la escritura infantil y que anima a los niños a usar el buscador.

icono 1  Mi opinión es; cualquier iniciativa que realice un esfuerzo para garantizar una navegación segura y entretenida para los más pequeños es siempre bienvenida, y en este caso, al realizar búsquedas ya sabemos que se filtran para que sean aptas para menores. Aunque esté en inglés al usar el motor de búsqueda de google, nos aparecen resultados básicamente en el idioma que realicemos la búsqueda.

icono_direccion  www.kidrex.org

 

RADIOESPAÑA.NET
icono 3 Qué es: un directorio de cadenas de radio españolas. Almacena enlaces a las páginas web de miles de ellas para que puedas sintonizarlas y disfrutar de la música que emiten, o visitar su página web.

Dibujo6

icono 2 Úsala para encontrar emisoras que te interesen y que estén en el lugar en el que vives. Para ello, dispones de un práctico buscador en forma de mapa interactivo, y también puedes buscar por nombre de emisora.

icono 4 Su mejor característica es la posibilidad de descargar una barra de herramientas que permite sintonizar las cadenas de forma automática para escucharlas en tu PC.

icono 1  Mi opinión es; una web interesante, ya que su directorio de radios y emisoras es muy completo, y nos permite además la posibilidad de buscar casi cualquier sintonía en un lugar determinado de la península.

icono_direccion  www.radioes.net


Artículo revista Personal Computer & Internet. Nº 75, Abril 2009 Revista mensual – Año VI
PIE DE PAGINA POST,¸ .•’´PIE DE PAGINA POST

Anuncios

Webs muy recomendadas: (2)

CABECERA POST
GANGA.ES
icono 3 Qué es: un portal gratuito de compraventa de artículos nuevos y de segunda mano entre particulares. Incluso puedes montar tu propia tienda “amateur”. Si tienes un negocio profesional, entonces puedes convertirte en vendedor Premium.

  

icono 2 Úsala para comprar o vender casi cualquier artículo imaginable, desde artes y antigüedad a complementos para mascotas, películas o juguetes. Hay docenas de categorías y más de un millón de anuncios recopilados. Los vendedores tienen una reputación de votos emitidos por los clientes, para que sepas quiénes son de confianza. Ganga.es dispone de programas de protección de transacciones y sistemas de pago seguro.

icono 4 Su mejor característica es que te dan la posibilidad de montar tu propia tienda de objetos de segunda mano de forma relativamente sencilla, a un bajo coste.

icono 1  Mi opinión es; se trata de una web muy interesante, al menos desde el punto de vista de comprador, ya que hay un montón de categorías de artículos y con un golpe de vista podemos ver algo en concreto. Una alternativa a los archiconocidos portales que hay en Internet para comprar o vender.

icono_direccion  www.ganga.es

 

ECOMOVE
icono 3 Qué es: un portal dedicado a los vehículos ecológicos y la movilidad sostenible. Tiene como objetivo concienciar a la gente sobre el uso abusivo de los vehículos contaminantes, y la paulatina migración hacia los vehículos eléctricos o de baja contaminación

  

icono 2 Úsala para seguir el desarrollo de este nuevo campo de locomoción, que alcanzará su auge en los próximos años. En este portal encontrarás noticias y reportajes sobre nuevos modelos de coches eléctricos, proyectos para reducir la contaminación, entrevistas, videoteca, y mucho más.

icono 4 Su mejor característica es la sección de Eventos y Jornadas, en donde se recogen las ferias, conferencias y proyectos relacionados con la movilidad sostenible que tienen lugar en todo el territorio nacional.

icono 1  Mi opinión es; se trata de una web que nos permite estar al día con el mundo del las tecnologías NO contaminantes en relación al motor. Tiene multitud de enlaces interesantes para no perdernos las novedades del sector.

icono_direccion  www.ecomove.es

 

PR4XY.INFO
icono 3 Qué es: la privacidad en Internet es un tema muy preocupante, cada vez más difícil de controlar. Todas las webs que visitamos permanecen almacenadas en los servidores de nuestro proveedor de Internet durante un tiempo, y todos nuestros movimeintos son monitorizados por programas publicitarios o espías, buscadores, cookies, troyanos, y otras fuentes. Si quieres mantener tu privacidad mientras navegas, necesitas un proxy.

  

icono 2 Úsala para visitar webs sin revelar tu dirección IP o tu lugar de origen. Pr4xy.info recoge la dirección de la página web que quieras visitar, y realiza el acceso desde otro servidor, para ofrecerte resultados. De esta manera la web que visitas no recopila tus datos privados. Obviamente, este proceso hace que la navegación más lenta.

icono 4 Su mejor característica es la facilidad de uso: simplemente teclea la dirección que quieras visitar en la casilla central, y listos.

icono 1  Mi opinión es; se trata de un web que ‘enmascara’ nuestra dirección IP. Sin embargo es muy importante la velocidad de acceso al sitio que deseamos entrar, y en este apartado precisamente esta web hace la navegación extremadamente tediosa.

icono_direccion  www.pr4xy.info

 

ESTOYPARADO.COM
icono 3 Qué es: una web dedicada a las personas que están en paro. Su principal interés radica en las secciones centradas en la comunidad, pero tiene otro contenido reseñable.

  

icono 2 Úsala para leer noticias relacionadas con el empleo. La portada de EstoyParado.com recoge noticias, leyes, propuestas y otras novedades relacionadas con el tema. No falta el foro en donde se pueden resolver dudas y buscar ayuda, y reportajes prácticos para aprender a afrontar las entrevistas de trabajo, o solicitar el paro

icono 4 Su mejor característica es el directorio de páginas web de empleo y de asociaciones de parados, con abundante información y actualización constante.

icono 1  Mi opinión es; se trata de una web muy completa en relación con aspectos sobre los trabajadores, sin embargo se echa en falta algún tipo de información exclusiva precisamente para ‘parados’. No me imagino a una persona en paro y entrando a ésta web para a penas si encontrar información de cómo salir de esa triste situación.

icono_direccion  www.estoyparado.com

 

ACTUALIDAD GADGET
icono 3 Qué es: los gadgets… ¿quién puede resistirse a ellos? Los hay de todos los tipos y para todos los gustos. Si te entusiasman los “gadgets” en general, esta página está hecha para ti.

  

icono 2 Úsala para descubrir nuevos “aparatitos” que llegan todos los días a las tiendas: teléfonos con encendedor (en serio), ordenadores ultraligeros, nuevos modelos de móviles, dispositivos USB con todo tipo de funciones, etc. La web se actualiza con frecuencia y es amena y divertida

icono 4 Su mejor característica es el acceso por columnas, con enlaces a las noticias agrupadas por categorías, marcas, u otras webs dedicadas a los gadgets.

icono 1  Mi opinión es; un sitio para echarle un vistazo a artículos novedosos, y que incluyen opiniones sobre los mismos. Es desde luego un principio muy interesante para buscar opiniones sobre algún producto en concreto que tengamos en mente comprar, así nos servirá la opinión ofrecida en esta web.

icono_direccion  www.actualidadgadget.com

 

CONVERSOR DE DIVISAS
icono 3 Qué es: ahora que el dólar y la libra está por los suelos, es un buen momento para comprar en el extranjero a través de Internet. Cada vez más tiendas americanas y británicas permiten comprar en euros, pero aún hay muchas que trabajan con sus monedas locales. Si necesitas cambiar de divisa, este conversor te resultará de gran utilidad.

  

icono 2 Úsala para convertir una moneda en otra, en cualquier combinación. Las cotizaciones se actualizan diariamente y la web está en español.

icono 4 Su mejor característica es que el euro, el dólar y la libra aparecen en primer lugar en la lista de monedas, así que bastan un par de clics para convertir divisas entre cualquiera de ellas.

icono 1  Mi opinión es; un sitio en el que podemos conocer el cambio de divisas muy fácil.

icono_direccion  www.xe.com/ucc/es

 

MY CONFIG
icono 3 Qué es: una utilidad que te permite realizar una exploración exhaustiva de tu ordenador, generando un listado con todos los componentes hardware y software (drivers y programas) que hay en tu equipo. La novedad es que no necesita instalación, ya que funciona directamente desde el navegador de Internet.

  

icono 2 Úsala para generar informes que pueden ser muy útiles para descubrir si te han vendido lo que has pagado, o si tienes que actualizar algún componente o programa de tu equipo. También puede servir para encontrar un problema o entregar el informe a un servicio técnico.

icono 4 Su mejor característica es la posibilidad de convertir el documento al formato PDF para archivarlo y compartirlo de forma sencilla, e incluso transcribir las principales características de tu PC a una firma para usar en redes sociales, tal y como hacen muchos usuarios de foros de hardware o videojuegos.

icono 1  Mi opinión es; al tratarse de un página en inglés dificultad un montón su entendimiento, y carece de sentido la información que ofrece sino se domina el lenguaje técnico al respecto. Si es interesante la capacidad de ofrecer un resumen de los componentes de nuestro PC on-line, sin necesidad de instalar software… aunque irremediablemente tengamos que instalar los controlesX que permiten el escaneo de nuestra máquina.

icono_direccion  www.ma-config.com


Artículo revista Personal Computer & Internet. Nº 87, Abril 2010 Revista mensual – Año VII
PIE DE PAGINA POST,¸ .•’´PIE DE PAGINA POST

Webs muy recomendadas:

CABECERA POST
BOXOFFICE.ES

icono 3 Qué es: pese a que la mayor parte de los beneficios de una película provienen de la explotación televisiva y las ventas de DVDs, los anglosajones dedican páginas y más páginas; numerosos artículos y acalorados debates, a comentar la taquilla cinematográfica. Es una costumbre muy poco extendida en España… hasta ahora.

Dibujo

icono 2 Úsala para consultar la taquilla semanal, tanto en nuestro país como en Estados Unidos. Abundan las completas tablas con las diez primeras películas que más recaudan, incluyendo la variación desde su estreno, el número de salas en las que se proyectan, el promedio recaudado por sala, el total acumulado, así como el presupuesto del filme, entre otros datos de interés. Las estadísticas se complementan con noticias, reportajes y predicciones de futuros éxitos.

icono 4 Su mejor característica es la mencionada especialización en la recaudación de taquilla, una “rara avis” en el colectivo de webs cinéfilas en español.

icono 1 Mi opinión es; Una web de aspecto intuitivo en la que podemos dar nuestro correo electrónico para estar al día de las taquillas de nuestras películas favoritas. También podemos acceder a un riguroso informe sobre las recaudaciones y demás detalles de taquilla. Destacar la ausencia de publicidad que hace que la lectura de la información importante sea más rápida.

icono_direccion  www.boxoffice.es

 

WEBCÓMICS
icono 3 Qué es: los dibujantes de tiras cómicas han encontrado en Internet, y muy especialmente, en las bitácoras, una herramienta inmejorable para dar a conocer su trabajo. Gracias a ellas pueden publicar sus proyectos, darse a conocer y, mediante el “boca a boca” –o blog a blog-, obtener el suficiente reconocimiento como para publicar sus trabajos en formato libro. Si tienes un webcómic o, simplemente, te gusta leerlos, esta página te resultará de gran utilidad.

Dibujo1

icono 2 Úsala para conocer esta Asociación de Webcomiqueros de Hispana. Agrupa a más de 200 webcómics, que tratan los más variados temas: humor, críticas políticas, actualidad, erotismo, etc. Desde este portal puedes acceder a ellos para leerlos, conocer cuándo se actualizan o cuáles son los más populares.

icono 4 Su mejor característica es la atención que dedica a los creadores de webcómics. Si tienes uno, puedes apuntarte a la asociación, inscribir el tuyo, participar en concursos y campañas, y conocer toda la actualidad relacionada con la creación de tiras cómicas digitales.

icono 1 Mi opinión es; Una web de obligada visita para los amantes del cómic, o para aquellos que deseen pasar un rato agradable con la lectura de cientos de enlaces a cómics. Incorpora un tutorial con herramientas para poder iniciarse en éste mundo de los cómics. Destacar que podemos acceder a un foro y concursos para ayudarnos a mejorar si ya tenemos experiencia diseñando.

icono_direccion  www.webcomics.es

 

DOSBIT
icono 3 Qué es: una web de informática, programación y tecnología. Se actualiza con frecuencia y dispone de contenido interesante.

Dibujo2

icono 2 Úsala para seguir la actualidad de la Red, bajo la perspectiva de un programador o de un usuario de alto nivel. Se habla de sistemas operativos, estándares de creación de páginas web, utilidades para mejorar el ordenador, navegadores, estándares de audio… ¿Coges la idea?

icono 4 Su mejor característica es la sección “La semana con Dosbit en seis enlaces”. Se da un repaso a las mejores noticias que han tenido lugar en los últimos siete días. Muy útil si no tienes tiempo para leer toda la bitácora y quieres enterarte de lo más importante.

icono 1 Mi opinión es; Una web con un aspecto de blog, en el que los usuarios agregan contenido y nos podemos encontrar con multitud de categorías en las que podemos consultar la opinión expresadas por otros usuarios y enlaces a los programas comentados, etc.

icono_direccion  www.dosbit.com

 

CHAVALES
icono 3 Qué es: el pasado 10 de febrero 2009, se celebró el Día Internacional por una Internet Más Segura. El objetivo de esta conmemoración es que niños y mayores aprendan a conocer las reglas de Internet para aprovecharse de sus ventajas y evitar sus riesgos. El portal Chavales, promovido por la Secretaría de Estado de Telecomunicaciones, ha preparado una interesante iniciativa para conmemorar el evento.

Dibujo3

icono 2 Úsala para ver diversos reportajes audiovisuales en donde diferentes expertos responden a las preguntas realizadas por niños y jóvenes relativas a la seguridad y los problemas de Internet. Se trata de entrevistas de indudable interés por el tema que tratan y la respuesta a preguntas directas. También merece la pena echar un vistazo al resto de contenidos del portal, pensado para que lo más jóvenes aprendan a usar Internet de forma segura.

icono 4 Su mejor característica es la sección Ciberpadres. Aquí puedes descargar diversos documentos PDF que tratan temas como la violencia en el ciberespacio, la música, los jóvenes e Internet o una guía de ayuda para las familias.

icono 1 Mi opinión es; Una web muy atractiva para estar al día en contenido con relación a la seguridad en Internet. Destacar que permite el registros de usuario y que cuenta con la posibilidad de insertar nuestro correo electrónico para recibir los boletines informativos.

icono_direccion  www.chaval.es

 

SPAMLOCO
icono 3 Qué es: un blog de seguridad informática, regido por un hacker vocacional. Trata sobre los virus, troyanos, ataques web, fallos de seguridad y demás cuestiones relacionadas con este tema.

Dibujo4

icono 2 Úsala para seguir la actualidad de los ataques spam, y derivados. En la bitácora no sólo se ofrecen noticias, sino que también hay soluciones y trucos para prevenir cualquier intromisión en tu ordenador.

icono 4 Su mejor característica es la explicación, en términos asequibles, de los mecanismos que utiliza el software malicioso para actuar.

icono 1 Mi opinión es; Un blog para poder leer los artículos más variados de; un uruguayo nacido en 1983, hacker desde chico, blogger desde el 2005 y ex fanático del juego Ghost Recon. la temática en SpamLoco es variada, los temas principales son los consejos y trucos para mantener una PC doméstica segura y en condiciones. Destacar que cómo la mayoría de los blogs permite agregar comentarios y tanto el autor cómo los visitantes comentan los artículos.

icono_direccion  http://spamloco.net

 

BAILE RETRO
icono 3 Qué es: tal y como su nombre indica, se trata de un portal informativo dedicado al baile clásico y popular: danzas regionales, flamenco, salsa, tanto, etc. Sorprende por la gran cantidad de secciones disponibles y su constante actualización.

Dibujo5

icono 2 Úsala para leer noticias relacionadas con los bailes retro: concursos, actualidad de los bailarines y grupos de moda, entrevistas, certámenes profesionales y mucho más. Los apartados son muy numerosos, dedicando secciones temáticas a los artistas más conocidos, campeonatos, coreografía, escuelas de baile, etc.

icono 4 Su mejor característica es la gran cantidad de noticias de actualidad que se incluyen en todas y cada una de las secciones.

icono 1 Mi opinión es; Una parada obligatoria para los amantes del baile, ya que cuenta con abundante material audiovisual al respecto. Muy fácil de usar la herramienta de búsqueda y una buena organización en la página inicial. Destacar que nos da la posibilidad de subscripción RSS para estar a la última en las novedades que ésta web propone.

icono_direccion  www.baileretro.com

 

BITDEFENDER QUICKSCAN
icono 3 Qué es: se trata de un detector gratuito de software maligno. Funciona en línea, directamente desde el navegador, así que no hay que instalar ningún software. Tiene algunas características novedosas, como su ejecución remota en los servidores de BitDefender, mientras realiza el chequeo. Esto significa que no ralentiza el ordenador, mientras lleva a cabo la búsqueda de programas malignos en tu equipo.

Dibujo6

icono 2 Úsala para encontrar virus, troyanos, gusanos, y otras variantes de software espía. Aunque la web está en inglés, es muy fácil de usar ya que sólo hay que pulsar sobre el botón Start. Si es la primera vez, deberás instalar un control ActiveX en el navegador, si no lo tienes ya.

icono 4 Su mejor característica es la protección global que incorpora, ya que no se limita a un único tipo de amenazas.

icono 1 Mi opinión es; Una web interesante que podemos utilizar cómo complemento a nuestro antivirus y que en cualquier caso, si detectamos algún mal-ware en nuestro ordenador, seguramente tengamos que utilizar una herramienta específica para eliminar software malicioso.

icono_direccion http://qscan.bitdefender.com


Artículo revista Personal Computer & Internet. Nº 75, Abril 2009 Revista mensual – Año VI
PIE DE PAGINA POST,¸ .•’´PIE DE PAGINA POST

Windows Server 2008, el servidor modular (Artículo Revista)

EL LANZAMIENTO DE WINDOWS SERVER 2008 SUPONE UN GRAN AVANCE EN TORNO A LA PRODUCTIVIDAD, SEGURIDAD Y GESTIÓN DE LOS RECURSOS DE LA INFRAESTRUCTURA. EN LAS SIGUIENTES PÁGINAS VAMOS A REPASAR ALGUNAS DE LAS PRINCIPALES APORTACIONES Y, ADEMÁS, CONOCEREMOS ALGUNOS CASOS DE IMPLANTACIÓN EXITOSA EN CLIENTES DE NUESTRO PAÍS.

Introducción
Prácticamente cualquier empresa necesita, en mayor o menor medida, una infraestructura adecuada para facilitar sus procesos de negocio. En este sentido, la elección del sistema operativo es crucial para obtener la eficiencia necesaria a la hora de asegurar el buen funcionamiento de los recursos y servicios que necesitemos en todo momento.
   win-server-2008Windows Server es, por excelencia, el sistema operativo para servidores de Microsoft. De hecho, recientemente la compañía presentaba la última versión del producto, Windows Server 2008, que incluye un gran número de novedades a nivel conceptual y de arquitectura.
   Del mismo modo que Windows Server 2003 estaba basado en el núcleo (Kernel) de Windows XP, Windows Server 2008 está basado en el núcleo de Windows Vista, concretamente con el Service Pack 1 integrado. Por lo tanto, esto supone un gran número de ventajas de integración entre ambos.
   Sin embargo, uno de los esfuerzos que Microsoft ha querido realizar en Windows Server 2008 es que no sólo sea interoperable con sus sistemas, sino que, consciente de que cada vez existen más entornos heterogéneos, ha llegado a acuerdos con varios fabricantes para que sus sistemas pueden entenderse entre sí. Entre ellos podríamos citar el acuerdo al que ha llegado con Novell para realizar implantaciones conjuntas de SuSE y Windows, o el entendimiento entre la futura plataforma de virtualización de Microsoft, Hyper-V, y el sistema de Xen para que cualquier máquina Linux que soporte Xen pueda ser virtualizada bajo Windows Server (aspecto que veremos más adelante).

Server Manager
A partir de ese núcleo compartido, Windows Server 2008 es capaz de agregar diferentes capas que le permiten actuar de forma distinta en base a las necesidades de cada negocio. Estas formas de actuar se denominan roles. Concretamente, la nueva versión del producto dispone de hasta 17 roles, entre los que se encuentran el de servidor web (IIS), servidor de ficheros, Terminal Server o virtualización, entre otros. Como complemento a estos, el sistema también permite añadir ciertos componentes que afectan al funcionamiento general del servidor. Entre ellos podríamos citar desde el nuevo sistema de encriptación (BiLocker Drive Experience), pasando por las capacidades de .NET Framework 3.0.
   No obstante, para gestionar el gran número de aspectos configurables que integra Windows Server 2008, sería necesario disponer de bastantes consolas aisladas para configurar las particularidades de cada uno de ellos, dando como resultado un sistema complicado de manejar. Por este motivo, Microsoft ha decidido unificar todas estas consolas en una única, desde la que poder, no sólo agregar o eliminar roles y funcionalidades, sino tener acceso pormenorizado a las incidencias que cada no de estos módulos requiera. Esta consola se ha bautizado con el nombre de Administrador del Servidor (Server Manager). Por lo tanto, éste será el punto de referencia para controlar cualquier tipo de configuración que afecte al funcionamiento general del sistema. De hecho, debido a que únicamente veremos las utilidades que gestionan los roles instalados en el sistema, estaremos siempre ante un entorno limpio, que nos muestra únicamente las consolas que necesitamos.
   Es más, con el fin de repercutir en la facilidad de integración de los componentes del sistema, el producto incorpora técnicas de análisis de dependencias, de tal forma que si queremos, por ejemplo instalar un servidor web, un inspector interno se encarga de analizar posibles dependencias y nos indica automáticamente el componente necesario para proceder a su instalación, que el caso del servidor web sería el servicio WPAS (Windows Process Activation Service).
   Paralelamente a esto, además de mejorar la gestión, Windows Server 2008 optimiza sustancialmente la cantidad de servicios y recursos que tiene instalado en cada momento. Esto es así debido a su naturaleza modular, que le permite instalar sólo y exclusivamente los componentes que necesitamos para configurar el rol o funcionalidad que vamos a integrar. Esto supone una gran ventaja que incide en el principio de defensa en profundidad, ya que en cada momento el servidor contará con los bits necesarios para ejecutar únicamente las funciones para las que ha sido programado, y ninguna más. Con esto se consigue un producto bastionado que ofrece un mejor rendimiento, que no necesita ejecutar tareas para las que no ha sido concebido, y mejora la seguridad e higiene, porque reducimos la superficie de ataque en todo momento y nos aseguramos un entorno de mínima exposición (por ejemplo, si un servidor está concebido para actuar como servidor web no le afectan en absoluto las incidencias que se apliquen a un servidor de ficheros).

Server Core
Sin embargo, para minimizar al máximo los recursos que tenemos instalados en el sistema, Windows Server 2008 ofrece la posibilidad de realizar una instalación denominada Server Core, cuya finalidad es reducir al máximo los servicios y componentes instalados en el servidor. Si optamos por realizar una instalación de este tipo nos encontraremos con menos recursos disponibles, pero como contraprestación obtendremos un entorno bastionado y preparado para desempeñar únicamente la función para la que fue instalado, evitando su manipulación por el personal no técnico, ya que se presenta como una mera consola de comandos. Esto le confiere un interés especial para los entornos en los que existen delegaciones remotas, ya que es una opción más segura y controlada que la que podría encarnar un servidor tradicional.
   A nivel más específico, cuando optamos por una instalación Server Core eliminamos la disponibilidad de varios componentes, como el entorno de escritorio (por ejemplo, no hay menú de inicio), la navegación convencional por carpetas o la posibilidad de ejecutar código (ya que no cuenta con NET Framework). También renunciaremos a las consolas MMC y a sus añadidos (snaps-ins) y a una multitud de aplicaciones que sí se incluyen en un servidor de instalación completa (Windows Mail, WordPad, Internet Explorer, Paint o ventanas de búsqueda, entre otros). El concepto de esta modalidad es otro. windows2008logo
   Esta modalidad se desarrolló bajo una serie de elementos básicos que ayudan a mejorar el resultado que obtenemos. En primer lugar, tenemos el principio de que, cuanto menos binarios tengamos en el sistema, menor superficie de ataque expondremos (en este tipo de instalación se reduce el espacio necesario hasta siete veces). Por lo tanto, obtendremos un sistema más protegido. En este mismo sentido, como se trata de un entorno pensado para la instalación de roles se han eliminado multitud de servicios y componentes que no son necesarios para esta tarea, lo que redunda en un sistema bastionado y optimizado. Igualmente, si tenemos menos binarios y menos servicios activos, la necesidad de actualización del sistema obligatoriamente tendrá que ser mucho menor, lo que redunda en mejoras de gestión.
   Una instalación basada en Server Core está pensada para mejorar el resultado que se obtiene generalmente cuando instalamos un servidor para soportar un único residente (por ejemplo, la instalación de un servidor para soportar el rol de DHCP). En este caso, Server Core ayudará a eliminar todo aquello que nos sobra, dejando únicamente lo estrictamente necesario.
   Para instalar Windows Server 2008 en la modalidad Server Core tendremos que seleccionar dicha opción en el momento de la instalación (justo después de introducir el número de licencia). Posteriormente, la instalación continuará seleccionando el disco duro de destino y comenzará la instalación propiamente dicha.
   Una vez que concluye la instalación, en lugar de contar con las típicas ayudas, como la pantalla de configuración inicial o el Administrador del Servidor que comentábamos en la modalidad convencional, Server Core nos muestra una consola de comandos, lo que implica que deberemos realizar todas las configuraciones (cambiar la contraseña del administrador, configuración de red o añadir usuarios y establecer la zona horaria, entre otras) de forma manual.

NAP: Network Acces Protection
NAP (Network Acces Protection o protección de acceso a red) es una plataforma de gestión que se incluye de serie en Windows Server 2008.
   Con NAP, Microsoft proporciona a los responsables de sistemas una infraestructura integrada en sus sistemas operativos de servidor y usuario, con el que pueden imponer y validar, mediante la definición de un conjunto de directivas, el software y parametrización que ha de tener un ordenador para considerarlo seguro dentro de la red. También proporciona los mecanismos necesarios que permiten limitar el acceso a la red de los equipos que no cumplan los requerimientos y facilita automatismos para que estos ordenadores puedan obtener el software y configuración que les falta para alcanzar el cumplimiento de esas directivas.
   La Protección de Acceso de Red de Microsoft es una herramienta de gestión y, como tal, debe ser entendida y aplicada. Esta herramienta simplifica el trabajo de administración, permitiendo definir la configuración de seguridad y programas que han de cumplir los equipos para considerarlos seguros en su conexión a la red, vigila el cumplimiento de esos requisitos y limita la visibilidad de la red a aquellos ordenadores que no tengan el mínimo de seguridad exigido para operar en el sistema. Esta característica, por orientación y diseño, no está capacitada para evitar ataques y otros riesgos derivados de personas que activamente quieran cometer alguna tropelía en el sistema. Resulta muy útil para prevenir que, por descuido, dejadez o falta de atención, los ordenadores que se conecten a la red puedan ser foco de infección vírica o vulnerables a código malicioso y puedan ser utilizados como palanca para forzar la protección establecida.
   En definitiva, gracias a NAP, con la próxima plataforma de sistema operativo Windows los administradores van a disponer de una herramienta de gestión que va a facilitar mucho las tareas de mantenimiento de los equipos que se conectan a su red y tendrán oportunidad de mejorar el nivel de seguridad de forma cómoda. Al ser una tecnología de reciente aparición, aún no tiene el grado de desarrollo que sería deseable y esto le restará eficacia, aunque es previsible que esta circunstancia dure poco debido al apoyo decidido del resto de los fabricantes. De momento, sienta las bases de lo que será el futuro inmediato del acceso a red seguro
   Microsoft vertebra NAP con varios componentes. Para implementar esta herramienta, se debe contar primero con los Puntos de Acceso con imposición NAP, que el fabricante denomina NAP Enforcement Points. Estos son utilizados en la conexión de los ordenadores y tienen capacidad para evaluar el nivel de cumplimiento de las directivas de Protección de Acceso a Red por parte de los ordenadores que se conectan. Establecida la conexión, los servidores NAP se encargan de establecer y validar los requisitos que se han de cumplir para definir el nivel de acceso que tendrán los ordenadores conectados. Hay varios roles en la plataforma. Los NAP Healt Policy Servers, Servidores NAP de Directivas de Estado, son quienes alojan las directivas de acceso a la red y proporcionan la validación de su nivel de cumplimiento. También pueden desempeñar las funciones de autenticación, autorización y contabilidad para el acceso a la red. Del nivel de revisión de actualizaciones, parches y demás software exigido en las directivas de estado, se encargan de su mantenimiento los Servidores de Requerimientos del Sistema, Health Requirement Servers. El Servidor de Requerimientos del Sistema para el programa antivirus será el encargado de mantener la información sobre las últimas versiones de motor y firmas del antivirus
   Para completar el despliegue en el lado del servidor, se encuentran los Servidores de Actualización, Remediation Servers. Actúan bajo esta denominación aquellos servidores que alojan el software que ha de tener instalado los ordenadores que se conectan a la red. Sirven como repositorio para la distribución del software exigido en la conexión. Actualizaciones, parches y configuraciones pueden ser descargados desde estos servidores automáticamente, y sin necesidad de intervención del usuario, por aquellos ordenadores que no cumplen con los requisitos exigidos.
   Por último, se encuentra el cliente NAP, cualquier ordenador, de escritorio o servidor, que se conecta a la red. En la práctica, son aquellos ordenadores que disponen de soporte para esta funcionalidad. Los clientes NAP requieren como característica soporte para DHCP, VPN, IPSec y autenticación 802.1x.

Terminal Services Gateway
Otra de las mejoras que aportan valor añadido a Windows Server 2008 es el acceso remoto tanto a aplicaciones como a datos internos de la red. En esta ocasión, Microsoft ha tenido especial interés en mejorar esta funcionalidad, debido a la proliferación de clientes y usuarios remotos con cada vez más requerimientos de acceso.
   En este sentido, uno de los aspectos más relevantes es Terminal Server Gateway, un elemento que proporciona acceso a datos o aplicaciones internas a los clientes o usuarios corporativos. En esencia, Terminal Server Gateway extiende el concepto de las VPN (Virtual Private Network, o redes privadas virtuales), ya que añade una serie de ventajas a la hora de implementar un sistema de acceso remoto con garantías. A nivel básico, la comunicación entre el cliente y el servidor se efectúa de forma segura de extremo a extremo, mediante la creación de un túnel SSL (encriptado, gracias al nuevo cliente de conexión Remote Desktop Connection) en el que se encuentran el protocolo de conexión remota, RDP (Remore Desktop Protocol). Una vez que alcanza el servidor de destino, éste elimina el encapsulado el resultado y procede a comunicar de forma interna a los servidores Terminal Server internos dentro de la infraestructura de la empresa. Por lo tanto, debido a que Terminal Server Gateway ha de actuar como frontal de acceso, debe ser situado en una DMZ, por delante del resto de servidores o servicios. No obstante, es posible realizar ciertas mejoras sobre este esquema, por ejemplo añadiendo validaciones de los usuarios contra el Directorio Activo de la empresa antes de proceder a su direccionamiento interno. Además de esto, también es posible configurar un servidor de políticas de acceso, denominado Network Policy Server, con el fin de realizar previamente un chequeo del estado de salud en la máquina con el fin de comprobar si está preparada para acceder al interior de la red y a los datos o aplicaciones que allí se encuentran (para conocer más acerca de este aspecto, recomendamos leer parte de NAP, Network Acces Protection).OverVw-Ent-BoxShotSm
   En el capítulo de las ventajas podemos comentar que con Terminal Server Gateway tenemos acceso seguro con independencia de si el entorno de conexión es fiable o no (ya sea desde un cibercafé, un portátil no gestionado o un equipo de un hotel, lo que ya de por sí es una ventaja), ya que nosotros podemos especificar medidas de análisis y protección en el lado del servidor.
   Otra de las ventajas de esta modalidad es que no tendremos limitaciones de acceso, ni a nivel de cortafuegos intermedios ni a la hora de penetrar  en redes que hagan traducción en las direcciones de red (NAT).
   A la hora de realizar su instalación, Terminal Server Gateway se muestra en Windows Server 2008 como un rol más, aunque su instalación implicará dos dependencias. Por un lado, el servidor web (IIS) y, por el otro, el servidor de políticas para chequeo de salud (NPS). Después será necesario instalar un certificado (bien emitido por nuestra propia empresa, de una PKI de nuestro dominio o emitido por una entidad externa), debido a que las aplicaciones se publican a través de una interfaz web.
   Por último, además de lo comentado, es posible complementar este escenario con la incorporación de Terminal Server Web Acces (ya sea en la misma máquina o en una en paralelo), que permite publicar las aplicaciones que necesitemos en cada momento a través de un frontal web de fácil acceso, intuitivo y multiplataforma.

Windows Small Business Server 2008, el sistema operativo para la pequeña empresa
No obstante, aunque muchas de las características de Windows Server 2008 tienen sentido en un entorno de empresa media o grande, Microsoft también se ha ocupado de las empresas con necesidades menos agresivas. Para ello, dispone de Windows Small Business Server 2008 (servidor para pequeños negocios), que forma parte de su familia Essential Business Server, la opción actualizada a la nueva versión del sistema operativo.
   Se trata de una modalidad aligerada del producto completo en la que se han incluido los aspectos más importantes que todo negocio pequeño debería tener, como herramientas para el trabajo en grupo y la colaboración entre departamentos, un entorno centralizado para la mensajería de la empresa, así como protección para todos los recursos desplegados, entre otros aspectos, medidas todas ellas orientadas a empresas que no dispongan de personal interno de TI.
   Las empresas que optar por SBS obtienen una serie de beneficios, entre los que se encuentran la completa integración de todos los componentes de que dispone un único paquete y en un único servidor, la automatización de procesos (ya que todos los integrantes del producto han sido modificados para que sean capaces de trabajar de forma conjunta) y la implantación de un único punto centralizado desde el que configurar y gestionar la zona más importante de la red (gracias a una consola de gestión integral).
   Además de esto, Small Business Server cuanta con técnicas de protección, tanto a nivel de datos (copias de seguridad y restauración) como de actualizaciones del sistema de forma automática (Windows Update). De hecho, la nueva versión de SBS profundiza aún más en este sentido, ya que incorpora también seguridad a nivel de malware y en la protección del correo electrónico.
   Por último, otra de las ventajas del producto es la incorporación de ciertas funcionalidades que aumentan valor, como la generación de un sitio web (tanto a nivel externo como de intranet) o el soporte de correo para dispositivos móviles y los usuarios más nómadas a través de Outlook Web Acces (acceso al correo electrónico interno mediante el navegador web), entre otras.
   Dentro del entorno de SBS podemos optar por dos modalidades, la edición Standard y la Premium. La diferencia entre ambas es el número y calidad de las funcionalidades integradas. No obstante, ambos casos han experimentado un proceso de actualización de sus componentes, con el fin de adaptarlos a las últimas versiones de cada uno de ellos. De hecho, si optamos por la alternativa Standard contaremos, además del núcleo de Windows Server 2008, con la tercera versión de los servicios de Sharepoint, que permite la colaboración entre los diferentes grupos de trabajo estableciendo entornos de gestión sencilla y centralizada, lo que aumenta la productividad y mejora el ciclo de producción.
   También dispone de Exhange Server 2007 para dotar a los usuarios con cuentas de correo que les permitan comunicarse tanto con clientes y socios para incrementar posibilidades de venta o mejorar los procesos de fabricación, por ejemplo. Además, con el fin de asegurar la protección del sistema de mensajería centralizado contamos, como novedad en esta versión, con Forefront for Exchange, que filtra todo tipo de malware por nosotros antes de que pase a fluir por los canales internos de la infraestructura, así como Windows Live OneCare, lo que mejora la seguridad del tráfico que pasa por la red.19042008
   Por supuesto, la edición Premium, como es lógico, parte de la base de la Standard, pero va un poco más allá, ya que incluye una base de datos profesional como la edición Standard de SQL Server 2008, así como los servicios de Terminal Services en modo aplicación, que permite a los usuarios móviles acceder a los recursos de la organización de forma remota. También, como particularidad de la versión Premium, contamos con una segunda licencia de Windows Server 2008, que nos permite, por ejemplo, la posibilidad de instalar la característica de Terminal Services de forma independiente, algo que, según los datos de Microsoft, ha sido una petición muy demandada en anteriores versiones del producto.
   La última diferencia entre la versión Standard y Premium es la licencia de acceso (conocida como CAL). Aquí, la Standard CAL otorga acceso al sistema y las aplicaciones que éste tiene instalada. Por su parte, la Preimum CAL va más allá, ofreciendo la posibilidad de acceso tanto en el primer servidor como en el segundo, así como a la versión SQL Server 2008 Standard instalada en él.
   A nivel general, una de las diferencias más palpables con respecto a la versión anterior  es la eliminación del cortafuegos integrado (ISA Server), ya que, durante el proceso de desarrollo, Microsoft comprobó que los clientes prefieren instalar esta funcionalidad de forma ajena, en un equipo externo.
   Desde el punto de vista de despliegue, en cualquiera de las versiones, el servidor principal ha de estar basado en la tecnología de 64 bits, ya que favorece el rendimiento (de hecho, Exchange Server 2007 está disponible únicamente para entornos compatibles con esta arquitectura). Además de esto, en la versión Premium es posible que el segundo servidor (con SQL Server y Terminal Services) esté instalado sobre una base de 32 bits.
   Tal y como ocurre con todos los productos profesionales de Microsoft, uno de los puntos más importantes de Small Business Server es la gestión. En este caso, se trata de un modelo muy sencillo para manejar (para esta versión ha sido totalmente rediseñada), desde donde tenemos acceso a configurar todos los aspectos que se incluyen en el sistema (desde la gestión básica de los usuarios hasta la administración de las copias de seguridad, por ejemplo). Esta consola de gestión funciona a base de simples asistentes que nos guían paso a paso durante el proceso de creación o el mantenimiento de los elementos de la red (crear un nuevo usuario o la compra de un dominio de internet para nuestra organización, entre otros).
   Además, esta consola es totalmente extensible con utilidades de terceros, con el fin de integrar en el entorno de gestión de SBS las herramientas de control del resto de elementos que componen la infraestructura (por ejemplo, las utilidades del servidor o el control de un servidor NAS, entre otros). De esta forma se pretende conseguir que el mantenimiento de todos los componentes de la red se efectúe desde un único punto, lo que simplifica enormemente la tarea de gestión.
   Paralelamente a esto, al igual que se accede a la consola de administración, los usuarios con grandes capacidades de movilidad tendrán la posibilidad (previa concesión por parte de los permisos adecuados) de acceder a un entorno web muy sencillo desde el que acceder a los recursos habituales.
   No obstante, aunque Windows Server 2008 ya ha alcanzado el estatus de producto final, algunos componentes, como por ejemplo SBS, todavía están en la recta final de su desarrollo. En el caso de Small Business Server, la versión final está prevista para la segunda mitad de 2008.

Internet Information Services 7 (IIS)
De hecho, uno de los aspectos que más se han querido fomentar desde Microsoft para esta nueva versión de Windows Server 2008 es la función de servidor web, ya que se trata de dos modalidades con gran potencial de crecimiento.
   En primer lugar, la alternativa que propone Microsoft para el servidor web se denomina Internet Information Services. En el caso concreto de Windows Server 2008 debuta la séptima edición de IIS, una versión cargada de novedades encaminadas a mejorar la productividad, la seguridad y la compatibilidad con todo tipo de lenguajes.
   Como principales novedades, IIS7 está basado ahora en una arquitectura modular que lo convierte en un producto muy flexible (instalando únicamente los componentes que necesitamos para cada servicio). La nueva versión de IIS dispone de 40 componentes diferentes que podemos instalar, aunque por defecto, al instalar este rol, el sistema añade los servicios mínimos necesarios para funcionar con normalidad. El hecho de que sea una arquitectura modular permite reducir la superficie de exposición y minimizar los riesgos cuando aplicamos parches (ya que únicamente habremos de instalar los que afectan a nuestro entorno). De hecho, otro dato interesante es que, a la hora de actualizar o de aplicar parches al servidor, únicamente aplicará los que requiera (en base a los componentes instalados), lo que, una vez más, nos permite optimizar el uso del ancho de banda y se reduce la superficie de ataque, mejora la gestión (puesto que no es necesario mantener o administrar componentes que no necesitamos), además de contribuir drásticamente en la mejora del rendimiento del sistema. En este sentido, IIS 7 también es capaz de aislar completamente los diferentes sitios que generamos, de tal forma que los problemas que afecten a uno de ellos no tengan repercusiones en el resto.
   A nivel general, esta nueva versión se presenta como una plataforma de gestión eficiente para aplicaciones, no sólo basadas en la plataforma .NET (para las que la migración de aplicaciones ASP o ASP.NET es prácticamente transparente), sino que ya permita la posibilidad de ejecutar código desarrollado en PHP (gracias a la integración del módulo FastCGI, que además de dotarle de la posibilidad de ejecutar múltiples versiones de PHP, permite ejecutar este tipo de aplicaciones hasta un 25% más rápidas), además de profundizar en la integración con ASP.NET (a lo que contribuyen las API nativas de Win32 y .NET Framework) y ser totalmente compatible con tecnología como Silverlight o Ajax, entre otros.
   Otro punto importante de IIS es la posibilidad de extender sus funcionalidades, ya que el propio producto está basado en API públicas, por lo que, en caso de necesitar cualquier tipo de mejora o cambio en este aspecto, sería posible modificarla e incorporarla a nuestro sistema en particular.
   En cuanto al rendimiento se refiere, IIS 7 permite manejar hasta cuatro procesadores y un total de 32 GB de memoria RAM por cada instancia virtual que creemos en máquinas de 64 bits, lo que ofrece potencia necesaria para mantener un servidor con bastantes requerimientos. Por otra parte, la gestión también se ha mejorado sustancialmente gracias a la incorporación de Xcopy, que nos permite migrar, no sólo los datos que tengamos de un servidor a otro, sino que traslada la configuración existente, lo que nos asegura el resultado que deseamos en cada momento (esto es especialmente bueno para cuando trabajamos con un servidor de desarrollo y queremos asegurarnos de que funcionará del mismo modo en el servidor de producción).
   En cuanto a la gestión se refiere, contamos con el Administrador de Internet Information Services, que nos abre la puerta a la gestión más particular del servidor web. Desde aquí tenemos acceso directo a las funcionalidades tanto a del propio IIS como de ASP.NET, reduciendo el tiempo de gestión por parte del personal técnico.
   Dentro de este mismo apartado, tenemos que comentar la posibilidad de la administración delegada que nos ofrece la opción de confiar en otros usuarios cierto tipo de tareas de mantenimiento o gestión rutinarias (es posible establecer distintos tipos de usuarios; de sólo lectura, de lectura/escritura o no visibles) para gestionar los servidores de nuestra organización. Esta posibilidad resulta especialmente interesante en los entornos de oficinas remotas o delegaciones, donde podemos confiar algunas de las labores más típicas y menos intrusivas al personal técnico in situ.
   Como complemento a esto, IIS 7 también aporta herramientas de diagnóstico, como Failed request tracing, que monitorizan en todo momento (en base a reglas configurables) las aplicaciones que pueden estar generando errores produciendo un tiempo de respuesta inadecuado, con el fin de identificarlas y depurarlas. Igualmente, cuando una página muestra un error, IIS 7 es capaz de discernir de forma mucho más avanzada la causa que lo provocó, informando a nivel interno (al desarrollador) los posibles problemas y soluciones.

Virtualización
Sin duda, junto con el apoyo al servidor web (Internet Information Services 7), una de las apuestas más importantes de Windows Server 2008 es la entrada de Microsoft en el mercado de la virtualización, ya que se esperan crecimientos en este área bastantes importantes. De hecho, las cifras que se manejan actualmente es que tan sólo el 5% de los servidores auguran que esta tecnología será bastante lucrativa en los próximos años.
   Aunque sabemos que la necesidad de virtualizar equipos y sistemas no es nueva, lo cierto es que en los últimos años está adquiriendo ventajas bastantes importantes, debido fundamentalmente al desarrollo que está experimentando el mundo del hardware. En este sentido, el significativo aumento en la potencia de los nuevos servidores, gracias a la aparición de los procesadores multinúcleo o las arquitecturas de 64 bits, hace que plantearse un esquema de servicios virtualizados sea una apuesta ganadora en muchos casos.
   Tanto es así que el compromiso de Microsoft con las tecnologías de virtualización se efectúa desde varios frentes (desde el punto de vista de las aplicaciones, con Softgrid o Terminal Services, a nivel de infraestructura, con Virtual Server 2008 o desde el plano de la interoperabilidad, llegando a acuerdos con Novell o XEN, entre otros).
   Sin embargo, aunque Windows Server 2008 da cobertura a todas ellas, el aspecto más importante lo encontramos en la nueva arquitectura de virtualización que debuta con la nueva versión, denominada Hyper-V Server (anteriormente conocida como Windows Server Virtualization). Esta nueva arquitectura está basada en la incorporación de un nuevo hypervisor que permite implementar técnicas de virtualización de máquinas a nivel de  sistemas operativos.
   Desde el punto de vista de los entornos de aplicaciones, Hyper-V está diseñado para optimizar infraestructuras aprovechando la consolidación de servidores (unificar en un mismo hardware múltiples sistemas o servicios), generación de escenarios para pruebas en preproducción (ejecución y análisis de los posibles efectos de nuestros productos en diferentes entornos antes de su publicación masiva), implantación de un sistema eficaz para entornos con delegaciones remotas (tanto en modo consolidado como distribuido) o diseño de planes de contingencia que aseguren la continuidad de negocio en caso de caída o desastre.
   Hyper-V Server está basado en un Hyervisor, un reducido componente software (ocupa menos que el controlador de un ratón) que se ejecuta entre el propio hardware de la máquina y el sistema operativo. La ventaja de este modelo es, en primer lugar, la total independencia que se produce entre las máquinas virtuales generadas a partir de él y que no permite el traspaso de información entre una y otra (evitando así que en un ataque masivo pueda afectar a varias máquinas virtuales a la vez). Otra de las ventajas teóricas de esta alternativa es el mayor rendimiento, ya que para implantar un modelo de estas características es necesario que la CPU donde se quiera instalar sea compatible con las últimas técnicas de virtualización (Virtualización Asistida por Hardware) que han desarrollado tanto Intel (VT) como AMD (V). Gracias a estas técnicas se consigue una comunicación más directa y eficaz a la ora de acceder a los recursos del hardware desde cada uno de los sistemas virtualizados, lo que implica un mayor aprovechamiento del entorno.
   Además, el Hypervisor está basado, de forma conceptual, en el principio de microkernel, que únicamente se ocupa de realizar las tareas de virtualización, utilizando tan sólo el código estrictamente necesario para ello (lo que redunda en mayor seguridad y menores problemas de estabilidad o incompatibilidades, además de acelerar el rendimiento). El modelo de microkernel no incorpora código de terceros, ya que los controladores necesarios se ejecutan en cada máquina virtual, y además usan el propio controlador original, lo que redunda en una mayor agilidad y compatibilidad por parte del fabricante.0179418
   Por lo tanto, dentro de lesquema de aplicación quedaría el hypervisor por encima del hardware del equipo, y sobre éste se montaría una partición padre (que contiene el sistema operativo inicial, concretamente Windows Server 2008 con arquitectura de 64 bits, ya que el rol de virtualización requiere un servidor x64). En esta partición se instala una serie de componentes a nivel de usuario, sobre todo para llevar a cabo las típicas tareas de gestión (creación de máquinas virtuales o reiniciarlas, por ejemplo). Por su parte, a nivel de núcleo aparecen una serie de piezas que posibilitan el buen funcionamiento del sistema entre las diferentes instancias virtuales, como por ejemplo un proveedor de servicios (Virtual Service Provider, VSP), un bus de comunicación entre el resto de particiones o los controladores reales de la máquina, entre otros.
   Una vez que tenemos esto, ya contamos con los mimbres para levantar instancias virtuales (o particiones hijas), que podrán ser de varios perfiles según el tipo de sistema operativo, fundamentalmente. En primer lugar, podemos optar por instalar una máquina virtual basada en Windows Server 2003 (o el propio 2008), en cuyo caso el sistema sabrá que está siendo virtualizado, lo que otorga un nivel de integración muy mejorado. En este caso la máquina virtual contará con el núcleo del sistema (Windows Server) y un cliente que se encarga de consumir los servicios de la partición padre (Virtual Service Client, VSC), además de un bus de comunicación entre ambas particiones.
   En el caso de instalar un sistema operativo que no sepa que está siendo virtualizado, el funcionamiento se basará principalmente en en emulaciones, lo que, sobre el papel resultará menos óptimo, ya que la comunicación ha de pasar por un proceso de traducción antes de alcanzar su destino. Éste sería el caso, por ejemplo, de un sistema Windows NT, Windows 98 o Windows X, por citar algunos ejemplos.
   Por último, otra de las posibilidades que tenemos a la hora de crear nuevas instancias virtuales con Windows Server 2008 es instalar un sistema operativo con núcleo basado en Linux. Aquí entran en juego otra serie de aspectos, por ejemplo el acuerdo al que Microsoft y Xen llegaron para hacer que las máquinas capaces de funcionar bajo entornos Xen pudieran comunicarse con la arquitectura de virtualización de Microsoft. Si éste es el caso, el sistema montará una serie de componentes, como un adaptador para hiper llamadas, el cliente para consumir los servicios de la partición padre (VSC) o el bus de comunicación virtual, pero previamente optimizados para hacer interoperables ambos sistemas.
   A modo de conclusión, Hyper-V se presenta como la alternativa de Microsoft a la hora de crear y gestionar máquinas virtuales a nivel de sistema operativo. Dentro de Windows Server, Hyper-V se presenta como un rol más que podemos añadir o eliminar desde la consola Server Manager (aunque para activarlo es necesario contar con n sistema totalmente compatible con la plataforma de 64 bits). Sin embargo, tal y como ha ocurrido con algunos de los productos aquí comentados, Hyper-V por el momento está en fase beta y su comercialización final se espera para la primera mitad de 2008 (verano, aproximadamente). No obstante, como Windows Server 2008 ya está en lista de precios y es posible comprarlo, todos los clientes que compren una licencia de Windows Server 2008 tendrán la posibilidad de descargar Hyer-V de forma gratuita cuando alcance su fase de comercialización (se distribuirá a través de Windows Update).
   Cuando esto ocurra, Microsoft ofrecerá una sere de opciones de compra en torno a Windows Server 2008, en la que será posible comprar el producto con o sin Hyper-V. De hecho, Microsoft ya ha confirmado que existirá la posibilidad de comprar Hyper-V Server de forma individual a un precio que rondará los 27 dólares.

System Center Virtual Machine Manager
Pero la apuesta de Microsoft en lo que se refiere a la virtualización no sólo afecta a nivel de arquitectura. De hecho, consciente de que uno de los principales problemas de la implantación de máquinas virtuales es precisamente el riesgo a encontrarnos con un gran número de sistemas en nuestra infraestrucutra, Microsoft tiene previsto dotara los administradores de TI(Tecnología de la Información) con las herramientas necesarias para, no sólo controlar el excesivo aumento del parque virtual, sino administrar cada una de ellas con el fin de poder actualizarlas o generar sistemas de contingencia ante desastres, entre otros.
   Y Microsoft pretende conseguir todo esto mediante Virtual Machine Manager, un componente que forma parte de System Center, la estrategia de gestión y administración de productos de la compañía.
   De hecho, System Center Virtual Machine Manager será capaz de ayudarnos de forma integral en el proceso, tanto de creación como de mantenimiento de nuestro parque virtual. En primer término, una de las utilidades que se integran en este producto es la posibilidad de buscar entre nuestra infraestructura candidatos óptimos para pasar de entorno físico a virtual, con el fin de obtener un sistema de consolidación de garantías.
   Una vez identificados los candidatos más apropiados, también contaremos con herramientas que nos facilitan el traspaso de la conversión tanto desde el servidor físico al virtual (P2V), como de virtual a virtual (V2V, desde entornos VMware al formato de Microsoft, VHD). En cualquier caso, los lectores con experiencia en este campo saben que, tanto el mantenimiento como la migración de máquinas, no es una tarea sencilla. Por este motivo Virtual Machine MAnager nos propone Administrator Console (basada en la interfaz de Operations Manager 2007), un entorno que nos permite afinar en la configuración de los equipos virtuales una vez que están establecidos, además de ayudarnos en el proceso del cambio de una máquina virtual de un host a otro.
   Junto a esto, Virtual MAchine Manager también nos propone ayudas a la hora de seleccionar el mejor emplazamiento para nuestros equipos virtuales, gracias al componente Intelligent Placement, que analiza el rendimiento, el espacio necesario en disco o la carga que necesita de CPU para proponer una ubicación más adecuada a cada caso.
   Tal y como es habitual en los entornos de Microsoft, Virtual Machine Manager funciona con sencillos asistentes que nos guían durante el aprovisionamiento y despliegue de nuevas máquinas virtuales. También contamos con una librería que nos proporciona un catálogo de máquinas virtuales en el que vemos, no sólo la ubicación, sino una descripción del contenido y la ruta física de acceso a sus discos duros virtuales, por ejemplo. Esta librería aporta igualmente una serie de plantillas que nos ayudan a la hora de establecer una serie de normativas cuando queremos generar nuevos equipos virtuales, como la configuración del hardware o el sistema operativo a utilizar.
   Con el fin de aligerar la complejidad que supone gestionar las máquinas virtuales, los administradores tienen la posibilidad de implementar la gestión delegada, con el fin de otorgar a un cierto tipo de usuarios el control o aprovisionamiento de nuevas máquinas virtuales, mientras que nos aseguramos de que cumplen con la normativa establecida y de que se cumple un determinado procedimiento de creación, mantenimiento y, en los casos necesarios, su posterior eliminación.
   Del mismo modo, con el objetivo de mejorar el rendimiento, Virtual Machine Manager es capaz de integrarse en sistemas SAN para realizar el copiado de las imágenes de disco (generalmente pesadas en tamaño) a través de sistemas de fibra, reduciendo el tiempo de copiado y mejorando la distribución interna de los recursos virtuales.
   Por último, desde el punto de vista de la gestión, Virtual Machine Manager es compatible con la generación de scripts en PowerShell, lo que  facilita la integración de varios procesos por lotes.




Artículo extraído de PCWORLD – Nº 252 – Abril 2008, página 51.

:Más información en INTERNET:

Fundamentos de programación con Módula-2 (Tema 14_2)

14.4 Realización de tipos abstractos en Modula-2

Tal como se ha indicado, el concepto de módulo está ligado a la idea de abstracción; en particular, los módulos de Modula-2 son un mecanismo muy apropiado para la definición de tipos abstractos de datos.

14.4.1 Definición de tipos abstractos como módulos
Los módulos de Modula-2 permiten definir bien tipos abstractos de datos, gracias a la posibilidad de agrupación de diferentes elementos relacionados entre sí, y a la ocultación de los detalles de realización interna.

Podríamos decir que la interfaz del módulo equivale a la especificación del tipo, abstracto, de datos, y que la realización del módulo establece su representación interna.

Continuando con el ejemplo de los meses del año, lo definiremos como tipo abstracto especificando la colección de valores posibles y la colección de operaciones de manipulación que necesitemos. Fijando de manera un tanto arbitraria estas operaciones de manipulación, podríamos escribir una primera versión de la especificación del tipo abstracto:

(*_/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\_
_/-\_
_/-\_   Este módulo define el tipo abstracto MES
_/-\_
_/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\_
*)

DEFINITION MODULE Meses;

TYPE TipoMes =
   ( MesNulo, Enero, Febrero, Marzo, Abril, Mayo, Junio, Julio,
     Agosto, Septiembre, Octubre, Noviembre, Diciembre );

PROCEDURE Siguiente( mes: TipoMes; n: INTEGER ): TipoMes;
(* Mes que será dentro de ‘n’ meses *)

PROCEDURE Leer( VAR mes: TipoMes );
(* Lee el mes, en letra, desde el fichero de entrada *)

PROCEDURE Escribir( mes: TipoMes; ancho: INTEGER );
(* Escribe el mes en letra, con el ancho indicado *)

END Meses.

Teniendo definida la interfaz podemos ya pasar a escribir algún programa que use ese tipo abstracto de datos. Por ejemplo, podemos programar simplemente el cálculo del mes final de un plazo, conociendo el mes inicial y la duración. El programa podría ser:

(*_/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\_
_/-\_
_/-\_   Este programa determina el mes en que termina un plazo,
_/-\_   sabiendo el mes inicial y los mese que dura.
_/-\_
_/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\_
*)

MODULE MesFinal;
   FROM InOut IIMPORT ReadInt, WriteString, WriteLn;
   IMPORT Meses;
   VAR
      ahora, luego: Meses.TipoMes;
      plazo: INTEGER;

BEGIN
   (*– Leer los datos –*)
      LOOP
         WriteString( ‘¿En qué mes estamos? ‘ );
         Meses.Leer( ahora );
         Meses.Escribir( ahora, 10 ); WriteLn;
         IF ahora <> Meses.MesNulo THEN EXIT END;
         WriteString( ‘Mes no reconocido, repita’ ); WriteLn
      END;
      WriteString( ‘¿Cuántos meses faltan? ‘ );
      ReadInt( plazo ); WriteLn;
   (*– Calcular e imprimir el resultado –*)
      luego := Meses.Siguiente( ahora, plazo );
      WriteString( ‘El plazo acaba en ‘ );
      WriteLn
END MesFinal.

Las posibilidades de usar el tipo abstracto con sólo definir la interfaz incluyen la compilación real del programa que acabamos de escribir. No podremos, sin embargo, ejecutarlo hasta haber escrito la realización de tipo abstracto.

A continuación presentamos una posible realización del módulo Meses.

(*_/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\_
_/-\_
_/-\_   Este módulo realiza el tipo abstracto MES
_/-\_
_/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\_
*)

IMPLEMENTATION MODULE Meses;

FROM InOut IMPORT Read, Write, EOL;
TYPE NombreMes = ARRAY [0..10] OF CHAR;
VAR nombres: ARRAY [MesNulo..Diciembre] OF NombreMes;

PROCEDURE Siguiente( mes: TipoMes; n: INTEGER ); TipoMes;
(* Mes que será dentro de ‘n’ meses *)
   VAR x, m: INTEGER;
BEGIN
   (*– ajusta el incremento a un año, como máximo –*)
      x := n MOD 12;
   (*– incrementa en forma circular –*)
      m := ORD(mes); INC( m, x);
      IF m > 12 THEN DEC( m, 12 ) ENDM
      RETURN VAL( TipoMes, m )
END Siguiente;

PROCEDURE Leer( VAR mes: TipoMes );
(* Lee el mes, en letra, desde el fichero de entrada *)
   VAR c: CHAR;

PROCEDURE Ensayo( c1, c2: CHAR; m1, m2: TipoMes): TipoMes;
(* Distingue entre dos meses por el siguiente carácter *)
BEGIN
   Read( c );
   IF CAP( c ) = c1 THEN RETURN m1
   ELSIF CAP( c ) = c2 THEN RETURN m2
   ELSIF RETURN MesNulo END
END Ensayo;

BEGIN (* Leer *)
   (*– Buscar el comienzo del nombre –*)
      REPEAT Read( c ) UNTIL c<>’ ‘;
   (*– Reconocer los primeros caracteres –*)
      CASE CAP( c ) OF
          ‘A’: mes := Ensayo( ‘B’, ‘G’, Abril, Agosto )
      |   ‘D’: mes := Diciembre
      |   ‘E’: mes := Enero
      |   ‘F’: mes := Febrero
      |   ‘J’: Read( c );
              IF CAP( c ) = ‘U’ THEN
                 mes := Ensayo( ‘L’, ‘N’, Julio, Junio )
              ELSE
                 mes := MesNulo
              END
      |   ‘M’: Read( c );
               IF CAP( c ) = ‘A’ THEN
                  mes := Ensayo( ‘R’, ‘Y’, Marzo, Mayo )
               ELSE
                  mes := MesNulo
               END
      |   ‘N’: mes := Noviembre
      |   ‘O’: mes := Octubre
      |   ‘S’: mes := Septiembre
      ELSE mes := MesNulo END;

   (*– Salar el resto del nombre –*)
      WHILE (CAP( c ) >= ‘A’) AND (CAP( c ) <= ‘Z’) DO
         Read( c )
      END
END Leer;

PROCEDURE Escribir( mes: TipoMes; ancho: INTEGER );
(* Escribe el mes en letra, con el ancho indicado *)
   VAR k: INTEGER;
BEGIN
   FOR k := 0 TO ancho-1 DO
      IF k < 10 THEN              (* escribir letras del nombre *)
         Write( nombre[ mes, k ] )
      ELSE                            (* rellenar con blancos *)
         Write( ‘ ‘ )
      END
   END
END Escribir;

BEGIN (* Meses *)
   nombres[ MesNulo    ] := ‘??????????’;
   nombres[ Enero      ] := ‘Enero     ‘;
   nombres[ Febrero    ] := ‘Febrero   ‘;
   nombres[ Marzo      ] := ‘Marzo     ‘;
   nombres[ Abril      ] := ‘Abril     ‘;
   nombres[ Mayo       ] := ‘Mayo      ‘;
   nombres[ Junio      ] := ‘Junio     ‘;
   nombres[ Julio      ] := ‘Julio     ‘;
   nombres[ Agosto     ] := ‘Agosto    ‘;
   nombres[ Septiembre     ] := ‘Septiembre’;
   nombres[ Octubre    ] := ‘Octubre   ‘;
   nombres[ Noviembre  ] := ‘Noviembre ‘;
   nombres[ Diciembre  ] := ‘Diciembre ‘;
END Meses.

Una vez compilados el programa principal y el módulo, podemos ya montar y ejecutar el programa completo, y obtener, por ejemplo:

 

14.4.2 Tipos opacos
El módulo Meses del ejemplo anterior define realmente un tipo abstracto de datos, ya que especifica la colección de valores posibles del TipoMes, y las operaciones que pueden realizarse con esos valores.

Sin embargo no se aplica de manera total la propiedad de ocultación, ya que es visible en la interfaz que el tipo se define como un tipo enumerado, y esto permite usar todas las operaciones posibles del lenguaje para estos tipos. Por ejemplo, nada impide emplear el procedimiento predefinido INC para intentar obtener el mes final del plazo, escribiendo:
                . . . .
                luego := ahora;
                INC( luego, plazo );
                . . . .
Esto sería un error, ya que estas setencias no tienen en cuenta que los meses van avanzando cíclicamente, y que después de Diciembre viene de nuevo Enero. El procedimiento INC no opera cíclicamente, sino que da error si se rebasa el final del año.

Para asegurarse de que a los datos de un tipo abstracto se les aplican únicamente las operaciones que se han definido expresamente para ellos, es posible usar un artificio que permite definir los llamados tipos opacos en Modula-2.

Un tipo opaco se define en un "módulo de definición" escribiendo sólo la parte inicial de una definición de tipo, en la forma:

               TYPE nombre_de_tipo;

Como puede observarse, sólo se especifica el nombre del tipo, pero no se da ninguna información acerca de los posibles valores de este tipo ni de su representación. De esta manera es imposible aplicar ninguna construcción del lenguaje a los valores de ese tipo, salvo las siguientes:

  • Un valor del tipo opaco puede asignarse a una variable del mismo tipo.
  • Los valores o variables de ese tipo pueden pasarse como argumentos.
  • Dos valores del mismo tipo pueden comparase para ver si son iguales.

La definición completa del tipo ha de hacerse en el correspondiente "módulo de implementación". Sin embargo esta definición está sometida a fuertes limitaciones, para permitir que el "módulo de definición" pueda compilarse sin usar ninguna información del "módulo de implementación".

Las versiones más estrictas de Modula-2 exigen que los tipos opacos se definan internamente como tipos puntero, exclusivamente. Otras versiones permiten definir estos tipos con más libertad, pero de modo que el espacio de memoria necesario para almacenar cada valor del tipo sea mayor que el espacio ocupado por un puntero. Esto permite, en general, definir también los tipos opacos como tipos ordinales de cualquier clase.

De todas formas la seguridad conseguida en el uso de la interfaz del módulo es a costa de complicar la invocación de ciertos elementos. Por ejemplo, no es posible definir funciones que devuelvan los valores constantes que se necesiten, o bien que determinen si el valor del tipo opaco es un valor en particular.

En el caso de tipos opacos que deban realizarse como estructuras de datos, será necesario, en general, realizarlos con variables dinámicas, y habrá que incluir sistemáticamente operaciones sobre el tipo abstracto para crear o destruir variables de ese tipo.

14.4.3 Datos encapsulados
Los esquemas anteriores equivalen a definir un tipo (abstracto), del que luego hay que declarar las variables necesarias. Cuando en un programa sólo hay que manejar una única variable de ese tipo, se puede conseguir fácilmente una ocultación total sin necesidad de recurrir a tipos opacos, si dicha variable única es interna al módulo en que se desarrolla el tipo abstracto.

Existe una analogía clara entre esta idea y las dos formas básicas de declaración de variables en Modula-2. En el primer caso escribiríamos, por ejemplo:

              TYPE Nombre = ARRAY [0..20] OF CHAR;
              . . . .
              VAR autor: Nombre;
              . . . .
              ReadString( autor );
              WriteString( autor )

En el segundo caso escribiríamos:

             VAR autor: ARRAY [0..20] OF CHAR;
             . . . .
             ReadString( autor );
             WriteString( autor )

En este segundo caso el tipo es anónimo, y no tiene nombre particular. Aplicando esta idea al manejo de datos abstractos en módulos, el primer caso, descrito en las acciones anteriores, equivaldría a escribir:

DEFINITION MODULE Nombres;
   TYPE Nombre = ARRAY [0..20] OF CHAR;
   PROCEDURE Leer( VAR n: Nombre );
   PROCEDURE Escribir( n: Nombre );
END Nombres.

MODULE Principal;
   IMPORT Nombres;
   VAR autor: Nombres.Nombre;
BEGIN
   Nombres.Leer( autor );
   Nombres.Escribir( autor );
END Principal.

El esquema correspondiente al segundo caso, sin tipo explícito, sería:

DEFINITION MODULE Autor;
   PROCEDURE Leer;
   PROCEDURE Escribir;
END Autor.

MODULE Principal;
BEGIN
   Autor.Leer;
   Autor.Escribir
END Principal.

En este segundo esquema el módulo no corresponde al tipo, sino a la variable, y de acuerdo con ello se ha elegido el nombre del módulo. La variable en sí estaría oculta en el "módulo de implementación", en la forma:

IMPLEMENTATION MODULE Autor;
   VAR autor: ARRAY [0..20] OF CHAR;
   . . . .
END Autor.

El módulo constituye una cápsula que protege al dato, de manera que sólo se puede acceder a él usando las operaciones de la interfaz, y ninguna otra en absoluto. Cuando se usa esta técnica no se pueden aplicar al dato desde el exterior del módulo ni siquiera las operaciones enunciadas para los tipos opacos, pues lo que está encapsulado no es ya el tipo, sino el dato mismo. Obsérvese que las operaciones que manejan el dato no lo mencionan como argumento.

Repetimos que esta técnica resulta fácil de aplicar sólo cuando existe únicamente una variable del tipo abstracto que se desea ocultar.

Fundamentos de programación con Módula-2 (Tema 14_1)

Tema 14
Módulos

 

En este Tema se da una introducción a la programación modular, en especial basada en el empleo de tipos abstractos de datos.

Se introduce el concepto de módulo, en general, y su realización en Modula-2, en particular. Se discuten brevemente las características necesarias para compilar módulos por separado, en forma segura, y la manera de conseguirlo en este lenguaje.

Se describe la noción de tipo abstracto de datos, y las técnicas para programarlos usando el mecanismo de módulos en Modula-2. Se menciona la posibilidad de realizar ocultación mediante tipos opacos, con las limitaciones impuestas por el lenguaje.

Finalmente se extiende la metodología de desarrollo de programas con la posibilidad de descomposición en módulos separados, estableciendo las recomendaciones del desarrollo modular basado en abstracciones.

14.1 Concepto de módulo

En programación, un módulo es, en general, un fragmento de programa utilizado en algún momento para la construcción del programa completo. Lo que distingue a un módulo propiamente dicho de un fragmento arbitrario del programa es el hecho de que en algún momento de la construcción haya sido reconocido como tal, y por tanto que se haya desarrollado o refinado en forma relativamente independiente del resto del programa. Podríamos definir:

MÓDULO: Fragmento de programa desarrollado en forma independiente.

El desarrollo independiente debe serlo en el máximo grado posible. Atendiendo a las técnicas de preparación de programas en lenguaje de programación simbólicos, diremos que un módulo debería ser compilado por separado, y no tratarse de un simple fragmento de texto dentro de un único programa fuente.

La razón de exigir compilación por separado para los distintos módulos de un programa obedece a la necesidad de limitar la complejidad de aquello que está siendo elaborado por una persona en un momento dado. Si el módulo se va a compilar por separado, la persona que lo desarrolle podrá concentrarse en él, prescindiendo en parte de cómo se utiliza ese módulo desde el resto del programa. De la misma forma, quien escriba el resto del programa no se preocupará de los detalles de cómo está codificado el módulo, sino sólo de cómo hay que usarlo.

El concepto de módulo, por tanto, está íntimamente ligado a la idea de abstracción. Un módulo debe definir un elemento abstracto (o varios relacionados entre sí) y debe ser usado desde fuera con sólo saber qué hace el módulo, pero sin necesidad de conocer cómo lo hace.

14.1.1 Especificación y realización
Igual que en cualquier otro elemento abstracto, en un módulo podemos distinguir dos puntos de vista, correspondientes a su especificación y a su realización. Tal como se ha indicado con anterioridad, la primera visión nos dice qué hace el módulo, y la segunda nos dice cómo lo hace.

La especificación de un módulo que contenga la definición de una serie de elementos abstractos consistirá, fundamentalmente, en el conjunto de las especificaciones de cada uno de ellos, por separado, más una indicación de los posibles efectos de unos sobre otros cuando se usan en forma combinada.

La realización del módulo consistirá en la realización de cada uno de los elementos abstractos contenidos en dicho módulo.

La especificación del módulo es todo lo necesario para poder usar los elementos definidos en él. Esta especificación constituye la interfaz (en inglés "interface") entre el módulo (incluida su realización) y el programa que lo usa.

La independencia entre la realización de un módulo y el programa que lo usa se incrementa si la realización de un elemento abstracto no esvisible desde donde se usa. Esta castacterística se denomina ocultación, y ha sido ya desarrollada en un Tema anterior para las funciones y procedimientos, explicando el mecanismo de visibilidad por bloques.

Referida a los módulos, la ocultación consiste en que el programa que usa un elemento de un módulo sólo tiene visible la información de la interfaz, pero no la de la realización.

14.1.2 Compilación separada
Los lenguajes de programación que permiten programar usando módulos pueden emplear diversas técnicas para definirlos e invocar los elementos definidos en ellos. Tal como se ha comentado antes, es importante que los módulos puedan compilarse por separado. Esto quiere decir que los lenguajes de programación deben permitir escribir un programa complicado como un conjunto de varios ficheros fuente distintos, cada uno de los cuales pueda compilarse de manera más o menos independiente de los demás.

Por otra parte, para que el uso de los elementos de un módulo sea correcto, habrá que hacerlo de acuerdo con la interfaz establecida. La interfaz debe ser tenida en cuenta al compilar un programa que use elementos de un módulo separado. Por el contrario, la realización del módulo debe permanecer invisible para el programa que lo usa con objeto de mantener la deseable ocultación de los detalles de los elementos abstractos contenidos en él.

En la Figura 14.1 se representa gráficamente la visibilidad deseable entre un módulo y el programa que lo usa.

Figura(14_1)
   Figura 14.1. Visibilidad de un módulo

Resumiendo:

COMPILACIÓN SEPARADA: El programa está formado por varios ficheros fuente, cada uno de los cuales se compila por separado.

COMPILACIÓN SEGURA: Al compilar un fichero fuente el compilador comprueba que el uso de elementos de otros módulos es consistente con la interfaz.

OCULTACIÓN: Al compilar un fichero fuente el compilador no usa información de los detalles de realización de elementos de otros módulos.

Entre las técnicas empleadas por los lenguajes de programación reales en lo que respecta a compilación separada, tenemos situaciones tales como las siguientes:

   a)  El fichero del programa y del módulo se tratan en forma totalmente separada, sin visibilidad de la interfaz (lenguaje FORTRAN y las primeras versiones del lenguaje C).

   b)  La parte necesaria de la interfaz se copia manualmente en el programa que la usa. La compilación de los ficheros del programa y del módulo se hace con total independencia (lenguaje C ANSI, con prototipos, y algunas versiones del lenguaje Pascal, con la directiva EXTERN).

   c)  La interfaz del módulo y su realización se escriben en ficheros separados. El mismo fichero de interfaz se usa tanto al compilar la realización del módulo como al compilar el programa que lo usa (lenguajes Modula-2 y Ada).

En los lenguajes que usan la técnica (a) no hay compilación segura. En los mencionados en (b) la seguridad es mayor, pero aún hay posibilidad de errores si no coincide la interfaz del módulo con la copia usada en el programa. Con los lenguajes que usan la técnica (c) la compilación es completamente segura.

14.1.3 Descomposición modular
La posibilidad de compilar módulos en forma separa permite repartir el trabajo de desarrollo de un programa, a base de realizar su descomposición modular. Los diferentes módulos pueden ser encargados a programadores diferentes, y gracias a ello todos pueden trabajar al mismo tiempo.

De esta forma se pueden desarrollar en un tiempo razonable los grandes programas correspondientes a las aplicaciones de hoy día, que totalizan cientos de miles de sentencias.

La descomposición modular de un programa puede reflejarse en un diagrama de estructura, tal como el de la Figura 14.2. En este diagrama se representa cada módulo en forma de un rectángulo, con el nombre del módulo en su interior, y se usan líneas para indicar las relaciones de uso entre ellos.

Figura(14_2) 
     Figura 14.2. Ejemplo de diagrama de estructura

En este ejemplo el módulo A usa elementos de los módulos B y C, y el módulo B usa elementos de C y D. Los módulos C y D no usan ningún otro módulo. Las líneas que indican relaciones de uso pueden llevar punto de flecha si es necesario indicar expresamente cuál es el sentido de la relación. Normalmente no es necesario, pues, como en este caso, un módulo que usa otro se dibuja encima de él, de manera que las líneas de uso se interpretan siempre de arriba a abajo, estableciendo al mismo tiempo una jerarquía entre módulos.

El objetivo de la ingenería de software es facilitar el desarrollo de la aplicación en forna organizada, y de manera que muchas personas puedan colaborar simultáneamente en un mismo proyecto. Para que la descomposición en módulos sea adecuada, desde ese punto de vista, conviene que los módulos resulten tan independientes unos de otros como sea posible. Esta independencia se analiza según dos criterios, denominados acoplamiento y cohesión.

El acoplamiento entre módulos indica cuántos elementos distintos o característicos de uno o varios módulos han de ser tenidos en cuenta a la vez al usar un módulo desde otro. Este acoplamiento debe reducirse a un mínimo.

La cohesión indica el grado de relación que existe entre los distintos elementos de un mismo módulo, y debe ser lo mayor posible. Esto quiere decir que dos elementos íntimamente relacionados deberían ser definidos en el mismo módulo.

14.2 Módulos en Modula-2

El nombre con que se ha bautizado al lenguaje Modula-2 nos indica ya que debe disponer de mecanismos adecuados para la definición de módulos que pueden ser desarrollados por separado.

Un programa descompuesto en módulos se escribe como un conjunto de ficheros fuente relacionados entre sí, y que pueden compilarse por separado. Cada fichero fuente constituye así una unidad de compilación. A continuación se describen las distintas unidades de compilación que pueden definirse en Modula-2.

14.2.1 Módulo principal
Un programa en Modula-2 se puede descomponer en varios módulos. Uno de estos módulos ha de ser el programa o módulo principal. La ejecución del programa completo equivale, en principio, a la ejecución del módulo principal. Por supuesto, el módulo principal puede invocar durante su ejecución operaciones definidas en otros módulos.

Todos los ejemplos de programas completos desarrollados hasta ahora se componían exclusivamente de un módulo principal. Para ser precisos habrá que decir que en estos ejemplos se usaban módulos "estándar", pero puede considerarse que estos módulos no son parte del programa o aplicación desarrollada.

El módulo principal debe importar explícitamente de los otros módulos todos los elementos que vaya a usar. La manera de escribir un módulo principal ya ha sido expuesta en los Temas anteriores, por lo que no merece la pena dar más explicaciones en este momento.

14.2.2 Módulos de definición
La terminología de Modula-2 es quizá un poco inadecuada en cuanto a los nombres dados a las unidades de compilación, ya que se llama módulo a cada una de ellas. Por una parte tenemos que el programa principal representa de alguna forma la aplicación completa, por lo que puede resultar confuso llamarle "módulo". Por otra parte, cada módulo que forme parte del desarrollo de un programa en Modula-2 ha de escribirse como dos ficheros o unidades de compilación separadas, cada una de las cuales se denomina "módulo" aunque en realidad sean partes de un mismo módulo.

Las dos unidades de compilación de un módulo corresponden, como se había apuntado, a la especificación (o interfaz) y la realización (o "implementación"). La especificación de un módulo se escribe como módulo de definición en Modula-2. La forma general de un módulo de definición es:

                DEFINITION MODULE  Nombre;
                   … listas de importaciones …
                   … definiciones …
                END Nombre.

Las listas de importaciones se escriben igual que para el módulo principal. Las definiciones pueden incluir definiciones de constantes, tipos y variables, y también pueden incluir especificaciones de subprogramas (procedimientos y funciones). Una especificación de subprograma consistirá en la cabecera de la función o procedimiento. Por supuesto, se pueden añadir cuantos comentarios se consideren apropiados para documentar la interfaz del módulo.

Como ejemplo consideramos un módulo que contenga los elementos necesarios para imprimir series de números formando varias columnas a lo ancho del listado. La impresión a varias columnas ya se había desarrollado anteriormente en dos ejemplos del Tema 8. Ahora reuniremos los elementos necesarios para formar con ellos un módulo separado. La interfaz de este módulo puede ser como la que aparece en el siguiente listado:

(*_/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\_
_/-\_
_/-\_   Este módulo contiene los elementos para imprimir series
_/-\_   de números a varias columnas.
_/-\_
_/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\_*)

DEFINITION MODULE Tabulación;
VAR
   numColumnas: INTEGER;               (* número de columnas *)
   ancho: INTEGER                        (* ancho de cada columna*)

PROCEDURE Imprimir( numero: INTEGER );
(* Imprime el número, tabulando *)

PROCEDURE Terminar;
(* Completa la impresión de la última línea *)

END Tabulacion.

Los parámetros de impresión pueden fijarse modificando directamente las variables en la interfaz del módulo. Si no se modifica el valor de estas variables está previsto usar unos parámetros por defecto.

La forma exacta de escribir un módulo de definición se describe mediante la siguientes reglas BNF:

Módulo_definición ::=
          Cabecera_definición
          { Definición_de_elementos }
          END Identificador .

Cabecera_definición ::=
          DEFINITION MODULE Identificador ;
          { Lista_importados ; }
          [ Lista_exportados ; ]

Definición_de_elementos ::=

          Declaración_de_constantes |
          TYPE { Identificador [ = Esquema_de_tipo ] ; } |
          Declaración_de_variables |
          Cabecera_subprograma ;

La lista de exportación sólo se emplea en versiones antiguas de Modula-2, y en ella se enumeran explícitamente los elementos que pueden ser usador por otros módulos, en la forma

                                     EXPORT QUALIFIED   … lista de identificadores …;

En las versiones actuales todos los elementos del "módulo definición" se exportan implícitamente.

14.2.3 Módulos de implementación
Los módulos de implementación de Modula-2 contienen la realización de un módulo. Esta realización tiene exactamente la misma forma que un módulo principal, precedido de la palabra clave IMPLEMENTATION:

                                   IMPLEMENTATION MODULE Nombre;
                                      … lista de importaciones …
                                      … definiciones …

                                   BEGIN
                                      … sentencias de inicialización …
                                   END Nombre.

Las sentencias ejecutables que figuran al final del módulo son opcionales (si no hay sentencias se suprime también la palabra BEGIN). Estas sentencias se ejecutan automáticamente al comienzo de la aplicación, antes de que se ejecute el programa principal,  y antes de que se ejecute la inicialización de cualquier otro módulo que utilice este módulo.

Si examinamos la jerarquía de módulos reflejada en el diagrama de estructura de una aplicación, podemos darnos cuenta de que las partes ejecutables de los módulos (incluyendo el programa principal) se ejecutan estrictamente de abajo a arriba, empezando por inicializar los módulos que no usan a ningún otro, luego los que usan éstos, y terminando por ejecutar el módulo principal.

En el siguiente ejemplo tenemos la realización del módulo para tabular series de números:

(*_/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\_
_/-\_
_/-\_   Este módulo contiene los elementos para imprimir series
_/-\_   de números a varias columnas.
_/-\_
_/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\_*)

IMPLEMENTATION MODULE Tabulacion;
   FROM InOut IMPORT WriteLn, WriteInt;

VAR   columna: INTEGER;              (* columna a imprimir *)

PROCEDURE Iniciar;
(* Prepara la impresión desde la 1ª columna *)
BEGIN
   columna := 1
END Iniciar;

PROCEDURE Imprimir( numero: INTEGER );
(* Imprime el número, tabulando *)
BEGIN
   IF columna > numColumnas THEN
      WriteLn;
       columna := 1
   END;
   WriteInt( numero, ancho );
   INC( columna )
END Imprimir;

PROCEDURE Terminar;
(* Completa la impresión de la última línea *)
BEGIN
   IF columna > 1 THEN WriteLn END;
   Iniciar
END Terminar;

BEGIN
   (*– fijar parámetros por defecto e iniciar impresión –*)
      numColumnas := 4;
      ancho := 10;
      Iniciar

END Tabulacion.

Las sentencias de inicialización asignan valores por defecto a los parámetros y preparan el módulo para imprimir números desde la primera columna.

14.2.4 Uso de módulos
Los elementos definidos en un módulo se pueden usar desde otro, en la forma que ya se ha venido realizando en los módulos estándar. Ahora daremos una visión más completa de los mecanismos de Modula-2 para usar elementos de otros módulos.

Para usar elementos de otros módulos hay que importarlos. La importación se realiza al comienzo del programa (o módulo) que desea usarlos. La forma de importación usada hasta el momento ha sido:

                                FROM nombre_de_módulo IMPORT lista_de_nombre;

Con esta forma de importación los elementos importados se usan directamente por su nombre, tal como si hubieran sido definidos directamente en el programa que los usa.

Existe otra forma de importación, que se escribe simplemente:

                                IMPORT  nombre_de_módulo;

Con esta segunda forma de importación se puede usar cualquier elemento definido en ese módulo, pero no directamente por su nombre, sino designándolo mediante la combinación:

                                nombre_de_módulo . nombre_de_elemento

Esta notación se llama nombre cualificado, y tiene una apariencia similar a la referencia a campos de un registro, ya que también se usa el punto (.) para ligar los dos identificadores usados para la designación de un elemento particular.

A continuación se muestra un sencillo programa para tabular la serie de números del 1 al 20, usando el módulo de tabulación anterior, y empleando los parámetros de tabulación por defecto:

(*_/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\_
_/-\_
_/-\_   Este programa imprime la serie de números del 1 al 29,
_/-\_   a varias columnas.
_/-\_
_/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\_*)

MODULE Serie;

   FROM Tabulacion IMPORT Imprimir, Terminar;

   VAR k: INTEGER;

BEGIN
   FOR k := 1 TO 20 DO
      Imprimir( k )
   END;
   Terminar
END Serie.

El resultado es:

-/@\

En este ejemplo se emplea la misma forma de importación usada habitualmente en los ejemplos anteriores.

Este ejemplo funciona correctamente gracias al orden apropiado en que se ejecutan automáticamente las acciones descritas en la parte ejecutable de cada módulo. La inicialización de módulo de tabulación se ejecuta antes que el módulo principal que lo utiliza. De esta manera al invocar por primera vez la operación de Imprimir las variables de la interfaz del módulo de tabulación contienen los parámetros por defecto y el contador de columnas oculto en su realización está inicializado a 1.

A continuación se muestra un programa similar al anterior, ampliado para mostrar cómo se pueden ajustar los parámetros de tabulación a los valores deseados en cada caso:

(*_/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\_
_/-\_
_/-\_   Este programa imprime la serie de números del 1 al 29,
_/-\_   dos veces, formando diferentes números de columas.
_/-\_
_/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\_*)

MODULE Serie2;

   IMPORT Tabulacion;

   VAR k: INTEGER;

BEGIN
   (*– imprimir a 3 columnas de 13 caracteres –*)
      Tabulacion.numColumnas := 3;
      Tabulacion.ancho := 13;
      FOR k := 1 TO 29  DO
         Tabulacion.Imprimir( k )
      END;
      Tabulacion.Terminar;
   (*– imprimir a 6 columnas de 5 caracteres –*)
      Tabulacion.numColumnas := 6;
      Tabulacion.ancho := 5;
      FOR k := 1 TO 29 DO
         Tabulacion.Imprimir( k )
      END;
      Tabulacion.Terminar;
END Serie2.

Ahora los resultados son:

-/@\

En este ejemplo se ha usado la forma de importación simple, que exige usar nombres cualificados.

Quizá convenga hacer algunas recomendaciones de estilo con respecto al empleo de nombres cualificados. La referencia simple a elementos importados usando directamente su nombre resulta, en principio, más sencilla. Sin embargo sólo puede considerarse recomendable en aquellos casos en que los elementos nombrados son bien conocidos por todos los que han de consultar en algún momento el texto del programa. Esto ocurre, por ejemplo, con los elementos definidos en los módulos "estándar" asociados al lenguaje.

Por el contrario, cuando una aplicación tiene un número relativamente importante de módulos particulares, el uso de los nombres simples puede acabar siendo confuso, ya que es difícil recordar de memoria en qué módulo está definido cada uno. Incluso se pueden presentar ambigüedades, ya que el nombre de un elemento de un módulo puede coincidir con el otro elemento distinto definido en otro módulo.

En estos últimos casos es preferible usar nombres cualificados, aunque la redacción del programa sea algo más prolija, ya que se gana en precisión, y en cada punto en que se usa un elemento importado queda explícitamente indicado en qué módulo se encuentra definido.

14.3 Tipos abstractos de datos

En programación tradicional, se ha identificado el concepto de tipo de dato con el de la clase de valores que pueden tomar los datos de ese tipo. De hecho esta idea se ha aplicado más a la forma de representación de los valores que a los valores en sí. Por ejemplo, si tenemos que operar con valores correspondientes a los meses del año, lo podremos hacer representándolos mediante números (1 al 12) o bien mediante ristras de caracteres (‘ENE’, ‘FEB’, etc.), entre otras posibilidades. Estas representaciones se asocian con diferentes tipos de datos. En Modula-2 escribiríamos:

                 TYPE TipoMes = INTEGER;

o bien:

                TYPE TipoMes = ARRAY [0..3] OF CHAR;

Un enfoque más moderno de la programación trata de asociar la idea de tipo de datos con la clase de valores, abstractos, que pueden tomar los datos. Esto quiere decir que la representación o codificación particular de los valores no cambia, de hecho, el tipo del dato considerado. Un paso adelante en este sentido ha sido la introducción (en lenguajes como Pascal, Modula-2 o Ada) de los tipos enumerados, en que se definen colecciones de valores, abstractos, asociados a identificadores utilizables dentro del programa.

Los valores de los tipos enumerados no son valores numéricos, ni ristras de caracteres, aunque pueden transformarse en esas otras formas de representación usando apropiadamente los mecanismos del lenguaje. Por ejemplo:

               TYPE TipoMes = (Enero, Febrero, … Diciembre);
               VAR mes: TipoMes;
               . . . .
               WriteInt( ORD(mes)+1, 2 )

En este enfoque más moderno de la programación se identifican los tipos de datos en forma completamente abstracta, llegando a la idea de tipos abstractos de datos. Esto quiere decir que un programa que use ese tipo de datos no debería necesitar ningún cambio por el hecho de modificar la representación o codificación de los valores de ese tipo. Si analizamos con cuidado qué necesita un programa para poder usar datos de un tipo, encontraremos que hace falta:

  • Hacer referencia al tipo en sí, mediante un nombre, para poder definir variables, subprogramas, etc.
  • Hacer referencia a algunos valores particulares, generalmente como constantes con nombre.
  • Invocar operaciones de manipulación de los valores de ese tipo, bien usando operadores en expresiones aritméticas o bien mediante subprogramas.

El conjunto de todos estos elementos constituye el tipo abstracto de datos:

TIPO ABSTRACTO DE DATOS: Agrupación de una colección de valores y una colección de operaciones de manipulación.

Es importante comprender que estas colecciones son cerradas, es decir sólo se deben poder usar los valores abstractos y las operaciones declaradas para ese tipo. Esto no ocurría cuando se asociaba el tipo de valor con su forma de representación. Por ejemplo, si representamos los meses del año mediante números, podremos usar el número 33, aunque no sea ningún mes válido, al igual que podremos multiplicar los números dos meses aunque esto no tenga ningún sentido.

14.4

::= DEFINICION

| alternativa

{} REPETICION

[]OPCION

()AGRUPAR

Estudiar Informática en España (artículo de revista)

Convierte tu pasión en profesión

Si estás leyendo esto es porque la informática forma parte de tus aficiones, e incluso de tus pasiones. ¿Has pensado alguna vez en convertirla en un trabajo gratificante? Para ello, una buena forma de empezar es enterarte de qué es lo que tienes que estudiar y dónde puedes hacerlo en España. Aquí tienes algunas pistas.

Basta echar un vistazo a las páginas web de ofertas de empleo para comprobar que convertirse en profesional de la informática es una buena elección. Los tiempos de la caída de las ".com" terminaron y actualmente sólo los comerciales lo tienen más fácil que los informáticos para encontrar trabajo. Ya sea en un negocio familiar o en una importante sociedad cotizada, antes de incorporarte a este mercado laboral has de prepararte.
   Ahora es un momento ideal para lanzarte a estudiar y, además, las posibilidades para hacerlo en España son muchas. Lejos queda ya ese 1976 cuando la Politécnica de Madrid, la de Cataluña y la Universidad del País Vasco sorprendieron anunciando que en sus aulas se podía estudiar una titulación nueva: Informática. Durante estos 31 años, la carrera ha ido evolucionando y el sistema educativo del siglo XXI ofrece múltiples opciones.

Las empresas se rifan a los informáticos

  El escaparate educativo comienza en la universidad tradicional, que ofrece tres carreras dentro del campo de la informática: Ingeniero en Informática, Ingeniero Técnico en Informática de Gestión, e Ingeniero Técnico en Informática de Sistemas. Pero eso no es todo, ya que además de las licenciaturas y diplomaturas existen otras posibilidades de estudios, como los títulos propios de algunas universidades privadas, carreras extranjeras y Formación Profesional. Elijas lo que elijas, recuerda que cualquier empresa tiene ordenadores y requiere de la labor de los informáticos. Entre las actividades que podrás realizar una vez que hayas finalizado los estudios está la de integrar los sistemas de la empresa, instalando y ajustando los sistemas operativos y las redes informáticas, y también trabajar como arquitecto de soluciones, técnico en desarrollo de programación y mantenimiento de aplicaciones.
   Las Comunidades Autónomas que generan mayor número de empleos son, por este orden, Madrid, Cataluña, Andalucía, Valencia y País Vasco, que suman un 73% del total de las ofertas, según el informe anual de
www.infoempleo.com. Además, las empresas que trabajan en los sectores de informática, consultoría, telecomunicaciones, enseñanza e industrial acumulan el 58% de las ofertas de informática, y son los departamentos de informática, comercial, producción y servicios generales los más necesitados, concentrando el 80% del total del trabajo de los informáticos.
   Hasta aquí las buenas noticias ya que, como suele ser norma en muchas profesiones, en el 80% de las ofertas de empleo se requiere experiencia, y en el 50% se precisa conocimiento de otros idiomas, especialmente inglés. Estos datos indican que lo complicado es encontrar tu primer empleo, pero recuerda que la mayoría de las universidades ofrecen prácticas en empresas que te ayudarán a "meter la cabeza". Aunque de encontrar trabajo ya te preocuparás cuando acabes los estudios. Ahora es el momento de elegir.
   Para empezar, la carrera de Ingeniero en Informática -estipulada en cinco años- presenta la dificultad de que sus asignaturas tienen un marcado carácter técnico, poco apta para estudiantes que tengan problemas con las Matemáticas. Además, la constante evolución del sector provoca que, según los expertos de la editorial Círculo del Progreso, el alumno tenga algunas carencias en la formación recibida cuando se enfrenta al mercado laboral.
   A pesar de este "handicap", el objetivo de esta titulación es, según el Ministerio de Educación y Ciencia, formar a profesionales capacitados para crear todo tipo de programas y aplicaciones informáticas que se ajusten a las necesidades de la empresa que lo haya contratado. El contenido básico de la hermana mayor de las ingenierías está compuesto por conocimientos técnicos clásicos, tales como Matemáticas, Lógica, Ingeniería, Física, Electrónica y Estadística, más lenguajes informáticos de programación.

Dificultad alta, acceso sencillo

   Una vez finalizado el primer ciclo, tres años, se puede acceder -por si te lo has pensado mejor- a otras titulaciones ajenas a la informática, como Ciencias y Técnicas Estadísticas, Ingeniero en Electrónica, Investigación y Técnicas de Mercado, etc. Esta característica es compartida por las titulaciones menores de informática: Ingeniero Técnico en Informática de Gestión e Ingeniero Técnico en Informática de Sistemas. La primera de ellas tiene unos objetivos finales similares a la ingeniería de cinco años, pero con menos materias al durar sólo tres años.
   De todas formas, no te confíes, ya que acabar estas titulaciones en 3 o 5 años está al alcance de unos pocos, según el Consejo de Universidades. De hecho, para la ingeniería de cinco años, la duración suele ser de 7,3 años, mientras que para la técnica roza casi los cinco años. A pesar de estos números, la informática no es ni de lejos la carrera más difícil. Semejante galardón se lo lleva la Ingeniería de Arquitectura, con una media de 8,4 años, seguida de Aeronáutica, con 7,8 años.
   La última titulación, la Técnica en Informática de Sistemas (también en tres años), tiene el objetivo de formar estudiantes capaces de manejar múltiples aplicaciones informáticas, sistemas operativos y sistemas de transmisión de datos. Es decir, ideal para los que estén interesados en integrarse en el departamento de sistemas de una compañía, aunque también cuenta con cursos especializados para acceder a puestos de programador.
   Si llegados a este punto ya has decidido qué quieres hacer y qué carrera se adapta mejor a tus objetivos, ahora falta otro paso: comprobar que la nota obtenida en selectividad te permite acceder a ella. A la gran mayoría de las universidades públicas y privadas les basta con un 5, aunque existen contadas excepciones como la Politécnica de Valencia que pide un 6,32 para cursar la ingeniería en Informática; o la Universidad del País Vasco, que sólo acepta notas superiores a 6,12 para la técnica de Gestión.
   Y si eres de aquellos a los que no le asustan los retos, hay universidades en España (Internacional de Cataluña, Rey Juan Carlos, Politécnica de Cataluña, Jaén, Vic y Málaga) que ofrecen la posibilidad de estudiar dobles licenciaturas, como Informática de Gestión más Administración y Dirección de Empresas, o Empresariales, Estadística, Matemáticas… Eso sí, habrás de dedicarle más tiempo y esfuerzo.
   Si, por el contrario, no andas sobrado de tiempo o acudir a clase cada día es más una carga que una satisfacción, existen otras dos opciones. En la Universidad a Distancia (
UNED) también se cursan las tres titulaciones y con tutorías específicas. Por ejemplo, en el caso de la Técnica de Informática de Gestión se puede acudir tres días a la semana. Al no tener que acudir a clase, la lógica indica que obtener el título por la UNED requiere de mayor fuerza de voluntad, ya que no hay una obligación diaria de acudir a ningún centro.
   En línea similar está la Universitat Oberta de Catalunya, la universidad virtual. En este centro se emplean de manera intensiva las tecnologías de la información y la comunicación, para así tratar de superar las barreras de tiempo y espacio y ofrecer un modelo educativo más personalizado. En la UOC, estudiantes, profesores y gestores interactúan y cooperan en el "Campus Virtual".

La opción privada

   Otra posibilidad más que existe para convertirte en un experto informático son las carreras privadas y las que imparten universidades extranjeras con presencia en España. Estas titulaciones han adquirido prestigio en los últimos años, aunque para acceder a ellas es necesario disponer de una holgada solvencia económica ya que su coste es de una media de 3.500 € por curso. Existen muchas opciones, aunque algunas de las más interesantes son las titulaciones que ofrece la Universidad de Mississippi, la Saint Louis University, el Instituto Cibernos y el Centro de Estudios Superiores Franceses.

Formación profesional

   Vilipendiada hace años, la Formación Profesional es una opción más que válida para aprender una profesión. Los titulados en informática por FP se encargan de arreglar los ordenadores, y se preocupan para que la gestión y la administración de la empresa pueda realizarse sin problemas. Hay tres posibilidades para obtener el grado de Técnico Superior, y las tres de dos años de duración y 2.000 horas lectivas. Se accede a ellas desde el Bachillerato.
   El objetivo del título de Administración de Sistemas Informáticos es mantener los ordenadores de una empresa totalmente operativos, Desarrollo de Aplicaciones Informáticas tiene por objeto desarrollar herramientas informáticas para los departamentos de una compañía, y Explotación de Sistemas Informáticos hace hincapié en el mantenimiento de redes e Internet. De todas formas, y al igual que ocurre con las ingenierías, lo que aquí se aprende puede quedar obsoleto en pocos meses por el rápido desarrollo del sector. Por esto motivo, es imprescindible completar la FP con cursos especializados.
   Pero si quieres meterte de lleno en el "corazón" de la informática, has de saber que expertos "cirujanos" como IBM, Oracle, o Microsoft imparten cursos propios. La ventaja en estos casos es que recibirás formación adaptada a las necesidades de la empresa y es más fácil acceder a la plantilla.
   Ahora sólo queda que tú decidas. Y recuerda que, por mucho que aprendas, la pasión por la informática no se enseña.

Pistas en Internet

Federación Nacional de Asociaciones de Ingenieros Informáticos: www.ai2.as

Ingenieros en Informática: www.ingenieroseninformatica.org

Algoritmo. Revista digital para programadores: www.algoritmodigital.com

Estudiantes de informática de España: www.ritsi.org

Internet Society: www.isoc.org

Consejo Superior de Informática: www.csi.map.es

Asociación de Técnicos en Informática: www.ati.es

Recursos para webmaster: http://directorio.adfound.com

_____________________________________________________________________

Revista -Personal Computer & Internet- Septiembre – 2007 Nº 56 – Año IV

Fundamentos de programación con Módula-2 (28)

Tema 12
Registros

 

En este Tema, tal como indica su título, se introduce la estructura de tupla y su realización mediante la construcción RECORD de Modula-2. Se ilustra su uso con ejemplos, mostrando la posibilidad de combinar estructuras tupla y formación.

Se introduce también, de forma breve, la estructura "unión" y su realización mediante registros con variantes en Modula-2.

Finalmente se analiza la correspondencia entre los esquemas abstractos de las estructuras de datos y los de las estructuras de control.

12.1 El esquema tupla

Ya se ha explicado anteriormente que los datos pueden ser simples o estructurados, y que un dato estructurado contiene varios elementos de información, que son sus componentes. Hasta el momento se han visto dos esquemas de datos estructurados: los conjuntos y las formaciones.

Otra forma de construir un dato estructurado a base de agrupar elementos de información es usando el esquema de tupla o agregado. En este esquema el dato estructurado está formado por una colección de componentes, cada una de las cuales puede ser de un tipo diferente.

Por ejemplo, una fecha se describe habitualmente como un dato compuesto de los elementos día, mes y año. Un punto en el plano cartesiano se describe mediante dos números, que son sus coordenadas. El nombre completo de una persona es la colección formada por el nombre de pila y sus dos apellidos. Como ejemplos concretos podemos poner:

       Dato                              Valor
       fecha                       < 12, Octubre, 1992 >
       punto                       < 4, -2 >
       nombre_completo     < Fernando, Jiménez, Rodríguez >

En estos ejemplos se ha supuesto un orden implícito entre las componentes. En la fecha se ha escrito primero el día, luego el mes, y luego el año. Es importante identificar claramente a qué componentes corresponde cada elemento de información. El punto <4, -2> es distinto del punto <-2, 4>.

En realidad el orden es hasta cierto punto arbitrario. Normalmente cada componente se identifica mediante un nombre simbólico. En los ejemplos anteriores podríamos nombrar las componentes en la forma:

       Dato                              Valor
       fecha                       < día: 12, mes: Octubre, año: 1992 >
       punto                       < x: 4, y: -2 >
       nombre_completo     < nombre: Fernando, apellido1: Jiménez, apellido2: Rodríguez >

Identificando cada componente por su nombre, se pueden escribir en el orden que convenga:

       Dato                              Valor
       fecha                       < mes: Octubre, día: 12, año: 1992 >
       punto                       < x: 4, y: -2 >
       nombre_completo     < apellido1: Jiménez, apellido2: Rodríguez, nombre: Fernando >

Tras las consideraciones anteriores, podríamos dar una definición de este esquema de datos:

TUPLA:   Colección de elementos componentes, de diferentes tipos, cada uno de los cuales se identifica por un nombre.

Un aspecto importante del empleo de datos estructurados corresponde al punto de vista de abstracción. Una tupla, como cualquier otro dato compuesto, puede verse en forma abstracta como un todo, prescindiendo del detalle de sus componentes. La posibilidad de hacer referencia a toda la colección de elementos mediante un nombre único correspondiente al dato compuesto, simplifica en muchos casos la escritura del programa que lo maneja.

12.2 Los tipos registros

Los esquemas de tupla pueden usarse en programas en Modula-2 definiéndolos como estructuras del tipo registro. Un registro (en inglés "record") es una estructura de datos formada por una colección de elementos de información llamados campos (en inglés "fields").

12.2.1 Definición de registros
La descripción de un tipo registro en Modula-2 se hace en la forma:

       RECORD
          nombre: tipo;
          nombre: tipo;
          . . . .
       END;

donde cada una de las parejas nombre: tipo, separadas por punto y coma (;), define un campo o elemento componente. Esta descripción puede usarse para definir el tipo registro como un tipo con nombre, o bien directamente como descripción del tipo de una variable. Como ejemplos de definiciones tenemos:

       TYPE TipoMes = (Enero, Febrero, … Diciembre);
       TYPE TipoFecha = RECORD
                                      dia: [1..31];
                                      mes: TipoMes;
                                      anno: INTEGER
                                   END;

       VAR   punto1, punto2: RECORD
                                           x: REAL;
                                           y: REAL
                                        END;

Cuando varios campos seguidos son del mismo tipo, la descripción puede abreviarse escribiendo seguidos los nombres de los campos, separados por comas (,) y poniendo el tipo común a todos ellos sólo una vez al final, detrás del carácter de dos puntos (:). Por ejemplo:

       VAR   punto1, punto2: RECORD
                                           x, y: REAL;
                                        END;

12.2.2 Uso de registros
Al manejar datos estructurados de tipo registro se dispone de dos posibilidades: operar con el dato completo, o bien operar con cada campo por separado.

Las posibilidades de operar con el dato completo son bastante limitadas. La única operación admisible en Modula-2 es la de asignación. El valor de un dato de tipo registro puede asignarse directamente a una variable de su mismo tipo. Por ejemplo, con las definiciones anteriores es posible escribir:

       punto2 := punto1

En estas asignaciones debe cumplirse la compatibilidad de tipos. Dos estructuras son compatibles en asignación si son del mismo tipo, o de tipos sinónimos, o son variables declaradas conjuntamente, como en este ejemplo. No es suficiente la llamada compatibilidad estructural; es decir, dos estructuras con los mismos campos no son compatibles si sus definiciones se hacen por separado.

También es posible pasar como argumento un dato de tipo registro a una función o procedimiento. En este caso es obligatorio que la estructura registro esté definida como un tipo con nombre, ya que en la definición de los argumentos de un subprograma sus tipos han de designarse mediante identificadores. Por ejemplo, podemos especificar los subprogramas siguientes:

       PROCEDURE LeerFecha( VAR fecha: TipoFecha );
       (* Leer el día, mes y año *)

       PROCEDURE Distancia( p1, p2: TipoPunto ): REAL;
       (* Distancia entre p1 y p2 *)

Para poder escribir la segunda especificación, habrá sido necesario definir previamente:

       TYPE TipoPunto = RECORD
                                      x, y: REAL;
                                   END;

No sería válido poner:

       PROCEDURE Distancia( p1, p2: RECORD … END ): REAL;

ya que no es admisible según las reglas de Modula-2. Además, no tendría sentido hacerlo, pues no se podría invocar el subprograma, ya que al no existir nombre para el tipo de los puntos, no podría definirse y pasarse como argumento ningún dato estructurado que fuera compatible con el tipo argumento.

Las operaciones de tratamiento de estructuras registro consisten normalmente en operar con sus campos por separado. La forma de hacer referencia a un campo es mediante la notación:

       registro.campo

Cada campo se puede usar como cualquier otro dato del correspondiente tipo; es decir, se pueden usar los valores de los campos en expresiones aritméticas, se puede asignar valor a cada uno de los campos de una variable de tipo registro, y se pueden pasar los campos como argumentos en llamadas a subprogramas. Como ejemplo daremos una posible definición de los subprogramas anteriores:

PROCEDURE LeerFecha( VAR fecha: TipoFecha );
(* Leer el día, mes y año *)
   VAR d: INTEGER;
BEGIN
   ReadInt( d );
   IF (d>0) AND (d<=31) THEN
      fecha.dia := d
   ELSE
      fecha.dia := 1
   END;
   LeerMes( fecha.mes );
   ReadInt( fecha.anno )
END LeerFecha;

PROCEDURE Distancia( p1, p2: TipoPunto ); REAL;
(* Distancia entre p1 y p2 *)
   VAR   dx, dy: REAL;
BEGIN
   dx := p2.x – p1.x;
   dy := p2.y – p1.y;
   RETURN sqrt( dx*dx + dy*dy )
END Distancia;

Las versiones modernas de Modula-2 permiten que una función devuelva como resultado un valor estructurado. Esto representa una gran ventaja a la hora de escribir programas claros, bien organizados, pero la posibilidad de hacerlo depende del compilador particular que se esté utilizando. Por ejemplo, es muy elegante poder escribir:

PROCEDURE PuntoMedio( p1, p2: TipoPunto ): TipoPunto;
   VAR   m: TipoPunto;
BEGIN
   m.x := (p1.x + p2.x) / 2.0;
   m.y := (p1.y + p2.y) / 2.0;
   RETURN m
END PuntoMedio;
. . . .
VAR   a, b, centro: TipoPunto;
. . . .
centro := PuntoMedio( a, b );

Si el compilador no admite esta posibilidad, siempre es posible transformar el planteamiento anterior en otro equivalente, en que la función se transforma en un procedimiento, y el resultado se devuelve como un argumento adicional, pasado por referencia. El ejemplo siguiente, aunque menos elegante, es equivalente al anterior y será admitido por cualquier compilador.

PROCEDURE PuntoMedio( p1, p2: TipoPunto; VAR m: TipoPunto );
BEGIN
   m.x := (p1.x + p2.x) / 2.0;
   m.y := (p1.y + p2.y) / 2.0
END PuntoMedio;
. . . .
VAR a, b, centro: TipoPunto;
. . . .
PuntoMedio( a, b, centro );

12.2.3 La sentencia WITH
Para simplificar la redacción de los programas que usan registros campo a campo, existe una sentencia que permite fijar de antemano la estructura registro con la que se quiere operar, de manera que la referencia a cada campo pueda hacerse simplemente con el nombre; es decir, en lugar de escribir

       registro.campo

bastará escribir:

       campo

ya que el registro concreto con que se ha de operar ha sido establecido de antemano. El formato de esta sentencia es:

       WITH registro DO
          Secuencia_de_sentencias
       END

En la secuencia de sentencias se puede hacer referencia a los campos del registro escribiendo sólo su nombre. Usando esta sentencia podemos reescribir, en forma más sencilla, alguno de los ejemplos anteriores:

PROCEDURE LeerFecha( VAR fecha: TipoFecha );
(* Leer el día, mes y año *)
   VAR   d: INTEGER;
BEGIN
   WITH fecha DO
      ReadInt( d );
      IF (d>0) AND (d<=31) THEN
         dia := d
      ELSE
         dia := 1
      END;
      LeerMes( mes );
      ReadInt( anno )
   END
END LeerFecha;

Las sentencias WITH pueden anidarse. Al hacerlo hay que tener en cuenta que si los registros tienen campos con los mismo nombres, se presenta una situación de ambigüedad en la parte más interna. En este caso se entiende que el nombre de un campo hace referencia al campo del registro de la sentencia WITH más interna que lo incluya y que tenga un campo con dicho nombre. Así se indica en el siguiente esquema:

VAR
   a: RECORD
          uno, dos: …
       END;
   b: RECORD
          dos, tres:
       END;

. . . .
WITH a DO
   … uno …                 = a.uno
   … dos …                 = a.dos

   WITH b DO
      … uno …              = a.uno
      … dos …              = b.dos
      … tres …              = b.tres
   END
END

De acuerdo con lo anterior, en caso de manejarse a la vez varios registros con los mismos campos sólo se podrá usar la sentencia WITH para simplificar las referencias a los campos de uno de ellos, lo cual podrá resultar quizá más confuso que si no se simplificase, por la asimetría que introduce. Por ejemplo:

PROCEDURE Distancia( p1, p2: TipoPunto ): REAL;
(* Distancia entre p1 y p2 *)
   VAR   dx, dy: REAL;
BEGIN
   WITH p1 DO
      dx := p2.x – x;
      dy := p2.y – y
   END;
   RETURN sqrt( dx*dx + dy*dy )
END Distancia;

Como puede observarse, se hace referencia de manera diferente a los campos p1 y p2, lo cual introduce cierta confusión.

12.2.4 Ejemplo: Cálculos con fracciones
Como ejemplo de empleo de registros, se reescriben aquí algunos de los subprogramas desarrollados en el Tema 8 para realizar cálculos con fracciones. La nueva versión aparece listada a continuación:

FROM InOut IMPORT
   WriteString, Write, WriteInt, WriteLn, Read, ReadInt;

TYPE TipoFraccion =
   RECORD
      numerador, denominador: INTEGER
   END;
. . . . . . . .
PROCEDURE ReducirFraccion( VAR fracion: TipoFraccion );
(* Simplificar la fracción *)
   VAR   divisor: INTEGER;
BEGIN
   WITH fracion DO
      divisor := 2;
      WHILE (divisor <= numerador) AND (divisor <= denominador) DO
         WHILE (numerador MOD divisor = 0) AND (denominador MOD divisor = 0) DO
            numerador := numerador DIV divisor;
            denominador := denominador DIV divisor
         END;
         INC( divisor )
      END
   END
END ReducirFraccion;

PROCEDURE SumaFracciones( f1, f2: TipoFraccion ): TipoFraccion;
(* SumaFracciones = f1 + f2 *)
   VAR   suma: TipoFraccion;
BEGIN
   suma.numerador := f1.numerador*f2.denominador + f2.numerador*f1.denominador;
   suma.denominador := f1.denominador*f2denominador;
   ReducirFraccion( suma );
   RETURN suma
END SumaFracciones;

PROCEDURE RestaFracciones( f1, f2: TipoFraccion ): TipoFraccion;
(* RestaFracciones = f1 – f2 *)
   VAR   menosf2: TipoFraccion;
BEGIN
   menosf2.numerador := -f2.numerador;
   menosf2.denominador := -f2.denominador;
   RETURN SumaFracciones( f1, menosf2 )
END RestaFracciones;

PROCEDURE LeerFraccion( VAR fraccion: TipoFraccion );
(* Lee la fraccion y la simplifica *)
BEGIN
   WITH fraccion DO
      ReadInt( numerador ); Write( ‘/’ );
      ReadInt( denominador ); Write( ‘ ‘ );
      ReducirFraccion( fraccion )
   END
END LeerFraccion;

PROCEDURE EscribirFraccion( fraccion: TipoFraccion );
(* Imprime la fracción como ‘numerador/denominador’ *)
BEGIN
   WITH fraccion DO
      WriteInt( numerador, 1 );
      Write( ‘/’ );
      WriteInt( denominador, 1 );
   END
END EscribirFraccion;

En este ejemplo cada fracción se almacena como un registro con dos campos, correspondientes al numerador y al denominador, respectivamente. Comparando esta versión con la del Tema 8 se aprecia que las cabeceras de los subprogramas, y por tanto las llamadas, son ahora más sencillas. El precio a pagar es una ligera complicación al tener que hacer referencia a los valores de numerador y denominador como campos de registros, y no directamente como argumentos separados.

12.3 Estructuras combinadas

Una característica de los lenguajes de programación modernos es que se pueden combinar con bastante libertad elementos de la misma naturaleza. Esto ocurre en Modula-2 con las sentencias estructuradas, que permiten anidar esquemas de tipo secuencia, selección e iteración unos dentro de otros.

Con las estructuras de datos ocurre algo similar. Se pueden definir estructuras cuyas componentes son a su vez estructuras, sin límite de complejidad de los esquemas de datos resultantes.

12.3.1 Formas de combinación
Las estructuras ARRAY y RECORD se pueden combinar entre sí de la forma que se desee. Los campos de un registro pueden ser formaciones, y las componentes de una formación pueden ser registros. Por supuesto, también se pueden definir registros cuyos campos sean a su vez registros o cualquier otro tipo de datos. Podemos analizar algunos ejemplos:

       TYPE TipoPunto = RECORD
                                      x, y: REAL;
                                   END;

       TYPE Triangulo = ARRAY [1 .. 3] OF TipoPunto;

       CONST   maxPuntos = 100;

       TYPE   ListaDePuntos =
          RECORD
             numeroPuntos: INTEGER;
             puntos: ARRAY [1 .. maxPuntos] OF TipoPunto;
          END;

       TYPE   Poligonal = ListaDePuntos;

       TYPE   Poligono = ListaDePuntos;

En estos ejemplos tenemos la representación de un triángulo como una formación de tres puntos, que son registros. La lista de puntos se estructura como un registro, uno de cuyos campos es una formación de puntos, que son a su vez registros. Las últimas declaraciones definen tipos sinónimos de la lista de puntos, en general, con nombres particulares para ser usados en casos particulares.

Los siguientes ejemplos definen registros que contienen campos que son ristras de caracteres. El último ejemplo es un registro que contiene a su vez otro registro anidado.

       TYPE   NombreCompleto =
          RECORD
             nombre: ARRAY [0 .. 20] OF CHAR;
             apellido1, apellido2: ARRAY [0 .. 30] OF CHAR
          END;

       TYPE   LineaDeTexto = ARRAY [0 .. 40] OF CHAR;

       TYPE   TipoProvincia =
          ( SinProvincia, Alava, Albacete, … Zaragoza );

       TYPE   DatosPersonales =
          RECORD
             nombreyApellidos: NombreCompleto;
             domicilio: RECORD
                               calle: LineaDeTexto;
                               numero: INTEGER;
                               zona, poblacion: LineaDeTexto;
                               codigoPostal: INTEGER;
                               provincia: TipoProvincia;
                            END;
          END;

Cuando se utilizan estructuras combinadas, para hacer referencia a una componente en particular hay que usar los selectores apropiados, combinados uno tras otro si es necesario. Como ejemplos de uso de las estructuras definidas en este apartado, podemos poner:

VAR
   pieza: Triangulo;
   camino: ListaDePuntos;
   empleado: DatosPersonales;
. . . .
pieza[1].x := 2.33;
pieza[1].y := -3.45;
pieza[2].x := pieza[1].y;
pieza[2].y := 88.3;
. . . .
camino.numeroPuntos := 3;
camino.puntos[1].x := 5.67;
camino.puntos[1].y := 7.21;
camino.puntos[2] := pieza[3];
camino.puntos[3] := camino.puntos[2];
. . . .
empleado.nombreyApellidos.nombre := ‘Alberto          ‘;
WriteString( empleado.domicilio.calle );
IF empleado.domicilio.poblacion[0] = ‘ ‘ THEN
   WriteString( ‘Sin domicilio’ )
END;
. . . .

En estos ejemplos aparecen combinados los selectores de campo de registro y de componentes de formación. La combinación es admisible cuando una componente de una estructura es a su vez una estructura de datos. A cada estructura se debe aplicar el selector que le corresponda.

12.3.2 Tablas
Aunque el estudio de las estructuras de datos excede del ámbito de este libro, resulta interesante mencionar algunos esquemas típicos que se obtienen combinando estructuras básicas. Este es el caso del esquema de tabla, que puede plantearse como una formación simple de registros. Por ejemplo, podemos definir una tabla destinada a contener la identificación de las provincias:

VAR   provincias: ARRAY TipoProvincia OF
                             RECORD
                                siglas: ARRAY [1 .. 2] OF CHAR;
                                nombre: ARRAY [0 .. 30] OF CHAR;
                                codigo, prefijo: INTEGER;
                             END;

En esta tabla se podrán almacenar los valores apropiados, asignándolos a los correspondientes campos, por ejemplo:

WITH   provincias[ Madrid ] DO
   siglas[1] := ‘M’;
   siglas[2] := ‘ ‘;
   nombre := ‘Madrid’;
   codigo := 28;
   prefijo := 91
END

Estos datos podrán ser usados luego en programas que manejen direcciones postales, matrículas de coches, números de teléfono, etc.

Pueden construirse estructuras de datos bastante complejas combinándolas de manera que en algunas de ellas hagamos referencia a datos almacenados en otras. Una forma de hacer referencia a los datos de una tabla es usando el índice correspondiente a la posición de cada registro. A continuación se muestra un ejemplo para manejo de figuras geométricas a partir de puntos:

TYPE   TipoPunto = RECORD
                                 x, y: REAL;
                              END;

CONST   maxPuntos = 1000;

TYPE IndicePunto = [1 .. maxPuntos];

VAR   puntos: ARRAY IndicePunto OF TipoPunto;

TYPE   TipoTriangulo = ARRAY [1 .. 3] OF IndicePunto;

TYPE TipoCirculo = RECORD
                                centro: IndicePunto;
                                radio: REAL
                             END;

En este ejemplo, la tabla puntos almacena las coordenadas de todos los puntos utilizados para definir cualquiera de las figuras geométricas que se manejan. Las figuras se definen almacenando referencias a los puntos de la tabla, en lugar de almacenar directamente las coordenadas de los puntos. Un triángulo T definido por tres puntos A, B y C se podría registrar, por ejemplo, almacenando los puntos, arbitrariamente, en las posiciones 10, 11 y 12 de la tabla de puntos:

VAR   trianguloT: TipoTriangulo;
. . . .
LeerPunto( puntos[10] );
LeerPunto( puntos[11] );
LeerPunto( puntos[12] );
trianguloT[1] := 10;
trianguloT[2] := 11;
trianguloT[3] := 12

Cuando se hacen recorridos o búsquedas en tablas y se quiere usar la sentencia WITH para simplificar el manejo de los registros, es importante tener en cuenta que el registro al que hace referencia la sentencia WITH se determina sólo una vez, al comienzo, y no cada vez que se hace referencia a un campo.

Por ejemplo, si queremos convertir todas las figuras geométricas en su imagen especular respecto al eje vertical, tendremos que invertir el signo de la abscisa de cada punto, es decir, tendremos que sustituir el valor de la coordenada x por -x. Para ello será válido escribir:

VAR k: INTEGER;
. . . .
k := 1;
WHILE k <= maxPuntos DO
   WITH puntos[k] DO
      x := -x
   END;
   INC( k )
END

En cambio, sería incorrecto escribir:

VAR k: INTEGER;
. . . .
k := 1;
WITH puntos[k] DO
   WHILE k <= maxPuntos DO
      x := -x;
      INC( k )
   END
END

Esta segunda versión lo que haría es cambiar de signo la coordenada x del primer punto repetidamente, ya que el bucle WHILE se ejecuta íntegramente dentro del ámbito de la sentencia WITH referida al registro puntos[k] evaluado con k=1.

12.4 El esquema unión

Hay aplicaciones en las que resultaría deseable que el tipo de un dato variase según las circunstancias. Si las posibilidades de variación son un conjunto finito de tipos, entonces se puede decir que el tipo del dato corresponde a un esquema que es la unión de los tipos particulares posibles. Cada uno de los tipos particulares constituye una variante del tipo unión. Representamos simbólicamente este esquema en la forma:

       tipo_unión = variante  |  variante  …

Como situaciones típicas en las que pueden aplicarse los esquemas unión tenemos, entre otras, las siguientes:

  • Datos que pueden representarse de diferentes maneras.
  • Programas que operan indistintamente con varias clases de datos.
  • Datos estructurados con elementos opcionales.

Algunos ejemplos concretos serían:

número_general = entero  |  fracción  |  real  |  complejo
coordenadas = coordenadas_cartesianas  |  coordenadas_polares
figura = punto  |  círculo  |  cuadrado  |  rectángulo  |  rombo  |  triángulo  |  elipse
datos_persona = datos_soltero  |  datos_menor  |  datos_casado

El primer caso correspondería a un programa que opere indistintamente con números de diferentes clases. Los números enteros son datos simples, al igual que los reales, aunque las colecciones de valores son diferentes. Los números fraccionarios se representan como dos números enteros (numerador y denominador), y los complejos como dos números reales (partes real e imaginaria).

En el segundo caso tenemos dos sistemas de coordenadas diferentes para representar los puntos del plano. Las coordenadas cartesianas son dos longitudes, mientras que las polares son una longitud y un ángulo.

En el tercer caso tenemos un programa que maneja un repertorio limitado de elementos gráficos. Para cada figura se necesitará conocer una colección de parámetros diferentes.

En el último caso, los datos de un soltero mayor de edad constituirían la información básica de una persona. Los menores deberían tener además un tutor o persona responsable de ellos, y los casados deberían tener una fecha de matrimonio y un cónyuge.

Fundamentos de programación con Módula-2 (27)

11.7 Ejemplos de programas

A continuación se muestran varios programas completos con ejemplos de sus respectivas ejecuciones.

11.7.1 Sopa de letras
Con este programa se trata de realizar la búsqueda de una palabra dentro de una matriz de caracteres. La búsqueda debe realizarse en horizontal, vertical y diagonal en ambos sentidos. Por tanto, se pueden establecer 8 direcciones de búsqueda: norte, sur, este, oeste, noroeste, suroeste, noreste y sureste. En la búsqueda se deben tener en cuenta los límites de la matriz. La función Buscar comprueba si la palabra P de longitud L coincide con los caracteres de la matriz desde la posición: fila F y columna C, siguiendo la dirección R. Esta función tienen en cuenta los límites de la matriz y devuelve un resultado cierto o falso según se encuentre o no la palabra buscada.

Los demás procedimientos son auxiliares. El procedimiento IniciarSopa inicializa de forma aleatoria la matriz, mediante un recorrido de la misma. Cada carácter se obtiene a partir de un número aleatorio entre 0 y 26, al que se suma la posición del carácter "a" dentro de la tabla ASCII.

El procedimiento Cambiar, es el encargado de pasar de minúsculas a mayúsculas la palabra encontrada. Este cambio se realiza mediante un recorrido parcial de Lg caracteres de la matriz desde la posición: fila Fil y columna Col, siguiendo la dirección Ru.

El procedimiento EscribirSopa es un recorrido total de la matriz en el que se escriben por filas todos los caracteres de la matriz separados por un blanco.

En el programa se lee la palabra a buscar, acabada en punto, e inmediatamente se realiza su búsqueda exhaustiva desde todas las posiciones de la matriz y con todas las direcciones posibles. Si se encuentra, se cambia a mayúsculas. El listado del programa es el siguiente:

(**************************************************************************************************
*
*   Programa: SopaLetras
*
*   Descripción:
*      Este programa busca una palabra en una matriz de caracteres, en cualquier
*      dirección de forma semejante a como se hace en una sopa de letras
*
**************************************************************************************************)
MODULE SopaLetras;
   FROM InOut IMPORT
      WriteString, Write, WriteLn, Read;
   FROM Lib IMPORT RANDOMIZE, RANDOM;
   CONST
      Filas = 10;               (* Filas de la sopa de letras *)
      Columnas = 20;    (* Columnas de la sopa de letras *)
      TotalLetras = 26;    (* Total letras abecedario inglés *)
   TYPE
      Largo = [1..Filas];
      Ancho = [1..Columnas];
      TipoSopa = ARRAY Largo, Ancho OF CHAR;
      Ristra = ARRAY Ancho OF CHAR;
      TipoRumbo = ( Norte, Sur, Este, Oeste, Noroeste, Suroeste, Noreste, Sureste );
      Caracteres = SET OF CHAR;
   VAR
      sopa: TipoSopa;   palabra: Ristra;   long: Ancho;
      indFila: Largo;   indColu: Ancho;   rumbo: TipoRumbo;
      tecla: CHAR;

PROCEDURE IniciarSopa;
(*=====================================
Procedimiento para iniciar aleatoriamente una sopa de letras
=====================================*)
   VAR i : Largo; j : Ancho;
BEGIN
   RANDOMIZE;
   FOR i := 1 TO Filas DO
      FOR j := 1 TO Columnas DO
         sopa[i,j] := CHR(RANDOM(TotalLetras) + ORD("a"))
      END
   END
END IniciarSopa;

PROCEDURE Cambiar( Lg, Col: Ancho; Fil: Largo; Ru : TipoRumbo);
(*=====================================
Procedimiento para cambiar Lg letras a mayusculas desde
la posición Col, Fil con el rumbo RU
=====================================*)
   VAR i : Ancho;
BEGIN
   FOR i := 1 TO Lg DO
      sopa[Fil,Col] := CAP(sopa[Fil,Col]);
      (*– Nueva fila según el rumbo –*)
      CASE Ru OF
         Norte, Noreste, Noroeste : Fil := Fil-1 |
         Sur, Sureste, Suroeste : Fil := Fil+1 |
         Este, Oeste :
      END;
      (*– Nueva columna según el rumbo –*)
      CASE Ru OF
         Este, Noroeste, Sureste : Col := Col+1 |
         Oeste, Suroeste : Col := Col-1 |
         Norte, Sur :
      END
   END
END Cambiar;

PROCEDURE  Buscar( P: Ristra; L,C: Ancho; F: Largo; R: TipoRumbo): BOOLEAN;
(*============================================================
Procedimiento para buscar las L letras de la ristra P, desde la posición C, F con el
rumbo R en la sopa de letras
============================================================*)
   VAR i : Ancho; sigue : BOOLEAN;
BEGIN
   i := 1; sigue := TRUE;
   WHILE (i <= L) AND sigue DO
      (*– Se sigue buscando si está la letra buscada en mayúscula o minúscula –*)
      (*sigue := ( CAP( P[i] ) = CAP( sopa[F,C] ) );*)
      CASE R OF
         Norte, Noreste, Noroeste : F := F – 1 |
         Sur, Sureste, Suroeste : F := F + 1 |
         Este, Oeste:
      END;
      (*– Seguir si la nueva fila está dentro de la sopa –*)
      sigue := sigue AND (F > 0) AND (F <= Filas);
      CASE R OF
         Este, Noreste, Sureste : C := C+1 |
         Oeste, Suroeste : C := C-1 |
         Norte, Sur :
      END;
      (*– Seguir si la nueva columna está en la sopa –*)
      sigue := sigue AND (C > 0) AND (C <= Columnas);
      i := i+1
   END;
   RETURN sigue
END Buscar;

PROCEDURE EscribirSopa;
(*=====================================
Procedimiento para escribir la sopa de letras
=====================================*)
   VAR i : Largo; j : Ancho;
BEGIN
   WriteLn;
   FOR i := 1 TO Filas DO
      FOR j := 1 TO Columnas DO
         Write(sopa[i,j]); Write(" ")
      END;
      WriteLn
   END
END EscribirSopa;

BEGIN
   IniciarSopa;
   EscribirSopa;
   REPEAT
      long := 1;
      WriteString("¿Palabra a buscar.?");
      (*– Leer palabra a buscar –*)
      REPEAT
         Read(tecla); Write(tecla);
         IF tecla IN Caracteres{"a".."z"} THEN
            long := long + 1; palabra[long] := tecla
         END
      UNTIL tecla = ".";
   (*– Buscar desde todos los puntos posibles y en todas las direcciones  posibles –*)
   FOR indFila := 1 TO Filas DO
      FOR indColu := 1 TO Columnas DO
         FOR rumbo := Norte TO Sureste DO
            IF Buscar( palabra, long, indColu, indFila, rumbo)
            THEN
               (*– Cuando se encuentra se camba a mayusculas –*)
               Cambiar( long, indColu, indFila, rumbo )
             END
         END
      END
   END;
   (*– Escribir cómo queda la sopa –*)
   EscribirSopa;
   WriteString( "¿Otra Palabra (s/n)?");
   Read( tecla ); Write( tecla ); WriteLn
   UNTIL tecla = "n"
END SopaLetras.

La ejecución del programa produce el siguiente resultado:

w a u l k v j x j c q d x w g l u v u w
t y j k j d a l d p a i t j k d t n m e
w n r u x v o h c f o f r q y j n g o d
d n e v y w r b q q f r t k d p s z i i
e w k i d c i w d y j o e n p v a p q j
d q k w r p o n s n k v k e d z t v y o
g t h x w d c h g e u j l z e s z i b w
q k q o a u c a l f j v q r p k a w q y
u m i o c b l z x i g z k q y a z y e n
j o c t w b g n v d b c m x w m z b h a
¿Palabra a buscar.?re.
w a u l k v j x j c q d x w g l u v u w
t y j k j d a l d p a i t j k d t n m e
w n R u x v o h c f o f r q y j n g o d
d n E v y w r b q q f R t k d p s z i i
e w k i d c i w d y j o E n p v a p q j
d q k w r p o n s n k v k e d z t v y o
g t h x w d c h g e u j l z E s z i b w
q k q o a u c a l f j v q R p k a w q y
u m i o c b l z x i g z k q y a z y e n
j o c t w b g n v d b c m x w m z b h a
¿Otra Palabra (s/n) ?n

11.7.2 Recortar una imagen
Este programa es un ejemplo de utilización de una matriz orlada. El procedimiento Recortar ya fue explicado en el apartado dedicado a las matrices orladas. El procedimiento Imprimir es simplemente un recorrido de la matriz para imprimir la imagen contenida. El procedimiento LeerFoto lee una imagen de los datos de entrada, leyendo un carácter por cada punto.

El listado completo del programa es el siguiente:

(*****************************************************************************
*     Programa: RECORTE
*    
*     Descripción:
*        Este programa recorta una imagen digitalizada
*
****************************************************************************)
MODULE Recorte;

FROM InOut IMPORT WriteString, WriteLn, Read, Write;

CONST
   Ancho = 40;                      (* Anchura de la imagen *)
   Alto = 20;                          (* Altura de la imagen *)
   Borde = -1;                         (* Indicador de borde de la imagen *)
   Blanco = 0;                        (* Nivel bajo de grises = blanco *)
   Negro = 5;                         (* Nivel alto de grises = negro *)

TYPE
   Grises = [Borde..Negro];
   TipoImagen = ARRAY [0..Alto+1], [0..Ancho+1] OF Grises;

VAR
   imagen: TipoImagen;

PROCEDURE LeerImagen;
(*===============================================
   Lee la imagen como dato de entrada.
================================================*)
   VAR i, j: INTEGER; c: CHAR;
BEGIN
   (*– 1º Paso: Inicializar toda la imagen a ‘Borde’ –*)
      FOR i := 0 TO Alto+1 DO
         FOR j := 0 TO Ancho+1 DO
            imagen[i,j] := Borde
         END
      END;
   (*– 2º Paso: Leer los datos, punto a puto –*)
      FOR   i := 1 TO Alto DO
         FOR j := 1 TO Ancho DO
            Read( c );
            imagen[i,j] := ORD( c ) – ORD( ‘0’ )
         END;
         Read( c )                     (* salto de línea *)
      END;
   END LeerImagen;

PROCEDURE Constrastar( nivel: Grises );
(*===============================================
    Procedimiento para constrastar la imagen
================================================*)
   VAR i,j: INTEGER;
BEGIN
   FOR i := 1 TO Alto DO
      FOR j := 1 TO Ancho DO
         IF imagen[i,j] <= nivel THEN
            imagen[i,j] := Blanco
         ELSE
            imagen[i,j] := Negro
         END
      END
   END;
END Constrastar;

PROCEDURE Recortar;
(*===============================================
   Procedimiento para recortar la imagen
================================================*)
   VAR i, j: INTEGER; fin : BOOLEAN;
BEGIN
   REPEAT
      fin := TRUE;
      FOR i := 1 TO Alto DO
         FOR j := 1 TO Ancho DO
            IF (imagen[i,j] = Blanco) AND ( (imagen[i-1, j] = Borde)
                                                          OR (imagen[i, j-1] = Borde)
                                                          OR (imagen[i, j+1] = Borde)
                                                          OR (imagen[i+1,j] = Borde) ) THEN
                 imagen[i,j] := Borde;
                 fin := FALSE
            END
         END
      END
   UNTIL fin
END Recortar;

PROCEDURE Imprimir;
(*================================================
   Procedimiento para imprimir la imagen
=================================================*)
   VAR i, j: INTEGER;
BEGIN
   FOR i := 1 TO Alto DO
      FOR j := 1 TO Ancho DO
         CASE imagen[i,j] OF
            Borde: Write( " " ) |
            Blanco: Write( "." ) |
            1:       Write( ".") |
            2:       Write( "+") |
            3:       Write( "x") |
            4:       Write( "*") |
            Negro: Write( "#" )
         END
       END;
       WriteLn
   END
END Imprimir;
BEGIN
(*– Leer la imagen inicial –*)
   LeerImagen;
   WriteString( "Imagen inicial:"  ); WriteLn;
   Imprimir;
(*– Reducir la imagen a blanco y negro –*)
   Constrastar( 3 );
   WriteLn;
   WriteString( "Imagen constratada:" ); WriteLn;
   Imprimir;
(*– Recortar la imagen, marcando el borde externo –*)
   Recortar;
   WriteLn;
   WriteString( "Imagen recortada:xXx" ); WriteLn;
   Imprimir;
END Recorte.

A continuación se presenta un ejemplo de la ejecución de este programa. Los datos de entrada contienen un carácter por cada punto de la imagen, y simulan una rejilla. Una de las esquinas del borde derecho está rota. Los datos son:

0123454321012345432101234543210123454321
1234545432123454543212345454321234545432
2345434543234543454323454345432345434543
3454323454345432345434543234543454323454
4543212345454321234545432123454543212344
5432101234543210123454321012345432101233
4543212345454321234545432123454543212344
3454323454345432345434543234543454323454
2345434543234543454323454345432345434543
1234545432123454543212345454321234545432
0123454321012345432101234543210123454321
1234545432123454543212345454321234545432
2345434543234543454323454345432345434543
3454323454345432345434543234543454323454
4543212345454321234545432123454543212345
5432101234543210123454321012345432101234
4543212345454321234545432123454543212345
3454323454345432345434543234543454323454
2345434543234543454323454345432345434543
1234545432123454543212345454321234545432

El resultado de la ejecución del programa es el siguiente:

Imagen inicial:
..+x*#*x+…+x*#*x+…+x*#*x+…+x*#*x+.
.+x*#*#*x+.+x*#*#*x+.+x*#*#*x+.+x*#*#*x+
+x*#*x*#*x+x*#*x*#*x+x*#*x*#*x+x*#*x*#*x
x*#*x+x*#*x*#*x+x*#*x*#*x+x*#*x*#*x+x*#*
*#*x+.+x*#*#*x+.+x*#*#*x+.+x*#*#*x+.+x**
#*x+…+x*#*x+…+x*#*x+…+x*#*x+…+xx
*#*x+.+x*#*#*x+.+x*#*#*x+.+x*#*#*x+.+x**
x*#*x+x*#*x*#*x+x*#*x*#*x+x*#*x*#*x+x*#*
+x*#*x*#*x+x*#*x*#*x+x*#*x*#*x+x*#*x*#*x
.+x*#*#*x+.+x*#*#*x+.+x*#*#*x+.+x*#*#*x+
..+x*#*x+…+x*#*x+…+x*#*x+…+x*#*x+.
.+x*#*#*x+.+x*#*#*x+.+x*#*#*x+.+x*#*#*x+
+x*#*x*#*x+x*#*x*#*x+x*#*x*#*x+x*#*x*#*x
x*#*x+x*#*x*#*x+x*#*x*#*x+x*#*x*#*x+x*#*
*#*x+.+x*#*#*x+.+x*#*#*x+.+x*#*#*x+.+x*#
#*x+…+x*#*x+…+x*#*x+…+x*#*x+…+x*
*#*x+.+x*#*#*x+.+x*#*#*x+.+x*#*#*x+.+x*#
x*#*x+x*#*x*#*x+x*#*x*#*x+x*#*x*#*x+x*#*
+x*#*x*#*x+x*#*x*#*x+x*#*x*#*x+x*#*x*#*x
.+x*#*#*x+.+x*#*#*x+.+x*#*#*x+.+x*#*#*x+

Imagen constratada:
….###…….###…….###…….###…
…#####…..#####…..#####…..#####..
..###.###…###.###…###.###…###.###.
.###…###.###…###.###…###.###…###
###…..#####…..#####…..#####…..##
##…….###…….###…….###……..
###…..#####…..#####…..#####…..##
.###…###.###…###.###…###.###…###
..###.###…###.###…###.###…###.###.
…#####…..#####…..#####…..#####..
….###…….###…….###…….###…
…#####…..#####…..#####…..#####..
..###.###…###.###…###.###…###.###.
.###…###.###…###.###…###.###…###
###…..#####…..#####…..#####…..##
##…….###…….###…….###…….#
###…..#####…..#####…..#####…..##
.###…###.###…###.###…###.###…###
..###.###…###.###…###.###…###.###.
…#####…..#####…..#####…..#####..

Imagen recortada:
    ###       ###       ###       ###
   #####     #####     #####     #####
  ###.###   ###.###   ###.###   ### ###
###…### ###…### ###…### ###   ###
###…..#####…..#####…..#####     ##
##…….###…….###…….###
###…..#####…..#####…..#####     ##
###…###.###…###.###…###.###   ###
  ###.###…###.###…###.###…### ###
   #####…..#####…..#####…..#####
    ###…….###…….###…….###
   #####…..#####…..#####…..#####
  ###.###…###.###…###.###…###.###
###…###.###…###.###…###.###…###
###…..#####…..#####…..#####…..##
##…….###…….###…….###…….#
###…..#####…..#####…..#####…..##
###…### ###…### ###…### ###…###
  ###.###   ###.###   ###.###   ###.###
   #####     #####     #####     #####

11.7.3 Frases políndromas
Este programa ilustra el uso de vectores abiertos. Se trata de comprobar si una frase es un políndromo, esto es, si las letras de las que consta se leen igual hacia adelante que hacia atrás. Para ello se define un procedimiento LeerTexto, capaz de leer un vector de caracteres de cualquier longitud. Este procedimiento sólo guarda las letras válidas de la "a" a la "z" y finaliza cuando se introduce un punto "." o se llena el vector pasado como argumento.

La función Simetrico es la encargada de comprobar que el contenido del vector abierto, pasado como argumento por valor, es simétrico. Primeramente, se busca el punto de final del texto a analizar o el final del vector. Esto se hace mediante el esquema típico de búsqueda. La posición final se decrementa en uno después de la búsqueda para apuntar al primer carácter válido Después, se comprueba si coinciden los caracteres de un extremo con los del otro. Esta comprobación acaba o bien cuando se cruzan los índices y todos los caracteres han sido iguales o bien cuando no coinciden algunos de ellos.

El listado completo del programa es el siguiente:

(**************************************************************************************************
*
*   Programa: Palindromo
*
*   Descripción:
*      Este programa comprueba si una frase es un palindromo.
*
**************************************************************************************************)
MODULE Palindromo;
   FROM InOut IMPORT
      WriteString, WriteLn, Write, Read;

   CONST
      Fin = ".";
      Maximo = 100;            (* Máxima longitud de la frase *)

   TYPE
      TipoLong = [0..Maximo];
      TipoRistra = ARRAY TipoLong OF CHAR;
      Caracteres = SET OF CHAR;

   VAR
      frase : TipoRistra;

PROCEDURE LeerTexto( VAR Tex: ARRAY OF CHAR );
(*===============================================
Procedimiento para leer una frase acabada en un punto (.) y dejarla
en el argumento vector abierto. Solo se guardan en el vector las letras
de a..z mayúsculas o minúsculas y el punto final.
===============================================*)
   VAR   car: CHAR;   long: TipoLong;
BEGIN
   WriteString( "¿Frase acabada en punto(.)?"); WriteLn;
   long := 0;
   REPEAT
      Read(car);   Write(car);
      (*– Se comprueba si es un caracter correcto –*)
      IF car IN Caracteres{"A".."Z", "a".."z", Fin} THEN
         long := long + 1;   Tex[long] := CAP(car)
      END;
      (*– Se acaba al encontrar el punto o si se acaba el vector  –*)
   UNTIL (car = Fin) OR (long = HIGH(Tex));
END LeerTexto;

PROCEDURE Simetrico( Texto: ARRAY OF CHAR ): BOOLEAN;
(*===============================================
Función que comprueba si hay simetría entre las letras del
comienzo y las del final de una frase: es un palindromo. El
argumento pasado es de tipo vector abierto
===============================================*)
   VAR i, j: TipoLong;
BEGIN
(*– 1º Paso: Buscar el punto final (.) o final del vector –*)
   j := 0;
   WHILE (Texto[j] <> Fin) AND (j <= HIGH(Texto)) DO
      j := j + 1
   END;
   j := j – 1; i := 1;
(*– 2º Paso: Comprobar igualdad entre caracteres simetricos –*)
   WHILE (i < j) AND (Texto[i] = Texto[j]) DO
      i := i+1; j := j-1
   END;
   RETURN i >= j
END Simetrico;

BEGIN
   LeerTexto( frase );
   IF Simetrico( frase ) THEN
      WriteString( " Es Palindromo")
   ELSE
      WriteString( " No es Palindromo")
   END
END Palindromo.

El resultado de la ejecución del programa es el siguiente:

¿Frase acabada en punto(.)?
Dabale arroz a la zorra el abad. Es Palindromo

Fundamentos de programación con Módula-2 (26)

11.4.2 Búsqueda secuencial
Para buscar un elemento dentro de una formación es necesario recorrerla, pero no siempre en su totalidad. El recorrido se debe detener en cuanto se encuentre el elemento buscado, y por tanto sólo será completo cuando no se encuentre el elemento buscado dentro de la formación. Este planteamiento del problema indica que no se puede utilizar una sentencia FOR para la operación de búsqueda.

Para establecer un esquema general de búsqueda es necesario fijar la condición o condiciones que determinan las características del elemento buscado. Además se debe tener en cuenta el tamaño y estructura de la formación para controlar cuándo se da por finalizada una búsqueda infructuosa. En algunos casos es posible incluso que el tamaño de la formación sea nulo y no contenga ningún elemento. Todos estos condicionantes apuntan en el sentido de emplear una sentencia WHILE para realizar la búsqueda. Como esquema general se puede plantear el siguiente:

Iniciar búsqueda
WHILE ( NOT Encontrado ) AND ( NOT Final ) DO
   Pasar al siguiente elemento;
   Verificar encuentro
END

Este esquema se puede emplear, por ejemplo, para la búsqueda del contenido de la variable elemento en la formación vectorUno. Para ello se necesitan las siguientes declaraciones previas:

VAR
   elemento: INTEGER;
   posicion: Dimension;
   visto: BOOLEAN;

el fragmento de programa que realiza la búsqueda sería el siguiente:

visto := FALSE;
posicion := 0;
WHILE ( NOT visto ) AND ( posicion < Ultimo ) DO
   posicion := posicion + 1;
   visto := elemento = vectorUno[ posicion ]
END

El valor final de la variable booleana visto indica si ha sido encontrado elemento y el valor de la variable posicion apunta la posición en la que ha sido encontrado. El empleo de dos variables tiene el incoveniente de que ambas deben ser analizadas al finalizar la búsqueda para conocer el resultado. Para evitar esto se puede dar a la variable posicion un valor fuera del rango de las posiciones posibles (normalmente la posición cero), para indicar que elemento no ha sido encontrado. Para concluir la búsqueda infructuosa apuntado a la posición cero se puede realizar el recorrido hacia atrás, empezando por Ultimo. Con este planteamiento el resultado es el siguiente:

visto := FALSE;
posicion := Ultimo;
WHILE ( NOT visto ) AND (poisicon > 0) DO
   IF elemento <> vectorUno[ posicion ] THEN
      posicion := posicion -1
   ELSE
      visto := TRUE
   END
END

Cuando se sabe que el vector tiene al menos un elemento, es posible emplear la sentencia REPEAT de la siguiente forma:

visto := FALSE;
posicin := Ultimo;
REPEAT
   IF elemento <> vectorUno[ posicion ] THEN
      posicion := posicion – 1
   ELSE
      visto := TRUE
   END
UNTIL visto OR ( posicion = 0 )

También se puede utilizar la sentencia LOOP, incluso con un vector vacío. En este caso el esquema a emplear es el siguiente:

Iniciar la búsqueda;
LOOP
   IF Final THEN EXIT END
   Verificar encuentro;
   IF Encontrado THEN EXIT END;
   Pasar al siguiente elemento
END

La búsqueda en vectoUno sería de la siguiente forma:

posicion := Ultimo;
LOOP
   IF posicion = 0 THEN EXIT END;
   IF ( elemento = vectorUno[ posicion ] ) THEN EXIT END;
   posicion := posicion – 1
END

La elección del esquema más adecuado depende de la complejidad de las operaciones Verificar encuentro y Pasar al siguiente elemento, y de las posibles simplificaciones que se puedan introducir en ambas empleando uno u otro esquema.

11.4.3 Inserción
Cuando los elementos de un vector se van incorporando al mismo de una forma paulatina, uno detrás de otro, se puede aprovechar esta circunstancia para insertar el nuevo elemento en la posición que le corresponda. De esta forma, los datos del vector podrían estar siempre ordenados, lo que supone grandes ventajas.

En general, una operación de inserción de un nuevo elemento en una formación supone desplazar algunos de sus datos actuales para conseguir el hueco que le corresponde al nuevo elemento y después insertarlo en el hueco. Un posible esquema sería:

Iniciar inserción;
WHILE ( NOT Encontrado hueco ) AND ( NOT Final ) DO
   Desplazar elemento;
   Pasar al siguiente elemento

END
Insertar nuevo elemento

Este esquema, para la inserción de elemento dentro de los N primeros elementos de vectorUno, que ya están ordenados, se convierte en el siguiente fragmento de programa:

j := N;
WHILE ( elemento < vectorUno[ j ] ) AND ( j >= 1 ) DO
   vectorUno[ j + 1 ] := vectorUno[ j ];
   j := j – 1
END;
vectorUno[ j + 1 ] := elemento;

Evidentemente, después de la inserción, el vector tiene un elemento más. Por tanto, el valor de N siempre deberá ser menor que Ultimo.

11.4.4 Ordenación por inserción directa
En este apartado se aborda una solución para la ordenación de un número indeterminado de datos dentro de un vector. Existen diversos métodos de ordenación de vectores cuyo estudio cae fuera del alcance de es libro (entradas de blog). El método de ordenación por inserción directa es uno de los más sencillos y está basado en el esquema de inserción mostrado en el apartado anterior. Por ejemplo, se trata de ordenar vectorUno definido como vector de diez elementos y que inicialmente está desordenado, tal como se muestra en la Figura 11.3.

Figura(11_3)
       Figura 11.3. Vector Inicial

Para comenzar, el primer elemento ( 21 ) se supone ordenado. A continuación, extraemos el segundo elemento ( 5 ) y se genera un hueco, que se puede utilizar para ampliar el vector ya ordenado. El método de ordenación consiste en insertar el elemento extraído en su lugar correspondiente entre los elementos ya ordenados. Este proceso se repite con el tercero, cuarto, quinto, … y décimo elemento hasta quedar ordenado todo el vector. La secuencia de inserciones de los sucesivos elementos del vector es la siguiente:

Figura(11_3a)

En la secuencia se muestra la posición del hueco inmediatamente antes de la inserción del siguiente elemento. La línea quebrada indica hasta qué punto se amplía el vector ordenado con cada nueva inserción. La inserción se realiza desde la posición anterior a la del elemento extraído. La variable elemento guarda el elemento extraído de la posición i. La ordenación total del vector se consigue mediante el recorrido de todos sus elementos, desde el segundo, para buscarles su hueco e insertarlos en él. Así, el fragmento de programa de ordenación es el siguiente:

FOR i := 2 TO Ultimo DO
   elemento := vectorUno[ i ]; j := i – 1;
   WHILE ( elemento < vectorUno[ j ] ) AND ( j >= 1 ) DO
      vectorUno[ j + 1 ] := vectorUno[ j ];
      j := j-1
   END;
   vectorUno[ j + 1 ] := elemento
END

Este programa es válido para cualquier tamaño del vector, ya que sólo depende del valor que tome la constante Ultimo.

11.4.5 Búsqueda por dicotomía
Cuando los datos están ordenados la búsqueda resulta mucho mas rápida. Si comparamos el elemento a buscar con el que está justo en la mitad de los datos ordenados, podemos decidir si es ése el elemento que buscamos o debemos continuar buscando, pero sólo en la mitad derecha o sólo en la mitad izquierda.

El mismo proceso se puede repetir con la mitad elegida, comparando con el elemento que está en el centro de dicha mitad. En cada comparación, la búsqueda se reduce a comprobar si el dato buscado está entre la mitad de los anteriores. La búsqueda finaliza cuando el elemento se encuentra, o bien cuando no es ninguno de los dos datos consecutivos a los que queda reducida la comparación después de sucesivas divisiones en mitades. Esta búsqueda se denomina búsqueda por dicotomía.

Como esquema general de búsqueda sigue siendo válido el mismo utilizado anteriormente. Sin embargo, ahora es necesario cambiar la obtención del siguiente elemento a comparar. Como ejemplo, realizaremos la búsqueda por dicotomía de elemento vectorUno. Se necesitan dos variables para acotar el trozo de vector que todavía queda por comprobar y otra variable para señalar el punto medio de ambas. Estas variables las denominaremos izq, dch y mitad. Sus declaraciones serán:

VAR izq, dch, mitad: Dimension;

El fragmento de programa sería como sigue:

posicion := 0; izq := 1; dch := Ultimo;
WHILE ( posicion = 0 ) AND ( izq <= dch ) DO
   mitad := ( izq + dch ) DIV 2;
   IF Elemento = VectorUn[ mitad ] THEN
      posicion := mitad
   ELSIF Elemento < VectorUno[ mitad ] THEN
      dch := mitad – 1
   ELSIF
      izq := mitad + 1
   END
END

En este caso la variable posicion se utiliza para conocer si ha sido encontrado Elemento y se inicializa a cero (no encontrado). Este valor sólo se modifica cuando se consigue encontrar el elemento buscado. La búsqueda por dicotomía se puede aplicar también, por ejemplo, en el esquema de ordenación por inserción, para localizar el lugar en que hay que insertar el nuevo elemento.

11.4.6 Simplificación de las condiciones de contorno
La programación de operaciones con vectores, realizadas elemento a elemento, exige con frecuencia realizar un tratamiento especial de los elementos extremos del vector o, en general, de los elementos del contorno de una formación. A continuación veremos algunas técnicas particulares para evitar la necesidad de detectar de manera explícita si se ha llegado a un elemento del contorno, o realizar con él un tratamiento especial.

Por ejemplo, en el procedimiento general de búsqueda es necesario comprobar con cada iteración si no se ha alcanzado todavía el Final del vector. Esto complica la condición del bucle de iteración y supone un tiempo adicional en la ejecución de cada iteración. Si el dato que se trata de buscar está dentro del vector, antes o después se termina encontrando y nunca se intenta buscar fuera de los límites del mismo. En este caso la condición Final resulta innecesaria. Por tanto, se podrá prescindir de la condición Final cuando se puede asegurar que cualquier dato que se busque estará en el vector. La manera de asegurar esto es incluir el dato en el vecor antes de comenzar la búsqueda. El vector se amplía, según se muestra en la Figura 11.4, en un elemento más de índice 0. En él se copia el dato a buscar antes de iniciar la búsqueda para que actúe como centinela (C) y asegure que la búsqueda nunca acaba de forma infructuosa.

Figura(11_4)
       Figura 11.4. Vector con centinela

Ahora, el esquema general de búsqueda se simplifica de la siguiente forma:

Iniciar centinela;
Iniciar búsqueda;
WHILE ( NOT Encontrado ) DO
   Pasar al siguiente elemento
END

Este esquema para la búsqueda del contenido de la variable elemento en el vectorUno requiere modificar la declaración de la dimensión del vector de la siguiente forma:

TYPE Dimension = [ 0..Ultimo ];
         TipoVector = ARRAY Dimension OF INTEGER;

y se tiene que redifinir la variable:

VAR vectorUno: TipoVector;

La posición cero del vector estará destinada a situar el centinela y la búsqueda se simplificaría de la siguiente forma:

vectorUno[ 0 ] := elemento;
posicion := Ultimo;
WHILE elemento <> vectorUno[ posicion ] DO
   posicion := posicion – 1
END

Igual que antes, si al final de la búsqueda, la variable posición tiene un valor igual a cero, quiere decir que la búsqueda ha sido infructuosa: el elemento encontrado ha sido el centinela.

La misma técnica del centinela se puede emplear en la inserción, lo que simplifica el algoritmo de ordenación. La nueva redacción del programa es la siguiente:

FOR i := 2 TO Ultimo DO
   elemento := vectorUno[ i ];
   vectorUno[ 0 ] := elemento; j := i – 1;
   WHILE elemento < vectorUno[ j ] DO
      vectorUno[ j + 1 ] := vectorUno[ j ];
      j := j – 1
   END;
   vectorUno[ j + 1 ] := elemento
END

Como se puede observar, la técnica del centinela simplifica las condiciones de contorno para cualquier operación que se realice con un vector y el programa resulta más simple y fácil de entender.

Cuando se trabaja con matrices, también se pueden simplificar las condiciones de contorno utilizando matrices orladas. Estas matrices se dimensionan con dos filas y dos columnas más de las necesarias tal como se muestra en la Figura 11.5.

Figura(11_5)
        Figura 11.5. Matriz Orlada

En esa matriz se inicializa todo su contorno (filas y columnas extras) con un valor tal que permita identificar dicho contorno (C). Si se elige adecuadamente el valor C, cualquier operación que se realice con la matriz no necesita tener en cuenta sus límites declarados. Además, en algunos casos el contorno puede jugar un papel fundamental en la operación con la matriz.

Para ilustrar el uso de una matriz orlada, supongamos que tenemos una imagen en blanco y negro digitalizada dentro de una matriz definida de la siguiente forma:

CONST       Puntos = 20;
                  Blanco = 0;
                  Negro = 5;

TYPE   Grises = [ Blanco .. Negro ];
            Indice = [ 1 .. Puntos ];

VAR   imagen: ARRAY Indice, Indice OF Grises;

Cada elemento de la matriz guarda el nivel de grises del correspondiente punto de la imagen. Para tratar cada punto de la imagen individualmente basta con hacer un recorrido completo, sin ninguna complicación. Por ejemplo, para contrastar la imagen y reducir todos los puntos gris claro a blanco y todos los grises oscuro a negro, bastará escribir:

FOR i := 1 TO Puntos DO
   FOR j := 1 TO Puntos DO
      IF imagen [ i, j ] <= Nivel THEN
         imagen [ i, j ] := Blanco
      ELSE
         imagen [ i, j ] := Negro
      END
   END
END;

Supongamos ahora que queremos recortar la imagen, esto es, eliminar aquellos puntos externos de la imagen que están en blanco, pero dejando los puntos blancos que son interiores y están rodeados de puntos negros. El tratamiento de cada punto exige examinar al mismo tiempo los puntos contiguos. El programa se simplifica si se garantiza que todo punto útil de la imagen tiene puntos contiguos en todas las direcciones, es decir, no hay situaciones excepcionales en los bordes.

Para ello lo mejor es que la matriz de la imagen sea una matriz orlada, por lo que se redefine de la siguiente forma:

TYPE Indice = [ 0 .. Puntos + 1 ];
         TipoImagen = ARRAY Indice, Indice OF Grises;

Para establecer el nivel de contorno se declara un valor de borde y se redefine la escala de grises de la siguiente forma:

CONST   Borde = -1;
TYPE   Grises = [ Borde .. Negro ];

Suponiendo que imagen está ya contrastada anteriormente y que su contorno (es decir, la orla) está inicializado al valor de Borde, el recorte se realizaría mediante sucesivos recorridos de toda la matriz en los que los puntos blancos que tienen algún punto Borde alrededor deben pasar también a puntos de Borde. El proceso de recorte se termina cuando en un recorrido completo de toda la imagen no hay ningún punto que cambie. Esta forma de operar se denomina de fuerza bruta, y puede ser poco eficiente, pero es muy sencilla de programar. El fragmento de programa que realiza ésto es el siguiente:

REPEAT
   fin := TRUE;
   FOR   i := 1 TO Puntos DO
      FOR j := 1 TO Puntos DO
         IF ( imagen [ i, j ] = Blanco ) AND (( imagen [ i-1, j ] = Borde )
             OR ( imagen [ i, j-1 ] = Borde )
             OR ( imagen [ i, j+1 ] = Borde )
             OR ( imagen [ i+1, j ] = Borde )
         THEN
            imagen [ i, j ] := Borde; fin := FALSE
         END
      END
   END
UNTIL fin

Este ejemplo es un fragmento de uno de los programas completos que figura como ejemplo al final del Tema.

11.5 Vector de caracteres: Ristra (String)

Debido a su frecuente uso, en el Tema 2 fueron ya presentadas las constantes de tipo ristra. Sin embargo, hasta ahora no hemos podido utilizar variables de este tipo. Esto se debe a que en realidad las ristras son vectores de caracteres y los vectores no han sido estudiados hasta este Tema. Sin embargo, en todos los lenguajes es habitual que las ristras tengan ciertas peculiaridades que no tienen el resto de los vectores y por esta razón son objeto de este apartado específico.

En Modula-2 cualquier vector cuya declaración sea de la forma:

ARRAY [ 0 .. N ] OF CHAR

se considera una ristra o string, con independencia de su longitud particular, esto es, del valor de N. Las características peculiares de las ristras son:

   a) El primer elemento de una ristra siempre es el índice igual a cero.

   b) En un vector de esta clase se pueden almacenar ristras de diferentes longitudes (si caben). Para distinguir la longitud útil en cada momento se reserva siempre espacio para un carácter más, y se hace que toda ristra termine con un carácter nulo (0C) situado al final.

Por tanto, para declarar una ristra de veinte caracteres se debe hacer de la siguiente forma:

TYPE
   Ristra20 = ARRAY [ 0 .. 20 ] OF CHAR;

La declaración de variables de este tipo se hace de la forma habitual:

VAR
   nombre, apellido: Ristra20;
   direccion: ARRAY [ 0 .. 40 ] OF CHAR;

La asignación de un valor a una variable de tipo ristra se realiza de la siguiente forma:

apellido := "Gonzalez";
direccion := "Paseo de la Castellana 345 – 6º";

Como se puede observar, no es necesario asignar una ristra con los veinte o cuarenta caracteres. Cuando el número de caracteres asignados es menor que los declarados, a continuación del último se sitúa el carácter nulo (0C) de final de ristra. Este carácter es especial y no se puede escribir. Lo que nunca se puede hacer es asignar más caracteres de los declarados pues se rebasarían los límites previstos y se provocaría un error. Al igual que con cualquier otro tipo de vector, para poder realizar asignaciones entre variables de tipo ristra es necesario que ambas sean del mismo tipo. Por ejemplo:

nombre := apellido;

Estas variables se pueden utilizar como argumento del procedimiento de escritura de ristras. Por ejemplo:

WriteString( "APELLIDO : " ); WriteString( apellido );

produce el siguiente resultado:

APELLIDO : Gonzalez

El procedimiento de escritura sólo escribe el contenido de la variable hasta el primer carácter nulo, aunque en versiones antiguas del lenguaje puede que se escriba el vector completo.

También es posible utilizar variables de tipo ristra con el procedimiento de lectura de ristras que suele estar disponible en el módulo InOut. Por ejemplo:

ReadString( nombre );

Las características y funcionamiento de este procedimiento dependen del compilador concreto y por tanto se debe consultar el manual correspondiente. En cualquier caso, el procedimiento guardará en la variable la ristra introducida por teclado.

11.6 Argumentos de tipo vector abierto

Una de las operaciones que se puede realizar con los vectores es pasarlos como argumento de un procedimiento o función. En su definición se tienen que indicar la estructura y tamaño del vector que se puede pasar como argumento. Por ejemplo:

TYPE TipoVector = ARRAY [ 1 .. 10 ] OF INTEGER;
. . . .
PROCEDURE LeerVector( VAR v: Vector )

Este procedimiento sólo permite operar con vectores de diez elementos de tipo INTEGER. Si dentro del mismo programa se necesita realizar un procedimiento idéntico para vectores de once elementos también de tipo INTEGER, sería necesario realizar un nuevo procedimiento para once elementos. En general, sería necesario realizar una versión distinta del procedimiento para cada tamaño diferente del vector con el que se quiera trabajar. Evidentemente ésto no es la solución más adecuada.

Una forma de trabajar con vectores de diferentes tamaños es definir un tipo único con capacidad para el mayor de todos los que se necesiten. Cuando no se utiliza todo el tamaño, es necesario indicar de alguna forma qué elementos se están empleando realmente. Esto se puede hacer, por ejemplo, almacenando en alguna parte el número de elementos en uso, o marcando el final con un valor nulo como sucede con las ristras. Esto se deberá tener en cuenta en la programación del procedimiento. Con esta solución todos los vectores que se pasen como argumento deben tener el mismo tamaño máximo, lo que supone un despilfarro de memoria en la mayoría de los casos.

Otra solución permitida en Modula-2 es emplear vectores abiertos como argumentos en la definición del procedimiento o función. Un vector abierto es aquél del que sólo se define el tipo de sus elementos, pero no el rango del índice. El tipo implícito de su índice es siempre un subrango comprendido entre 0 y un valor máximo. En Modula-2 se expresa en la forma:

PROCEDURE Muestra( X: ARRAY OF TipoElemento )

Esta definición indica que es posible pasar en la llamada cualquier vector con una estructura tal como la siguiente:

ARRAY [ P .. Q ] OF TipoElemento;

Por ejemplo, si tenemos la siguiente declaración de función:

PROCEDURE Simetrico( texto: ARRAY OF CHAR ): BOOLEAN;

es válido realizar cualquiera de las siguientes llamadas:

VAR nombre: ARRAY [0..20] OF CHAR;
        rotulo: ARRAY [1..10] OF CHAR;

(1)   IF Simetrico( rotulo ) THEN …
       …
(2)   IF Simetrico( nombre ) THEN …
       …
(3)   IF Simetrico( "abracadabra" ) THEN …

Para hacer referencia dentro de la función al tamaño del vector utilizado en cada llamada, se puede usar la función predefinida siguiente;

HIGH( X )

Esta función devuelve como resultado el valor superior del índice del vector pasado como argumento X en la llamada. Por ejemplo, HIGH( texto ) vale 9 en la llamada (1) del ejemplo anterior, 20 en la llamada (2), y 11 en la llamada (3). Nótese que internamente el rango del índice siempre se cuenta como si empezase en cero.

Un ejemplo típico de la utilidad de los vectores abiertos es el procedimiento predefinido WriteString. Este procedimiento se puede utilizar con ristras constantes o variables de cualquier tamaño. Su funcionamiento puede describirse basándose en el procedimiento Write para escribir un carácter, de la manera siguiente:

PROCEDURE WriteString( s: ARRAY OF CHAR );
   CONST   Nulo = 0C;
   VAR   k: INTEGER;
BEGIN
   k := 0;
   LOOP
      IF k > HIGH( s ) THEN EXIT END;
      IF s[ k ] = Nulo THEN EXIT END;
      Write( s[ k ] );
      INC( k )
   END
END WriteString;

De la misma forma, es posible definir un procedimiento para ordenar vectores de cualquier tamaño. Este era el problema que se planteaba al comenzar este tema. Por ejemplo, para ordenar vectores de enteros se puede definir un procedimiento con un argumento del tipo vector abierto, que aplique el método de ordenación por inserción. El vector pasado como argumento debe tener la primera posición reservada para usarla como centinela. El código sería:

PROCEDURE Ordenar( VAR v: ARRAY OF INTEGER );
   VAR i, j: Dimension;
           elemento: INTEGER;
BEGIN
   FOR  := 2 TO HIGH( v ) DO
      elemento := v[ i ];
      v[ 0 ] := elemento;
      j := i – 1;
      WHILE elemento < v[ j ] DO
         v[ j + 1 ] := v[ j ];
         j := j – 1
      END
      v[ j + 1 ] := elemento
   END
END Ordenar;

Finalmente, es importante resaltar que no se pueden utilizar matrices abiertas.