Está en la página 1de 219

Aspectos

fundamentales
de desarrollo de
software

Official Academic Course


Microsoft® Official Academic Course

Aspectos fundamentales
del desarrollo de software,
examen 98-361
Créditos
EDITOR Bryan Gambrel
DIRECTOR DE VENTAS Mitchell Beaton
DIRECTOR EJECUTIVO DE MARKETING Chris Ruel
GERENTE DE PRODUCTOS DE MICROSOFT Merrick Van Dongen de Microsoft Learning
ASISTENTE DE PROGRAMA EDITORIAL Jennifer Lartz
DIRECTORA DE CONTENIDO Micheline Frederick
EDITORA DE PRODUCCIÓN Amy Weintraub
DIRECTOR CREATIVO Harry Nolan
DISEÑO DE PORTADA Jim O’Shea
TECNOLOGÍA Y MEDIOS Tom Kulesa/Wendy Ashenberg
Foto de portada: © Pgiam/iStockphoto
Este libro lo realizó Aptara, Inc. usando Garamond y lo imprimió y encuadernó Bind Rite Robbinsville.
La portada la imprimió Bind Rite Robbinsville.
Copyright © 2012 por John Wiley & Sons, Inc. Todos los derechos reservados.
Ninguna parte de esta publicación puede ser reproducida, almacenada en sistemas de recuperación o transmitida en
cualquier forma o por cualquier medio, ya sea electrónico, mecánico, fotocopia, grabación, escaneo o de otro modo,
excepto según lo permitido bajo las Secciones 107 o 108 de la ley de Propiedad Intelectual de Estados Unidos de
1976, sin la autorización previa por escrito de la editorial, o la autorización a través del pago por ejemplar de la tarifa
correspondiente al Copyright Clearance Center, Inc. 222 Rosewood Drive, Danvers, MA 01923, sitio web www.
copyright.com. Las solicitudes de permiso a la editorial deberán dirigirse a Permissions Department, John Wiley &
Sons, Inc., 111 River Street, Hoboken, NJ 07030-5774, (201)748-6011, fax (201)748-6008, sitio web http://www.
wiley.com/go/permissions.
Microsoft, ActiveX, Excel, InfoPath, Microsoft Press, MSDN, OneNote, Outlook, PivotChart, PivotTable, PowerPoint,
SharePoint, SQL Server, Visio, Visual Basic, Visual C#, Visual Studio, Windows, Windows 7, Windows Mobile,
Windows Server y Windows Vista son marcas comerciales o marcas registradas de Microsoft Corporation en los
Estados Unidos y/u otros países. Otros nombres de productos y compañías mencionados aquí pueden ser marcas
comerciales de sus respectivos propietarios.
Los ejemplos de compañías, organizaciones, productos, nombres de dominio, direcciones de correo electrónico,
logotipos, personas, lugares y acontecimientos mencionados son ficticios. No se pretende ni se debe inferir de ningún
modo relación con ninguna empresa, organización, producto, nombre de dominio, dirección de correo electrónico,
logotipo, persona, lugar o acontecimientos reales.
El libro expresa puntos de vista y opiniones del autor. La información contenida en este libro se proporciona sin
ninguna garantía expresa, implícita ni estatuaria. Ni los autores, John Wiley & Sons, Inc., Microsoft Corporation, ni
sus revendedores o distribuidores serán responsables de cualquier daño causado o presuntamente causado directa o
indirectamente por este libro.
Fundada en 1807, John Wiley & Sons, Inc. ha sido una valiosa fuente de conocimientos y comprensión durante más de
200 años, ayudando a personas en todo el mundo a satisfacer sus necesidades y cumplir con sus aspiraciones. Nuestra
empresa está construida sobre una base de principios que incluyen la responsabilidad con las comunidades a las
que servimos y donde vivimos y trabajamos. En 2008, pusimos en marcha una iniciativa de ciudadanía empresarial,
Corporate Citizenship, un esfuerzo global para abordar los retos ambientales, sociales, económicos y éticos a los que
nos enfrentamos en nuestro negocio. Entre las cuestiones que abordamos se encuentra el impacto medioambiental
del carbono, las especificaciones del papel y su adquisición, la conducta ética de nuestro negocio y entre nuestros
proveedores y la comunidad, así como el apoyo solidario. Para obtener más información, visite nuestro sitio web:
www.wiley.com/go/citizenship.
ISBN 978-0-470-88911-4
Impreso en los Estados Unidos de América
10 9 8 7 6 5 4 3 2 1

www.wiley.com/college/microsoft o llame al número de teléfono gratuito de MOAC: 1 + (888) 764-7001 (solo EE. UU. y Canadá).
CONTRATO DE LICENCIA DEL USUARIO FINAL DE WILEY
PARA EL EBOOK DE MOAC Y EL CONTENIDO PARA EL INSTRUCTOR
Este es el Contrato de Licencia del Usuario Final limitado de John Wiley and Sons, Inc. (“Wiley”), que rige
el uso que hace del eBook de Microsoft Official Academic Course (“eBook de MOAC”) y del contenido
relacionado (“Contenido para el Instructor”) de Wiley. Al acceder, descargar o utilizar el eBook de
MOAC O EL CONTENIDO PARA EL INSTRUCTOR, usted acepta los términos y condiciones de
este Contrato. Si no los acepta, no acceda, descargue ni utilice el eBook de MOAC NI EL
CONTENIDO PARA EL INSTRUCTOR.
Licencia:
Por medio de este documento, Wiley concede al miembro, instructor o estudiante del Programa Microsoft IT
Academy (“usted”) derechos que puede ejercer en virtud de este contrato, y usted acepta una licencia no
exclusiva y no transferible para utilizar el eBook de MOAC y el Contenido para el Instructor solo según los
siguientes términos y condiciones:
a. Usted reconoce que los eBooks de MOAC y el Contenido para el Instructor se le licencian por
un periodo breve y que el uso que haga de estos está sujeto a los términos y condiciones de
este contrato.

b. Los siguientes son dos conjuntos independientes de derechos de uso. Solo uno de estos conjuntos se
aplica a su caso.
i. Si usted es un miembro activo del Programa Microsoft IT Academy:
1. Los eBooks de MOAC son solo para el uso de los instructores y estudiantes.
2. Solo puede descargar la cantidad de copias del título del eBook de MOAC aplicable
necesarias para los instructores que imparten la clase correspondiente a dicho título
y para los estudiantes que asisten a la misma.
3. Solo puede distribuir los títulos del eBook de MOAC a los instructores que imparten
una de las clases correspondientes a dicho título y a los estudiantes que asisten a la
misma, a través de:
o correo electrónico;
o un dispositivo USB seguro conectado directamente a los dispositivos personales
de los estudiantes;
o un sitio web protegido con contraseña al que solo tengan acceso los
instructores y estudiantes.
4. Solo puede distribuir el Contenido para el Instructor a los instructores, con fines de
preparación y enseñanza de una de las clases correspondientes al título del eBook
de MOAC asociado.
5. Antes de proporcionar acceso de cualquier tipo a un eBook de MOAC, se le notificará
a cada persona que solo puede acceder o utilizar un eBook de MOAC si acepta hacer
uso de este en cumplimiento con los siguientes criterios:
o Solo se utilizará el eBook de MOAC para fines personales de entrenamiento.
o Solo se instalará el eBook de MOAC en un dispositivo que sea de propiedad
de la persona o que esté bajo el control de esta.
o No se copiará, modificará, imprimirá, transmitirá, publicará, mostrará, vinculará,
reenviará ni distribuirá el eBook de MOAC, ni total ni parcialmente.
o Solo se podrá utilizar el título del eBook de MOAC mientras dure la clase en
la que la persona está participando, es decir, mientras se enseñe el título del
eBook de MOAC o por un periodo de ciento ochenta (180) días, lo que sea
mayor. Después de esto, se deben eliminar de forma segura todas las copias
del título del eBook de MOAC que la persona posea o que estén bajo su control.
o El uso que se haga de los títulos del eBook de MOAC también cumplirá con
todos los términos, condiciones o licencias adicionales que se apliquen, que
acompañen o que se incluyan en el eBook de MOAC.
6. Antes de proporcionar acceso de cualquier tipo al Contenido para el Instructor, se le notificará a cada instructor
que solo puede acceder o utilizar el Contenido para el Instructor si acepta hacer uso de este en cumplimiento con
los siguientes criterios:
o Solo se utilizará el Contenido para el Instructor con fines de preparar y enseñar la sesión de entrenamiento.
o Solo se instalará el Contenido para el Instructor en un dispositivo que sea de propiedad del instructor o que
esté bajo el control de este.
o No se copiará, modificará, imprimirá, transmitirá, publicará, mostrará, vinculará, reenviará ni distribuirá el
Contenido para el Instructor, ni total ni parcialmente.
o Solo se podrá utilizar el Contenido para el Instructor mientras dure la clase en la que el instructor enseña
el título del eBook de MOAC relacionado o por un periodo de ciento ochenta (180) días, lo que sea
mayor. Después de esto, se deben eliminar de forma segura todas las copias del título del Contenido
para el Instructor que el instructor posea o que estén bajo su control.
o El uso que se haga del Contenido para el Instructor también cumplirá con todos los términos, condiciones o
licencias adicionales aplicables, que acompañen o que se incluyan en el Contenido para el Instructor.

ii. Si es un estudiante, usted reconoce y acepta que:


1. Actualmente asiste a la clase de un miembro de IT Academy Program que enseña el eBook de MOAC.
2. Solo utilizará los eBooks de MOAC para fines personales de entrenamiento.
3. Solo instalará el eBook de MOAC en un dispositivo que sea de su propiedad o que usted controle.
4. No copiará, modificará, imprimirá, transmitirá, publicará, mostrará, vinculará, reenviará ni distribuirá el eBook de
MOAC, ni total ni parcialmente.
5. El uso que haga de los títulos del eBook de MOAC también cumplirá con todos los términos, condiciones o
licencias adicionales que se apliquen, que acompañen o que se incluyan en el título del eBook de MOAC.
c. Salvo según se autorice expresamente en la sección b anterior, no puede cargar, copiar, modificar, transmitir, hacer trabajos
derivados, reenviar ni distribuir ningún eBook de MOAC ni Contenido para el Instructor, ni total ni parcialmente, creado mediante
descompilación, así como tampoco el código fuente de ningún eBook de MOAC o Contenido para el Instructor. No puede imprimir
copias de ningún eBook de MOAC ni Contenido para el Instructor completo; sin embargo, puede imprimir páginas individuales o
secciones de los capítulos del eBook de MOAC específicamente para su uso en el aula. No puede utilizar ni total ni parcialmente
el eBook de MOAC ni el Contenido para el Instructor con fines de retribución monetaria por medio de la venta, reventa, préstamo,
transmisión, contratación o cualquier otra forma de explotación del eBook de MOAC o del Contenido para el Instructor. Si
transmite la propiedad de cualquier eBook de MOAC o Contenido para el Instructor a terceros, se pondrá término a su licencia
automáticamente. Dicha terminación será adicional y sustituirá cualquier recurso de equidad, civil o de otro tipo disponibles para
Wiley.
d. Solo podrá utilizar el título del eBook de MOAC y el Contenido para el Instructor mientras dure la clase en la que se enseñe el título
del eBook de MOAC específico o por un periodo de ciento ochenta (180) días, lo que sea mayor. Después de esto, deberá eliminar
de forma segura todas las copias del título del eBook de MOAC y del Contenido para el instructor que posea o estén bajo su control.

e. LOS EBOOKS DE MOAC Y EL CONTENIDO PARA EL INSTRUCTOR SE LICENCIAN “TAL CUAL” Y “SEGÚN
DISPONIBILIDAD”, SIN GARANTÍAS DE NINGÚN TIPO.

f. Usted reconoce que todos los derechos (incluyendo, sin limitación, la propiedad intelectual, las patentes y los secretos empresariales)
en los eBook de MOAC y el Contenido para el Instructor son propiedad única y exclusiva de Wiley y sus licenciantes. La aceptación
de este contrato no lo convierte en propietario de los eBooks de MOAC ni del Contenido para el Instructor, sin embargo, sí le
concede una licencia limitada para utilizar el eBook de MOAC y el Contenido para el Instructor de acuerdo con las disposiciones
de este contrato. Usted acepta proteger el eBook de MOAC y el Contenido para el Instructor del uso, la carga, la descarga, la
reproducción o la distribución no autorizados. Además, acepta no traducir, descompilar, desensamblar ni realizar ingeniería inversa
de ninguno de los eBooks de MOAC ni del Contenido para el Instructor. Wiley se reserva todos los derechos que no se le concedan
expresamente en este contrato.
Prólogo del editor

La visión editorial de Wiley para la serie de cursos Microsoft Official Academic Course es
proporcionar a los alumnos e instructores las habilidades y los conocimientos necesarios para
usar la tecnología de Microsoft de forma eficaz en todos los aspectos de sus vidas personales
y profesionales. Para que los educadores y alumnos aprovechen al máximo las herramientas
de software de Microsoft y sean más productivos, se requiere una enseñanza de calidad. Por
tanto, nuestra misión es hacer que nuestros programas de enseñanza sean compañeros docentes
de confianza de por vida.
Para lograr esta misión, Wiley y Microsoft se han asociado y han desarrollado programas
educativos de la más alta calidad dirigidos a trabajadores de la información, profesionales de
TI y desarrolladores. Los materiales creados por esta asociación llevan el nombre comercial
“Microsoft Official Academic Course”, lo que asegura a instructores y alumnos por igual
que el contenido de estos libros de texto está totalmente respaldado por Microsoft y que
proporciona información e instrucción sobre los productos de Microsoft de la más alta
calidad. Los libros de texto de Microsoft Official Academic Course son, de alguna manera,
más “oficiales”: constituyen el material didáctico oficial para los miembros de Microsoft IT
Academy.
La serie de cursos Microsoft Official Academic Course se centra en el desarrollo laboral.
Estos programas están dirigidos a aquellos alumnos que buscan ingresar al mercado laboral,
cambiar de trabajo o embarcarse en nuevas carreras como trabajadores de la información,
profesionales de TI y desarrolladores. Los programas Microsoft Official Academic Course
atienden estas necesidades haciendo hincapié sobre escenarios con entornos de trabajo
auténticos con una gran cantidad de proyectos, ejercicios, casos prácticos y evaluaciones.
Los cursos de Microsoft Official Academic Course están asignados a la extensa investigación
y análisis de trabajo en tareas de Microsoft, la misma investigación y análisis que se usa para
desarrollar los exámenes de Microsoft Technology Associate (MTA) y Microsoft Certified
Information Technology Professional (MCITP). Los libros de texto se centran en competencias
reales de los puestos de trabajos reales. Mientras los alumnos trabajan en los proyectos
y ejercicios de los libros de texto, mejoran su nivel de conocimiento y su capacidad para
aplicar la última tecnología de Microsoft a las tareas diarias. Estos alumnos también obtienen
credenciales para crear un Currículum Vitae que sirva de ayuda a la hora de encontrar un
trabajo, mantener el trabajo actual o continuar con su educación.
El concepto de aprendizaje permanente es hoy una necesidad máxima. Los puestos de trabajo,
e incluso todas las categorías laborales, están cambiando con tanta rapidez que ninguno de
nosotros puede seguir siendo competitivo y productivo sin actualizar continuamente nuestras
habilidades y capacidades. Las ofertas de Microsoft Official Academic Course, y su enfoque
en la preparación de exámenes de certificación de Microsoft, proporcionan un medio para que
las personas adquieran y actualicen de forma eficaz sus habilidades y conocimientos. Wiley
apoya a los alumnos en este esfuerzo a través de la elaboración y distribución de estos cursos
como editor académico oficial de Microsoft.
Actualmente, las publicaciones educativas deben prestar atención a la hora de proporcionar
gran calidad de impresión y contenido electrónico sólido. Mediante la integración de los
productos Microsoft Official Academic Course, WileyPLUS y las certificaciones de Microsoft
estamos en mejores condiciones para poder ofrecer soluciones eficientes de aprendizaje a los
alumnos y profesores por igual.
Bonnie Lieberman
Director general y Vicepresidente Senior

www.wiley.com/college/microsoft o llame al número de teléfono gratuito de MOAC: 1 + (888) 764-7001 (solo EE. UU. y Canadá).
| v
Prefacio

Bienvenido al programa Microsoft Official Academic Course (MOAC) de Aspectos


fundamentales del desarrollo de software. MOAC representa la colaboración entre Microsoft
Learning y la editorial John Wiley & Sons, Inc. Microsoft y Wiley se unieron para crear una
serie de libros de texto que ofrecieran soluciones de enseñanza convincentes e innovadoras
para los instructores y destrezas de aprendizaje superiores para los alumnos. Estos libros
de texto maximizan la transferencia de conocimientos en un tiempo mínimo gracias a la
preparación e instrucción por el conocimiento en profundidad de los creadores de productos
de Microsoft, así como por la elaboración de los libros de texto por una editorial reconocida
mundialmente debido a la calidad pedagógica de sus productos. Se desafía a los alumnos para
que alcancen su potencial mediante nuevos conocimientos técnicos como miembros altamente
productivos del área de trabajo.
Debido a que esta base de conocimiento proviene directamente de Microsoft, creador de los
exámenes Microsoft Certified Technology Specialist (MCTS), Microsoft Certified Professional
(MCP) y Microsoft Technology Associate (MTA), (www.microsoft.com/learning/certification),
seguro que recibirá la cobertura de contenido más relevante para su éxito personal y
profesional. La participación directa de Microsoft no solo le asegura que el contenido de los
libros de texto MOAC es preciso y está actualizado; también significa que recibirá la mejor
instrucción posible para tener éxito en los exámenes de certificación y en el entorno de trabajo.

n Programa Microsoft Official Academic Course


La serie Microsoft Official Academic Course es un programa completo dirigido a instructores
e instituciones para preparar e impartir grandes cursos sobre tecnologías de software de
Microsoft. Con MOAC, reconocemos que, debido al rápido ritmo de cambios en la tecnología
y el plan de estudios desarrollado por Microsoft, existe un conjunto de necesidades más allá de
las herramientas de instrucción académica para que un instructor esté preparado para impartir
el curso. El programa MOAC trata de proporcionar soluciones para todas estas necesidades
de manera sistemática con el fin de garantizar una experiencia de entrenamiento satisfactoria
y gratificante para el instructor y el alumno: aprendizaje técnico y plan de estudios para la
preparación del instructor con nuevas versiones de software; el propio software para que
los alumnos lo usen en casa para la adquisición de conocimientos prácticos, evaluación y
validación del desarrollo de habilidades; y un excelente conjunto de herramientas para realizar
la instrucción en el aula y en el laboratorio. Todas ellas son importantes para la entrega sin
problemas de un interesante curso sobre software de Microsoft y todas se proporcionan
con el programa MOAC. Pensamos en el siguiente modelo como medida para asegurar que
le apoyamos completamente en su objetivo de impartir un curso excelente. Al evaluar sus
opciones de material de instrucción, puede que desee usar este modelo con fines comparativos
con los productos disponibles:

www.wiley.com/college/microsoft o llame al número de teléfono gratuito de MOAC: 1 + (888) 764-7001 (solo EE. UU. y Canadá).
vi |
Recorrido por el libro ilustrado

n Características pedagógicas
El libro de texto MOAC de Aspectos fundamentales del desarrollo de software está diseñado
para cubrir todos los objetivos de aprendizaje del examen 98-361 de MTA, que se conoce
como su “lección matriz de conocimientos”. Los objetivos del examen Microsoft Technology
Associate (MTA) se destacan a lo largo del libro de texto. Muchas características pedagógicas
se han desarrollado de forma específica para el programa Microsoft Official Academic Course.
Mediante una extensa información sobre los procedimientos y conceptos técnicos integrados,
a lo largo del libro de texto se plantean desafíos para el alumno y el instructor por igual.
El recorrido por el libro ilustrado que aparece a continuación proporciona una guía de
características que contribuyen al plan pedagógico del programa Microsoft Official Academic
Course. La siguiente es una lista de las principales características de cada lección diseñada
para preparar a los alumnos para el éxito a medida que continúan con su educación en TI, con
los exámenes de certificación y en el entorno de trabajo:
• Cada lección comienza con una Matriz de conocimientos de la lección. Más que una
lista estándar de objetivos de aprendizaje, la matriz de conocimientos de la lección
relacionará cada conocimiento del software tratado en la lección con el objetivo del
examen específico.
• Los ejercicios paso a paso concisos y frecuentes enseñan a los alumnos características
nuevas y ofrecen la oportunidad de ponerlas en práctica. Los pasos numerados
proporcionan instrucciones paso a paso detalladas que sirven de ayuda para que los
alumnos adquieran conocimientos de software.
• Las ilustraciones (en particular, imágenes de la pantalla) proporcionan información
visual mientras los alumnos realizan los ejercicios. Estas imágenes refuerzan los
conceptos clave, proporcionan pistas visuales acerca de los pasos que se deben realizar y
permiten a los alumnos comprobar su progreso.
• Las listas de Términos clave que figuran al principio de cada lección presentan a los
alumnos el vocabulario técnico importante. Cuando se usan estos términos más adelante
en la lección, aparecen en fuente negrita y cursiva en el lugar donde se definen.
• Un atractivo punto de uso son las ayudas para el lector, que se encuentran a lo largo de
las lecciones e indican a los alumnos por qué un tema es importante (Conclusión) o les
proporcionan consejos útiles (Tome nota). Las ayudas para el lector también proporcionan
información adicional relevante o general que agrega valor a la lección.
• Las características Listo para certificación que aparecen por todo el texto señalan a
los alumnos dónde se cubre un objetivo específico de certificación. Proporcionan a los
estudiantes la oportunidad de comprobar el grado de comprensión sobre ese objetivo
MTA particular y, si fuera necesario, revisar la sección de la lección donde se trata.
MOAC ofrece una preparación completa para la certificación MTA.
• Preguntas al final de la lección: la sección Evaluación de conocimientos ofrece una
gran variedad de preguntas que pueden ser de varias opciones, verdadero o falso, de
relacionar o de rellenar espacios en blanco.
• Ejercicios del final de la lección: los escenarios posibles de Evaluación de competencias
y los escenarios posibles de Evaluación de aptitudes y los ejercicios de Preparación del
lugar de trabajo son proyectos que ponen a prueba la capacidad de los alumnos para
aplicar lo que han aprendido en la lección.

www.wiley.com/college/microsoft o llame al número de teléfono gratuito de MOAC: 1 + (888) 764-7001 (solo EE. UU. y Canadá).
| vii
viii | Recorrido por el libro ilustrado

■ Características de la lección

2 LECCIÓN
Introducción a
la programación
orientada a objetos
M AT R I Z D E C O N O C I M I E N T O S D E L A L E C C I Ó N Matriz de conocimientos
Conocimientos y conceptos Objetivo del examen MTA Número de objetivo del
examen MTA de la lección
Conceptos de los objetos Conceptos de los aspectos 2.1
fundamentales de las clases.
Conceptos de los valores Conceptos del almacenamiento y
y las referencias los tipos de datos de los equipos. 1.1

Conceptos de la encapsulación Conceptos de la encapsulación. 2.4


Conceptos de la herencia Conceptos de la herencia. 2.2
Conceptos del polimorfismo Conceptos del polimorfismo. 2.3
Conceptos de las interfaces Conceptos de la encapsulación. 2.4

TÉRMINOS CLAVE
clase espacio de nombres objetos
eventos polimorfismo
Introducción a la programación | 3
clases abstractas
clases selladas
constructores
herencia
interfaces
propiedades
propiedades implementadas
automáticamente
Términos Por ejemplo, en la figura 1-1 se muestra un diagrama de flujo que toma dos números (entrada),
los compara y, a continuación, indica cuál es el mayor (salida).
clave
delegados método
modificador de acceso signatura
descriptores de acceso
números estáticos tipo de referencia
encapsulación
tipo de valor

Usted es un desarrollador de software de la empresa Northwind Corporation. Trabaja Figura 1-1


como parte de un equipo que desarrolla programas para resolver problemas empresariales
complejos. Todos los programas que escriba deben ser fáciles de entender y mantener Diagrama de flujo simple
a largo plazo. Por lo tanto, debe desarrollarlos mediante técnicas que fomenten la que compara dos números
colaboración, la extensibilidad y la reutilización del código. Además, en lugar de y produce como salida el
plantearse los programas principalmente como listas de métodos, prefiere tomar como
modelo conceptos empresariales reales, tales como los clientes, los productos, los
mayor de los dos
proveedores y las interacciones entre ellos.

32

Diagramas
Ayuda para el lector informativos
Referencia cruzada (XREF)
Introducción a la programación | 9

C# proporciona varios tipos de datos integrados que se pueden usar en los programas. También
X REF
se pueden definir tipos nuevos mediante una estructura de datos, como una clase o un struct.
Como puede observarse, el diagrama de flujo enumera en el orden correcto todos los pasos
Encontrará más Este capítulo se centra en algunos de los tipos de datos integrados que más se usan.
información sobre cómo
necesarios para realizar la operación. El flujo de control comienza con el símbolo de inicio y
En la tabla 1-3 se muestran varios tipos de datos integrados de uso frecuente que están termina con el símbolo de fin. Los símbolos del proceso y de entrada y salida siempre tienen
crear sus propios tipos disponibles en C#. Los tamaños indicados en la tabla se refieren a un equipo que ejecuta un
de datos en la lección 2. sistema operativo de 32 bits, como Windows 7 de 32 bits. Para un sistema operativo de 64 bits, un único punto de entrada y uno de salida. En cambio, el símbolo de decisión tiene una sola
como Windows 7 de 64 bits, estos tamaños serán diferentes. entrada pero varias salidas. Para probar un diagrama de flujo, realizamos un “simulacro”,
es decir, seguimos manualmente los pasos del diagrama de flujo con datos de prueba para
comprobar si se siguen las rutas apropiadas.
Tabla 1-3
Tipos de datos integrados Tipo de datos Tamaño Intervalo de valores
que se usan con frecuencia INTRODUCCIÓN A LAS TABLAS DE DECISIÓN
byte 1 byte de 0 a 255
en C# Cuando los algoritmos comprenden grandes cantidades de condiciones, las tablas de decisión
char 2 bytes de U+0000 a U+ffff (caracteres Unicode) presentan un formato más compacto y fácil de leer. La tabla 1-2 muestra una tabla de decisión
short 2 bytes −de 32 768 a 32 767 para calcular un descuento. Esta tabla genera un porcentaje de descuento en función de la
cantidad de producto comprado. Las líneas en negrita de la tabla de decisión la dividen en
int 4 bytes −de 2 147 483 648 a 2 147 483 647
cuatro cuadrantes. El primer cuadrante (parte superior izquierda) especifica las condiciones
long 8 bytes −de 9 223 372 036 854 775 808 a (“Cantidad < 10,” etc.). El segundo cuadrante (parte superior derecha) especifica las reglas.
9 223 372 036 854 775 807 Las reglas son las combinaciones posibles de los resultados de cada condición. El tercer
float 4 bytes de ±1,5 × 10-45 a ±3,4 × 1038 cuadrante (parte inferior izquierda) especifica la acción (“Descuento”, en este caso) y el último
double 8 bytes de ±5.0e−324 a ±1.7e308 cuadrante (parte inferior derecha) especifica los elementos de acción correspondiente a cada
regla.
TOME NOTA
* bool 2 bytes true o false
Las versiones sin signo
de short, int y long son string - Cero o más caracteres Unicode
ushort, uint y ulong,
respectivamente. Los
tipos sin signo tienen
el mismo tamaño que Todos los tipos de datos enumerados en el cuadro 1-3 son tipos de valor, excepto string, que es
sus versiones con un tipo de referencia. Las variables que se basan directamente en los tipos de valor contienen
signo, pero almacenan el valor. En el caso del tipo de referencia, la variable contiene la dirección de la ubicación de
un intervalo muy memoria donde se almacenan los datos en sí. Aprenderemos más sobre las diferencias entre los
superior de valores solo tipos de valor y los tipos de referencia en la lección 2.
positivos.
CONCEPTOS DE LAS MATRICES

Una matriz es una colección de elementos, a cada uno de los cuales se puede obtener
acceso mediante un índice único.

En C#, se suelen usar las matrices para representar colecciones de objetos de tipo similar. En
el código siguiente se muestra un ejemplo de declaración de matriz:
int[] numbers = { 1, 2, 3, 4, 5 };
Esta declaración crea una matriz identificada por los números de nombre. Puede almacenar
una colección de cinco números enteros. Esta declaración también inicializa cada uno de los
elementos de la matriz respectivamente mediante los números del 1 al 5.
A cualquier elemento de la matriz se puede obtener acceso directamente mediante un índice.
En .NET Framework, los índices de la matriz son de base cero. Esto significa que para obtener
acceso al primer elemento de una matriz se usa el índice 1; para obtener acceso al segundo
elemento, el índice 2 y así sucesivamente.
Para obtener acceso a un elemento individual de la matriz, se usa el nombre de la matriz
seguido por el índice entre corchetes. Por ejemplo, en la matriz que hemos declarado
anteriormente, numbers[0] devolverá el valor 1 y numbers[4] devolverá el valor 5. No es
válido obtener acceso a una matriz fuera de sus límites definidos. Por ejemplo, obtendremos
un error si intentamos obtener acceso al elemento numbers[5] de la matriz.

www.wiley.com/college/microsoft o llame al número de teléfono gratuito de MOAC: 1 + (888) 764-7001 (solo EE. UU. y Canadá).
Recorrido por el libro ilustrado | ix

44 | Lección 2

2. Modifique el código de la clase Program de manera que se ajuste a lo siguiente:


class Program
{
  static void Main(string[] args)
  {
     Rectangle rect = new Rectangle
      { Length = 10.0, Width = 20.0 };
     Console.WriteLine(“Nombre de la forma: {0}, Area: {1}”,
      Rectangle.ShapeName,
      rect.GetArea());
  }
}
3. Seleccione Depurar > Iniciar sin depurar. Aparecerá una ventana de consola que
mostrará el nombre y el área de la forma.
4. GUARDE el proyecto.
PAUSA. Deje el proyecto abierto para usarlo en el siguiente ejercicio.
Cuando se crea una instancia de una clase, se crea una copia independiente para cada campo
de instancia, pero solo hay una copia de un campo estático que se comparte entre todas las
instancias.
LISTO PARA CERTIFICACIÓN No se puede hacer referencia a un miembro estático a través de un objeto de instancia. En
¿Comprende los conceptos cambio, se hace referencia a un miembro estático a través del nombre de clase (por ejemplo,
fundamentales de las clases? Rectangle.ShapeName en el ejercicio anterior). Tenga en cuenta que no se puede usar la
2.1 referencia de palabra clave this con un método o propiedad static (estático) debido a que la
palabra clave this solo se puede usar para obtener acceso a objetos de instancia.

■ Conceptos de los valores y las referencias

CONCLUSIÓN
Un tipo de valor almacena directamente un valor, mientras que un tipo de referencia solo
almacena una referencia al valor propiamente dicho. Ayuda para el lector
Un tipo de valor almacena datos directamente en su memoria. Por su parte, los tipos
de referencia, solo almacenan una referencia a una ubicación de memoria; es decir, los
Conclusión
verdaderos datos se almacenan en la ubicación de memoria a la que se hace referencia. La 4 | Lección 1
mayoría de los tipos de datos elementales integrados (tales como bool, int, char, double, etc.)
son tipos de valor. Los tipos de datos definidos por el usuario creados mediante la palabra
Tabla 1-2
clave struct son también tipos de valor. Los tipos de referencia son aquellos creados mediante
las palabras clave object, string, interface, delegate y class. Tabla de decisión para Cantidad < 10 S N N N
calcular descuentos
Conceptos de los structs Cantidad < 50 S S N N
Cantidad < 100 S S S N
La palabra clave struct se usa para crear tipos definidos por el usuario que consisten en
pequeños grupos de campos relacionados. Los structs son tipos de valor, a diferencia de Descuento  5%  10%  15%  20%
las clases, que son tipos de referencia.

Los structs se definen mediante el uso de la palabra clave struct, como se muestra a Para averiguar qué elemento de acción se debe aplicar, es preciso evaluar cada condición a
continuación: fin de encontrar la regla correspondiente y, a continuación, elegir la acción especificada en
la columna de esa regla. Por ejemplo, si el valor “Cantidad” de los datos de prueba es 75,
public struct Point entonces la primera regla se evalúa en “No”, la segunda regla se evalúa en “No” y la tercera
{ regla se evalúa en “Sí”. Por lo tanto, elegiremos el elemento de acción de la columna (N, N, S)
  public double X, Y; que establece el descuento del 15 %.
}
Los structs pueden contener casi todos los elementos que pueden contener las clases, tales
como constructores, métodos, propiedades, etc. Sin embargo, como aprenderemos en la Introducción a C#
C# es un conocido lenguaje de alto nivel que permite escribir programas en un formato
legible. C# forma parte de .NET Framework y saca partido de la compatibilidad con el
tiempo de ejecución y las bibliotecas de clases que este entorno proporciona.

Como hemos explicado en la sección anterior, los equipos necesitan instrucciones precisas
y completas para llevar a cabo una tarea. Estos conjuntos de instrucciones se denominan
programas informáticos o, simplemente, programas .
AEn el nivel más básico, los equipos usan el sistema de números binario para representar
la información y el código. En este sistema, cada valor se representa mediante dos símbolos
únicamente, 0 y 1. Un programa escrito en el sistema de números binario se llama código
Conceptos generales del desarrollo de software | 77 binario.
Usar el código binario para programar un equipo resulta árido y sumamente difícil para
BubbleSort funciona mediante la comparación de dos elementos para comprobar si están cualquier tarea mínimamente compleja. Por lo tanto, para simplificar la programación, los
desordenados. En el caso de que lo estén, intercambia sus posiciones. El algoritmo repite la científicos e ingenieros informáticos han desarrollado varios niveles de abstracción entre los
equipos y sus operadores humanos. Estas abstracciones incluyen un software (por ejemplo,
operación hasta que toda la lista está en el orden deseado. BubbleSort recibe este nombre
los sistemas operativos, los compiladores y varios sistemas de tiempo de ejecución) que se
por su funcionamiento: a medida que el algoritmo progresa, los elementos de menor tamaño encargan de traducir un programa legible por el ser humano en un programa que la máquina
ascienden hacia la superficie como si fueran burbujas (bubble, en inglés). pueda interpretar.
Vamos a visualizar BubbleSort con la ayuda de un ejemplo. Supongamos que deseamos La mayoría de los programas modernos están escritos en un lenguaje de alto nivel como C#,
organizar todos los elementos de la lista siguiente en orden ascendente: (20, 30, 10, 40). Estos Visual Basic o Java. Estos lenguajes permiten escribir instrucciones precisas de forma legible
elementos deben organizarse de menor a mayor. El algoritmo BubbleSort intenta resolver el para el ser humano. Posteriormente, un compilador traduce el lenguaje de alto nivel en un
problema en una o varias pasadas; en cada una de ellas analiza la lista completa de elementos. lenguaje de nivel inferior que resulta comprensible al sistema de ejecución runtime.
Si el algoritmo encuentra elementos desordenados, los intercambia. El algoritmo finaliza
cuando analiza la lista completa sin intercambiar ningún elemento. Si no se han producido Cada lenguaje de programación ofrece su propio conjunto de terminología y gramática
intercambios, significa que ningún elemento estaba desordenado, de modo que la lista está (también denominado “sintaxis”). En este curso, aprenderemos a programar con el lenguaje de
ordenada de principio a fin. programación C# en el entorno .NET Framework. .NET Framework proporciona un entorno
de ejecución runtime para el programa C#. Asimismo, contiene las bibliotecas de clases
que proporcionan gran cantidad de funciones básicas reutilizables que se pueden incorporar
directamente a los programas escritos en C#.
Tabla 3-1
Primera pasada de
BubbleSort
Pasada Antes Después Comentarios Tablas de ✚ MÁS INFORMACIÓN
.NET Framework proporciona tres componentes principales: un entorno de ejecución runtime, un conjunto

fácil lectura
1 20, 30, 10, 40 20, 30, 10, 40 El algoritmo compara los dos primeros de bibliotecas de clases que proporcionan muchas funciones reutilizables y compiladores de lenguaje para C#,
elementos (20 y 30); dado que están Visual Basic y Managed C++. .NET Framework admite muchos lenguajes de programación y también la adición de
lenguajes adicionales al sistema. Aunque la sintaxis y la terminología de cada lenguaje varían, todos pueden usar
en el orden correcto, no es necesario
las bibliotecas de clases base proporcionadas por .NET Framework.
intercambiarlos.
2 20, 30, 10, 40 20, 10, 30, 40 El algoritmo compara los dos
elementos siguientes (30 y 10);
puesto que están desordenados, se
intercambian.
3 20, 10, 30, 40 20, 10, 30, 40 El algoritmo compara los dos
elementos siguientes (30 y 40); como
Ayuda para
están en el orden correcto, no es
necesario intercambiarlos. el lector Más
Como se muestra en la tabla 3-1, al final del primer paso, BubbleSort ha realizado un
información
intercambio y existe la posibilidad de que los elementos sigan sin estar totalmente ordenados.
Por lo tanto, BubbleSort da otra pasada a la lista, como se muestra en la tabla 3-2.

Tabla 3-2
Segunda pasada de Pasada Antes Después Comentarios
BubbleSort
1 20, 10, 30, 40 10, 20, 30, 40 El algoritmo compara los dos primeros
elementos (20 y 10); dado que están
desordenados, se intercambian.
2 10, 20, 30, 40 10, 20, 30, 40 El algoritmo compara los dos
elementos siguientes (20 y 30); como
están en el orden correcto, no es
necesario intercambiarlos.
3 10, 20, 30, 40 10, 20, 30, 40 El algoritmo compara los dos
elementos siguientes (30 y 40); como
están en el orden correcto, no es
necesario intercambiarlos.

www.wiley.com/college/microsoft o llame al número de teléfono gratuito de MOAC:


www.wiley.com/college/microsoft o 1 + (888) 764-7001 (solo EE. UU. y Canadá).
llame al número de teléfono gratuito de MOAC: 1 + (888) 764-7001 (solo EE. UU. y Canadá).
x | Lesson 1 por el libro ilustrado
x | Recorrido

68 | Lección 3

Conceptos de las pruebas de software

Durante las pruebas de software se comprueba que la aplicación coincida con los
requisitos del sistema.
Las pruebas de software se usan para garantizar la calidad del producto final. Las pruebas
pueden identificar posibles diferencias entre las expectativas respecto al sistema descritas en el
documento de requisitos y el comportamiento real del sistema.
Entre los participantes más importantes de la actividad de pruebas de software se encuentran
los evaluadores, que comprueban la aplicación de trabajo para asegurarse de que satisface
las necesidades identificadas. Cuando estos evaluadores identifican cualquier defecto en la
aplicación, se lo asignan a la persona adecuada para que lo arregle. Por ejemplo, un defecto del
código se asignaría a un desarrollador para que lo subsanase.

Conceptos de la administración de versiones


La actividad de administración de versiones se usa para administrar la imple-
mentación, la distribución y el soporte de las versiones de software.

La administración de versiones incluye actividades tales como empaquetado e implementación


del software, administración de defectos del software y administración de solicitudes de
cambio del software.
Los principales participantes de la actividad de administración de versiones son las siguientes
personas:
• Administrador de versiones: el administrador de versiones coordina los diversos
equipos y unidades de negocio para asegurarse del lanzamiento oportuno de un producto
de software.
• Personal de operaciones: los miembros del personal de operaciones se aseguran de que
el sistema se entregue conforme a lo prometido. Esto puede requerir la copia de discos de
LISTO PARA CERTIFICACIÓN DVD y su envío a medida que se reciben los pedidos o la realización del mantenimiento
¿Comprende la continuo de un sistema de software como servicio (SaaS). El personal de operaciones
administración del ciclo de también es responsable de lanzar las actualizaciones del sistema (por ejemplo,
vida de las aplicaciones y correcciones o nuevas características).
sus actividades?
• Personal de soporte técnico: estos empleados interactúan con los clientes y les ayudan
3.1 a resolver sus problemas con el sistema. El personal de soporte técnico puede generar
estadísticas valiosas sobre qué áreas del sistema presentan más dificultades para los
usuarios y posiblemente deberían actualizarse en la próxima versión de la aplicación.

■ Conceptos de las pruebas

Las pruebas de software consisten en comprobar el software en relación con sus requisitos. Ejercicios paso a paso
CONCLUSIÓN Las pruebas se llevan a cabo después de completar la mayor parte del trabajo de desarrollo.

Como hemos mencionado anteriormente, las pruebas de software consisten en comprobar que 46 | Lección 2
una aplicación de software funciona tal y como se esperaba y satisface todos los requisitos
de negocios y técnicos. Cuando existe una diferencia entre los comportamientos esperado y
real del sistema, se registra un defecto de software (o “error”) que se asigna a una persona COPIA DE TIPOS DE VALOR Y DE REFERENCIA
responsable de corregirlo.
Las pruebas de software pueden incluir pruebas funcionales y no funcionales. Las pruebas USE el proyecto guardado en el ejercicio anterior para completar los pasos siguientes:
funcionales se refieren a los requisitos funcionales del sistema y comprueban las características
que conforman la funcionalidad básica del sistema. Por ejemplo, comprobar si los usuarios 1. Agregue el código siguiente después de la definición de la clase Rectangle para crear
pueden agregar elementos al carro de la compra constituye una parte importante de las pruebas el struct Point:
struct Point
{
  public double X, Y;
Alerta Listo para }

certificación
2. Modifique el código del método Main como se muestra a continuación:
TOME NOTA
*
Es posible crear un struct static void Main(string[] args)

Ayuda para el sin usar el operador


new. Basta con escribir
{
  Point p1 = new Point();

lector Tome nota


Point p1; para crear una
  p1.X = 10;
variable de tipo struct.
  p1.Y = 20;
  Point p2 = p1;
  p2.X = 100;
  Console.WriteLine(“p1.X = {0}”, p1.X);
Introducción a la programación | 7
  Rectangle rect1 = new Rectangle
    { Length = 10.0, Width = 20.0 };
Figura 1-3
  Rectangle rect2 = rect1;
Listado del programa con
números de línea   rect2.Length = 100.0;
  Console.WriteLine(“rect1.Length = {0}”,
    rect1.Length);
TOME NOTA
* }
Cuando se copia una
Imágenes de variable de tipo de
referencia en otra variable
3. Seleccione Depurar > Iniciar sin depurar. Aparecerá una ventana de consola que
mostrará los valores de p1.X y rect1.Length.

la pantalla del mismo tipo, solo se


copian las referencias. En
4. GUARDE el proyecto.
PAUSA. Deje el proyecto abierto para usarlo en el siguiente ejercicio.
consecuencia, después de
la copia, ambas variables Aquí, la primera parte del programa crea una copia del tipo de valor Point y la segunda mitad
señalarán al mismo crea una copia del tipo de referencia Rectangle.
objeto.
Comenzaremos por analizar cómo se realiza la copia de un tipo de valor. Para empezar,
cuando se ejecuta la instrucción siguiente, se crea una nueva variable p2 en la memoria, cuyo
contenido se copia de la variable p1:
Point p2 = p1;
Después de ejecutar esta instrucción, se crea la variable p2 y se copia el contenido de
la variable p1 en la variable p2. Tanto p1 como p2 tienen su propio conjunto de valores
disponibles en sus ubicaciones de memoria respectivas. Así pues, cuando se ejecuta la
instrucción siguiente:
Un programa C# está compuesto de una o más clases. Una clase es un conjunto de datos y p2.X = 100;
métodos. Por ejemplo, el código de la figura 1-3 define una sola clase denominada Program en
las líneas 5 a 11. Una clase se define mediante la palabra clave “class”, seguida por el nombre solo afecta al valor de X correspondiente a la ubicación de memoria de la variable p2. El valor
de la clase. El contenido de una clase se define entre una llave de apertura ({) y una llave de de X para la variable p1 permanece invariable.
X REF cierre (}).

Encontrará más La línea 3 del código de la figura 1-3 define un espacio de nombres, Lesson01. Los espacios
información sobre las de nombres se usan para organizar las clases e identificarlas de manera exclusiva. El espacio
clases en la lección 2. de nombres y los nombres de clase se combinan entre sí para crear un nombre de clase
completo. Por ejemplo, el nombre de clase completo de la clase Program es Lesson01.
Program. C# requiere que el nombre completo de una clase sea único. Así pues, no puede
haber otra clase que se llame Program en el espacio de nombres Lesson01, pero sí una clase
denominada Program en otro espacio de nombres, como Lesson02, por ejemplo. En este
caso, la clase Program definida en el espacio de nombres Lesson02 se identificará de forma
exclusiva por su nombre de clase completo, Lesson02.Program.
.NET Framework proporciona gran cantidad de clases útiles organizadas en muchos espacios
de nombres. El espacio de nombres System contiene algunas de las clases base que más se
X REF
usan. Una de estas clases contenidas en el espacio de nombres System es Console. La clase
Encontrará más Console proporciona funcionalidad de entrada y salida para aplicaciones de consola. La línea
información sobre los 9 del código de la figura 1-3 se refiere a la clase Console y llama a su método WriteLine. Para
métodos en la lección 2. obtener acceso al método WriteLine de manera inequívoca, se debe escribir así:
System.Console.WriteLine(“¡Hola, mundo!”);
Dado que los nombres de clase aparecen en el código con frecuencia, escribir su nombre
completo todas las veces puede resultar tedioso y hacer que el programa resulte demasiado
TOME NOTA
* detallado. Para solucionar este problema, se usa la directiva using de C# (consulte el código de
Todas las instrucciones la línea 1 en la figura 1-3). La directiva using permite usar las clases de un espacio de nombres
de C# deben terminar sin tener que escribir el nombre completo de la clase.
con un punto y coma (;).
La clase Program define un método único denominado Main (líneas 7 y 10 del listado de
código que se muestra en la figura 1-3). Main es un método especial que también sirve como
punto de entrada al programa. Cuando el runtime ejecuta un programa, siempre empieza en
el método Main. Un programa puede tener muchas clases y cada clase puede tener muchos

www.wiley.com/college/microsoft o llame al número de teléfono gratuito de MOAC: 1 + (888) 764-7001 (solo EE. UU. y Canadá).
Recorrido por el libro ilustrado | xi

Conceptos generales del desarrollo de software | 69

funcionales de un sitio web de comercio electrónico. Por su parte, las pruebas no funcionales
se refieren a comprobar los atributos de software que no forman parte de la funcionalidad
básica, sino de los requisitos no funcionales del software, tales como la usabilidad, la
escalabilidad o la seguridad.

Es importante señalar que el proceso de las pruebas de software solo puede ayudar a
encontrar defectos pero no puede garantizar la ausencia de estos. Todo software complejo
*
TOME NOTA posee un gran número de rutas de ejecución posibles y gran cantidad de parámetros que
pueden afectar a su comportamiento. No es viable ni, con frecuencia, posible, probar todas Ayuda para el lector
las situaciones diferentes que se le presentarán a ese software en un entorno de producción.
Tome nota
Conceptos de los métodos de prueba

Los métodos de las pruebas de software se suelen dividir en dos categorías: pruebas
de caja blanca y pruebas de caja negra.

Tradicionalmente, existen dos enfoques generales respecto a las pruebas de software:


• Pruebas de caja negra
• Pruebas de caja blanca
Las pruebas de caja negra tratan al software como una caja negra y se centran solamente en las
entradas y las salidas. Con este enfoque, no se usa ningún conocimiento del funcionamiento
interno del sistema durante las pruebas. En cambio, en las pruebas de caja blanca, los
evaluadores aplican sus conocimientos del funcionamiento interno del sistema mientras lo
comprueban. Por ejemplo, en las pruebas de caja blanca, los evaluadores tienen acceso al
código fuente.
Estas dos técnicas de prueba son complementarias entre sí. Las pruebas de caja negra se Resumen de
usan principalmente para asegurarse de que la aplicación de software responda a todos sus
requisitos. Por su parte, las pruebas de caja blanca se emplean para asegurarse de que existan
casos de prueba disponibles para cada método o función.
conocimientos
Conceptos de los niveles de pruebas

Las pruebas se llevan a cabo en diferentes fases del ciclo de vida de desarrollo de las Comprensión de bases de datos | 173
aplicaciones. Los distintos niveles de pruebas especifican en qué punto del ciclo de
vida se lleva a cabo una prueba concreta y qué tipo de prueba se ha de efectuar. RESUMEN DE CONOCIMIENTOS

En esta lección hemos aprendido lo siguiente:


Los niveles de pruebas se definen en función del momento del ciclo de vida del desarrollo de
software en que tienen lugar las pruebas. Existen cinco niveles de pruebas distintos: • Una base de datos relacional organiza la información en tablas. Una tabla es una lista
de filas y columnas.
• Pruebas unitarias: las pruebas unitarias comprueban la funcionalidad de una unidad de • El diseño de bases de datos relacionales es el proceso que consiste en determinar
código. Por ejemplo, una prueba unitaria puede evaluar si un método devuelve el valor cuál es la estructura de una base de datos relacional apropiada para satisfacer los
correcto. Las pruebas unitarias son de caja blanca y con frecuencia las realiza el propio requisitos de la empresa.
desarrollador que está escribiendo el código. Para las pruebas unitarias se suele usar • Los diagramas de relación entre entidades se usan para modelar las entidades, sus
atributos y las relaciones entre ellas. Los diagramas de relación entre entidades
una herramienta automatizada que simplifica el desarrollo de casos y también realiza pueden ayudarle a determinar qué datos es preciso almacenar en una base de datos.
el seguimiento por si una modificación del código provoca que no se supere alguna de • El proceso de normalización de datos asegura que el diseño de una base de datos se
las pruebas unitarias existentes. Visual Studio presenta compatibilidad integrada con las encuentre exento de problemas que puedan causar una pérdida de la integridad de
pruebas unitarias. También se pueden usar herramientas de código abierto como NUnit los datos. La mayoría de los problemas de diseño se puede resolver asegurándose de
para automatizar las pruebas unitarias del código de .NET Framework. que las tablas satisfagan los requisitos de la tercera forma normal.
• Pruebas de integración: las pruebas de integración evalúan las interfaces entre los com- • El Lenguaje de consulta estructurado (SQL) proporciona instrucciones, tales como
SELECT, INSERT, UPDATE y DELETE, para trabajar con datos relacionales.
• Un procedimiento almacenado es un conjunto de instrucciones SQL almacenadas
en una base de datos. Los procedimientos almacenados se pueden usar en varias
aplicaciones.
• Las clases XmlReader y XmlWriter proporcionan una manera rápida, sin caché y
solo hacia delante de leer o escribir datos XML. La clase XmlDocument es una
representación en memoria de los datos XML y permite navegar por el documento
XML y editarlo.
• La clase DataSet es una representación en memoria de datos relacionales. La clase
DataAdapter es un puente de conexión entre el origen de datos y el objeto DataSet.
DataAdapter almacena los comandos y las conexiones de datos necesarios para
conectarse al origen de datos.

■ Evaluación de conocimientos
Evaluación de
64 | Lección 2
Rellene los espacios en blanco

■ Evaluación de competencias conocimientos Complete las oraciones siguientes escribiendo la palabra o palabras correctas en los
espacios en blanco proporcionados.
1. Para que una tabla se ajuste a la _______________, ninguna de las columnas de la tabla
Escenario 2-1: Creación de propiedades debe tener varios valores en la misma fila de datos.
Debe crear una clase denominada Product que representa un producto. La clase tiene una sola 2. Además, la _______________ exige que todas las columnas no clave sean
propiedad, denominada Name. Los usuarios de la clase Product deben poder obtener y también funcionalmente dependientes de la clave principal completa.
definir el valor de la propiedad Name. Sin embargo, cualquier intento de establecer el valor de
Name en una cadena vacía o un valor null debe iniciar una excepción. Además, los usuarios 3. La _______________ exige que no exista ninguna dependencia funcional entre atributos
de la clase Product no deben tener la capacidad de obtener acceso a ningún otro miembro de no clave.
datos de la clase Product. ¿Cómo se puede crear dicha clase? 4. Los bloques de creación básicos de un diagrama de relación entre entidades son la
_______________, el _______________ y la _______________.
Escenario 2-2: Creación de un struct 5. La cláusula _______________ de una instrucción SELECT evalúa cada fila para
Está desarrollando un juego que requiere representar la ubicación de un objetivo en el espacio comprobar si se cumple una condición y decide si la incluirá en el conjunto de resultados.
tridimensional. La ubicación se identifica por tres valores enteros (de tipo int) denominados x, 6. El objeto que se usa con la instrucción using debe implementar la interfaz
y y z. Debe crear miles de estas estructuras de datos en el programa, de modo que debe hallar _______________.
una manera eficiente y ligera de almacenarlos en la memoria. Además, es poco probable que
sea preciso heredar otros tipos de este tipo de ubicación. ¿Cómo debe representar la ubicación 7. La instrucción _______________ de T-SQL se puede usar para crear un procedimiento
en el programa? almacenado.

■ Evaluación de aptitudes
Escenario 2-1: Invalidación del método ToString
Supongamos que estamos escribiendo código para una clase Product. La clase Product
contiene el nombre y el precio de un producto. Debe invalidar el método ToString de la
clase base (System.Object) de modo que proporcione información sobre los objetos de la
clase Product al código de llamada. ¿Qué código debe escribir para la clase Product a fin de
satisfacer este requisito?

Escenario 2-2: Creación y control de eventos


Imaginemos que vamos a escribir código para crear y controlar eventos en el programa. La
clase SampleClass debe implementar la siguiente interfaz: Escenarios
public delegate void SampleDelegate();
public interface ISampleEvents posibles
{
  event SampleDelegate SampleEvent;
  void Invoke();
}
Debe escribir código para SampleClass y para un método de prueba que cree una instancia de
SampleClass e invoque el evento. ¿Qué código debe escribir?

www.wiley.com/college/microsoft o llame al número de teléfono gratuito de MOAC: 1 + (888) 764-7001 (solo EE. UU. y Canadá).
Convenciones y características
que se usan en este libro

En este libro se usan determinadas convenciones para fuentes, símbolos y títulos que resaltan
la información importante y llaman la atención sobre determinados pasos. Para obtener más
información sobre las características de cada lección, consulte la sección Recorrido por el libro
ilustrado.

Convención Significado

Esta característica proporciona un breve resumen del
CONCLUSIÓN
material que se trata en la sección que sigue.
LISTO PARA CERTIFICACIÓN 
Esta característica señala un punto en el texto donde se
cubre un objetivo específico de certificación. Proporciona
la oportunidad de comprobar el grado de comprensión de
ese objetivo MTA particular y, si fuera necesario, revisar la
sección de la lección donde se trata.
 Las ayudas para el lector aparecen en recuadros
TOME NOTA*
* sombreados que se encuentran en el texto. Tome nota
proporciona consejos útiles relacionados con tareas o temas
concretos.
Estas notas proporcionan referencias a cualquier
REF X
información tratada en otra parte del libro de texto o
describen características interesantes que no se abordan
directamente en el tema o ejercicio actual.
Alt  +  Tab Un signo más (+) entre dos nombres de teclas indica que
se deben presionar ambas teclas al mismo tiempo. Las
teclas que se le indique que debe presionar en un ejercicio
aparecerán en el tipo de fuente que se muestra aquí.
Ejemplo Los términos clave aparecen en negrita y cursiva cuando se
definen.

www.wiley.com/college/microsoft o llame al número de teléfono gratuito de MOAC: 1 + (888) 764-7001 (solo EE. UU. y
xii |  Canadá).
Programa de apoyo
para el instructor
Los programas Microsoft Official Academic Course van acompañados de una generosa
variedad de recursos que incluyen extensas imágenes del libro de texto para formar un paquete
pedagógico coherente. Estos recursos proporcionan todo el material que los instructores
necesitan usar para impartir sus cursos. Los recursos disponibles en línea para su descarga
incluyen:
• MSDN Academic Alliance está diseñado para proporcionar herramientas de desarrollo
más fáciles y económicas, productos y tecnologías disponibles para profesores y alumnos
en los laboratorios, aulas y en los equipos de los alumnos. Existe una suscripción gratuita
disponible durante tres años para usuarios MOAC cualificados.
Nota: Microsoft Windows 2008 Server, Microsoft Windows 7 y Microsoft Visual Studio
se pueden descargar de MSDN AA para uso de los alumnos en este curso.
• La Guía del instructor contiene las soluciones a todos los ejercicios del libro de texto y
programas de estudio de varios plazos. La Guía del instructor también incluye resúmenes
de capítulos y notas de la lección. La Guía del instructor está disponible desde el sitio del
libro complementario (http://www.wiley.com/college/microsoft).
• El banco de pruebas contiene cientos de preguntas en formato de varias opciones,
verdadero o falso, respuesta corta y redacción, y está disponible para la descarga desde
el sitio del libro complementario del instructor (www.wiley.com/college/microsoft). Se
proporciona una clave de respuestas completa.
• Un juego completo de presentaciones de PowerPoint e imágenes está disponible en el
sitio del libro complementario del instructor (http://www.wiley.com/college/microsoft)
para mejorar las presentaciones en el aula. Se proporcionan aproximadamente 50
diapositivas de PowerPoint para cada lección. Adaptadas a la cobertura de actualidad del
texto y a la matriz de conocimientos, estas presentaciones están diseñadas para transmitir
conceptos claves abordados en el texto. Todas las imágenes del texto son del sitio del
libro complementario del instructor (http://www.wiley.com/college/microsoft). Puede
integrarlas en las presentaciones de PowerPoint o crear sus propias transparencias y
documentos. Mediante el uso de estas imágenes en las conversaciones en el aula, puede
ayudar a centrar la atención de los alumnos sobre los elementos clave de las tecnologías
tratadas y ayudarles a entender cómo usarlas eficazmente en el entorno de trabajo.
• Cuando se trata de mejorar la satisfacción en el aula, no hay mejor fuente de ideas e
inspiración que sus colegas. La red de profesorado de Wiley, Wiley Faculty Network,
conecta a los profesores con la tecnología, facilita el intercambio de prácticas mejoradas
y contribuye a aumentar la eficiencia y la eficacia de la enseñanza. Las actividades de la
red de profesorado incluyen entrenamiento tecnológico y tutoriales, seminarios virtuales,
intercambio de conocimientos e ideas entre iguales, asesoramiento personal e intercambio
de recursos. Para obtener más detalles, visite www.WhereFacultyConnect.com.

www.wiley.com/college/microsoft o llame al número de teléfono gratuito de MOAC: 1 + (888) 764-7001 (solo EE. UU. y Canadá).
| xiii
xiv | Programa de apoyo para el instructor

MSDN ACADEMIC ALLIANCE: SUSCRIPCIÓN GRATUITA DE


TRES AÑOS DISPONIBLE PARA USUARIOS CUALIFICADOS.
La Microsoft Developer Network Academic Alliance (MSDN AA) está diseñada para
permitir de la forma más fácil y económica que las universidades pongan a disposición de
sus usuarios las últimas herramientas de desarrollo, productos y tecnologías de Microsoft
en los laboratorios, las aulas y los equipos de los alumnos. MSDN AA es un programa de
suscripción anual para los departamentos de enseñanza de cursos de ciencias, tecnología,
ingeniería y matemáticas (STEM). La suscripción proporciona una solución completa
para mantener los laboratorios académicos, profesores y alumnos a la vanguardia de la
tecnología.
El software disponible a través del programa MSDN AA se proporciona sin gasto
adicional para los departamentos asociados a través de la colaboración editorial entre
Wiley y Microsoft.
Esta oferta gratuita incluye además la presentación al personal docente de la red
de profesorado Microsoft Faculty Connection y su centro de recursos Academic
Resource Center. Mantener la atención de los alumnos mientras se les explican los
conceptos de la teoría requiere tiempo y preparación. La red Microsoft Faculty
Connection se ha diseñado para ayudar a los profesores de STEM a prepararse para
ello mediante artículos, material curricular y herramientas que pueden usar para
suscitar la atención e inspiración de los estudiantes de tecnología actuales.
*Para obtener más detalles, póngase en contacto con su representante de Wiley.
Para obtener más información sobre el programa MSDN Academic Alliance, visite:
http://msdn.microsoft.com/academic/
Nota: Microsoft Windows Server 2008, Microsoft Windows 7 y Microsoft Visual Studio
se pueden descargar de MSDN AA para uso de los alumnos en este curso.

■ Direcciones web y números de teléfono importantes


Para localizar al representante de Wiley Higher Education de su área, vaya a http://
www.wiley.com/college y haga clic en el vínculo “¿Quién es mi representante?” en la
parte superior de la página, o llame al número gratuito de MOAC: 1 + (888) 764-
7001 (solo EE. UU. y Canadá).
Para obtener más información sobre cómo llegar a ser un especialista en tecnología
certificado de Microsoft (Certified Technology Specialist) y sobre la disponibilidad de
exámenes, visite www.microsoft.com/learning/mcp/mcp.

www.wiley.com/college/microsoft o llame al número de teléfono gratuito de MOAC: 1 + (888) 764-7001 (solo EE. UU. y Canadá).
Programa de apoyo
para el alumno
■ Recursos adicionales
Sitio web del libro complementario (www.wiley.com/college/microsoft)
El sitio web del libro complementario para alumnos de la serie MOAC incluye recursos,
archivos de ejercicios y vínculos web que se usarán junto con este curso.

Ediciones de escritorio Wiley


Las ediciones de escritorio Wiley MOAC son innovadoras versiones electrónicas de los
libros de texto impresos. Los alumnos compran la versión de escritorio con hasta el 50 % de
descuento sobre el precio del texto impreso en los EE. UU. y obtienen un valor añadido en
la permanencia y portabilidad. Las ediciones de escritorio Wiley proporcionan a los alumnos
numerosos beneficios adicionales que no se encuentran disponibles en otras soluciones de
texto electrónico.
Las ediciones de escritorio Wiley NO son suscripciones, los alumnos descargan la edición
de escritorio Wiley en los escritorios del equipo. Los alumnos son propietarios de los
contenidos que compran y los mantienen durante todo el tiempo que deseen. Una vez que
la edición de escritorio Wiley se descarga en el escritorio del equipo, los alumnos tienen
acceso instantáneo a todos los contenidos sin necesidad de estar en línea. Los alumnos pueden
imprimir las secciones que prefieran leer en copia impresa. También, tienen acceso a los
recursos totalmente integrados dentro de la edición de escritorio Wiley. Además de resaltar el
texto electrónico para tomar y compartir notas, los alumnos pueden personalizar fácilmente su
edición de escritorio Wiley mientras están leyendo o siguiendo una clase.

■Acerca de la certificación Microsoft Technology


Associate (MTA)
Preparación de los recursos tecnológicos del futuro
La tecnología desempeña una función importante en prácticamente todos los negocios
alrededor del mundo. Poseer el conocimiento fundamental de cómo funciona la tecnología y
comprender su impacto en el entorno académico y laboral actual cada vez es más importante,
sobre todo para aquellos alumnos interesados en explorar profesiones que implican tecnología.
Es por eso que Microsoft ha creado la certificación Microsoft Technology Associate (MTA),
una nueva credencial de nivel básico que valida el conocimiento tecnológico fundamental
entre los alumnos que buscan desarrollar una carrera en tecnología.
La certificación Microsoft Technology Associate (MTA) es el camino ideal y preferido para
los programas de certificación de tecnología de Microsoft de fama mundial, como Microsoft
Certified Technology Specialist (MCTS) y Microsoft Certified IT Professional (MCITP). MTA
se posiciona para convertirse en el credencial principal para aquellas personas que buscan
explorar y desarrollar una carrera profesional en tecnología, o reforzar actividades conexas,
como negocios o cualquier otro campo donde la tecnología está omnipresente.

www.wiley.com/college/microsoft o llame al número de teléfono gratuito de MOAC: 1 + (888) 764-7001 (solo EE. UU. y Canadá).
| xv
xvi | Programa de apoyo para el alumno

Perfil del candidato MTA


El programa de certificación MTA está específicamente diseñado para alumnos de educación
secundaria y superior interesados en explorar las opciones académicas y profesionales en
el campo de la tecnología. Ofrece a los alumnos una certificación en TI básica y desarrollo.
Como nuevo punto de partida recomendado para las certificaciones de tecnología de
Microsoft, MTA está especialmente diseñada para los nuevos alumnos en TI y desarrollo de
software. Está disponible exclusivamente en los centros educativos y se integra fácilmente en
los programas existentes de clases de informática.

MTA potencia a los educadores y motiva a los alumnos


MTA ofrece un nuevo estándar para medir y validar los conocimientos fundamentales de
tecnología directamente en el aula sin que afecte al presupuesto ni a los recursos didácticos.
MTA ayuda a las instituciones que destacan como proveedores innovadores de credenciales
de la industria de alta demanda y se puede implementar fácilmente con un conjunto simple,
conveniente y asequible de exámenes de certificación de tecnología de nivel básico. MTA
permite a los alumnos explorar carreras en tecnología que no requieren una gran inversión en
tiempo y recursos, al tiempo que proporciona una base profesional y la confianza para tener
éxito en estudios avanzados y futuros proyectos de aprendizaje profesional.
Además de conceder a los alumnos una certificación de Microsoft de nivel básico, MTA
está diseñada como plataforma para otras certificaciones de tecnología más avanzadas de
Microsoft, como la certificación Microsoft Certified Technology Specialist (MCTS).

Entrega de exámenes MTA: licencia MTA Campus


La implementación de un nuevo programa de certificación en el aula nunca ha sido tan
fácil como con la licencia MTA Campus. A través de la compra de una licencia anual MTA
Campus, no se necesitarán las solicitudes de presupuesto ad hoc ni las compras periódicas
de los cupones de exámenes. Ahora, puede realizar un presupuesto de bajo costo para todo el
año y después administrar los exámenes MTA a sus alumnos y otros profesores de la escuela,
donde y cuando desee.
La licencia MTA Campus ofrece un conjunto conveniente y asequible de certificaciones de
tecnología de nivel básico diseñadas para potenciar a los educadores y motivar a los alumnos a
medida que construyen una base para sus carreras.
La licencia MTA Campus está administrada por Certiport, proveedor exclusivo de exámenes
MTA de Microsoft.
Para obtener más información sobre cómo llegar a ser un asociado en tecnología de
Microsoft (Microsoft Technology Associate) y sobre la disponibilidad de exámenes, visite
www.microsoft.com/learning/mta.

www.wiley.com/college/microsoft o llame al número de teléfono gratuito de MOAC: 1 + (888) 764-7001 (solo EE. UU. y Canadá).
Programa de apoyo para el alumno | xvii

■ Activar la prueba práctica GRATUITA de MTA


La compra de este libro le da derecho a una prueba práctica gratuita MTA de GMetrix (por un
valor de 30 $). Vaya a www.gmetrix.com/mtatests y use el siguiente código de validación para
canjear la prueba gratuita:MTA 98-361-A19875B7D810
El sistema de administración de habilidades GMetrix Skills Management System ofrece todo
lo necesario para la práctica de la certificación Microsoft Technology Associate (MTA).
Información general de las características de la prueba:
• Pruebas prácticas que se asignan a los objetivos del examen de Microsoft Technology
Associate (MTA)
• Pruebas prácticas MTA de GMetrix que simulan el entorno real de pruebas MTA
• Más de 50 preguntas por prueba que abarcan todos los objetivos
• Progreso a ritmo propio, guardar la prueba para reanudarla más tarde, permite volver a
las preguntas omitidas
• Informe de resultados detallado e imprimible que destaca aquellas áreas que requieren
una revisión adicional
Para obtener el máximo rendimiento de su preparación MTA, aproveche las ventajas de las
pruebas de práctica gratuitas MTA de GMetrix desde este momento.
Para obtener soporte técnico sobre problemas en la instalación o activación del código, escriba
un correo electrónico a support@gmetrix.com.

www.wiley.com/college/microsoft o llame al número de teléfono gratuito de MOAC: 1 + (888) 764-7001 (solo EE. UU. y Canadá).
Reconocimientos

■ Revisores de los fundamentos de la tecnología MOAC MTA


Nos gustaría dar las gracias a los numerosos revisores que han leído cuidadosamente el manuscrito y han
proporcionado información muy valiosa al servicio de los materiales didácticos de calidad:

Yuke Wang, Universidad de Texas en Dallas Sharon Moran, Centro de estudios superiores de
Palaniappan Vairavan, Universidad de Bellevue Hillsborough
Harold “Buz” Lamson, Instituto técnico ITT Keith Hoell, Universidad de Briarcliffe y Universidad
Colin Archibald, Centro de estudios superiores de de Queens, Universidad de la Ciudad de Nueva York
Valencia (CUNY)
Catherine Bradfield, Universidad en línea DeVry Mark Hufnagel, Distrito escolar de Lee County
University Online Rachelle Hall, Centro de estudios superiores de Glendale
Robert Nelson, Universidad de Blinn Scott Elliott, Christie Digital Systems, Inc.
Kalpana Viswanathan, Universidad de Bellevue Gralan Gilliam, Kaplan
Bob Becker, Universidad de Vatterott Steve Strom, Centro de estudios superiores de Butler
Carol Torkko, Universidad de Bellevue John Crowley, Centro de estudios superiores del condado
Bharat Kandel, Escuela universitaria Missouri Tech de Bucks
Linda Cohen, Centro de estudios técnicos superiores de Margaret Leary, Centro de estudios superiores del norte
Forsyth de Virginia
Candice Lambert, Centros tecnológicos Metro Sue Miner, Centro de estudios superiores de Lehigh
Carbon
Susan Mahon, Universidad de Collin
Gary Rollinson, Universidad de Cabrillo
Mark Aruda, Centro de estudios superiores de
Hillsborough Al Kelly, Universidad de tecnología avanzada
Claude Russo, Centro de estudios superiores de Brevard Katherine James, Universidad de Seneca
David Koppy, Universidad de Baker

www.wiley.com/college/microsoft o llame al número de teléfono gratuito de MOAC: 1 + (888) 764-7001 (solo EE. UU. y Canadá).
xviii | 
Contenido breve

1 Introducción a la programación 1

2 Introducción a la programación orientada a objetos 32

3 Comprensión general del desarrollo de software 65

4 Conceptos de las aplicaciones web 85

5 Conceptos de las aplicaciones de escritorio 120

6 Conceptos de las bases de datos 142

Apéndice A 177
Índice 179

www.wiley.com/college/microsoft o llame al número de teléfono gratuito de MOAC: 1 + (888) 764-7001 (solo EE. UU. y Canadá).
| xix
Contenido

Lección 1: Introducción a la Comprensión de la herencia 48


Conceptos de las clases abstractas y selladas 50
programación 1 Herencia de la clase Object 51
Conversión entre tipos 52
Matriz de dominio de objetivos 1
Comprensión del polimorfismo 53
Términos clave 1 Conceptos de las palabras clave override y new 55
Comprensión de la programación informática 2 Comprensión de las interfaces 56
Introducción a los algoritmos 2
Resumen de conocimientos 58
Introducción a C# 4
Evaluación de conocimientos 59
Comprensión de las estructuras de decisión 11
Instrucción if 11 Evaluación de competencias 64
Instrucción if-else 13 Evaluación de aptitudes 64
Instrucción switch 15
Comprensión de las estructuras de repetición 17
Conceptos del bucle while 17
Conceptos del bucle do-while 19
Lección 3: Comprensión general del
Conceptos del bucle for 20 desarrollo de software 65
Conceptos del bucle foreach 21
Conceptos de la recursión 22 Matriz de dominio de objetivos 65
Comprensión del control de excepciones 23 Términos clave 65
Control de excepciones 24 Comprensión de la administración del ciclo de vida
Uso de Try-Catch-Finally 25 de las aplicaciones 66
Resumen de conocimientos 26 Conceptos del análisis de requisitos 66
Evaluación de conocimientos 27 Conceptos del proceso de diseño 67
Conceptos del desarrollo de software 67
Evaluación de competencias 30
Conceptos de las pruebas de software 68
Evaluación de aptitudes 31 Conceptos de la administración de versiones 68
Comprensión de las pruebas 68
Lección 2: Introducción a la Conceptos de los métodos de prueba 69
programación orientada a Conceptos de los niveles de pruebas 69
objetos 31 Comprensión de las estructuras de datos 70
Comprensión de las matrices 70
Matriz de dominio de objetivos 32 Conceptos de las colas 72
Conceptos de las pilas 73
Términos clave 32
Listas de vínculo 74
Comprensión de los objetos 33
Comprensión de los algoritmos de ordenación 76
Pensamiento orientado a objetos 33
Conceptos de BubbleSort 76
Conceptos de las clases 33
Comprensión de QuickSort 79
Conceptos de los valores y las referencias 44
Resumen de conocimientos 81
Conceptos de los structs 44
Conceptos de la asignación de memoria 45 Evaluación de conocimientos 81
Comprensión de la encapsulación 47 Evaluación de competencias 83
Conceptos de los modificadores de acceso 48 Evaluación de aptitudes 84

www.wiley.com/college/microsoft o llame al número de teléfono gratuito de MOAC: 1 + (888) 764-7001 (solo EE. UU. y Canadá).
| xxi
xxii | Contenido

Lección 4: Conceptos de las Conceptos de las aplicaciones basadas en


consola 129
aplicaciones web 85 Trabajo con parámetros de línea de comandos 130
Conceptos de los servicios de Windows 131
Matriz de dominio de objetivos 85
Creación de un servicio de Windows 132
Términos clave 85
Resumen de conocimientos 137
Conceptos del desarrollo de páginas web 85
Evaluación de conocimientos 138
Conceptos de HTML 86
Conceptos de las hojas de estilos en cascada 88 Evaluación de competencias 140
Conceptos de JavaScript 92 Evaluación de aptitudes 141
Conceptos de la programación del lado cliente
comparada con la programación del lado servidor 94
Conceptos del desarrollo de aplicaciones Lección 6: Conceptos de las bases de
ASP.NET 95 datos 142
Conceptos del modelo de eventos y del ciclo de vida de
las páginas ASP.NET 96 Matriz de dominio de objetivos 142
Conceptos de la administración de estado 99
Términos clave 142
Conceptos del hospedaje de sitios web IIS 104
Conceptos de las bases de datos relacionales 142
Conceptos de Internet Information Services 105
Comprensión de las bases de datos 143
Creación de directorios virtuales y sitios web 105
Conceptos de las bases de datos relacionales 143
Implementación de aplicaciones web 106
Conceptos del diseño de bases de datos
Conceptos del desarrollo de servicios web 107 relacionales 144
Introducción a SOAP 107 Conceptos de los diagramas de relación entre
Introducción a WSDL 108 entidades 144
Creación de servicios web 108 Conceptos de la normalización de datos 146
Consumo de servicios web 112
Conceptos de los métodos de consulta de las bases
Resumen de conocimientos 115 de datos 149
Evaluación de conocimientos 115 Trabajo con consultas SQL 150
Evaluación de competencias 118 Trabajo con procedimientos almacenados 159
Evaluación de aptitudes 119 Conceptos de los métodos de conexión de bases de
datos 164
Trabajo con archivos planos 164
Lección 5: Conceptos de las aplicaciones Trabajo con XML 167
de escritorio 120 Trabajo con DataSet 170
Resumen de conocimientos 173
Matriz de dominio de objetivos 120 Evaluación de conocimientos 173
Términos clave 120 Evaluación de competencias 176
Conceptos de las aplicaciones de Windows Evaluación de aptitudes 176
Forms 120
Diseño de un formulario de Windows Forms 121
Conceptos del modelo de eventos de Windows Apéndice A 177
Forms 123 Índice 179
Uso de la herencia visual 123
Conceptos de las aplicaciones de interfaz de múltiples
documentos (MDI) 126

www.wiley.com/college/microsoft o llame al número de teléfono gratuito de MOAC: 1 + (888) 764-7001 (solo EE. UU. y Canadá).
Introducción a la LECCIÓN 1
programación
M AT R I Z D E C O N O C I M I E N T O S D E L A L E C C I Ó N

Conocimientos y conceptos Objetivo del examen MTA Número de objetivo


del examen MTA
Conceptos de la programación Conceptos del almacenamiento y 1.1
informática los tipos de datos de los equipos.
Conceptos de las estructuras Conceptos de las estructuras 1.2
de decisión de decisión informáticas.
Conceptos de las estructuras Identificación de los métodos 1.3
de repetición apropiados para controlar la repetición.
Conceptos del control de excepciones Conceptos del control de errores. 1.4

TÉRMINOS CLAVE
algoritmo código binario matriz
bloque finally constante métodos
bloque switch diagrama de flujo operador
bloque try-catch-finally estructuras de decisión programas (informáticos)
bucle do-while excepción recursión
bucle for instrucción default sistema de numeración binario
bucle foreach instrucción if tabla de decisión
bucle while instrucción if-else tipos de datos
case instrucción switch variable
clase lenguaje de alto nivel

Vamos a imaginar que usted es un desarrollador de software de la empresa Northwind


Corporation. Entre otras tareas, su trabajo consiste en desarrollar programas para resolver
problemas empresariales. Algunos ejemplos de sus tareas son: analizar los pedidos de
los clientes para determinar los descuentos aplicables; actualizar la información de
existencias relativa a los miles de artículos del inventario de la empresa; y elaborar
informes interactivos que permitan a los usuarios ordenar y filtrar los datos.
Es importante asegurarse de diseñar los programas respetando estrictamente las
especificaciones. También es preciso comprobar que todos los cálculos sean exactos y
estén completos. Los programas que escribimos han de ser robustos y capaces de mostrar
mensajes de error sin detener el procesamiento.

1
2 | Lección 1

El lenguaje de programación que usamos nos aporta diversas herramientas y técnicas que
facilitan nuestro trabajo. En función de la tarea que realicemos, seleccionamos los tipos
de datos y las estructuras de control más adecuadas para resolver el problema.

■ Conceptos de la programación informática

Un programa es un conjunto de instrucciones precisas para completar una tarea. En esta


sección, aprenderemos a escribir algoritmos y programas para resolver un problema
determinado. Además de escribir el primer programa mediante el lenguaje de programación
RESULTADO FINAL
C#, aprenderemos cuál es la estructura básica de los programas y a compilarlos, ejecutarlos,
proporcionarles información y generar resultados a partir de ellos.

Introducción a los algoritmos


Un algoritmo es un conjunto de pasos ordenados y finitos para resolver un problema dado.

El término algoritmo se refiere a un método para resolver problemas. Podemos describir los
algoritmos en nuestra lengua natal. No obstante, estas descripciones se suelen malinterpretar
debido a la complejidad y ambigüedad del lenguaje natural. Por lo tanto, los algoritmos se
escriben con frecuencia en formatos simples y precisos, como diagramas de flujo, árboles de
decisión y tablas de decisión, que representan el algoritmo en un diagrama, una tabla o un
gráfico. A menudo, estas técnicas se emplean antes de escribir los programas, con objeto de
permitir que comprendamos mejor la solución.
Estas herramientas de desarrollo de algoritmos pueden ayudarnos a expresar una solución de
una manera fácil de usar, pero un equipo no los entiende directamente. Para que un equipo
entienda nuestro algoritmo, deberemos escribir un programa, que constituye una fórmula más
formal para la que se usa un lenguaje de programación, como C#. Aprenderemos cómo hacerlo
en la sección siguiente.
Pero antes, esta sección de la lección se centra en dos técnicas que se usan para presentar
algoritmos (a saber, los diagramas de flujo y las tablas de decisión). Se trata de métodos más
precisos que el lenguaje natural pero menos formales y más fáciles de usar que un lenguaje de
programación.

INTRODUCCIÓN A LOS DIAGRAMAS DE FLUJO


Un diagrama de flujo es una representación gráfica de un algoritmo. Para dibujar un diagrama
de flujo, suelen usarse símbolos estándar. En la tabla 1-1 se muestran algunos símbolos
Tabla 1-1
comunes de los diagramas de flujo.
Símbolos comunes de los
diagramas de flujo
Introducción a la programación | 3

Por ejemplo, en la figura 1-1 se muestra un diagrama de flujo que toma dos números (entrada),
los compara y, a continuación, indica cuál es el mayor (salida).

Figura 1-1
Diagrama de flujo simple
que compara dos números
y produce como salida el
mayor de los dos

Como puede observarse, el diagrama de flujo enumera en el orden correcto todos los pasos
necesarios para realizar la operación. El flujo de control comienza con el símbolo de inicio y
termina con el símbolo de fin. Los símbolos del proceso y de entrada y salida siempre tienen
un único punto de entrada y uno de salida. En cambio, el símbolo de decisión tiene una sola
entrada pero varias salidas. Para probar un diagrama de flujo, realizamos un “simulacro”,
es decir, seguimos manualmente los pasos del diagrama de flujo con datos de prueba para
comprobar si se siguen las rutas apropiadas.

INTRODUCCIÓN A LAS TABLAS DE DECISIÓN


Cuando los algoritmos comprenden grandes cantidades de condiciones, las tablas de decisión
presentan un formato más compacto y fácil de leer. La tabla 1-2 muestra una tabla de decisión
para calcular un descuento. Esta tabla genera un porcentaje de descuento en función de la
cantidad de producto comprado. Las líneas en negrita de la tabla de decisión la dividen en
cuatro cuadrantes. El primer cuadrante (parte superior izquierda) especifica las condiciones
(“Cantidad < 10,” etc.). El segundo cuadrante (parte superior derecha) especifica las reglas.
Las reglas son las combinaciones posibles de los resultados de cada condición. El tercer
cuadrante (parte inferior izquierda) especifica la acción (“Descuento”, en este caso) y el último
cuadrante (parte inferior derecha) especifica los elementos de acción correspondiente a cada
regla.
4 | Lección 1

Tabla 1-2
Tabla de decisión para Cantidad < 10 S N N N
calcular descuentos
Cantidad < 50 S S N N
Cantidad < 100 S S S N
Descuento  5%  10%  15%  20%

Para averiguar qué elemento de acción se debe aplicar, es preciso evaluar cada condición a
fin de encontrar la regla correspondiente y, a continuación, elegir la acción especificada en
la columna de esa regla. Por ejemplo, si el valor “Cantidad” de los datos de prueba es 75,
entonces la primera regla se evalúa en “No”, la segunda regla se evalúa en “No” y la tercera
regla se evalúa en “Sí”. Por lo tanto, elegiremos el elemento de acción de la columna (N, N, S)
que establece el descuento del 15 %.

Introducción a C#
C# es un conocido lenguaje de alto nivel que permite escribir programas en un formato
legible. C# forma parte de .NET Framework y saca partido de la compatibilidad con el
tiempo de ejecución y las bibliotecas de clases que este entorno proporciona.

Como hemos explicado en la sección anterior, los equipos necesitan instrucciones precisas
y completas para llevar a cabo una tarea. Estos conjuntos de instrucciones se denominan
programas informáticos o, simplemente, programas .
AEn el nivel más básico, los equipos usan el sistema de números binario para representar
la información y el código. En este sistema, cada valor se representa mediante dos símbolos
únicamente, 0 y 1. Un programa escrito en el sistema de números binario se llama código
binario.
Usar el código binario para programar un equipo resulta árido y sumamente difícil para
cualquier tarea mínimamente compleja. Por lo tanto, para simplificar la programación, los
científicos e ingenieros informáticos han desarrollado varios niveles de abstracción entre los
equipos y sus operadores humanos. Estas abstracciones incluyen un software (por ejemplo,
los sistemas operativos, los compiladores y varios sistemas de tiempo de ejecución) que se
encargan de traducir un programa legible por el ser humano en un programa que la máquina
pueda interpretar.
La mayoría de los programas modernos están escritos en un lenguaje de alto nivel como C#,
Visual Basic o Java. Estos lenguajes permiten escribir instrucciones precisas de forma legible
para el ser humano. Posteriormente, un compilador traduce el lenguaje de alto nivel en un
lenguaje de nivel inferior que resulta comprensible al sistema de ejecución runtime.
Cada lenguaje de programación ofrece su propio conjunto de terminología y gramática
(también denominado “sintaxis”). En este curso, aprenderemos a programar con el lenguaje de
programación C# en el entorno .NET Framework. .NET Framework proporciona un entorno
de ejecución runtime para el programa C#. Asimismo, contiene las bibliotecas de clases
que proporcionan gran cantidad de funciones básicas reutilizables que se pueden incorporar
directamente a los programas escritos en C#.

✚ MÁS INFORMACIÓN
.NET Framework proporciona tres componentes principales: un entorno de ejecución runtime, un conjunto
de bibliotecas de clases que proporcionan muchas funciones reutilizables y compiladores de lenguaje para C#,
Visual Basic y Managed C++. .NET Framework admite muchos lenguajes de programación y también la adición de
lenguajes adicionales al sistema. Aunque la sintaxis y la terminología de cada lenguaje varían, todos pueden usar
las bibliotecas de clases base proporcionadas por .NET Framework.
Introducción a la programación | 5

En este curso, usaremos un entorno de desarrollo integrado (IDE) para desarrollar el código.
Para escribir código, es posible usar Visual Studio o la edición gratuita Visual Studio Express.
Ambas herramientas proporcionan un entorno sumamente productivo para desarrollar y probar
los programas.

ESCRITURA DE UN PROGRAMA EN C#

PREPÁRESE. Para escribir un programa en C#, siga estos pasos:


1. Inicie Visual Studio. Seleccione Archivo >Nuevo proyecto. Seleccione las plantillas
Aplicación de consola de Visual C# .
2. Escriba IntroducingCS en el cuadro Nombre. Asegúrese de que esté activada la casilla
Crear directorio para la solución y escriba el nombre Lesson01 en el cuadro Nombre
de la solución. Haga clic en Aceptar para crear el proyecto.
3. Al crear el proyecto, comprobará que Visual Studio ya ha creado un archivo
denominado Program.cs y ha escrito una plantilla automáticamente.
4. Modifique la plantilla de forma que se asemeje al siguiente código:
using System;
namespace Lesson01
{
  class Program
  {
TOME NOTA
*     static void Main(string[] args)
C# es un lenguaje     {
de programación       Console.WriteLine(“¡Hola, mundo!”);
que distingue entre     }
mayúsculas y   }
minúsculas. Por ello, }
escribir “Class” en lugar
de “class” (por ejemplo) 5. Seleccione Depurar > Iniciar sin depurar o presione Ctrl+F5.
dará lugar a un error de 6. La salida del programa aparecerá en una ventana de comandos, como se muestra en
sintaxis. la figura 1-2.

Figura 1-2
Salida del programa en una
ventana de comandos

Para ejecutar el programa, otra opción consiste en abrir una ventana de comandos
(cmd.exe) y, a continuación, navegar a la carpeta de salida del proyecto que, de forma
ALTERNATIVA
predeterminada, es la subcarpeta bin\debug que se encuentra en la ubicación del proyecto.
Inicie el programa. Para ello, escriba el nombre del programa en la ventana de comandos y
presione Intro.

7. Presione una tecla para cerrar la ventana de comandos.


PAUSA. Deje el proyecto abierto para usarlo en el siguiente ejercicio.
6 | Lección 1

El programa que hemos creado es trivial por lo que hace, pero sin embargo resulta útil para
entender la estructura, compilación y ejecución de un programa. En primer lugar, vamos a
hablar de la parte de compilación y ejecución. Esto es lo que sucede al seleccionar la opción
Depurar > Iniciar sin depurar en el paso 5 anterior:
1. Visual Studio invoca el compilador de C# para traducir el código C# a un lenguaje de
nivel inferior, el código de Lenguaje intermedio común (CIL). Este código de bajo nivel
se almacena en un archivo ejecutable denominado (Lesson01.exe). El nombre del archivo
de salida se puede cambiar modificando las propiedades del proyecto.
2. A continuación, Visual Studio toma la salida del proyecto y pide al sistema operativo
que lo ejecute. En este punto es cuando aparece la ventana de comandos que muestra la
salida.
3. Cuando el programa concluye, Visual Studio muestra el siguiente mensaje: “Presione
cualquier tecla para continuar. . .”. Es importante tener en cuenta que este mensaje
solamente se genera si el programa se ejecuta mediante la opción Iniciar sin depurar.

Cuando se selecciona la opción de menú Depurar > Iniciar sin depurar, Visual Studio
muestra automáticamente el mensaje “Presione cualquier tecla para continuar . . .” Después,
la ventana de comandos permanece abierta para revisar la salida. Si, sin embargo, se
selecciona la opción Depurar > Iniciar depuración, la ventana de comandos se cierra tan
*
TOME NOTA
pronto como finaliza la ejecución del programa. Es importante saber que la opción Iniciar
depuración ofrece funciones como la posibilidad de hacer una pausa en un programa en
ejecución en un momento dado y revisar el valor de diversas variables en la memoria.

Aunque no usemos un entorno de desarrollo integrado (IDE) como Visual Studio, podemos
compilar el programa manualmente mediante las herramientas de la línea de comandos. Pero,
por supuesto, con Visual Studio resulta más fácil y rápido probar los programas.

Antes de poder ejecutar código de Lenguaje intermedio común (CIL), primero debe
traducirse para la arquitectura del equipo en que se ejecutará. El sistema de ejecución
*
TOME NOTA
runtime de .NET Framework se encarga de esta traducción en segundo plano, mediante un
proceso denominado compilación Just-In-Time.

CONCEPTOS DE LA ESTRUCTURA DE UN PROGRAMA C#

En esta sección de la lección, conoceremos los elementos estructurales del programa


simple que hemos creado en C# en la sección anterior.

En la figura 1-3 se describe el programa creado en el ejercicio anterior con los números de
línea. Durante esta sección, usaremos estos números para referirnos a las diferentes estructuras
del programa.

Para habilitar la visualización de los números de línea en Visual Studio, seleccione el menú
Herramientas > Opciones. A continuación, expanda el nodo Editor de texto y seleccione C#.
*
TOME NOTA
Por último, en la sección Mostrar, seleccione la opción Números de línea.
Introducción a la programación | 7

Figura 1-3
Listado del programa con
números de línea

Un programa C# está compuesto de una o más clases. Una clase es un conjunto de datos y
métodos. Por ejemplo, el código de la figura 1-3 define una sola clase denominada Program en
las líneas 5 a 11. Una clase se define mediante la palabra clave “class”, seguida por el nombre
de la clase. El contenido de una clase se define entre una llave de apertura ({) y una llave de
X REF cierre (}).

Encontrará más La línea 3 del código de la figura 1-3 define un espacio de nombres, Lesson01. Los espacios
información sobre las de nombres se usan para organizar las clases e identificarlas de manera exclusiva. El espacio
clases en la lección 2. de nombres y los nombres de clase se combinan entre sí para crear un nombre de clase
completo. Por ejemplo, el nombre de clase completo de la clase Program es Lesson01.
Program. C# requiere que el nombre completo de una clase sea único. Así pues, no puede
haber otra clase que se llame Program en el espacio de nombres Lesson01, pero sí una clase
denominada Program en otro espacio de nombres, como Lesson02, por ejemplo. En este
caso, la clase Program definida en el espacio de nombres Lesson02 se identificará de forma
exclusiva por su nombre de clase completo, Lesson02.Program.
.NET Framework proporciona gran cantidad de clases útiles organizadas en muchos espacios
de nombres. El espacio de nombres System contiene algunas de las clases base que más se
X REF
usan. Una de estas clases contenidas en el espacio de nombres System es Console. La clase
Encontrará más Console proporciona funcionalidad de entrada y salida para aplicaciones de consola. La línea
información sobre los 9 del código de la figura 1-3 se refiere a la clase Console y llama a su método WriteLine. Para
métodos en la lección 2. obtener acceso al método WriteLine de manera inequívoca, se debe escribir así:
System.Console.WriteLine(“¡Hola, mundo!”);
Dado que los nombres de clase aparecen en el código con frecuencia, escribir su nombre
completo todas las veces puede resultar tedioso y hacer que el programa resulte demasiado
TOME NOTA
* detallado. Para solucionar este problema, se usa la directiva using de C# (consulte el código de
Todas las instrucciones la línea 1 en la figura 1-3). La directiva using permite usar las clases de un espacio de nombres
de C# deben terminar sin tener que escribir el nombre completo de la clase.
con un punto y coma (;).
La clase Program define un método único denominado Main (líneas 7 y 10 del listado de
código que se muestra en la figura 1-3). Main es un método especial que también sirve como
punto de entrada al programa. Cuando el runtime ejecuta un programa, siempre empieza en
el método Main. Un programa puede tener muchas clases y cada clase puede tener muchos
8 | Lección 1

métodos, pero solo un método Main. A su vez, un método puede llamar a otros métodos. En la
línea 9, el método Main llama al método WriteLine de la clase System.Console para mostrar
una cadena de caracteres en la ventana de comandos; así es como se muestra el mensaje.

El método Main debe declararse como static. Cuando un método es static, es posible
llamarlo para una clase aunque no se haya creado ninguna instancia de ella. Aprenderemos
*
TOME NOTA
más sobre ello en la lección siguiente.

CONCEPTOS DE LAS VARIABLES

Las variables proporcionan almacenamiento temporal durante la ejecución de un programa.

En C#, las variables son marcadores de posición que se usan para almacenar valores. Una
variable tiene un nombre y un tipo de datos. El tipo de datos de una variable determina qué
valores puede contener y qué tipo de operaciones pueden realizarse con ella. Por ejemplo, la
siguiente instrucción crea una variable denominada number del tipo de datos int y le asigna el
valor 10:
int number = 10;
Cuando se declara una variable, en la memoria del equipo se crea una ubicación lo bastante
grande para contener su valor según su tipo de datos. Por ejemplo, en un equipo de 32 bits,
una variable cuyo tipo de datos es int necesita dos bytes de memoria. El valor de una variable
se puede modificar mediante una nueva asignación; por ejemplo:
number = 20;
El código anterior cambia el contenido de la ubicación de memoria identificado por el nombre
number.

Un nombre de variable debe comenzar con una letra o un guion bajo y solo puede contener
letras, números o guiones bajos. Un nombre de variable no debe exceder de 255 caracteres.
*
TOME NOTA
También debe ser exclusiva en el ámbito en el cual se define.

CONCEPTOS DE LAS CONSTANTES

Las constantes son campos de datos o variables locales cuyo valor no se puede modificar.

Las constantes se declaran mediante la palabra clave const. Por ejemplo, una constante se
puede declarar como sigue:
const int i = 10;
Este código declara una constante i de datos de tipo int y almacena el valor 10. Una vez
declarada, no se puede cambiar el valor de la constante.

CONCEPTOS DE LOS TIPOS DE DATOS

Los tipos de datos especifican el tipo de datos con que se trabaja en un programa. El tipo
de datos define el tamaño de la memoria necesaria para almacenar los datos y los tipos de
operaciones que se pueden realizar con los datos.
Introducción a la programación | 9

C# proporciona varios tipos de datos integrados que se pueden usar en los programas. También
X REF
se pueden definir tipos nuevos mediante una estructura de datos, como una clase o un struct.
Encontrará más Este capítulo se centra en algunos de los tipos de datos integrados que más se usan.
información sobre cómo En la tabla 1-3 se muestran varios tipos de datos integrados de uso frecuente que están
crear sus propios tipos disponibles en C#. Los tamaños indicados en la tabla se refieren a un equipo que ejecuta un
de datos en la lección 2. sistema operativo de 32 bits, como Windows 7 de 32 bits. Para un sistema operativo de 64 bits,
como Windows 7 de 64 bits, estos tamaños serán diferentes.

Tabla 1-3
Tipos de datos integrados Tipo de datos Tamaño Intervalo de valores
que se usan con frecuencia
en C# byte 1 byte de 0 a 255
char 2 bytes de U+0000 a U+ffff (caracteres Unicode)
short 2 bytes −de 32 768 a 32 767
int 4 bytes −de 2 147 483 648 a 2 147 483 647
long 8 bytes −
 de 9 223 372 036 854 775 808 a
9 223 372 036 854 775 807
float 4 bytes de ±1,5 × 10-45 a ±3,4 × 1038
double 8 bytes de ±5.0e−324 a ±1.7e308
TOME NOTA
* bool 2 bytes true o false
Las versiones sin signo
de short, int y long son string - Cero o más caracteres Unicode
ushort, uint y ulong,
respectivamente. Los
tipos sin signo tienen
el mismo tamaño que Todos los tipos de datos enumerados en el cuadro 1-3 son tipos de valor, excepto string, que es
sus versiones con un tipo de referencia. Las variables que se basan directamente en los tipos de valor contienen
signo, pero almacenan el valor. En el caso del tipo de referencia, la variable contiene la dirección de la ubicación de
un intervalo muy memoria donde se almacenan los datos en sí. Aprenderemos más sobre las diferencias entre los
superior de valores solo tipos de valor y los tipos de referencia en la lección 2.
positivos.
CONCEPTOS DE LAS MATRICES

Una matriz es una colección de elementos, a cada uno de los cuales se puede obtener
acceso mediante un índice único.

En C#, se suelen usar las matrices para representar colecciones de objetos de tipo similar. En
el código siguiente se muestra un ejemplo de declaración de matriz:
int[] numbers = { 1, 2, 3, 4, 5 };
Esta declaración crea una matriz identificada por los números de nombre. Puede almacenar
una colección de cinco números enteros. Esta declaración también inicializa cada uno de los
elementos de la matriz respectivamente mediante los números del 1 al 5.
A cualquier elemento de la matriz se puede obtener acceso directamente mediante un índice.
En .NET Framework, los índices de la matriz son de base cero. Esto significa que para obtener
acceso al primer elemento de una matriz se usa el índice 1; para obtener acceso al segundo
elemento, el índice 2 y así sucesivamente.
Para obtener acceso a un elemento individual de la matriz, se usa el nombre de la matriz
seguido por el índice entre corchetes. Por ejemplo, en la matriz que hemos declarado
anteriormente, numbers[0] devolverá el valor 1 y numbers[4] devolverá el valor 5. No es
válido obtener acceso a una matriz fuera de sus límites definidos. Por ejemplo, obtendremos
un error si intentamos obtener acceso al elemento numbers[5] de la matriz.
10 | Lección 1

CONCEPTOS DE LOS OPERADORES


X REF

El tema de las matrices


se aborda con más Los operadores son símbolos que especifican qué operación se realizará con los operandos
detalle en la lección 3, antes de devolver un resultado.
Conceptos generales del
desarrollo de software.

Ejemplos de operadores son, entre otros, +, -, *, /. Los operandos pueden ser variables,
constants, literals, etc. En función de la cantidad de operandos afectados, existen tres tipos de
operadores:
• Operadores unarios: Los operadores unarios funcionan con un solo operando.
Algunos ejemplos de estos son ++x, x++ o isEven, donde x es del tipo de datos
integer e isEven es del tipo de datos Boolean.
• Operadores binarios: Los operadores binarios toman dos operandos. Ejemplos de
ellos son x + y o x > y.
• Operadores ternarios: Los operadores ternarios toman tres operandos. En C#
solamente existe un operador ternario, ?:.
A menudo, en las expresiones se usa más de un operador. En este caso, el compilador debe
determinar cuál de ellos tiene precedencia sobre los demás. En la tabla 1-4 se muestran los
operadores de C# en orden de precedencia. Cuanto más arriba se encuentra un operador en la
tabla, mayor es su precedencia. Los operadores con mayor precedencia se evalúan antes que
los operadores con menor precedencia. Los operadores que aparecen en la misma fila tienen la
misma precedencia.
Tabla 1-4
Precedencia de los Categoría Operadores
operadores en C#
Principal x.y f(x) a[x] x++ x −− new typeof checked unchecked
Unario + - ! ~ ++x −−x (T)x
Multiplicativo */%
Aditivo +-
Desplazamiento << >>
Relacionales y de pruebas de tipo < > <= >= is as
Igualdad == !=
AND lógico &
XOR lógico ^
OR lógico |
AND condicional &&
OR condicional ||
Ternario condicional ?:
Asignación = *= /= %= += -= <<= >>= &= ^= |=

El operador unario de incremento (++) añade 1 al valor de un identificador. Del mismo modo,
el operador de decremento (−−) resta 1 al valor de un identificador. Los operadores unarios de
incremento y decremento pueden usarse como prefijos o sufijos. Por ejemplo:
Introducción a la programación | 11

int x = 10;
x++; //ahora, el valor de x es 11
++x; //ahora, el valor de x es 12
Sin embargo, el funcionamiento de los operadores unarios de incremento y decremento cuando
se usan como parte de una asignación puede afectar los resultados. En concreto, cuando los
operadores unarios de incremento y decremento se usan como prefijos, el valor actual del
identificador se devuelve antes que el incremento o decremento. Por otro lado, cuando se
usan como sufijo, el valor del identificador se devuelve después de completar el incremento
o decremento. Para entender lo que significa esto, vamos a estudiar el siguiente ejemplo de
código:
int y = x++; // el valor de y es 12
int z = ++x; // el valor de z es 14
En la primera instrucción, el valor de x se devuelve antes del incremento. En consecuencia,
después de ejecutar la instrucción, el valor de y es 12 y el valor de x es 13. En cambio, en la
segunda instrucción, el valor de x se incrementa antes de devolver su valor para asignarlo. Así
pues, después de ejecutar la instrucción, el valor de x y de z es 14.

CONCEPTOS DE LOS MÉTODOS


Los métodos son bloques de código que contienen una serie de instrucciones. Los
métodos pueden recibir datos de entrada mediante argumentos y pueden devolver un
valor al llamador.

En el listado de código anterior, conocimos el método Main. Los métodos son la parte de
los programas donde se realizan las acciones. Más en concreto, un método es un conjunto de
instrucciones que se ejecutan cuando se llama al método.
LISTO PARA CERTIFICACIÓN El método Main no devuelve un valor al código que lo llama. Esto se indica mediante la
¿Comprende los palabra clave void. Para que un método devuelva un valor, se ha de usar el tipo de datos
elementos básicos de apropiado para el valor devuelto, en lugar de void.
programación, como
variables, tipos de datos, Los miembros de una clase pueden tener modificadores, tales como static, public y private.
operadores y métodos? Estos modificadores especifican cómo y dónde se puede obtener acceso a los miembros de la
1.1 clase. Aprenderemos más sobre los modificadores en la lección 2.

■ Conceptos de las estructuras de decisión

Las estructuras de decisión introducen en un programa la capacidad de tomar decisiones.


Permiten establecer bifurcaciones hacia distintas secciones del código en función de si el
RESULTADO FINAL
valor de una expresión de tipo Boolean es verdadero o falso.

En C#, las estructuras de control de la toma de decisiones son las instrucciones if, if-else y
switch. En las siguientes secciones se explica cada una de ellas con mayor detalle.

Instrucción if
La instrucción if ejecutará una secuencia de instrucciones determinada únicamente si
la expresión de tipo Boolean correspondiente se evalúa en true (verdadero).
12 | Lección 1

A veces, en los programas, interesa que una secuencia de instrucciones solamente se ejecute
si se cumple determinada condición. En C#, esto se puede hacer mediante la instrucción if. El
procedimiento siguiente permite crear un programa que usa una instrucción if.

USO DE LA INSTRUCCIÓN IF

PREPÁRESE. Para usar la instrucción if, realice las siguientes tareas:


1. Agregue un nuevo proyecto de aplicación de consola denominado if_Statement a la
solución Lesson01.
2. Agregue el siguiente código al método Main de la clase Program.cs:
int number1 = 10;
int number2 = 20;
if (number2 > number1)
{
Console.WriteLine(“number2 es mayor que number1”);
}
3. Seleccione Depurar > Iniciar sin depurar o presione Ctrl+F5.
4. Aparece la salida del programa en una ventana de comandos.
5. Presione una tecla para cerrar la ventana de comandos.
PAUSA. Deje el proyecto abierto para usarlo en el siguiente ejercicio.
Este código es funcionalmente equivalente al diagrama de flujo que se muestra en la
figura 1-4.

Figura 1-4
Diagrama de flujo
equivalente a la instrucción if
de ejemplo

En este caso, la instrucción de salida únicamente se ejecutará si el valor de la expresión de tipo


Boolean que aparece entre paréntesis es true. Si el valor de la expresión es false, el control
pasará a la instrucción inmediatamente posterior a la instrucción if.
Introducción a la programación | 13

En el código C#, es obligatorio que la condición se escriba entre paréntesis. Sin embargo, las
llaves son opcionales cuando el bloque de código contiene una sola instrucción. Así pues, la
instrucción anterior equivale a la siguiente:
if (number2 > number1)
 Console.WriteLine(“number2 es mayor que number1”);
En cambio, vamos a fijarnos en este ejemplo:
if (number2 > number1)
 Console.WriteLine(“number2 es mayor que number1”);
Console.WriteLine(number2);
En este caso, solo la primera instrucción Console.WriteLine forma parte de la instrucción if.
La segunda instrucción Console.WriteLine siempre se ejecuta, independientemente del valor
de la expresión de tipo Boolean.
Para mayor claridad, siempre es conveniente incluir entre llaves las instrucciones que se deben
ejecutar condicionalmente.
Las instrucciones if también pueden anidarse en otras instrucciones if, como en el ejemplo
siguiente:
int number1 = 10;
if (number1 > 5)
{
  Console.WriteLine(“number1 es mayor que 5”);
  if (number1 < 20)
  {
    Console.WriteLine(“number1 es menor que 20”);
  }
}
Dado que ambas condiciones se evalúan en true, este código generaría la siguiente salida:
number1 es mayor que 5
number1 es menor que 20
Pero ¿qué pasaría si el valor de number1 fuese 25 en lugar de 10 antes de ejecutar la
instrucción if externa? En este caso, la primera expresión de tipo Boolean se evaluaría en true,
pero la segunda se evaluaría en false. Por lo tanto, se generaría la siguiente salida:
number1 es mayor que 5

Instrucción if-else
La instrucción if-else permite que un programa realice una acción si la expresión de
tipo Boolean se evalúa en true y otra acción distinta si se evalúa en false.

El procedimiento siguiente permite crear un programa de ejemplo que usa la instrucción


if-else.

USO DE LA INSTRUCCIÓN IF-ELSE

PREPÁRESE. Para usar la instrucción if-else, siga este procedimiento:


1. Agregue un nuevo proyecto de aplicación de consola denominado ifelse_Statement a
la solución Lesson01.
14 | Lección 1

2. Agregue el siguiente código al método Main de la clase Program.cs:


TestIfElse(10);
3. A continuación, agregue el siguiente método a la clase Program.cs:
public static void TestIfElse(int n)
{
  if (n < 10)
  {
   Console.WriteLine(“n es menor que 10”);
  }
  else if (n < 20)
  {
   Console.WriteLine(“n es menor que 20”);
  }
  else if (n < 30)
  {
   Console.WriteLine(“n es menor que 30”);
  }
  else
  {
   Console.WriteLine(“n es mayor o igual que 30”);
  }
}
4. Seleccione Depurar > Iniciar sin depurar o presione Ctrl+F5.
5. Aparece la salida del programa en una ventana de comandos.
6. Presione una tecla para cerrar la ventana de comandos.
7. Modifique el código del método Main para que llame al método TestIfElse con
diferentes valores. Observe que, a consecuencia de los cambios, se ejecuta una
bifurcación diferente de la instrucción if-else.
PAUSA. Deje el proyecto abierto para usarlo en el siguiente ejercicio.
En este caso, el código del TestIfElse combina varias instrucciones if-else para comprobar si se
cumplen varias condiciones. Por ejemplo, si el valor de n es 25, las dos primeras condiciones
(n < 10 y n < 20) se evaluarán en false, pero la tercera condición (n < 30) se evaluará en true.
En consecuencia, el método imprimirá la salida siguiente:
n es menor que 30
Este programa en C# equivale al diagrama de flujo que se muestra en la figura 1-5.
Introducción a la programación | 15

Figura 1-5
Diagrama de flujo
equivalente a la instrucción
if-else de ejemplo

Instrucción switch
La instrucción switch permite bifurcaciones multidireccionales. En muchos
casos, usar instrucciones switch puede simplificar una combinación compleja de
instrucciones if-else.

TOME NOTA
* La instrucción switch consta de la palabra clave switch, seguida de una expresión entre
La expresión que sigue paréntesis, seguida a su vez de un bloque switch. El bloque switch puede incluir una o más
a la instrucción case instrucciones case o una instrucción default. Cuando se ejecuta la instrucción switch, se
debe ser una expresión transfiere el control a una instrucción case coincidente según el valor de la expresión switch.
constante del mismo Si la expresión no coincide con ninguna de las instrucciones case, el control se transfiere a la
tipo de datos que la instrucción default. La expresión switch debe ir entre paréntesis.
expresión switch.
El procedimiento siguiente permite crear un programa que usa la instrucción switch para
evaluar expresiones simples.

USO DE LA INSTRUCCIÓN SWITCH

PREPÁRESE. Para usar la instrucción switch, haga lo siguiente:


1. Agregue un nuevo proyecto de aplicación de consola denominado switch_Statement
a la solución Lesson01.
2. Agregue el siguiente código al método Main de la clase Program.cs:
TestSwitch(10, 20, ’+’);
16 | Lección 1

3. Agregue el siguiente método a la clase Program.cs:


public static void TestSwitch(int op1, int op2, char opr)
{
   int result;
   switch (opr)
   {
    case ’+’:
     result = op1 + op2;
     break;
    case ’−’:
     result = op1 − op2;
     break;
    case ’*’:
     result = op1 * op2;
     break;
    case ’/ ’:
TOME NOTA
*      result = op1 / op2;
Los métodos Console.      break;
Write y Console.     default:
WriteLine pueden usar
cadenas de formato      Console.WriteLine(“Operador desconocido”);
como “Results: {0}”      return;
para dar formato a la
   }
salida. En este caso, la
cadena {0} representa    Console.WriteLine(“Resultado: {0}”, result);
el primer argumento    return;
proporcionado después
de la cadena de }
formato. En el método 4. Seleccione Depurar > Iniciar sin depurar o presione Ctrl+F5.
TestSwitch, la cadena 5. Aparece la salida del programa en una ventana de comandos.
de formato “{0}” se
sustituye por el valor 6. Presione una tecla para cerrar la ventana de comandos.
del argumento siguiente, 7. Modifique el código del método Main para que llame al método TestSwitch con
result. diferentes valores. Observe que, a consecuencia de los cambios, se ejecuta una
bifurcación diferente de la instrucción switch.
PAUSA. Deje el proyecto abierto para usarlo en el siguiente ejercicio.
En este caso, el método TestSwitch acepta dos operandos (op1 y op2) y un operador (opr) y
evalúa la expresión resultante. El valor de la expresión switch se compara con las instrucciones
case del bloque switch. Si hay alguna coincidencia, se ejecutan las instrucciones que respetan
el caso correspondiente. Si ninguna de las instrucciones case coinciden, se transfiere el control
a la bifurcación predeterminada (default) opcional.
Cabe señalar que hay una instrucción break después de cada case. La instrucción break termina
la instrucción switch y transfiere el control a la siguiente instrucción fuera del bloque switch.
El uso de break garantiza que solamente se ejecute una bifurcación y ayuda a evitar errores
de programación. De hecho, si se especifica código después de la instrucción case, es preciso
incluir una instrucción break (u otra instrucción de transferencia del control, como return) para
garantizar que el control no se transfiera directamente de una etiqueta case a otra.
Introducción a la programación | 17

Sin embargo, si no se especifica ningún código después de la instrucción case, es correcto


que el control se transfiera directamente a la instrucción case siguiente. El código siguiente
muestra por qué esta fórmula podría resultar útil:
public static void TestSwitchFallThrough()
{
   DateTime dt = DateTime.Today;
   switch (dt.DayOfWeek)
   {
    case DayOfWeek.Monday:
    case DayOfWeek.Tuesday:
    case DayOfWeek.Wednesday:
    case DayOfWeek.Thursday:
    case DayOfWeek.Friday:
     Console.WriteLine(“Hoy es un día de entre semana”);
     break;
    default:
     Console.WriteLine(“Hoy es un día del fin de semana”);
     break;
   }
LISTO PARA CERTIFICACIÓN }
¿Comprende las estructuras
En este caso, si el valor de la expresión dt.DayofWeek es DayOfWeek.Monday, se establece
de decisión informáticas,
la coincidencia con el primer caso, pero como no se especifica ningún código (ni ninguna
como la bifurcación y la
instrucción de transferencia de control), la ejecución se transfiere a la siguiente instrucción,
repetición?
con lo que se muestra el mensaje “Hoy es un día de entre semana” en la ventana de comandos.
1.2

Puede decidir si desea usar instrucciones if-else o switch en función de la naturaleza


de la comparación y de la legibilidad del código. Por ejemplo, el código del método
TestIfElse toma decisiones basadas en las condiciones que son más adecuadas para
TOME NOTA
* su uso con instrucciones if-else. En el método TestSwitch, las decisiones se basan en
valores constantes, de modo que el código es mucho más legible cuando se escribe como
instrucción switch.

■ Conceptos de las estructuras de repetición

C# tiene cuatro estructuras de control diferentes que permiten a los programas realizar
RESULTADO FINAL tareas repetitivas: el bucle while, el bucle do-while, el bucle for y el bucle foreach.

Estas instrucciones de control de repetición pueden usarse para ejecutar las instrucciones del
cuerpo del bucle un número determinado de veces, según el criterio de terminación del bucle.
Un bucle también se puede terminar mediante una de las diversas instrucciones de
transferencia de control que transfieren el control fuera del bucle. Estas instrucciones son
break, goto, return o throw. Por último, se puede usar la instrucción continue para pasar el
control a la siguiente iteración del bucle sin salir de él.

Conceptos del bucle while


El bucle while ejecuta reiteradamente un bloque de instrucciones hasta que una
expresión concreta de tipo Boolean se evalúa en false.
18 | Lección 1

La forma general del bucle while es la siguiente:


while (comprobación de tipo Boolean)
TOME NOTA
*   instrucción
Con el bucle while, la En este caso, se lleva a cabo una comprobación de tipo Boolean al principio del bucle. Si la
comprobación de tipo comprobación se evalúa en true, se ejecuta el cuerpo del bucle y la comprobación se repite.
Boolean debe ir entre Si la comprobación se evalúa en false, el bucle termina y se transfiere el control a la instancia
paréntesis. Si debe siguiente al bucle.
ejecutarse más de una
instrucción como parte Dado que la comprobación de tipo Boolean se realiza antes de ejecutar el bucle, es posible que
del bucle while, deben ir el cuerpo de un bucle while no se ejecute nunca. Esto sucede si la comprobación se evalúa en
juntas entre llaves. false la primera vez.
El procedimiento siguiente permite crear un programa que usa el bucle while.

USO DEL BUCLE WHILE

PREPÁRESE. Para usar el bucle while, realice las siguientes tareas:


1. Agregue un nuevo proyecto de aplicación de consola denominado while_Statement a
la solución Lesson01.
2. Agregue el siguiente código al método Main de la clase Program.cs:
WhileTest();
3. Agregue el siguiente método a la clase Program.cs:
private static void WhileTest()
{
  int i = 1;
  while (i <= 5)
  {
   Console.WriteLine(“El valor de i = {0}”, i);
   i++;
  }
}
4. Seleccione Depurar > Iniciar sin depurar o presione Ctrl+F5.
5. Aparece la salida del programa en una ventana de comandos.
6. Presione una tecla para cerrar la ventana de comandos.
PAUSA. Deje el proyecto abierto para usarlo en el siguiente ejercicio.
En este ejercicio, se asigna el valor 1 a la variable i. A continuación, se evalúa la condición
del bucle while. Como la condición se cumple (1 <= 5), se ejecuta el código contenido en
el bloque de instrucciones while. Se escribe el valor de i en la ventana de comandos y, a
continuación, se aumenta el valor de i en 1 para que se convierta en 2. Después, se devuelve el
control a la instrucción while y de nuevo se evalúa la condición. Como la condición se sigue
cumpliendo (2 <= 5), se ejecuta una vez más el bloque de instrucciones. El bucle continúa
hasta que el valor de i se convierte en 6 y la condición del bucle while (6 <= 5) ya no se
cumple (se evalúa en false). Al ejecutarse, el método anterior genera la siguiente salida:
El valor de i = 1
El valor de i = 2
El valor de i = 3
El valor de i = 4
El valor de i = 5
El diagrama de flujo equivalente a este bucle while se muestra en la figura 1-6.
Introducción a la programación | 19

Figura 1-6
Diagrama de flujo
equivalente al bucle while de
ejemplo

La instrucción contenida en el bucle, que incrementa el valor de i, desempeña un rol vital. Si


faltara esta instrucción, nunca se cumpliría la condición de terminación y, en consecuencia,
tendríamos un bucle sin fin.
En la mayoría de los casos, para que un bucle while esté bien diseñado, debe constar de tres
partes:
1. Inicializador: El inicializador establece el contador del bucle en el valor inicial correcto.
TOME NOTA
* En el ejemplo anterior, la variable i se establece en 1 antes de que el bucle comience.
Para evitar un bucle
2. Prueba de bucle: La prueba de bucle especifica la condición de terminación del bucle.
infinito, es preciso
En el ejemplo anterior, la expresión (i <= 5) es la expresión de condición.
asegurarse de que
el bucle while está 3. Expresión de terminación: La expresión de terminación cambia el valor del contador de
diseñado de tal manera bucle de tal forma que se cumpla la condición de terminación. En el ejemplo anterior, la
que provoque la expresión i++ es la expresión de terminación.
terminación.

Conceptos del bucle do-while


El bucle do-while ejecuta reiteradamente un bloque de instrucciones hasta que una
expresión concreta de tipo Boolean se evalúa en false. El bucle do-while comprueba
TOME NOTA
* la condición que figura al final del bucle.
Con el bucle do-while,
la comprobación de
tipo Boolean debe ir El bucle do-while es similar al bucle while, con la diferencia de que el cuerpo del bucle
entre paréntesis. Si debe do-while debe ejecutarse por lo menos una vez.
ejecutarse más de una La forma general del bucle do-while es la siguiente:
instrucción como parte
de un bucle do-while, do
estas instrucciones    instrucción
deben ir juntas entre
llaves. while (comprobación de tipo Boolean);
El procedimiento siguiente permite crear un programa que usa el bucle do-while.
20 | Lección 1

USO DEL BUCLE DO-WHILE

PREPÁRESE. Para usar el bucle do-while, realice las siguientes tareas:


1. Agregue un nuevo proyecto de aplicación de consola denominado dowhile_
Statement a la solución Lesson01.
2. Agregue el siguiente código al método Main de la clase Program.cs:
DoWhileTest();
3. Agregue el siguiente método a la clase Program.cs:
private static void DoWhileTest()
{
   int i = 1;
   do
   {
    Console.WriteLine(“El valor de i = {0}”, i);
    i++;
   }
   while (i <= 5);
}
4. Seleccione Depurar > Iniciar sin depurar o presione Ctrl+F5.
5. Aparece la salida del programa en una ventana de comandos.
6. Presione una tecla para cerrar la ventana de comandos.
PAUSA. Deje el proyecto abierto para usarlo en el siguiente ejercicio.
En este ejercicio, después de que a la variable i se le asigne el valor 1, el control entra
directamente en el bucle. En este punto, se ejecuta el código del bloque de instrucciones
do-while. En concreto, se escribe el valor de i en la ventana de comandos y se incrementa
en 1 para que se convierta en 2. Luego, se evalúa la condición del bucle do-while. Como la
condición se sigue cumpliendo (2 <= 5), se devuelve el control a la instrucción do-while y
el bloque de instrucciones se ejecuta de nuevo. El bucle continúa hasta que el valor de i se
convierte en 6 y la condición del bucle do-while (6 <= 5) ya no se cumple (se evalúa en false).
Al ejecutarlo, el método anterior genera la misma salida que el método WhileTest.
La elección entre un bucle while y un bucle do-while depende de si se desea que el bucle se
ejecute al menos una vez. Si el bucle debe ejecutarse cero o más veces, el bucle while es el
apropiado. En cambio, si debe ejecutarse una o más veces, deberá elegirse el bucle do-while.

Conceptos del bucle for


TOME NOTA
* El bucle for combina en un código más fácil de leer los tres elementos de iteración,
Con el bucle for, las tres
expresiones de control que son: la expresión de inicialización, la expresión de la condición de terminación y
deben ir entre paréntesis. la expresión de recuento.
Si debe ejecutarse más
de una instrucción como
El bucle for es parecido al bucle while; permite ejecutar reiteradamente una instrucción o un
parte del bucle, estas
bloque de instrucciones hasta que una expresión se evalúa en false. La forma general del bucle
instrucciones deben ir
for es la siguiente:
juntas entre llaves.
for (expresión-inicialización; expresión-condición; expresión-recuento)
  instrucción
Introducción a la programación | 21

Como se observa, el bucle for combina las tres expresiones de control esenciales de una
iteración. Esto da lugar a un código más legible. El bucle resulta útil sobre todo para crear
iteraciones que deben ejecutarse un número determinado de veces.
El procedimiento siguiente permite crear un programa que usa el bucle for.

USO DEL BUCLE FOR

PREPÁRESE. Para usar el bucle for, realice las siguientes tareas:


1. Agregue un nuevo proyecto de aplicación de consola denominado for_Statement a
la solución Lesson01.
2. Agregue el siguiente código al método Main de la clase Program.cs:
ForTest();
3. Agregue el siguiente método a la clase Program.cs:
private static void ForTest()
{
   for(int i = 1; i<= 5; i++)
   {
    Console.WriteLine(“El valor de i = {0}”, i);
   }
}
4. Seleccione Depurar > Iniciar sin depurar o presione Ctrl+F5.
5. Aparece la salida del programa en una ventana de comandos.
6. Presione una tecla para cerrar la ventana de comandos.
PAUSA. Deje el proyecto abierto para usarlo en el siguiente ejercicio.
Al ejecutarlo, el método ForTest genera la misma salida que el método WhileTest. En este
caso, se crea la variable i dentro del ámbito del bucle for y se le asigna el valor 1. El bucle
continúa mientras el valor de i sea menor o igual que 5. Después del cuerpo del bucle, se
evalúa la expresión de recuento y se devuelve el control a la expresión de condición.
Todas las expresiones de control de un bucle for son opcionales. Por ejemplo, se pueden omitir
todas las expresiones para crear un bucle infinito, como este:
for (; ;)
{
   //no hacer nada
}

Conceptos del bucle foreach


El bucle foreach resulta útil para recorrer en iteración los elementos de una colección.

El bucle foreach podría considerarse como una versión mejorada del bucle for para recorrer en
iteración colecciones, tales como matrices y listas. La forma general de la instrucción foreach
es la siguiente:
foreach (elemento ElementType de la colección)
   instrucción
22 | Lección 1

Las expresiones de control del bucle foreach deben ir entre paréntesis. Si debe ejecutarse más
de una instrucción como parte del bucle, estas instrucciones deben ir juntas entre llaves.
El procedimiento siguiente permite crear un programa que muestra una manera sencilla de
recorrer en iteración una colección mediante el bucle foreach.

USO DEL BUCLE FOREACH

PREPÁRESE. Para usar el bucle foreach, haga lo siguiente:


1. Agregue un nuevo proyecto de aplicación de consola denominado foreach_
Statement a la solución Lesson01.
2. Agregue el siguiente código al método Main de la clase Program.cs:
ForEachTest();
3. Agregue el siguiente método a la clase Program.cs:
private static void ForEachTest()
{
   int[] numbers = { 1, 2, 3, 4, 5 };
   foreach (int i in numbers)
   {
    Console.WriteLine(“El valor de i = {0}”, i);
   }
}
4. Seleccione Depurar > Iniciar sin depurar o presione Ctrl+F5.
5. Aparece la salida del programa en una ventana de comandos.
6. Presione una tecla para cerrar la ventana de comandos.
PAUSA. Deje el proyecto abierto para usarlo en el siguiente ejercicio.
En este ejercicio, el bucle recorre en iteración secuencialmente todos los elementos de la
colección de números enteros definida y los va mostrando en la ventana de comandos. Este
método genera la misma salida que el método ForTest.

Conceptos de la recursión
La recursión es una técnica de programación que hace que un método se llame a sí
mismo para calcular un resultado.

La recursión y la iteración están relacionadas. Es posible escribir un método que genere los
mismos resultados con la recursión que con la iteración. En general, la naturaleza del problema
en sí ayuda a elegir entre una solución de iteración o recursión. Por ejemplo, una solución
recursiva es más elegante cuando se puede definir la solución de un problema en términos de
una versión más reducida del mismo problema.
Para entender mejor este concepto, tomemos el ejemplo de la operación factorial de las
matemáticas. La definición general recursiva de n factorial (escrito n!) es la siguiente:

n! =

{ 1 if n = 0,
(n − 1)! × n if n > 0.
Según esta definición, si el número es 0, su factorial es uno. Si el número es mayor que
cero, su factorial es el número multiplicado por el factorial del siguiente número menor. Por
Introducción a la programación | 23

ejemplo, podemos descomponer 3! así: 3! = 3 * 2! —> 3 * 2 * 1! —> 3 * 2 * 1 * 0! —> 3 * 2


* 1 * 1 —> 6.
El procedimiento siguiente permite crear un programa que presenta una solución recursiva a
un problema de factorial.

USO DEL MÉTODO RECURSIVO

PREPÁRESE. Para usar el método recursivo, realice las siguientes acciones:


1. Agregue un nuevo proyecto de aplicación de consola denominado RecursiveFactorial
a la solución Lesson01.
2. Agregue el siguiente código al método Main de la clase Program.cs:
Factorial(5);
3. Agregue el siguiente método a la clase Program.cs:
public static int Factorial(int n)
{
   if (n == 0)
   {
    return 1; //caso base
   }
   else
   {
    return n * Factorial(n - 1); //caso recursivo
   }
}
4. Seleccione Depurar > Iniciar sin depurar o presione Ctrl+F5.
5. Aparece la salida del programa en una ventana de comandos.
6. Presione una tecla para cerrar la ventana de comandos.
7. Modifique el método Main para pasar un valor diferente al método Factorial y observe
los resultados.
PAUSA. Deje el proyecto abierto para usarlo en el siguiente ejercicio.
Como se observa en el ejercicio anterior, una solución recursiva consta de dos partes
claramente diferenciadas:
• Caso base: Es la parte que especifica la condición de terminación y no vuelve a
llamar al método. El caso base en el método Factorial es n == 0. Si el algoritmo
LISTO PARA CERTIFICACIÓN recursivo no contiene un caso base, se crea una recursión infinita. Una recursión
¿Sabe identificar los infinita hará que se agote la memoria del equipo y se inicie la excepción System.
métodos adecuados para
StackOverflowException.
controlar la repetición?
1.3 • Caso recursivo: Es la parte que hace que el algoritmo avance hacia el caso base. El
caso recursivo en el método Factorial es la parte else, donde se llama al método otra
vez pero con un valor menor a medida que se avanza hacia el caso base.

■ Conceptos del control de excepciones

.NET Framework admite el control de excepciones estándar para generar y controlar los
errores en tiempo de ejecución. En esta sección, aprenderemos a usar las palabras clave try,
RESULTADO FINAL
catch y finally para controlar excepciones.
24 | Lección 1

Una excepción es una condición de error que ocurre durante la ejecución de un programa.
Cuando esto sucede, el motor de tiempo de ejecución crea un objeto que representa el error y
lo inicia. A no ser que se capture la excepción escribiendo el código de control de excepciones
adecuado, la ejecución del programa termina.
Por ejemplo, si se intenta dividir un entero por cero, se iniciará la excepción
DivideByZeroException. En .NET Framework, una excepción se representa mediante
un objeto de la clase System.Exception o una de sus clases derivadas. Hay clases de
excepciones predefinidas que representan muchas situaciones de error frecuentes, tales
como DivideByZeroException mencionada anteriormente. Si se va a diseñar una aplicación
que necesita iniciar excepciones específicas de esa aplicación, es preciso crear una clase
personalizada de excepciones derivada de la clase System.Exception.

Control de excepciones
Para controlar las excepciones, debe incluirse el código que las inicia en un bloque
try y el código que las captura, en un bloque catch.

El ejercicio siguiente muestra cómo usar un bloque try-catch para controlar una excepción.
El ejercicio usa el método File.OpenText para abrir un archivo de disco. Esta instrucción se
ejecutará perfectamente en situación normal, pero si falta el archivo (o el permiso para leerlo),
entonces se iniciará una excepción.

CONTROL DE EXCEPCIONES

PREPÁRESE. Para controlar las excepciones, realice los siguientes pasos:


1. Agregue un nuevo proyecto de aplicación de consola denominado HandlingExceptions
a la solución Lesson01.
2. Agregue el siguiente código al método Main de la clase Program.cs:
ExceptionTest();
3. Agregue el siguiente método a la clase Program.cs:
private static void ExceptionTest()
{
   StreamReader sr = null;
   try
   {
    sr = File.OpenText(@”c:\data.txt”);
    Console.WriteLine(sr.ReadToEnd());
   }
   catch (FileNotFoundException fnfe)
   {
    Console.WriteLine(fnfe.Message);
   }
   catch(Exception ex)
   {
    Console.WriteLine(ex.Message);
   }
}
Introducción a la programación | 25

4. Cree un archivo de texto (“data.txt”) mediante el Bloc de notas o Visual Studio en


la unidad C: Si lo desea, puede crearlo en una ubicación diferente, pero si lo hace,
recuerde que debe modificar la ubicación del archivo en el programa. Escriba texto en
TOME NOTA
* el archivo.
La clase StreamReader 5. Seleccione Depurar > Iniciar sin depurar o presione Ctrl+F5.
forma parte del espacio
de nombres System.IO. 6. El contenido del archivo de texto aparecerá en una ventana de comandos.
Al ejecutar este código, 7. Presione una tecla para cerrar la ventana de comandos.
será preciso agregar 8. Elimine el archivo data.txt y vuelva a ejecutar el programa. Esta vez, obtendrá una
una directiva using para
excepción FileNotFoundException y se mostrará el mensaje correspondiente en la
el espacio de nombres
System.IO. ventana de salida.
PAUSA. Deje el proyecto abierto para usarlo en el siguiente ejercicio.

En el método ExceptionTest, es incorrecto cambiar el orden de los dos bloques catch.


TOME NOTA
* Las excepciones más específicas deben situarse antes de las genéricas; de lo contrario, se
producen errores de compilación.

Para controlar una excepción, las instrucciones que pueden provocarlas se incluyen en un
bloque try. A continuación, se agregan bloques catch para controlar una o más excepciones.
En este ejemplo, además de controlar la excepción FileNotFoundException más específica,
también usamos un bloque catch con excepciones más genéricas para detectar todas las demás
excepciones. El nombre de excepción de un bloque catch debe encerrarse entre paréntesis. Las
instrucciones que se deben ejecutar cuando se captura una excepción deben ir entre llaves.
TOME NOTA
* La ejecución del código se detiene cuando se produce una excepción. El motor de tiempo
Un bloque try debe de ejecución busca una instrucción catch que coincida con el tipo de excepción. Si el primer
contar al menos con bloque catch no captura la excepción iniciada, el control pasa al siguiente bloque catch y así
un bloque catch o un sucesivamente. Si la excepción no se controla en el método, el motor de tiempo de ejecución
bloque finally asociado busca la instrucción catch en el código de llamada y continúa con el resto de la pila de
a él. llamadas.

Uso de Try-Catch-Finally
El bloque finally se usa en asociación con el bloque try. El bloque finally siempre se
ejecuta, independientemente de que se inicie una excepción. El bloque finally se usa
con frecuencia para escribir código de limpieza.

Cuando se produce una excepción, a menudo significa que no se han ejecutado algunas de
las líneas de código que vienen detrás de ella. Esto puede hacer que el programa quede en un
estado inestable o sucio. Para evitar estas situaciones, se puede usar la instrucción finally para
garantizar que siempre se ejecute el código de limpieza. Esto puede requerir cerrar conexiones,
liberar recursos o establecer variables en sus valores esperados. En el siguiente ejercicio
estudiaremos un bloque finally.

USO DE TRY-CATCH-FINALLY

PREPÁRESE. Para usar la instrucción try-catch-finally, realice este procedimiento:


1. Agregue un nuevo proyecto de aplicación de consola denominado trycatchfinally a la
solución Lesson01.
2. Agregue el siguiente código al método Main de la clase Program.cs:
TryCatchFinallyTest();
26 | Lección 1

3. Agregue el siguiente método a la clase Program.cs:


private static void TryCatchFinallyTest()
{
   StreamReader sr = null;
   try
   {
    sr = File.OpenText(“data.txt”);
    Console.WriteLine(sr.ReadToEnd());
   }
   catch (FileNotFoundException fnfe)
   {
    Console.WriteLine(fnfe.Message);
   }
   catch (Exception ex)
   {
    Console.WriteLine(ex.Message);
   }
   finally
   {
    if (sr != null)
    {
     sr.Close();
    }
   }
}
4. Cree un archivo de texto (“data.txt”) mediante el Bloc de notas o Visual Studio en
la unidad C: Si lo desea, puede crearlo en una ubicación diferente, pero si lo hace,
recuerde que debe modificar la ubicación del archivo en el programa. Escriba texto en
el archivo.
5. Seleccione Depurar > Iniciar sin depurar o presione Ctrl+F5.
6. El contenido del archivo de texto aparecerá en una ventana de comandos.
7. Presione una tecla para cerrar la ventana de comandos.
LISTO PARA CERTIFICACIÓN 8. Elimine el archivo data.txt y vuelva a ejecutar el programa. Esta vez, obtendrá una
¿Comprende cómo deben excepción FileNotFoundException y se mostrará el mensaje correspondiente en la
controlarse los errores en ventana de salida.
los programas?
En este ejercicio, el programa se asegura de que se cierre el objeto StreamReader y se
1.4 liberen los recursos cuando se complete la operación. El código del bloque finally se ejecuta,
independientemente de que se inicie una excepción.
RESUMEN DE CONOCIMIENTOS

En esta lección hemos aprendido lo siguiente:

• Un algoritmo es un conjunto de pasos ordenados y finitos para resolver un problema dado.
Resulta útil expresar un algoritmo como un diagrama de flujo o una tabla de decisión antes de
desarrollar un programa formal.
• El lenguaje de programación C# forma parte del entorno .NET Framework y saca partido de
la compatibilidad con el tiempo de ejecución y las bibliotecas de clases que este entorno
proporciona.
• Main es un método especial porque también sirve como punto de entrada a un programa.
Cuando el runtime ejecuta un programa, siempre empieza en el método Main.
• En C#, las variables son marcadores de posición que se usan para almacenar valores. Una
variable tiene un nombre y un tipo de datos. El tipo de datos de una variable determina qué
valor puede contener y qué tipo de operaciones pueden realizarse con ella.
Introducción a la programación | 27

• Los operadores son símbolos, tales como +, -, *, y /, que especifican qué operación se realizará
con los operandos antes de devolver un resultado.
• Las instrucciones if-else permiten que un programa realice una acción si la expresión de tipo
Boolean se evalúa en true y otra acción distinta si se evalúa en false.
• La instrucción switch permite bifurcaciones multidireccionales. En muchos casos, usar
instrucciones switch puede simplificar una combinación compleja de instrucciones if-else.
• C# tiene cuatro estructuras de control diferentes que permiten a los programas realizar tareas
repetitivas: el bucle while, el bucle do-while, el bucle for y el bucle foreach.
• Los bucles while y do-while ejecutan reiteradamente un bloque de instrucciones hasta que
una expresión concreta de tipo Boolean se evalúa en false. El bucle do-while comprueba la
condición que figura al final del bucle.
• El bucle for combina en un código más fácil de leer los tres elementos de iteración, que son:
la instrucción de inicialización, la condición de terminación y la instrucción de incremento/
decremento.
• El bucle foreach resulta útil para recorrer en iteración los elementos de una colección.
• La recursión es una técnica de programación que hace que un método se llame a sí mismo para
calcular un resultado.
• .NET Framework admite el control de excepciones estándar para generar y controlar los errores
en tiempo de ejecución. Para controlar las excepciones, debe incluirse el código que las inicia
en un bloque try y el código que las captura en un bloque catch.
• El bloque finally se usa en asociación con el bloque try. El bloque finally siempre se ejecuta,
independientemente de que se inicie una excepción. El bloque finally se usa con frecuencia
para escribir código de limpieza.

■ Evaluación de conocimientos
Rellene los espacios en blanco

Complete las oraciones siguientes escribiendo la palabra o palabras correctas en los


espacios en blanco proporcionados.
1. La instrucción selecciona para su ejecución una lista de instrucciones que
contiene una etiqueta asociada que corresponde al valor de una expresión.
2. El bucle comprueba la condición del final del bucle en lugar de la inicial.
3. El único operador que acepta tres argumentos es el operador .
4. El bucle es el modo más compacto de recorrer en iteración los elementos de una
colección.
5. En un equipo de 32 bits, una variable cuyo tipo de datos es int ocupa bytes de
memoria.
6. Para obtener acceso al primer elemento de una matriz, se usa un índice .
7. es una técnica de programación que hace que un método se llame a sí mismo
para calcular un resultado.
8. Las son campos de datos o variables locales cuyo valor no se puede modificar.
9. En algoritmos que comprenden grandes cantidades de condiciones, un(a) ofrece
un formato compacto y de fácil lectura para presentar estos algoritmos.
10. Un(a) es una representación gráfica de un algoritmo.
28 | Lección 1

Varias opciones

Rodee con un círculo la letra correspondiente a la mejor respuesta.


1. Escriba el siguiente fragmento de código:
int n = 20;
int d = n++ + 5;
¿Cuál será el valor de d después de que este fragmento de código se ejecute?
a. 25
b. 26
c. 27
d. 28
2. Escriba el siguiente fragmento de código:
private static void WhileTest()
{
  int i = 1;
  while (i < 5)
  {
   Console.WriteLine(“El valor de i = {0}”, i);
   i++;
  }
}
¿Cuántas veces se ejecutará el bucle while en este fragmento de código?
a. 0
b. 1
c. 4
d. 5
3. Escriba el siguiente fragmento de código:
int number1 = 10;
int number2 = 20;
if (number2 > number1)
Console.WriteLine(“number1”);
Console.WriteLine(“number2”);
¿Qué salida se mostrará después de que este fragmento de código se ejecute?
a. number1
b. number2
c. number1
number2
d. number2
number1
4. En una instrucción switch, si ninguna de las instrucciones case coincide con la expresión
switch, ¿a qué instrucción se transfiere el control?
a. break
b. continue
c. default
d. return
5. Debe escribir código que cierre una conexión a una base de datos y asegurarse de que
este código se ejecute siempre, independientemente de que se inicie una excepción.
¿Dónde debe escribir este código?
a. Dentro de un bloque try
b. Dentro de un bloque catch
c. Dentro de un bloque finally
d. Dentro del método Main
Introducción a la programación | 29

6. Debe almacenar valores que oscilan entre 0 y 255. También debe asegurarse de que su
programa minimice el uso de memoria. ¿Qué tipo de datos debe usar para almacenar estos
valores?
a. byte
b. char
c. short
d. int
7. Si un algoritmo recursivo no contiene un caso base, se crea una recursión infinita. Una
recursión infinita causará que su programa inicie una excepción. ¿Qué excepción iniciará
su programa en este caso?
a. OutOfMemoryException
b. StackOverflowException
c. DivideByZeroException
d. InvalidOperationException
8. Está aprendiendo a desarrollar algoritmos repetitivos en C#. Escribe el siguiente método:
private static void ForTest()
{
  for(int i = 1; i < 5;)
  {
   Console.WriteLine(“El valor de i = {0}”, i);
  }
}
¿Cuántas repeticiones realizará el bucle for en este código?
a. 0
b. 4
c. 5
d. Repeticiones infinitas
9. ¿Cuál de las siguientes características de C# debe usar para organizar el código y crear
tipos únicos a nivel global?
a. Ensamblado
b. Espacio de nombres
c. Clase
d. Tipo de datos
10. Escribe el siguiente fragmento de código:
int[] numbers = {1, 2, 3, 4};
int val = numbers[1];
También crea una variable de tipo RectangleHandler como esta:
RectangleHandler handler;
¿Cuál es el valor de la variable val después de que se ejecute este fragmento de código?
a. 1
b. 2
c. 3
d. 4
30 | Lección 1

■ Evaluación de competencias
Escenario 1-1: Conversión de una tabla de decisión en un programa C#
Está desarrollando una aplicación de facturación que calcula porcentajes de descuento basados
en la cantidad que se adquiere de un producto. La lógica para calcular descuentos aparece en
la siguiente tabla de decisión. Si debe escribir un método de C# que use la misma lógica para
calcular el descuento, ¿cómo escribiría dicho programa?

Cantidad < 10 S N N N
Cantidad < 50 S S N N
Cantidad < 100 S S S N
Descuento  5%  10%  15%  20%

Escenario 1-2: Conversión de un diagrama de flujo en un programa C#


Está desarrollando una biblioteca de funciones matemáticas. Primero desarrolla el siguiente
diagrama de flujo que describe el algoritmo para calcular el factorial de un número. Debe
escribir en C# un programa equivalente al diagrama de flujo. ¿Cómo se escribe tal programa?
Introducción a la programación | 31

■ Evaluación de aptitudes
Escenario 1-3: Control de excepciones
Está escribiendo código para una biblioteca de aritmética simple. Decide crear un método
denominado Divide que toma dos argumentos, x e y, y devuelve el valor de x/y. Debe capturar
todas las excepciones aritméticas que se inicien debidas a errores aritméticos, de conversión
o de conversiones de tipo de datos. También debe capturar todas las demás excepciones que
se inicien a partir del código. Para satisfacer este requisito, debe crear un código de control de
excepciones debidamente estructurado. ¿Cómo se escribe tal programa?

Escenario 1-4: Creación de un algoritmo recursivo


Está desarrollando una biblioteca de funciones de utilidad para su aplicación. Debe escribir un
método que toma un entero y cuenta el número de dígitos significativos que contiene. Debe
crear un programa recursivo para resolver este problema. ¿Cómo se escribe tal programa?
2 LECCIÓN
Introducción a
la programación
orientada a objetos
M AT R I Z D E C O N O C I M I E N T O S D E L A L E C C I Ó N

Conocimientos y conceptos Objetivo del examen MTA Número de objetivo del


examen MTA
Conceptos de los objetos Conceptos de los aspectos 2.1
fundamentales de las clases.
Conceptos de los valores Conceptos del almacenamiento y
y las referencias los tipos de datos de los equipos. 1.1

Conceptos de la encapsulación Conceptos de la encapsulación. 2.4
Conceptos de la herencia Conceptos de la herencia. 2.2
Conceptos del polimorfismo Conceptos del polimorfismo. 2.3
Conceptos de las interfaces Conceptos de la encapsulación. 2.4

TÉRMINOS CLAVE
clase espacio de nombres objetos
clases abstractas eventos polimorfismo
clases selladas herencia propiedades
constructores interfaces propiedades implementadas
método automáticamente
delegados
modificador de acceso signatura
descriptores de acceso
números estáticos tipo de referencia
encapsulación
tipo de valor

Usted es un desarrollador de software de la empresa Northwind Corporation. Trabaja


como parte de un equipo que desarrolla programas para resolver problemas empresariales
complejos. Todos los programas que escriba deben ser fáciles de entender y mantener
a largo plazo. Por lo tanto, debe desarrollarlos mediante técnicas que fomenten la
colaboración, la extensibilidad y la reutilización del código. Además, en lugar de
plantearse los programas principalmente como listas de métodos, prefiere tomar como
modelo conceptos empresariales reales, tales como los clientes, los productos, los
proveedores y las interacciones entre ellos.

32
Introducción a la programación orientada a objetos | 33

■ Conceptos de los objetos

La programación orientada a objetos es una técnica de programación que usa objetos. Los
objetos son estructuras de datos autocontenidos que consisten en propiedades, métodos
CONCLUSIÓN y eventos. Las propiedades especifican los datos que el objeto representa, los métodos
especifican el comportamiento del objeto y los eventos proporcionan comunicación entre
los objetos.

Pensamiento orientado a objetos

Conceptualmente, un objeto de software es similar a un objeto del mundo real.

Un modo excelente de iniciarse en el pensamiento orientado a objetos consiste en fijarse en


objetos del mundo real, tales como automóviles, teléfonos, reproductores de música, etc.
Observaremos que todos poseen estados y comportamientos. Por ejemplo, un automóvil no
solo presenta varios estados (tales como nombre de modelo, color, velocidad actual, nivel de
combustible), sino también diversos comportamientos (por ejemplo, acelerar, frenar, cambiar
de marcha). Asimismo, podemos observar que algunos objetos son simples y otros, complejos.
La mayoría de los objetos complejos (como los automóviles) se componen de objetos de
menor tamaño que, a su vez, presentan sus propios estados y comportamientos. También
es evidente que, aunque un automóvil es un objeto complejo, solamente es preciso conocer
algunos aspectos para poder interactuar con él. Por ejemplo, al conducir un automóvil basta
con invocar determinados comportamientos, como acelerar o frenar; no es preciso conocer los
miles de elementos internos que han de realizar sus respectivas funciones bajo el capó.
Conceptualmente, un objeto de software es similar a un objeto del mundo real. En el entorno
de software, un objeto almacena su estado en campos y expone su comportamiento mediante
métodos. Cuando se invoca un método para un objeto, se obtiene una funcionalidad claramente
definida sin necesidad de preocuparse por la complejidad interna del objeto o del método en sí.
Este concepto de ocultar la complejidad se denomina encapsulación y es una de las numerosas
características de la programación orientada a objetos que vamos a conocer mejor en esta
lección.
Conceptos de las clases

Una clase es la plantilla a partir de la cual se crean los objetos individuales.

En el mundo real, los objetos necesitan una plantilla que defina cómo construirlos. Todos
los objetos creados con la misma plantilla tienen el mismo aspecto y se comportan de forma
similar. Por ejemplo, pensemos en una marca y un modelo concretos de automóvil.
En el entorno de software, una clase es la plantilla a partir de la cual se crean los objetos
individuales. Un objeto también se denomina una instancia de una clase.

CREACIÓN DE UNA CLASE

PREPÁRESE. Antes de comenzar con el siguiente procedimiento, es preciso iniciar Microsoft


Visual Studio y abrir un nuevo proyecto de aplicación de consola denominado Lesson02. A
continuación, realice las siguientes tareas:
1. Agregue una nueva clase de Visual C# denominada Rectangle al proyecto.
2. Reemplace el código de la clase Rectangle por el siguiente código:
class Rectangle
{
  private double length;
34 | Lección 2

  private double width;


  public Rectangle(double l, double w)
  {
    length = l;
    width = w;
  }
  public double GetArea()
  {
    return length * width;
  }
}
3. Seleccione Compilar > Lesson02 para compilar el proyecto. Asegúrese de que no haya
ningún error.
PAUSA. Deje el proyecto abierto para usarlo en el siguiente ejercicio.
TOME NOTA
* Hemos creado una nueva clase de C# denominada Rectangle. Una nueva clase se define
Cada clase es una mediante la palabra clave class. En este caso, la clase Rectangle tiene dos campos de datos,
definición de un nuevo length (longitud) y width (ancho). Estos campos se definen mediante el modificador de acceso
tipo de datos. Por lo private. Un modificador de acceso especifica qué región del código tendrá acceso a un campo.
tanto, a veces también Por ejemplo, el modificador de acceso public no limita el acceso; en cambio el modificador de
usamos el término “tipo” acceso private lo restringe a aquella clase en la que se define el campo.
para referirnos a la
Esta clase también define un método, denominado GetArea. Sin embargo, ¿qué es un método
definición de clase.
exactamente?
CONCEPTOS DE LOS MÉTODOS

Un método es un bloque de código que contiene una serie de instrucciones.

En el mundo del software, un método define las acciones o las operaciones compatibles con
una clase. Para definir un método, se especifica el nivel de acceso, el tipo de valor devuelto, el
nombre del método y una lista opcional de parámetros entre paréntesis seguida por un bloque
de código entre llaves. Por ejemplo, en el ejemplo anterior, la clase Rectangle define un único
método denominado GetArea. Para GetArea, el nivel de acceso es public, el tipo de valor
devuelto es double, el nombre del método es GetArea, la lista de parámetros está vacía y el
TOME NOTA
* bloque de código es una sola instrucción return.
El nombre de un
método, su lista de Un método puede devolver un valor al código de llamada. Si un método no está destinado a
parámetros y el orden de devolver ningún valor, su tipo de valor devuelto se especifica mediante la palabra clave void.
los tipos de datos de los El método debe usar una instrucción return para devolver un valor. La instrucción return
parámetros se reconocen termina la ejecución del método y devuelve el valor especificado en el código de llamada. El
colectivamente como la tipo de datos del valor devuelto por un método debe coincidir con el tipo de valor devuelto
signatura. La signatura especificado en la línea de declaración del método.
de un método debe ser Volviendo al ejemplo anterior, el tipo de valor devuelto del método GetArea es double, lo que
única en una clase. significa que el método GetArea debe devolver un valor de tipo double. El método GetArea
cumple este requisito devolviendo la expresión length * width, que es un valor de tipo double.
El código siguiente define un método InitFields que toma dos parámetros de tipo double y
devuelve un valor de tipo void:
public void InitFields(double l, double w)
{
  length = l;
  width = w;
}
Introducción a la programación orientada a objetos | 35

El método InitFields toma dos parámetros y usa sus valores para asignar respectivamente la
longitud y el ancho del campo de datos. Cuando el tipo de valor devuelto de un método es
void, se puede usar una instrucción return sin valor. Si no se usa una instrucción return, como
en el método InitFields, el método interrumpirá su ejecución cuando llegue al final del bloque
de código. Se puede usar el método InitFields para inicializar correctamente el valor de los
campos de datos, pero como veremos en la siguiente sección, los constructores ya ofrecen una
forma de inicializar una clase.
CONCEPTOS DE LOS CONSTRUCTORES

Los constructores se usan para inicializar los miembros de datos de un objeto.

Los constructores son métodos de una clase especial que se ejecutan cuando se crea una nueva
instancia de una clase. Los constructores se usan para inicializar los miembros de datos de
un objeto. Deben tener exactamente el mismo nombre que la clase y no tienen tipo de valor
devuelto. Se pueden definir varios constructores para una clase, cada uno con una signatura
única.
Un constructor que no toma ningún argumento se denomina constructor predeterminado.
Si se define una clase sin ningún constructor, se genera automáticamente un constructor
predeterminado invisible que no hace absolutamente nada.
A menudo resulta útil disponer de constructores adicionales que ofrezcan más formas de
inicializar un objeto. La clase Rectangle definida anteriormente es solo una de las formas de
crear e inicializar su objeto: llamar al constructor que acepta dos parámetros, ambos del tipo
de datos predeterminado.
CREACIÓN DE OBJETOS

Los objetos se crean a partir de las plantillas definidas por las clases.

CREACIÓN DE UN OBJETO

PREPÁRESE. Para esta actividad, use el proyecto de aplicación de consola (Lesson02) que
creó en el ejercicio anterior. A continuación, siga este procedimiento:
1. Modifique el código de la clase Program de manera que se ajuste a lo siguiente:
class Program
{
  static void Main(string[] args)
  {
    Rectangle rect = new Rectangle(10.0, 20.0);
    double area = rect.GetArea();
    Console.WriteLine(“Área del rectángulo: {0}”
     area);
  }
}
2. Seleccione Depurar > Iniciar sin depurar. Aparecerá una ventana de consola que
mostrará el área del rectángulo.
3. GUARDE el proyecto.
PAUSA. Deje el proyecto abierto para usarlo en el siguiente ejercicio.
La clase Rectangle proporciona una sola manera de construir una instancia de la clase: llamar
a un constructor con dos argumentos del tipo de datos double. En este caso, creamos un objeto
mediante la palabra clave new seguida de la llamada al constructor de la clase apropiada.
36 | Lección 2

Cuando se ejecuta el código, se crea un objeto del tipo Rectangle en la memoria del montón.
TOME NOTA
* Se almacena una referencia a esta memoria en la variable rect. A su vez, la variable rect
Las clases y los objetos se almacena en la pila. Más adelante en este bloque de código, puede usar rect para hacer
son diferentes. Una clase referencia al objeto recién creado y manipularlo.
define la plantilla de un
objeto, pero no es un Mediante la referencia al objeto, es posible obtener acceso a los miembros de la clase. Por
objeto en sí misma. Por ejemplo, el código llama al método GetArea para el objeto y el valor devuelto por el método
otro lado, un objeto es se almacena en la variable area. Los campos de datos, length y width, del objeto rect no están
una instancia concreta de accesibles aquí, porque se han marcado como privado (private) en la definición de clase.
una clase pero no es una
clase propiamente dicha. CONCEPTOS DE LAS PROPIEDADES
Las propiedades permiten obtener acceso a los datos de la clase de una manera segura y
flexible.
TOME NOTA
* Las propiedades son miembros de una clase a los que se puede obtener acceso, de forma
Con frecuencia
nos referimos a las similar a los campos de datos, pero que contienen código, como un método. Las propiedades
propiedades con el se suelen usar para exponer los campos de datos de una clase de una manera más controlada.
término “campos Por ejemplo, un campo privado se puede exponer mediante una propiedad pública, pero no es
inteligentes” porque necesario usar las propiedades de esta forma.
pueden incluir código que Una propiedad posee dos descriptores de acceso: get y set. El descriptor de acceso get se usa
compruebe la coherencia para devolver el valor de propiedad; el descriptor de acceso set se usa para asignar un valor
o validez de los datos. nuevo a la propiedad. Una propiedad se suele definir como pública (public) y, por convención,
siempre tiene un nombre que comienza por una letra mayúscula. En cambio, la convención
para nombrar los campos de datos privados es comenzar con una letra minúscula.

CREACIÓN DE PROPIEDADES

USE el proyecto guardado en el ejercicio anterior. A continuación, complete las tareas


siguientes:
1. Modifique el código de la clase Rectangle como se muestra a continuación. En este
código, se retira el constructor y se insertan dos propiedades:
class Rectangle
{
  private double length;
  private double width;
  public double Length
  {
    get
    {
      return length;
    }
    set
    {
      if ( value > 0.0)
      length = value;
    }
  }
  public double Width
  {
     get
     {
       return width;
     }
Introducción a la programación orientada a objetos | 37

     set
     {
      if ( value > 0.0)
       width = value;
    }
  }
  public double GetArea()
  {
    return length * width;
  }
}
2. Después, modifique el código de la clase Program de manera que se ajuste a lo
siguiente:
class Program
{
static void Main(string[] args)
{
   Rectangle rect = new Rectangle();
   rect.Length = 10.0;
   rect.Width = 20.0;
   double area = rect.GetArea();
   Console.WriteLine(
    “Área del rectángulo: {0}”, area);
   }
}
3. Seleccione Depurar > Iniciar sin depurar. Aparecerá una ventana de consola que
mostrará el área del rectángulo.
4. GUARDE el proyecto.
PAUSA. Deje el proyecto abierto para usarlo en el siguiente ejercicio.
TOME NOTA
* En este ejercicio, hemos modificado la clase Rectangle para introducir dos propiedades,
Según la forma de Length y Width (que representan la longitud y el ancho, respectivamente). Las propiedades
programación habitual, se suelen definir mediante un modificador de acceso público. En el código de la propiedad
todos los campos de Length, el descriptor de acceso get se limita a devolver el valor de la longitud del campo de
datos de una clase datos. Sin embargo, el descriptor de acceso set comprueba cuál es el valor asignado (mediante
deben declararse como la palabra clave value) a la propiedad y modifica la longitud del campo de datos únicamente
privados y el acceso a si el valor es positivo. Los campos privados length y width también se denominan campos de
estos campos privados respaldo para las propiedades que los exponen, respectivamente.
se realiza mediante Por otra parte, la clase Rectangle no declara ningún constructor explícito. En este caso, los
propiedades públicas que usuarios de la clase (el método Main) deben usar el constructor predeterminado y dependen de
comprueban la validez de las propiedades para inicializar los datos de la clase.
los valores de datos.
El método Main usa las propiedades Length y Width para configurar los datos del objeto rect.
Cualquier intento de establecer Length o Width en un valor negativo se omitirá, en cuyo caso
los campos de datos seguirán teniendo su valor original, 0.
Al definir propiedades, puede excluir el descriptor de acceso get o set. Cuando no se incluye
un descriptor de acceso set, no se proporciona ningún modo para establecer el valor de la
propiedad. En consecuencia, la propiedad será de solo lectura. Por otro lado, si no se incluye
el descriptor de acceso get, no se proporciona un modo de obtener el valor de la propiedad. Así
pues, la propiedad será de solo escritura.
CONCEPTOS DE LAS PROPIEDADES DE IMPLEMENTACIÓN AUTOMÁTICA

Las propiedades de implementación automática simplifican las declaraciones de


propiedades.
38 | Lección 2

C# incluye propiedades de implementación automática a partir de la versión 3, a fin de


simplificar la declaración de propiedades cuando no se especifica ninguna lógica adicional
en los descriptores de acceso get y set. Por ejemplo, sin los controles de validación, las
propiedades Length y Width se definen como sigue:
private double length;
private double width;
public double Length
{
   get
   {
    return length;
   }
   set
   {
    length = value;
   }
   }
  public double Width
  {
     get
     {
      return width;
     }
     set
     {
      width = value;
     }
  }
En comparación, con las propiedades de implementación automática de C#, la sintaxis
simplificada para declarar propiedades sería:
public double Length { get; set; }
public double Width { get; set; }
En este caso, los campos de respaldo de las propiedades se definen en segundo plano y no se
puede obtener acceso a ellos directamente desde el código.
El uso de propiedades de implementación automática con constructores predeterminados
también permite simplificar la creación y la inicialización de objetos. Por ejemplo, ahora es
posible crear e inicializar un objeto como sigue:
static void Main(string[] args)
{
  Rectangle rect = new Rectangle
    { Length = 10.0, Width = 20.0 };
  Console.WriteLine(
    “Área del rectángulo: {0}”, rect.GetArea());
}

USO DE LA PALABRA CLAVE THIS

La palabra clave this se puede usar para obtener acceso a los miembros desde el interior
de los constructores, los métodos de instancia y los descriptores de acceso de las
propiedades de instancia.
Introducción a la programación orientada a objetos | 39

La palabra clave this es una referencia a la instancia actual de la clase. Puede usar la palabra
clave this para referirse a cualquier miembro del objeto actual. Por ejemplo, previamente en
este capítulo, hemos escrito clase Rectangle como sigue:
class Rectangle
{
  private double length;
  private double width;
  public Rectangle(double l, double w)
  {
    length = l;
    width = w;
  }
  public double GetArea()
  {
    return length * width;
  }
}
Sin embargo, podríamos escribirla así:
class Rectangle
{
  private double length;
  private double width;
  public Rectangle(double l, double w)
  {
    this.length = l;
    this.width = w;
  }
  public double GetArea()
  {
    return this.length * this.width;
  }
}
Como puede observarse, en el segundo ejemplo hemos usado la palabra clave this dentro del
constructor y del método GetArea para referirnos a los campos de datos del objeto actual de la
clase Rectangle. Aunque no era necesario recurrir a la palabra clave this en este caso, su uso
aporta mayor flexibilidad para nombrar los parámetros del método. Por ejemplo, podríamos
definir el constructor de la siguiente manera:
TOME NOTA
*
En C#, los caracteres   public Rectangle(double length, double width)
// se usan para agregar   {
al código comentarios      // los nombres de parámetros length y width
de una sola línea. El      // prevalecen sobre los miembros de clase length y
compilador pasa por alto
     // width en este ámbito
todo el texto que aparece
detrás de los caracteres //.      this.length = length;
Los comentarios de varias      this.width = width;
líneas comienzan con los   }
caracteres /* y terminan
con los caracteres */. Dentro del ámbito de la definición del constructor Rectangle, los nombres length y width se
refieren ahora a los parámetros que se pasan. Los parámetros prevalecen sobre los nombres de
los campos de datos y solamente es posible obtener acceso a estos últimos mediante la palabra
clave this.
40 | Lección 2

CONCEPTOS DE LOS DELEGADOS

Los delegados son tipos especiales que se usan para encapsular un método con una
signatura específica.

Los delegados son objetos especiales que pueden conservar una referencia a un método
con una signatura específica. Un delegado se define mediante la palabra clave delegate. Por
ejemplo, puede definir un delegado de la siguiente manera:
public delegate void RectangleHandler(Rectangle rect);
La definición del delegado especifica la signatura del método cuya referencia puede estar
contenida en un objeto delegado. Por ejemplo, en el código anterior, definimos un delegado
RectangleHandler que puede contener referencias a un método que devuelve void y acepta un
solo parámetro del tipo Rectangle.
Así pues, si tenemos un método con una signatura similar, será un candidato idóneo para
asignárselo a una instancia del delegado. Por ejemplo:
public void DisplayArea(Rectangle rect)
{
  Console.WriteLine(rect.GetArea());
}
El tipo delegado puede usarse para declarar una variable que puede hacer referencia a
cualquier método que tenga la misma signatura que el delegado. Por ejemplo, podemos
escribir:
RectangleHandler handler;
A continuación, podemos asignar el método al delegado mediante la siguiente sintaxis:
handler += new RectangleHandler(DisplayArea);
Como alternativa, podemos usar la sintaxis abreviada que se muestra a continuación:
handler += DisplayArea;
Observe que la sintaxis usa la operación de adición. Esto significa que es posible asociar más
de un método (de signatura compatible), con lo que se crea una lista de invocaciones de uno o
más métodos.
Por último, puede realizarse una llamada a un delegado mediante una sintaxis de llamada al
método, así:
Rectangle rect = new Rectangle (10, 20);
handler(rect);
Cuando se llama al delegado de esta manera, invoca todos los métodos de su lista de
invocaciones. En este ejemplo concreto, el objeto handler se refiere a un solo método
DisplayArea y, por lo tanto, el método DisplayArea se invocará con el objeto rect como
parámetro.
Entre otras muchas aplicaciones, los delegados constituyen la base de las declaraciones de
eventos, como se explica en la siguiente sección.
CONCEPTOS DE LOS EVENTOS

Los eventos son un medio para que una clase notifique a otras clases u objetos que ha
sucedido algo de interés. La clase que envía la notificación se denomina publicador del
evento. La clase que recibe la notificación se denomina suscriptor del evento.

Es fácil comprender los eventos en el contexto de una interfaz gráfica de usuario (GUI).
Por ejemplo, cuando un usuario hace clic en un botón, se produce el evento Click. Varios
elementos de la interfaz de usuario pueden suscribirse a este evento y cambiar su estado visual
Introducción a la programación orientada a objetos | 41

en consecuencia (por ejemplo, algunos controles se habilitan o deshabilitan). En este tipo


de comunicación de evento, los publicadores de eventos no necesitan saber qué objetos se
suscriben a los eventos generados.
Pero los eventos no se limitan a la programación de GUI. De hecho, desempeñan un rol
importante en las bibliotecas de clases de .NET Framework, pues constituyen un medio
para que los objetos indiquen cualquier cambio en su estado. Se trabaja con eventos en
prácticamente todos los programas.
Al definir eventos, en general se requieren dos elementos de información:
• un delegado que conecta el evento con su método o métodos controladores y
• una clase que contiene los datos del evento. Esta clase suele derivarse de la clase
EventArgs.
Para definir un evento, puede usar un delegado personalizado. Sin embargo, en la mayoría
de los casos, si el evento no contiene datos específicos del evento, basta con usar el delegado
predefinido EventHandler. El delegado EventHandler se define como sigue:
public delegate void EventHandler(Object sender, EventArgs e);
Aquí, el parámetro sender es una referencia al objeto que genera el evento y el parámetro e es
una referencia a un objeto de datos de evento que no contiene datos de evento.
La clase EventArgs se usa con eventos que, cuando se generan, no pasan ninguna información
relacionada con el evento a un controlador de eventos. Si el controlador de eventos requiere
información relacionada con el evento, la aplicación debe derivar una clase de la clase
EventArgs para que contenga los datos relacionados con el evento.

PUBLICACIÓN DE EVENTOS Y SUSCRIPCIÓN A ELLOS

USE el proyecto guardado en el ejercicio anterior para llevar a cabo las siguientes tareas:
1. Modifique el código de la clase Rectangle como se muestra a continuación:
class Rectangle
{
  public event EventHandler Changed;
  private double length;
  public double Length
  {
     get
     {
      return length;
TOME NOTA
*      }
El campo EventArgs.
Empty representa un      set
evento sin datos de      {
evento. Este campo       length = value;
equivale a tener una       Changed(this, EventArgs.Empty);
instancia de solo lectura      }
de la clase EventArgs.
  }
}
2. Modifique el código de la clase Program de manera que se ajuste a lo siguiente:
class Program
{
  static void Main(string[] args)
  {
     Rectangle r = new Rectangle();
42 | Lección 2

     r.Changed += new EventHandler(r_Changed);


     r.Length = 10;
  }
  static void r_Changed(object sender, EventArgs e)
  {
     Rectangle r = (Rectangle)sender;
TOME NOTA
*      Console.WriteLine(
El código del método        “Valor cambiado: Longitud = {0}”,
r_Changed usa un        r.Length);
operador de conversión
  }
que convierte un tipo de
datos de objeto en el tipo }
de datos Rectangle. La 3. Seleccione Depurar > Iniciar sin depurar. Aparecerá una ventana de consola que
conversión se explica más mostrará que el valor de la propiedad Length ha cambiado.
adelante en esta lección,
4. GUARDE el proyecto.
en la sección titulada
“Conversión entre tipos”. PAUSA. Deje el proyecto abierto para usarlo en el siguiente ejercicio.
En el ejemplo que acabamos de completar, la clase Rectangle define un evento Changed que
se invoca cuando se cambia la propiedad Length del objeto Rectangle. El delegado del evento
Changed es de tipo EventHandler. En la clase Rectangle, el evento Changed se invoca cuando
se llama al descriptor de acceso set de la propiedad Length.
La suscripción al evento Changed se lleva a cabo dentro del método Main, al adjuntar el
método r_Changed como controlador del evento mediante el siguiente código:
r.Changed += new EventHandler(r_Changed);
La signatura del método r_Changed coincide con los requisitos del delegado EventHandler. El
método r_Changed se invoca tan pronto como se establece el valor de la propiedad Length en
el método Main.
En el código anterior se usa el operador += en lugar del operador de asignación simple (=)
para adjuntar el controlador de eventos. Con el uso del operador += nos aseguramos de que
el controlador de eventos se agregue a una lista de controladores de eventos que ya están
adjuntos al evento. Esta técnica permite disponer de varios controladores de eventos que
pueden responder a un evento. Si se usa el operador de asignación (=) para asignar el nuevo
controlador de eventos, invalidará todos los controladores de eventos existentes que se
adjunten al evento y, en consecuencia, el controlador de eventos recién adjuntado será el único
que se activará al invocar el evento.

CONCEPTOS DE LOS ESPACIOS DE NOMBRES

Un espacio de nombres permite organizar el código y crear nombres de clase únicos.

Un espacio de nombres es un elemento del lenguaje que permite organizar el código y crear
nombres de clase únicos a nivel global. Supongamos que creamos una clase denominada
Widget. Es probable que exista alguna otra empresa que distribuya código que contenga
una clase denominada Widget. En ese caso, ¿cómo controlaremos la ambigüedad en los
nombres? La solución consiste en organizar el código en el seno de un espacio de nombres.
La convención común consiste en usar el nombre de la empresa en el espacio de nombres. Por
ejemplo, podríamos escribir lo siguiente:
namespace CompanyA
{
  public class Widget { … }
}
Introducción a la programación orientada a objetos | 43

y
namespace CompanyB
{
  public class Widget { … }
}
En este caso, podemos hacer referencia a la clase del espacio de nombres CompanyA de
manera única mediante su nombre de clase completo: CompanyA.Widget. Por su parte, la otra
clase Widget puede identificarse inequívocamente mediante CompanyB.Widget.
.NET Framework usa espacios de nombres de forma generalizada para organizar todas sus
clases. Por ejemplo, el espacio de nombres System agrupa todas las clases fundamentales. El
espacio de nombres System.Data organiza las clases para el acceso de datos. De igual forma,
el espacio de nombres System.Web se usa para las clases relacionadas con la Web.
Es evidente que con el uso de espacios de nombres podríamos terminar usando nombres de
clase completos excesivamente largos, lo que daría lugar a programas demasiado detallados y
obligaría a mecanografiar mucho texto. C# soluciona este inconveniente mediante la directiva
using. La directiva using se puede usar en la parte superior del archivo de clase, así:
using System.Text;
Una vez que hemos incluido la directiva using para un espacio de nombres, no es preciso usar
el nombre completo de las clases de ese espacio de nombres en el archivo.

CONCEPTOS DE LOS MIEMBROS ESTÁTICOS

Los miembros estáticos pertenecen a la propia clase, en lugar de a objetos individuales.

Todos los miembros de la clase que hemos descrito hasta ahora en esta sección (por ejemplo,
campos de datos, métodos y propiedades) funcionan con objetos individuales. Se los denomina
miembros de instancia, porque solo se pueden usar después de haber creado una instancia
de una clase. En cambio, la clave static se usa para declarar miembros que no pertenecen a
objetos individuales, sino a una clase en sí. Los miembros de clase de este tipo se denominan
miembros estáticos. Un ejemplo común de un miembro estático es el método Main que hemos
mencionado ya y que actúa como punto de entrada al programa.

CREACIÓN DE MIEMBROS ESTÁTICOS

USE el proyecto guardado en el ejercicio anterior. A continuación, realice los siguientes pasos:
1. Modifique el código de la clase Rectangle como se muestra a continuación:
class Rectangle
{
  public static string ShapeName
  {
    get { return “Rectángulo”; }
  }
  public double Length { get; set; }
  public double Width { get; set; }
  public double GetArea()
  {
    return this.Length * this.Width;
  }
}
44 | Lección 2

2. Modifique el código de la clase Program de manera que se ajuste a lo siguiente:


class Program
{
  static void Main(string[] args)
  {
     Rectangle rect = new Rectangle
      { Length = 10.0, Width = 20.0 };
     Console.WriteLine(“Nombre de la forma: {0}, Area: {1}”,
      Rectangle.ShapeName,
      rect.GetArea());
  }
}
3. Seleccione Depurar > Iniciar sin depurar. Aparecerá una ventana de consola que
mostrará el nombre y el área de la forma.
4. GUARDE el proyecto.
PAUSA. Deje el proyecto abierto para usarlo en el siguiente ejercicio.
Cuando se crea una instancia de una clase, se crea una copia independiente para cada campo
de instancia, pero solo hay una copia de un campo estático que se comparte entre todas las
instancias.
LISTO PARA CERTIFICACIÓN No se puede hacer referencia a un miembro estático a través de un objeto de instancia. En
¿Comprende los conceptos cambio, se hace referencia a un miembro estático a través del nombre de clase (por ejemplo,
fundamentales de las clases? Rectangle.ShapeName en el ejercicio anterior). Tenga en cuenta que no se puede usar la
2.1 referencia de palabra clave this con un método o propiedad static (estático) debido a que la
palabra clave this solo se puede usar para obtener acceso a objetos de instancia.

■ Conceptos de los valores y las referencias

Un tipo de valor almacena directamente un valor, mientras que un tipo de referencia solo
CONCLUSIÓN almacena una referencia al valor propiamente dicho.

Un tipo de valor almacena datos directamente en su memoria. Por su parte, los tipos
de referencia, solo almacenan una referencia a una ubicación de memoria; es decir, los
verdaderos datos se almacenan en la ubicación de memoria a la que se hace referencia. La
mayoría de los tipos de datos elementales integrados (tales como bool, int, char, double, etc.)
son tipos de valor. Los tipos de datos definidos por el usuario creados mediante la palabra
clave struct son también tipos de valor. Los tipos de referencia son aquellos creados mediante
las palabras clave object, string, interface, delegate y class.
Conceptos de los structs

La palabra clave struct se usa para crear tipos definidos por el usuario que consisten en
pequeños grupos de campos relacionados. Los structs son tipos de valor, a diferencia de
las clases, que son tipos de referencia.

Los structs se definen mediante el uso de la palabra clave struct, como se muestra a
continuación:
public struct Point
{
  public double X, Y;
}
Los structs pueden contener casi todos los elementos que pueden contener las clases, tales
como constructores, métodos, propiedades, etc. Sin embargo, como aprenderemos en la
Introducción a la programación orientada a objetos | 45

sección siguiente, los structs son tipos de valor, mientras que las clases son tipos de referencia.
TOME NOTA
* A diferencia de una clase, un struct no puede heredar de otra clase o de otro struct.
Los structs se usan
principalmente para crear
tipos simples. Si observa Conceptos de la asignación de memoria
que está creando un
struct muy complejo, es
conveniente estudiar la Después de especificar un valor o texto en una celda, se puede modificar de diversas
posibilidad de usar una formas. En particular, se puede eliminar el contenido por completo, especificar otro valor
clase en su lugar. distinto que sustituya al que había previamente o modificar la información especificada.

Una manera excelente de entender la diferencia entre los tipos de valor y los tipos de
referencia consiste en visualizar cómo se representa cada uno de ellos en la memoria. En la
figura 2-1 se muestra cómo se crean los tipos de valor en la memoria. Al crear una variable
de tipo int, por ejemplo, se crea una ubicación de memoria con nombre que se puede usar
para almacenar un valor de tipo int. Inicialmente, si no se asigna explícitamente un valor, se
almacena el valor predeterminado del tipo de datos (para int, el valor predeterminado es 0) en
la ubicación de memoria. Luego, cuando se realiza una asignación, la dirección de memoria
identificada por el nombre de la variable se actualiza con el nuevo valor (10 en el caso de la
asignación de la figura 2-1).

Figura 2-1
Visualización de un tipo de
valor en la memoria

Ahora, vamos a fijarnos en la figura 2-2, que muestra un tipo de referencia; en concreto,
el tipo de datos string. Cuando se crea una variable de tipo string, se crea una ubicación de
memoria que se identifica con este nombre. Sin embargo, esta ubicación de memoria no estará
ocupada por el contenido de la cadena. En cambio, esta variable almacenará la dirección de
memoria (una referencia) del lugar donde realmente se almacena la cadena.

Figura 2-2
Visualización de un tipo de
referencia en la memoria

Inicialmente, mientras no se haya asignado ningún valor, la variable tendrá el valor null (una
referencia null; es decir, esta variable no hará referencia a una dirección de memoria válida).
Posteriormente, en la instrucción siguiente, cuando escribamos:
name = “Northwind”;
se creará el valor de tipo string “Northwind” en una ubicación de memoria concreta (para
simplificar, supongamos que la dirección de memoria es m100) y esta dirección de memoria
se almacenará en el nombre de la variable. Más tarde, cuando llegue el momento de recuperar
el valor del nombre de la variable, el runtime sabrá que su contenido no está almacenado en la
variable en sí, sino en la ubicación de memoria a la que esta variable señala.
46 | Lección 2

COPIA DE TIPOS DE VALOR Y DE REFERENCIA

USE el proyecto guardado en el ejercicio anterior para completar los pasos siguientes:
1. Agregue el código siguiente después de la definición de la clase Rectangle para crear
el struct Point:
struct Point
{
  public double X, Y;
}
2. Modifique el código del método Main como se muestra a continuación:
TOME NOTA
*
Es posible crear un struct static void Main(string[] args)
sin usar el operador {
new. Basta con escribir   Point p1 = new Point();
Point p1; para crear una
  p1.X = 10;
variable de tipo struct.
  p1.Y = 20;
  Point p2 = p1;
  p2.X = 100;
  Console.WriteLine(“p1.X = {0}”, p1.X);
  Rectangle rect1 = new Rectangle
    { Length = 10.0, Width = 20.0 };
  Rectangle rect2 = rect1;
  rect2.Length = 100.0;
  Console.WriteLine(“rect1.Length = {0}”,
    rect1.Length);
TOME NOTA
* }
Cuando se copia una
3. Seleccione Depurar > Iniciar sin depurar. Aparecerá una ventana de consola que
variable de tipo de
mostrará los valores de p1.X y rect1.Length.
referencia en otra variable
del mismo tipo, solo se 4. GUARDE el proyecto.
copian las referencias. En
consecuencia, después de
PAUSA. Deje el proyecto abierto para usarlo en el siguiente ejercicio.
la copia, ambas variables Aquí, la primera parte del programa crea una copia del tipo de valor Point y la segunda mitad
señalarán al mismo crea una copia del tipo de referencia Rectangle.
objeto.
Comenzaremos por analizar cómo se realiza la copia de un tipo de valor. Para empezar,
cuando se ejecuta la instrucción siguiente, se crea una nueva variable p2 en la memoria, cuyo
contenido se copia de la variable p1:
Point p2 = p1;
Después de ejecutar esta instrucción, se crea la variable p2 y se copia el contenido de
la variable p1 en la variable p2. Tanto p1 como p2 tienen su propio conjunto de valores
disponibles en sus ubicaciones de memoria respectivas. Así pues, cuando se ejecuta la
instrucción siguiente:
p2.X = 100;
solo afecta al valor de X correspondiente a la ubicación de memoria de la variable p2. El valor
de X para la variable p1 permanece invariable.
Introducción a la programación orientada a objetos | 47

Ahora, analizaremos cómo funciona la copia entre tipos de referencia. En este caso, cuando se
ejecuta la instrucción siguiente, se crea una nueva variable rect2 y, al igual que antes, se copia
el contenido de rect1 en la ubicación de memoria de rect2:
Rectangle rect2 = rect1;
Sin embargo, como la clase Rectangle es un tipo de referencia, en realidad el contenido
de la variable rect1 es una referencia a la ubicación de memoria que contiene un objeto
Rectangle. Así pues, después de la inicialización anterior, tanto rect1 como rect2 señalan a la
misma ubicación de memoria y, a su vez, al mismo objeto Rectangle. Es decir, solo existe un
objeto rectangle en la memoria y tanto rect1 como rect2 hacen referencia a él. La siguiente
instrucción modifica la longitud (Length) del objeto Rectangle:
rect2.Length = 100.0;
Esta instrucción hace referencia a la ubicación de memoria a la que señala rect2 (que resulta
ser la misma ubicación de memoria a la que señala rect1) y modifica el valor de Length del
objeto Rectangle. Ahora, si intentamos hacer referencia a la misma ubicación de memoria
LISTO PARA CERTIFICACIÓN mediante el objeto rect1, obtendremos el objeto modificado y el código siguiente mostrará el
¿Comprende los tipos valor “rect1.Length = 100”:
de datos y la asignación
de memoria? Console.WriteLine(“rect1.Length = {0}”,
1.1   rect1.Length);

✚ MÁS INFORMACIÓN
A los objetos siempre se les asigna memoria del montón. El montón es la parte de la memoria
disponible para la asignación dinámica a un programa en tiempo de ejecución. En cambio, algunos
elementos de datos se pueden crear en la pila de ejecución o la pila de llamadas. Los elementos
creados en la pila son los parámetros de método y las variables locales declaradas dentro de un
método. La memoria de pila se reclama cuando la pila se desenreda (cuando se devuelve un método,
por ejemplo). El recolector de elementos no utilizados reclama automáticamente la memoria asignada
en el montón cuando los objetos dejan de estar en uso (es decir, cuando no hay otros objetos que
contengan una referencia a ellos).

■ Conceptos de la encapsulación

La encapsulación es un mecanismo que oculta información para facilitar el mantenimiento


CONCLUSIÓN y la comprensión del código.

La encapsulación es un mecanismo orientado a restringir el acceso a una clase o a miembros


de una clase para ocultar las decisiones de diseño que probablemente estén sujetas a cambios.
La encapsulación ofrece a los diseñadores de clases la flexibilidad necesaria para cambiar una
sección de código cuando es preciso sin tener que cambiar los demás elementos de código que
hacen uso de ese código. Además, al ocultar la información, se oculta la complejidad asociada
a ella. En consecuencia, gracias a la encapsulación es posible escribir un código más fácil de
comprender y mantener.
En los ejercicios anteriores, hemos visto cómo funciona la encapsulación al declarar los
miembros de datos como privados y al realizar la inicialización de los campos de datos
mediante un constructor. Dado que los miembros de datos están ocultos a los usuarios de la
clase, el desarrollador de la clase Rectangle puede cambiar los nombres de los campos de
datos sin necesidad de realizar cambios en el código de llamada.
Las propiedades ofrecen una forma excelente de encapsular los campos de datos junto a
la lógica que los acompaña. Además, los modificadores de acceso como private y public
permiten controlar el nivel de acceso de un miembro de clase o de la propia clase.
En esta sección, continuaremos aprendiendo sobre los modificadores de acceso y su
funcionamiento.
48 | Lección 2

Conceptos de los modificadores de acceso

TOME NOTA
* Los modificadores de acceso controlan dónde se puede usar un tipo o un miembro de un
Es importante usar el tipo.
nivel de acceso más
restrictivo que resulte Todos los tipos y miembros de tipos tienen un nivel de acceso que especifica en qué lugares
lógico para un miembro del código se pueden usar esa clase o sus miembros. El nivel de acceso se puede establecer
de un tipo. mediante uno de los modificadores de acceso especificados en la tabla 2-1.

Tabla 2-1
Modificadores de acceso

Modificador de acceso Descripción


public El acceso no está restringido.
private El acceso está restringido a la clase contenedora.
protected El acceso está restringido a la clase contenedora y a cualquier clase derivada directa o
indirectamente de la clase contenedora. (Conoceremos mejor las clases derivadas más
adelante en esta lección, en la sección titulada “Conceptos de la herencia”.)
internal El acceso está restringido al código del mismo ensamblado.
protected internal Combinación de los descriptores de acceso protected e internal; es decir, el acceso está
restringido al código del mismo ensamblado y exclusivamente a las clases derivadas de
otro ensamblado.

Cuando se compila el código C#, el código ejecutable de salida contenido en un archivo .dll o
.exe también se denomina ensamblado. Un ensamblado es una unidad de código ejecutable que
TOME NOTA
* se puede instalar y que puede tener versiones.

Los modificadores de acceso no se admiten en las declaraciones de espacios de nombres;


para ellos está implícito el acceso público. Las clases de nivel superior (declaradas en el
nivel directamente inferior al de un espacio de nombres) solamente pueden ser públicas
LISTO PARA CERTIFICACIÓN (public) o internas (internal). El modificador de acceso internal es el valor predeterminado
¿Comprende la de una clase cuando no se especifica ningún modificador de acceso. (Por ejemplo, la clase
encapsulación? Rectangle definida en el ejercicio anterior usa de forma predeterminada el acceso interno.) La
2.4 accesibilidad de una clase anidada no puede ser menos restrictiva que la accesibilidad de la
clase contenedora.

■ Conceptos de la herencia

La herencia es una característica de la programación orientada a objetos que permite


desarrollar una clase y después volver a usar ese código como base para clases nuevas
tantas veces como desee. La herencia permite crear nuevas clases que reutilizan, amplían
y modifican la funcionalidad definida en las clases existentes. La clase que hereda la
CONCLUSIÓN funcionalidad se denomina clase derivada, y aquella cuya funcionalidad se hereda se
denomina clase base. Una clase derivada hereda toda la funcionalidad de la clase base y
también puede definir funciones adicionales que la hacen diferente de la clase base.
Introducción a la programación orientada a objetos | 49

Supongamos que queremos crear un conjunto de clases que describa polígonos, como
TOME NOTA
* rectángulos o triángulos. Estas clases tendrán algunas propiedades comunes, tales como el
A diferencia de las clases, ancho y la longitud. Para este caso, puede crear una clase base Polygon con las propiedades
los structs no admiten la Width y Length; las clases derivadas Rectangle y Triangle heredarán estas propiedades a la vez
herencia. que proporcionarán su propia funcionalidad. En el siguiente ejercicio se explica este concepto
con mayor detalle.

CREACIÓN DE CLASES DERIVADAS

USE el proyecto guardado en el ejercicio anterior para llevar a cabo las siguientes acciones:
1. Agregue una nueva clase denominada Polygon como se muestra a continuación:
class Polygon
{
  public double Length { get; protected set; }
  public double Width { get; protected set; }
}
2. Modifique la clase Rectangle como se muestra a continuación:
class Rectangle: Polygon
{
  public Rectangle(double length, double width)
  {
     Length = length;
     Width = width;
  }
  public double GetArea()
  {
     return Width * Length;
  }
}

3. Ahora, modifique el código del método Main como se muestra a continuación:


static void Main(string[] args)
{
  Rectangle rect = new Rectangle(10, 20);
  Console.WriteLine(
   “Width={0}, Length={1}, Area = {2}”,
   rect.Width, rect.Length, rect.GetArea());
}

4. Seleccione Depurar > Iniciar sin depurar. Aparecerá una ventana de consola que
mostrará el ancho, la longitud y el área del rectángulo.
5. GUARDE el proyecto.
PAUSA. Deje el proyecto abierto para usarlo en el siguiente ejercicio.
Para definir una clase derivada, se escribe un signo de dos puntos después del nombre de la
clase derivada, seguido por el nombre de la clase base. En este caso, la clase Polygon es la
clase base de la clase Rectangle.
50 | Lección 2

Las propiedades Length y Width en la clase Polygon se declaran con un modificador de acceso
protegido para el descriptor de acceso set. Esto significa que el acceso al descriptor de acceso
set está disponible solamente dentro de la clase Polygon y sus clases derivadas. Podemos
obtener el valor de las propiedades Length y Width en el método Main, pero obtendremos un
error si intentamos asignar un valor a estas propiedades.
La clase Rectangle hereda todos los datos y comportamientos no privados de la clase Polygon.
Además, la clase Rectangle define una funcionalidad adicional (el método GetArea) que no
está disponible en la clase base.
Conceptos de las clases abstractas y selladas

Las clases abstractas proporcionan una definición común de una clase base que pueden
compartir varias clases derivadas. Las clases selladas, por su parte, proporcionan una
funcionalidad completa, pero no pueden usarse como clases base.

En el ejercicio anterior, hemos definido un método GetArea para la clase Rectangle.


Supongamos que queremos crear otra clase, Triangle, que es de tipo Polygon. Necesitaremos
un método GetArea para la clase Triangle que calcule el área de un triángulo.
A menudo, las clases base actúan como repositorios de funcionalidades comunes. En el caso
de Polygon, el polígono en sí no sabe calcular el área si no conoce el tipo de forma. Pero en
general, cabe esperar que todas las clases de tipo Polygon sepan calcular su propia área. Este
tipo de expectativas se pueden implementar en la clase base con la ayuda de la palabra clave
abstract.

CREACIÓN DE CLASES ABSTRACTAS


USE el proyecto guardado en el ejercicio anterior y realice los siguientes pasos.
1. Modifique la clase Polygon como se muestra a continuación:
abstract class Polygon
{
  public double Length { get; protected set; }
  public double Width { get; protected set; }
  abstract public double GetArea();
}
2. Modifique la clase Rectangle como se muestra a continuación:
class Rectangle: Polygon
{
  public Rectangle(double length, double width)
  {
     Length = length;
     Width = width;
  }
  public override double GetArea()
  {
     return Width * Length;
  }
}
3. Tenga en cuenta que no es necesaria ninguna modificación en el método Main.
4. Seleccione Depurar > Iniciar sin depurar. Aparecerá una ventana de consola que
mostrará el ancho, la longitud y el área del rectángulo.
5. GUARDE el proyecto.
PAUSA. Deje el proyecto abierto para usarlo en el siguiente ejercicio.
Introducción a la programación orientada a objetos | 51

Esta versión de la clase Polygon define un método denominado GetArea. El motivo principal
para incluir este método en la clase base es que ahora esta puede proporcionar una plantilla
común de funcionalidad para las clases derivadas. Pero, como ya hemos explicado, la clase
TOME NOTA
* base Polygon no dispone de información suficiente para calcular el área de la forma. Esta
No puede crear instancias situación se puede resolver marcando el método como abstracto. Un método abstracto
de una clase abstracta. proporciona una definición pero no ofrece ninguna implementación (el cuerpo del método).
Si cualquiera de los miembros de una clase es abstracto, la clase en sí debe marcarse como
abstracta. No se pueden crear instancias de una clase abstracta.
Las clases derivadas pueden proporcionar una implementación de una clase abstracta para
crear una clase concreta (una clase no abstracta). Las clases derivadas pueden ofrecer una
implementación de un método abstracto invalidándolo en una clase derivada. Por ejemplo,
la clase Rectangle invalida el método GetArea abstracto de la clase base y proporciona una
implementación completa. En consecuencia, la clase Rectangle ya no es una clase abstracta y
se pueden crear instancias de ella directamente.
Las clases selladas, por el contrario, se definen cuando la implementación ha finalizado y no
se desea que se herede ninguna clase. Es posible crear una clase sellada mediante la palabra
clave sealed, como en el ejemplo siguiente:
sealed class Rectangle: Polygon
{
  // aquí van los miembros de la clase
}
Puesto que Rectangle es una clase sellada, no se puede usar como clase base. También es
posible marcar los miembros de la clase seleccionada como sellados para evitar que se
invaliden en una clase derivada. Por ejemplo, podríamos escribir:
TOME NOTA
* sealed public override double GetArea()
C# no admite la herencia {
de más de una clase
base, lo que a menudo   return Width * Length;
se denomina herencia }
múltiple.
Esta declaración asegura que el método GetArea no se pueda invalidar en una clase derivada.

Herencia de la clase Object

La clase Object es la clase base última de todas las clases de .NET Framework.

Todas las clases de .NET Framework heredan directa o indirectamente de la clase Object. Por
ejemplo, al declarar la siguiente clase anteriormente en esta lección:
class Polygon
{
  public double Length { get; protected set; }
  public double Width { get; protected set; }
}
era funcionalmente equivalente a la siguiente declaración:
class Polygon: Object
{
  public double Length { get; protected set; }
  public double Width { get; protected set; }
}
52 | Lección 2

Sin embargo, no es obligatorio declarar la clase Polygon de esta última forma, pues la herencia
de la clase Object se da por supuesta implícitamente. Como parte de esta herencia, una clase
derivada puede invalidar los métodos de la clase Object. A continuación se muestran dos de
los métodos más comunes para hacerlo:
• Equals: Admite la comparación entre dos objetos y devuelve true si ambos tienen el
mismo valor.
• ToString: Devuelve una representación de tipo string de la clase. De forma
predeterminada, devuelve el nombre completo de la clase. A menudo, resulta útil invalidar
este método para que devuelva una representación de tipo string del estado actual del
objeto.
En el ejemplo siguiente se muestra cómo invalidar el método ToString de la clase Rectangle:
class Rectangle: Polygon
{
  public Rectangle(double length, double width)
  {
    Length = length;
     Width = width;
  }
  public override double GetArea()
  {
    return Width * Length;
  }
  public override string ToString()
  {
    return String.Format(
       “Width = {0}, Length = {1}”,
        Width, Length);
  }
}

Conversión entre tipos

En C#, el runtime permite convertir un objeto en cualquiera de sus tipos base.

Las clases derivadas tienen una relación de tipo “es un(a)” con su clase base. Por ejemplo,
podemos decir que el rectángulo (Rectangle) “es un” polígono (Polygon). Por lo tanto, en
este caso un objeto de la clase Rectangle posee en realidad dos tipos de datos: el objeto es un
rectángulo y también el objeto es un polígono.
En C#, el runtime permite convertir un objeto en su clase o en cualquiera de sus clases base.
Por ejemplo, podemos escribir:
Polygon p = new Rectangle(10, 20);
Aquí, se crea un nuevo objeto Rectangle y se convierte en su tipo base, Polygon. En C# no
se requiere ninguna sintaxis especial para hacer esto, porque la conversión en el tipo base se
considera una conversión segura.
También es posible efectuar la conversión en sentido inverso. Por ejemplo, podemos escribir:
Object o = new Rectangle(10, 20);

Introducción a la programación orientada a objetos | 53

Rectangle r = (Rectangle) o;
Aquí, primero se asigna un objeto Rectangle a una clase Object (la clase base última) y se
realiza la conversión inversa del objeto resultante en Rectangle. Cuando se produce esta última
asignación, se requiere una conversión explícita porque estamos convirtiendo un objeto más
general en uno menos general. El runtime comprueba si el valor de la variable o es compatible
con la clase Rectangle. Si, al realizar la ejecución, el valor de o no es compatible con la clase
Rectangle, el runtime iniciará la excepción System.InvalidCastException.

USO DEL OPERADOR IS


Para evitar errores en tiempo de ejecución como la excepción InvalidCastException, se puede
usar el operador is para comprobar si se admite la conversión antes de efectuarla, como en este
ejemplo:
if (o is Rectangle)
{
Rectangle r = (Rectangle) o;
}
En este caso, el runtime comprueba el valor del objeto o. A continuación, solamente se
TOME NOTA
* ejecutará la conversión si o contiene un objeto Rectangle.
Si usamos el operador
as para convertir un
USO DEL OPERADOR AS
tipo, no es necesaria
la comprobación del Otro operador de conversión útil es as. El operador as es similar a la operación cast pero, en
operador. Bastará el caso de as, si la conversión de tipos no es posible, se devuelve null en lugar de iniciarse una
con comprobar el excepción. Por ejemplo, consideremos el siguiente código:
valor devuelto por as Rectangle r = o as Rectangle;
comparándolo con null.
if (r != null)
{
  // hacer algo
}
LISTO PARA CERTIFICACIÓN Si, en tiempo de ejecución, no es posible convertir el valor de la variable o en un rectángulo,
¿Comprende la se asignará el valor null a la variable r. No se iniciará ninguna excepción.
herencia?
2.2

■ Conceptos del polimorfismo

El polimorfismo es la posibilidad de que las clases derivadas compartan funcionalidades


CONCLUSIÓN comunes con las clases base pero puedan definir su propio comportamiento.

Estamos desarrollando una aplicación que permite a los usuarios trabajar con diferentes
tipos de polígonos. Tenemos una colección que contiene varios tipos de polígonos, como un
rectángulo, un triángulo y un cuadrado. Cada polígono proporciona su propia implementación
del método Draw. Al trabajar con esta colección, no sabemos necesariamente con qué forma
estamos trabajando. Sin embargo, deseamos que cada vez se invoque el método Draw correcto.
Esto es precisamente lo que permite hacer el polimorfismo.
54 | Lección 2

El polimorfismo permite tratar los objetos de una clase determinada como objetos de la
clase base en tiempo de ejecución. Cuando un método se invoca en tiempo de ejecución, se
identifica su tipo exacto y se invoca el método apropiado a partir de su clase derivada.

USO DEL POLIMORFISMO

USE el proyecto guardado en el ejercicio anterior para llevar a cabo los pasos siguientes:
1. Modifique la clase Polygon como se muestra a continuación:
class Polygon
{
  public virtual void Draw()
  {
    Console.WriteLine(“Dibujo: Polygon”);
  }
}
2. Modifique la clase Rectangle como se muestra a continuación:
class Rectangle: Polygon
{
  public override void Draw()
  {
    Console.WriteLine(“Dibujo: Rectangle”);
  }
}
3. Agregue una nueva clase denominada Triangle, como se muestra a continuación:
class Triangle: Polygon
{
  public override void Draw()
  {
     Console.WriteLine(“Dibujo: Triangle”);
  }
}
4. Modifique el método Main como sigue:
static void Main(string[] args)
{
  List<Polygon> polygons = new List<Polygon>();
  polygons.Add(new Polygon());
  polygons.Add(new Rectangle());
  polygons.Add(new Triangle());
Introducción a la programación orientada a objetos | 55

  foreach (Polygon p in polygons)


  {
    p.Draw();
  }
}
5. Seleccione Depurar > Iniciar sin depurar. Aparecerá una ventana de consola que
mostrará el mensaje de dibujo para cada polígono.
6. GUARDE el proyecto.
PAUSA. Deje el proyecto abierto para usarlo en el siguiente ejercicio.
En este ejercicio, hemos simplificado las definiciones de las clases Polygon y Rectangle para
enfatizar el concepto de polimorfismo. La clase base proporciona un único método Draw. Lo
importante aquí es la palabra clave virtual. Esta palabra clave permite que las clases derivadas
invaliden el método.
Las clases Rectangle y Triangle invalidan el método Draw de la clase base y lo invalidan
reemplazándolo por su propia definición mediante la palabra clave override. Al ejecutarse, el
método Main genera la siguiente salida:
Dibujo: Polygon
Dibujo: Rectangle
Dibujo: Triangle
El tipo de datos List<Polygon> permite almacenar una colección de objetos del tipo Polygon o
de tipos derivados de Polygon. El bucle foreach recorre en iteración una colección de objetos
Polygon. El tipo subyacente del primer objeto es Polygon, pero el segundo y tercer objetos de
la colección son en realidad objetos Rectangle y Triangle que simplemente se han convertido
en el tipo Polygon. El runtime comprobará el tipo subyacente real e invocará al método
invalidado de la clase derivada. Por ese motivo se llama a la versión de la clase derivada del
método Draw para los objetos Rectangle y Triangle.

Conceptos de las palabras clave override y new


La palabra clave override reemplaza un miembro de la clase base en una clase derivada.
La palabra clave new crea un nuevo miembro con el mismo nombre en la clase derivada
y oculta la implementación de la clase base.

Cuando una clase base define un miembro virtual, la clase derivada tiene dos opciones para
controlarlo; en concreto, puede usar la palabra clave override o la palabra clave new. La
palabra clave override tiene prioridad sobre la definición de la clase base del miembro. En este
caso, el objeto de la clase derivada llamará al miembro invalidado en lugar de al miembro de
la clase base.
En cambio, si se usa la palabra clave new, se creará una nueva definición del miembro y se
ocultará el miembro de la clase base. Sin embargo, si la clase derivada se convierte en una
instancia de la clase base, será posible llamar a los miembros ocultos de la clase.
56 | Lección 2

Para entender mejor estos conceptos, modificaremos el método de Triangle del ejercicio
TOME NOTA
* anterior, como sigue:
Si el método de la clase
derivada no va precedido class Triangle: Polygon
por la palabra clave new {
u override, el compilador   public new void Draw()
emitirá una advertencia y
el método se comportará   {
como si la palabra clave     Console.WriteLine(“Dibujo: Triangle”);
new estuviera presente.   }
}
A continuación, modifique el código de la clase Main, así:
Triangle t = new Triangle();
t.Draw();
Polygon p = t;
p.Draw();
El programa producirá la salida siguiente:
Dibujo: Triangle
Dibujo: Polygon
LISTO PARA CERTIFICACIÓN Aquí, cuando se invoca directamente el método Draw para el objeto de la clase derivada, se
¿Comprende el usa la nueva versión del método. Sin embargo, si el método se ejecuta cuando la clase derivada
polimorfismo? se convierte en una clase base, se ejecuta la versión del método Draw de la clase base oculta.
2.3

La clase System.Object proporciona un método ToString. Por convención, se debe usar este
método para devolver la representación de una clase en el lenguaje natural. Al crear tipos, es
TOME NOTA
* aconsejable invalidar este método para devolver información legible sobre los objetos.

■ Conceptos de las interfaces

Las interfaces se usan para establecer contratos en virtud de los cuales los objetos pueden
CONCLUSIÓN interactuar entre sí sin conocer los detalles de implementación.

Las interfaces se definen mediante el uso de la palabra clave interface. Una definición de
TOME NOTA
* interfaz consta de un conjunto de signaturas de métodos, propiedades, delegados, eventos o
Por convención, todas indizadores. Una definición de interfaz no puede constar de campos de datos ni detalles de
las interfaces definidas implementación, como los cuerpos de los métodos.
en .NET Framework
comienzan con una letra Una interfaz común que se define en el espacio de nombres System es el espacio de nombres
I mayúscula. Aunque IComparable. Se trata de una interfaz simple, que se define como sigue:
cada desarrollador puede
interface IComparable
asignar a sus interfaces
el nombre que desee, {
es preferible respetar   int CompareTo(object obj);
la convención de .NET }
Framework.
Introducción a la programación orientada a objetos | 57

La interfaz IComparable tiene un método único (CompareTo) que acepta un objeto y devuelve
un valor de tipo int. El valor devuelto por este método indica el resultado de comparar el
parámetro dado con el objeto actual. Según la documentación del método CompareTo:
• Si la instancia es igual al parámetro, CompareTo devuelve 0.
• Si el valor del parámetro es menor que la instancia o si el parámetro es null, se devuelve
un valor positivo.
• Si el valor del parámetro es mayor que el de la instancia, se devuelve un valor negativo.
• Si el parámetro no es del tipo compatible, se iniciará una excepción ArgumentException.

¿Cómo decide IComparable cómo comparar dos objetos Rectangle o dos objetos Employee?
No lo hace. Cuando se desee realizar tales comparaciones, las clases implicadas deberán
implementar la interfaz IComparable proporcionando un cuerpo de método para el método
CompareTo. Si se desea, es posible proporcionar, dentro del método CompareTo, la lógica
personalizada propia de cada clase que implementa IComparable.

USO DE LA INTERFAZ ICOMPARABLE

USE el proyecto guardado en el ejercicio anterior para llevar a cabo los pasos siguientes:
1. Modifique la clase Rectangle como se muestra a continuación:
class Rectangle: Polygon, IComparable
{
  public double Length { get; set; }
  public double Width { get; set; }
  public override void Draw()
{
    Console.WriteLine(“Dibujo: Rectangle”);
  }
  public double GetArea()
  {
    return Length * Width;
  }
  public int CompareTo(object obj)
  {
    if (obj == null)
      return 1;
    if (!(obj is Rectangle))
      throw new ArgumentException();
    Rectangle target = (Rectangle)obj;
    double diff = this.GetArea() - target.GetArea();
58 | Lección 2

    if (diff == 0)
      return 0;
    else if (diff > 0)
      return 1;
    else return -1;
  }
}
3. A continuación, modifique el método Main como se muestra a continuación:
static void Main(string[] args)
{
  Rectangle rect1 = new Rectangle
    { Length = 10, Width = 20 };
  Rectangle rect2 = new Rectangle
    { Length = 100, Width = 200 };
  Console.WriteLine(rect1.CompareTo(rect2));
}
4. Seleccione Depurar > Iniciar sin depurar. Aparecerá una ventana de consola que
mostrará el valor –1 porque el área de rect1 es menor que el área de rect2.
5. GUARDE el proyecto.
En este caso, la clase Rectangle se deriva de la clase Polygon e implementa la interfaz
IComparable. Una clase que implementa una interfaz debe implementar todos los métodos
declarados en esa interfaz.
Una interfaz es semejante a una clase abstracta, aunque con algunas diferencias notables. Por
un lado, una clase abstracta proporciona una implementación incompleta, mientras que una
interfaz no proporciona ninguna implementación. Además, una clase puede implementar varias
interfaces pero está limitada a heredar de una sola clase base.
Entonces, ¿cómo se decide entre usar una interfaz o una clase abstracta? Una forma consiste
en comprobar si existe una relación de tipo “es un(a)” entre los dos conceptos. Por ejemplo,
LISTO PARA CERTIFICACIÓN si existe una relación de herencia entre SalariedEmployee (empleado asalariado) y Employee
¿Comprende la (empleado), se puede usar una clase abstracta para estandarizar la funcionalidad común
encapsulación? de las clases derivadas. En cambio, no existe ninguna relación de tipo “es un(a)” entre un
2.4 empleado y la interfaz IComparable. Por lo tanto, es preferible implementar la funcionalidad
de comparación como una interfaz.

RESUMEN DE CONOCIMIENTOS

En esta lección hemos aprendido lo siguiente:


• La programación orientada a objetos es una técnica de programación que usa
objetos. Los objetos son estructuras de datos autocontenidos que consisten en
propiedades, métodos y eventos. Las propiedades especifican los datos que el objeto
representa, los métodos especifican el comportamiento del objeto y los eventos
proporcionan comunicación entre los objetos.
• Una clase es la plantilla a partir de la cual se crean los objetos individuales.
• Los constructores se usan para inicializar los miembros de datos de un objeto.
Introducción a la programación orientada a objetos | 59

• La palabra clave this se puede usar para obtener acceso a los miembros desde el
interior de los constructores, los métodos de instancia y los descriptores de acceso de
las propiedades de instancia.
• Los delegados son tipos especiales que se usan para encapsular un método con una
signatura específica.
• Los eventos son un medio para que una clase notifique a otras clases u objetos
que ha sucedido algo de interés. La clase que envía una notificación se denomina
publicador del evento y la que recibe la notificación, suscriptora del evento.
• Un espacio de nombres permite organizar el código y crear nombres de clase únicos.
• La palabra clave static se usa para declarar miembros que no pertenecen a objetos
individuales, sino a una clase en sí.
• Un tipo de valor almacena directamente un valor, mientras que un tipo de referencia
solo almacena una referencia al valor propiamente dicho.
• La palabra clave struct se usa para crear tipos definidos por el usuario que consisten
en pequeños grupos de campos relacionados. Los structs son tipos de valor, mientras
que las clases son tipos de referencia.
• La encapsulación es un mecanismo orientado a restringir el acceso a una clase o a
miembros de una clase para ocultar las decisiones de diseño que probablemente
estén sujetas a cambios. La encapsulación proporciona a los diseñadores de clases la
flexibilidad necesaria para cambiar una sección de código cuando es preciso sin tener
que cambiar los demás elementos de código que hacen uso de ese código.
• Un modificador de acceso especifica qué región del código tendrá acceso a un
campo. Por ejemplo, un modificador de acceso público no limita el acceso, pero un
modificador de acceso privado lo limita a aquella clase en la que está definido el
campo.
• La herencia permite crear nuevas clases que reutilizan, amplían y modifican la
funcionalidad definida en las clases existentes. La clase que hereda la funcionalidad
se denomina clase derivada y aquella cuya funcionalidad se hereda se denomina
clase base.
• El polimorfismo es la posibilidad de que las clases derivadas compartan
funcionalidades comunes con las clases base pero puedan definir su propio
comportamiento.
• La palabra clave override reemplaza un miembro de la clase base en una clase
derivada. La palabra clave new crea un nuevo miembro con el mismo nombre en la
clase derivada y oculta la implementación de la clase base.

■ Evaluación de conocimientos
Rellene los espacios en blanco
Complete las oraciones siguientes escribiendo la palabra o palabras correctas en los
espacios en blanco proporcionados.
1. Un(a) __________ es una plantilla de un objeto.
2. Una clase que no proporciona una implementación completa se debe declarar con la
palabra clave __________.
3. Las clases para las que se desean admitir las comparaciones deben implementar la
interfaz IComparable y después proporcionar un cuerpo para el método __________.
4. Se puede usar el operador __________ para comprobar si es válido convertir un tipo en
otro tipo.
60 | Lección 2

5. Las tres características principales de un lenguaje de programación orientado a objetos


son _________, __________ y __________.
6. Se puede usar __________ para agrupar las clases relacionadas a fin de reducir los
conflictos de nombres.
7. La palabra clave __________ hace referencia a la instancia actual de una clase.
8. Un(a) __________ es un tipo que hace referencia a un método.
9. Un(a) __________ es un tipo de valor, mientras que un(a) __________ es un tipo de
referencia.
10. Se puede usar la palabra clave __________ para declarar un miembro que pertenece a la
clase propiamente dicha, en lugar de pertenecer a un objeto específico.

Varias opciones
Rodee con un círculo la letra correspondiente a la mejor respuesta.
1. Desea restringir el acceso a un método de la clase contenedora o a una clase que
se deriva de la clase contenedora. ¿Qué modificador de acceso debe usar para este
método?
a. public
b. private
c. protected
d. internal
2. En una clase, hemos definido un método denominado Render. Este método
proporciona funcionalidades para representar archivos de mapa de bits en la
pantalla. Desea que las clases derivadas sustituyan esta funcionalidad para admitir
la representación de otros formatos de imagen adicionales. También desea que se
ejecute el método Render de las clases derivadas, aunque una clase derivada se
convierta en la clase base. ¿Qué palabra clave debe usar con la definición del método
Render en la clase base?
a. abstract
b. virtual
c. new
d. overrides
3. Se ha definido la clase AdvMath, que define la funcionalidad matemática avanzada.
No desea que la funcionalidad de esta clase se herede en las clases derivadas. ¿Qué
palabra clave debe usar para definir la clase AdvMath?
a. sealed
b. abstract
c. private
d. internal
4. Debe proporcionar funcionalidad de consulta para varias de sus clases.
Probablemente, el algoritmo de la consulta será diferente en cada clase. Además, no
todas las clases tienen relaciones de tipo “es un(a)” entre sí. ¿Qué debe hacer para
admitir esta funcionalidad?
a. Se agrega la funcionalidad de consulta a una clase base con el modificador de
acceso public.
b. Se procura que todas las clases hereden de una clase base abstracta y se invalida
el método de la clase base para que cada una proporcione su propia funcionalidad
de consulta.
c. Se procura que todas las clases hereden de una clase base que proporcione la
funcionalidad de consulta.
d. Se crea una interfaz común que se implementa en todas las clases.
Introducción a la programación orientada a objetos | 61

5. ¿Cuál de los siguientes elementos de clase debe usar para definir el comportamiento
de una clase?
a. Método
b. Propiedad
c. Evento
d. Delegado
6. Está escribiendo código para una clase denominada Product. Debe asegurarse de
que los miembros de datos de la clase se inicialicen en los valores correctos tan
pronto como se cree un objeto de la clase Product. El código de inicialización debe
ejecutarse siempre. ¿Qué debe hacer?
a. Crear un método static en la clase Product para inicializar los miembros de datos.
b. Crear un constructor en la clase Product para inicializar los miembros de datos.
c. Crear una propiedad static en la clase Product para inicializar los miembros de
datos.
d. Crear un evento en la clase Product para inicializar los miembros de datos.
7. Está creando una nueva clase denominada Square que se deriva de la clase Polygon.
La clase Polygon tiene el siguiente código:
class Polygon
{
  public virtual void Draw()
  {
    // código adicional. . .
  }
}
El método Draw de la clase Square debe proporcionar nueva funcionalidad, pero
también ocultar la implementación de la clase Polygon del método Draw. ¿Qué
segmento de código debe usar para lograr este objetivo?
a. class Square: Polygon
{
  public override void Draw()
  {
    // código adicional. . .
  }
}
b. class Square: Polygon
{
  public new void Draw()
  {
    // código adicional. . .
  }
}
c. class Square: Polygon
{
   public virtual void Draw()
   {
    // código adicional. . .
  }
}
62 | Lección 2

d. class Square: Polygon


{
   public static void Draw()
   {
    // código adicional. . .
  }
}
8. Está creando una nueva clase denominada Rectangle. Escribe el siguiente código:
class Rectangle: IComparable
{
  public double Length { get; set; }
  public double Width { get; set; }
  public double GetArea()
  {
      return Length * Width;
  }
   public int CompareTo(object obj)
   {
    // pendiente de completar
  }
}
Debe completar la definición del método CompareTo para permitir la comparación de
los objetos Rectangle. ¿Cuál de los siguientes códigos debe escribir?
a. public int CompareTo(object obj)
{
  Rectangle target = (Rectangle)obj;
  double diff = this.GetArea() − target.GetArea();
  if (diff == 0)
    return 0;
  else if (diff > 0)
    return 1;
  else return −1;
}
b. public int CompareTo(object obj)
{
  Rectangle target = (Rectangle)obj;
  double diff = this.GetArea() − target.GetArea();
  if (diff == 0)
     return 1;
  else if (diff > 0)
     return −1;
  else return 0;
}
Introducción a la programación orientada a objetos | 63

c. public int CompareTo(object obj)


{
  Rectangle target = (Rectangle)obj;
  if (this == target)
    return 0;
   else if (this > target)
    return 1;
  else return −1;
}
d. public int CompareTo(object obj)
{
  Rectangle target = (Rectangle)obj;
  if (this == target)
    return 1;
   else if (this > target)
    return −1;
  else return 0;
}
9. Está escribiendo código para un nuevo método denominado Process:
void Process(object o)
{
}
El código recibe un parámetro de tipo object. Necesita convertir este objeto en el tipo
Rectangle. A veces, el valor de o que se pasa al método podría no ser un valor de
Rectangle válido. Debe asegurarse de que el código no genere ningún error System.
InvalidCastException mientras hace las conversiones. ¿Cuál de las siguientes líneas
de código debería usar dentro del método Process para alcanzar esta meta?
a. Rectangle r = (Rectangle) o;
b. Rectangle r = o as Rectangle;
c. Rectangle r = o is Rectangle;
d. Rectangle r = (o != null) ? o as rectangle: (Rectangle) o;
10. Está escribiendo código de control de eventos en su programa. Define un delegado
denominado RectangleHandler de la siguiente manera:
public delegate void RectangleHandler(Rectangle rect);
También crea una variable de tipo RectangleHandler como se muestra a continuación:
RectangleHandler handler;
Más adelante en el programa, debe agregar un método denominado DisplayArea a
la lista de invocación de métodos de la variable handler. La signatura del método
DisplayArea coincide con la signatura del método RectangleHandler. El código que
escriba no debe afectar a ningún código de control de eventos existente. Dada esta
restricción, ¿cuál de los siguientes códigos debe escribir?
a. handler = new RectangleHandler(DisplayArea);
b. handler = DisplayArea;
c. handler += DisplayArea;
d. handler −= DisplayArea;
64 | Lección 2

■ Evaluación de competencias
Escenario 2-1: Creación de propiedades
Debe crear una clase denominada Product que representa un producto. La clase tiene una sola
propiedad, denominada Name. Los usuarios de la clase Product deben poder obtener y también
definir el valor de la propiedad Name. Sin embargo, cualquier intento de establecer el valor de
Name en una cadena vacía o un valor null debe iniciar una excepción. Además, los usuarios
de la clase Product no deben tener la capacidad de obtener acceso a ningún otro miembro de
datos de la clase Product. ¿Cómo se puede crear dicha clase?

Escenario 2-2: Creación de un struct


Está desarrollando un juego que requiere representar la ubicación de un objetivo en el espacio
tridimensional. La ubicación se identifica por tres valores enteros (de tipo int) denominados x,
y y z. Debe crear miles de estas estructuras de datos en el programa, de modo que debe hallar
una manera eficiente y ligera de almacenarlos en la memoria. Además, es poco probable que
sea preciso heredar otros tipos de este tipo de ubicación. ¿Cómo debe representar la ubicación
en el programa?

■ Evaluación de aptitudes
Escenario 2-1: Invalidación del método ToString
Supongamos que estamos escribiendo código para una clase Product. La clase Product
contiene el nombre y el precio de un producto. Debe invalidar el método ToString de la
clase base (System.Object) de modo que proporcione información sobre los objetos de la
clase Product al código de llamada. ¿Qué código debe escribir para la clase Product a fin de
satisfacer este requisito?

Escenario 2-2: Creación y control de eventos


Imaginemos que vamos a escribir código para crear y controlar eventos en el programa. La
clase SampleClass debe implementar la siguiente interfaz:
public delegate void SampleDelegate();
public interface ISampleEvents
{
  event SampleDelegate SampleEvent;
  void Invoke();
}
Debe escribir código para SampleClass y para un método de prueba que cree una instancia de
SampleClass e invoque el evento. ¿Qué código debe escribir?
Conceptos generales LECCIÓN 3
del desarrollo de
software
M AT R I Z D E C O N O C I M I E N T O S D E L A L E C C I Ó N

Conocimientos y conceptos Objetivo del examen MTA Número de objetivo del


examen MTA
Conceptos de la administración Conceptos de la administración 3.1
del ciclo de vida de las aplicaciones del ciclo de vida de las aplicaciones.
Conceptos de las pruebas Conceptos de la administración 3.1
del ciclo de vida de las aplicaciones.
Conceptos de las estructuras Conceptos de los algoritmos 3.3
de datos y las estructuras de datos.
Conceptos de los algoritmos Conceptos de los algoritmos 3.3
de ordenación y las estructuras de datos.

TÉRMINOS CLAVE
administración de versiones estructuras de datos pruebas de integración
administración del ciclo de vida lista de vínculo pruebas de regresión
de las aplicaciones (ALM) matrices pruebas de software
algoritmos de ordenación pila pruebas del sistema
análisis de requisitos proceso de diseño pruebas unitarias
BubbleSort pruebas de aceptación QuickSort
cola pruebas de caja blanca
desarrollo de software pruebas de caja negra

Usted es un desarrollador de software de la empresa Northwind Corporation. Trabaja


como parte de un equipo que desarrolla programas para resolver problemas empresariales
complejos. Todo desarrollador debe ser consciente de las diferentes fases del ciclo de vida
de las aplicaciones, pues desempeña un rol importante en varias de ellas. Por ejemplo,
no solo participa en las partes del ciclo dedicadas al diseño y al desarrollo, sino también
debe interactuar con frecuencia con el equipo de pruebas de software durante la parte del
ciclo dedicada a las pruebas. En ocasiones, incluso realizará las pruebas personalmente.
Por consiguiente, debe conocer los conceptos generales de este proceso.

65
66 | Lección 3

Al desarrollar software, se usan varios tipos de estructuras de datos y algoritmos. Por lo


tanto, es preciso saber qué estructura de datos ha de usarse para cada tarea y cuáles son
las implicaciones de rendimiento de la opción elegida. También es preciso entender los
conceptos generales de los diversos métodos de ordenación.

■ Conceptos de la administración del ciclo de vida de las aplicaciones

La administración del ciclo de vida de las aplicaciones (ALM) es el conjunto de


CONCLUSIÓN actividades que giran en torno a un nuevo producto de software, desde su concepción
hasta el momento en que el producto madura y, en última instancia, tal vez se retira.
Desarrollar una aplicación de software no consiste únicamente en escribir el código. Hay
otras actividades que han de realizarse también en el orden correcto para desarrollar una
aplicación satisfactoria. Colectivamente, estas actividades comprenden lo que denominamos
la administración del ciclo de vida de las aplicaciones (ALM). Algunas de las actividades que
forman parte del proceso de ALM se muestran en la figura 3-1 e incluyen la administración de
los requisitos, el diseño, el desarrollo, las pruebas, la entrega y las versiones.
Figura 3-1
Administración del ciclo
de vida de las aplicaciones
(ALM)

En esta sección, conoceremos mejor los diferentes roles y actividades correspondientes a cada
fase del proceso de ALM.
El ciclo de vida de una aplicación se inicia cuando se identifica la necesidad de una nueva
aplicación de software. Normalmente, el director general del negocio es quien patrocina el
proyecto. Esta persona analiza la necesidad, comprueba en qué medida encaja el proyecto en
la estrategia de negocio global, organiza el financiamiento e inicia el proceso de dotación de
personal para el proyecto.
Probablemente, la primera persona a quien contratará el director general será el jefe de
proyecto. El jefe de proyecto es responsable de la ejecución global del proyecto. Sus
principales responsabilidades consisten en asegurarse de que el proyecto no se salga del
presupuesto y se finalice a tiempo. El jefe de proyecto también es responsable de contratar a
los miembros del equipo y de facilitar la cooperación en el seno del equipo.

Conceptos del análisis de requisitos

El análisis de requisitos es el proceso de definición pormenorizada de los requisitos


empresariales de un sistema de software nuevo.
Conceptos generales del desarrollo de software | 67

El análisis de requisitos es uno de los pasos más importantes del ciclo de vida de una
aplicación. Contar con requisitos precisos, completos y bien documentados es fundamental
para el éxito del proyecto. Estos requisitos pueden ser funcionales o no funcionales. Los
requisitos funcionales especifican exactamente qué tareas deberá realizar el sistema.
En cambio, los requisitos no funcionales son aquellos relativos a la calidad, tales como
escalabilidad, seguridad, confiabilidad, etc.
Un analista de negocios es responsable de analizar las necesidades empresariales y convertirlas
en requisitos que el equipo de desarrollo pueda satisfacer.

Conceptos del proceso de diseño


El proceso de diseño se usa para crear los planes, los modelos y la arquitectura que
definen cómo se implementará el software.

El proceso de diseño genera especificaciones técnicas detalladas que se usarán para desarrollar
el sistema. La salida del proceso de diseño es un conjunto de modelos y especificaciones
técnicos que orientarán a los desarrolladores y a los demás miembros del equipo durante la
actividad de desarrollo del software. La salida del proceso de diseño es más abstracta y menos
concreta. En este punto, no existe ningún sistema real con el que se pueda interactuar.
Algunos de los participantes más importantes de esta fase del proceso de ALM son el
arquitecto y el diseñador de la experiencia del usuario:
• Arquitecto: un arquitecto diseña los planos técnicos del sistema. Esto incluye identificar
los componentes y servicios, su comportamiento y las interacciones entre ellos y con el
mundo exterior.
• Diseñador de la experiencia del usuario: un diseñador de la experiencia del usuario
crea la experiencia del usuario con el sistema. Esto incluye diseñar los elementos de la
interfaz de usuario (IU); diseñar la navegación entre los diversos formularios, pantallas o
páginas; etc.

Conceptos del desarrollo de software


La actividad del desarrollo de software se refiere a implementar el diseño mediante
la creación de código de software, bases de datos y otros contenidos asociados a ello.

El desarrollo de software es la parte del proceso de ALM en que se aplican los requisitos de
negocio en el código de trabajo, basándose en el diseño elaborado durante la actividad anterior.
Al final de esta actividad, se dispone de una salida concreta que consiste en un sistema de
software con el que los usuarios pueden interactuar.
Los participantes fundamentales de la fase de desarrollo de software son:
• Desarrolladores: los desarrolladores escriben código basado en los requisitos recopilados
por el analista de negocios, en la arquitectura elaborada por el arquitecto y la experiencia
del usuario desarrollada por el diseñador de la experiencia del usuario.
• Administradores de bases de datos (DBA): los DBA son responsables de implementar
y mantener las bases de datos del software. Los DBA también planean la integridad,
seguridad y velocidad de los datos.
• Escritores técnicos: los escritores técnicos elaboran los manuales del sistema y los
archivos de ayuda que se entregarán con la aplicación.
• Desarrolladores de contenido: los desarrolladores de contenido son expertos en la
materia que desarrollan el contenido para el sistema. Por ejemplo, si la aplicación es
un sitio web de críticas de películas, no bastará con implementar el sitio web, sino que
además será preciso asegurarse de que este contenga contenido suficiente para suscitar
interés en los usuarios.
68 | Lección 3

Conceptos de las pruebas de software

Durante las pruebas de software se comprueba que la aplicación coincida con los
requisitos del sistema.
Las pruebas de software se usan para garantizar la calidad del producto final. Las pruebas
pueden identificar posibles diferencias entre las expectativas respecto al sistema descritas en el
documento de requisitos y el comportamiento real del sistema.
Entre los participantes más importantes de la actividad de pruebas de software se encuentran
los evaluadores, que comprueban la aplicación de trabajo para asegurarse de que satisface
las necesidades identificadas. Cuando estos evaluadores identifican cualquier defecto en la
aplicación, se lo asignan a la persona adecuada para que lo arregle. Por ejemplo, un defecto del
código se asignaría a un desarrollador para que lo subsanase.

Conceptos de la administración de versiones


La actividad de administración de versiones se usa para administrar la imple-
mentación, la distribución y el soporte de las versiones de software.

La administración de versiones incluye actividades tales como empaquetado e implementación


del software, administración de defectos del software y administración de solicitudes de
cambio del software.
Los principales participantes de la actividad de administración de versiones son las siguientes
personas:
• Administrador de versiones: el administrador de versiones coordina los diversos
equipos y unidades de negocio para asegurarse del lanzamiento oportuno de un producto
de software.
• Personal de operaciones: los miembros del personal de operaciones se aseguran de que
el sistema se entregue conforme a lo prometido. Esto puede requerir la copia de discos de
LISTO PARA CERTIFICACIÓN DVD y su envío a medida que se reciben los pedidos o la realización del mantenimiento
¿Comprende la continuo de un sistema de software como servicio (SaaS). El personal de operaciones
administración del ciclo de también es responsable de lanzar las actualizaciones del sistema (por ejemplo,
vida de las aplicaciones y correcciones o nuevas características).
sus actividades?
• Personal de soporte técnico: estos empleados interactúan con los clientes y les ayudan
3.1 a resolver sus problemas con el sistema. El personal de soporte técnico puede generar
estadísticas valiosas sobre qué áreas del sistema presentan más dificultades para los
usuarios y posiblemente deberían actualizarse en la próxima versión de la aplicación.

■ Conceptos de las pruebas

Las pruebas de software consisten en comprobar el software en relación con sus requisitos.
CONCLUSIÓN Las pruebas se llevan a cabo después de completar la mayor parte del trabajo de desarrollo.

Como hemos mencionado anteriormente, las pruebas de software consisten en comprobar que
una aplicación de software funciona tal y como se esperaba y satisface todos los requisitos
de negocios y técnicos. Cuando existe una diferencia entre los comportamientos esperado y
real del sistema, se registra un defecto de software (o “error”) que se asigna a una persona
responsable de corregirlo.
Las pruebas de software pueden incluir pruebas funcionales y no funcionales. Las pruebas
funcionales se refieren a los requisitos funcionales del sistema y comprueban las características
que conforman la funcionalidad básica del sistema. Por ejemplo, comprobar si los usuarios
pueden agregar elementos al carro de la compra constituye una parte importante de las pruebas
Conceptos generales del desarrollo de software | 69

funcionales de un sitio web de comercio electrónico. Por su parte, las pruebas no funcionales
se refieren a comprobar los atributos de software que no forman parte de la funcionalidad
básica, sino de los requisitos no funcionales del software, tales como la usabilidad, la
escalabilidad o la seguridad.

Es importante señalar que el proceso de las pruebas de software solo puede ayudar a
encontrar defectos pero no puede garantizar la ausencia de estos. Todo software complejo
posee un gran número de rutas de ejecución posibles y gran cantidad de parámetros que
*
TOME NOTA
pueden afectar a su comportamiento. No es viable ni, con frecuencia, posible, probar todas
las situaciones diferentes que se le presentarán a ese software en un entorno de producción.

Conceptos de los métodos de prueba

Los métodos de las pruebas de software se suelen dividir en dos categorías: pruebas
de caja blanca y pruebas de caja negra.

Tradicionalmente, existen dos enfoques generales respecto a las pruebas de software:


• Pruebas de caja negra
• Pruebas de caja blanca
Las pruebas de caja negra tratan al software como una caja negra y se centran solamente en las
entradas y las salidas. Con este enfoque, no se usa ningún conocimiento del funcionamiento
interno del sistema durante las pruebas. En cambio, en las pruebas de caja blanca, los
evaluadores aplican sus conocimientos del funcionamiento interno del sistema mientras lo
comprueban. Por ejemplo, en las pruebas de caja blanca, los evaluadores tienen acceso al
código fuente.
Estas dos técnicas de prueba son complementarias entre sí. Las pruebas de caja negra se
usan principalmente para asegurarse de que la aplicación de software responda a todos sus
requisitos. Por su parte, las pruebas de caja blanca se emplean para asegurarse de que existan
casos de prueba disponibles para cada método o función.

Conceptos de los niveles de pruebas

Las pruebas se llevan a cabo en diferentes fases del ciclo de vida de desarrollo de las
aplicaciones. Los distintos niveles de pruebas especifican en qué punto del ciclo de
vida se lleva a cabo una prueba concreta y qué tipo de prueba se ha de efectuar.

Los niveles de pruebas se definen en función del momento del ciclo de vida del desarrollo de
software en que tienen lugar las pruebas. Existen cinco niveles de pruebas distintos:
• Pruebas unitarias: las pruebas unitarias comprueban la funcionalidad de una unidad de
código. Por ejemplo, una prueba unitaria puede evaluar si un método devuelve el valor
correcto. Las pruebas unitarias son de caja blanca y con frecuencia las realiza el propio
desarrollador que está escribiendo el código. Para las pruebas unitarias se suele usar
una herramienta automatizada que simplifica el desarrollo de casos y también realiza
el seguimiento por si una modificación del código provoca que no se supere alguna de
las pruebas unitarias existentes. Visual Studio presenta compatibilidad integrada con las
pruebas unitarias. También se pueden usar herramientas de código abierto como NUnit
para automatizar las pruebas unitarias del código de .NET Framework.
• Pruebas de integración: las pruebas de integración evalúan las interfaces entre los com-
70 | Lección 3

ponentes del software. Las pruebas de integración pueden realizarse progresivamente a


medida que se desarrollan los componentes o bien a modo de “big bang” cuando todos
los componentes están listos para funcionar conjuntamente. Es preferible el primero de
los dos enfoques, pues reduce el riesgo y aumenta la confianza de los interesados en el
desarrollo del sistema. Las pruebas de integración también pueden conllevar la compro-
bación de la interacción de los componentes con un sistema externo. Por ejemplo, si el
funcionamiento de un componente depende de los datos de un servicio web externo, las
pruebas de integración se asegurarán de que ese componente funcione correctamente con
la aplicación externa.
• Pruebas del sistema: las pruebas del sistema consisten en comprobar el sistema de soft-
TOME NOTA
* ware de forma global. En este punto, todos los componentes del sistema están desarrolla-
Es mucho más rentable dos y funcionan entre sí y con los sistemas externos.
encontrar los defectos lo
antes posible (y no más • Pruebas de aceptación: este nivel de pruebas suelen llevarlo a cabo los propios clientes.
adelante) en el ciclo de Generalmente, hay dos niveles de pruebas de aceptación antes de la distribución
desarrollo de producto. generalizada de un producto: las pruebas alfa y las pruebas beta. Las pruebas alfa las realiza
un grupo limitado de usuarios y constituyen una oportunidad de ofrecer una evaluación
precoz del producto a los clientes más importantes y de recabar sus comentarios. En las
versiones alfa pueden faltar algunas características y a menudo no están presentes muchos
atributos no funcionales, tales como el rendimiento. En el siguiente nivel de pruebas, las
pruebas beta, se puede proporcionar el producto a un público más amplio de clientes y
solicitar comentarios. En términos de funcionalidad, la versión beta del software es muy
LISTO PARA CERTIFICACIÓN similar a la versión final. Sin embargo, es posible que los equipos de desarrollo sigan
¿Comprende los trabajando para mejorar el rendimiento y corregir los defectos conocidos.
diversos métodos de • Pruebas de regresión: a medida que se notifican y corrigen los defectos de una apli-
pruebas de software? cación de software, es importante asegurarse de que las nuevas correcciones no afecten
3.1 a todo aquello que ya funcionaba correctamente. En este punto es donde las pruebas de
regresión resultan útiles. Generalmente, con cada corrección, los evaluadores de software
llevan a cabo una batería de pruebas de regresión para asegurarse de que cada funcionali-
dad de la cual se tenía constancia de que funcionaba correctamente siga de ese modo.

■ Conceptos de las estructuras de datos

Las estructuras de datos son técnicas que permiten organizar y almacenar datos en la
memoria del equipo. El modo en que se almacenan los datos afecta a su recuperación
CONCLUSIÓN y manipulación. Para comprender una estructura de datos no solo es preciso entender
el patrón de almacenamiento, sino también saber qué métodos se usan para crear la
estructura de datos, obtener acceso a ella y manipularla.

Las estructuras de datos son los bloques de creación de la mayoría de los programas y
permiten a los desarrolladores implementar funcionalidades complejas. La mayoría de los
entornos de programación proporcionan compatibilidad integrada con gran variedad de
estructuras de datos y métodos asociados para manipularlas. En esta sección, conoceremos
varios tipos de estructuras de datos diferenciados, a fin de familiarizarnos con las técnicas
generales que nos permiten manipularlas.

Conceptos de las matrices


Una matriz es una colección de elementos almacenados en ubicaciones contiguas de
memoria y cuyo direccionamiento se lleva a cabo mediante uno o más índices.
Conceptos generales del desarrollo de software | 71

Una matriz es una estructura de datos común que representa una colección de elementos de
tipo similar. Los elementos de una matriz se almacenan en ubicaciones de memoria contiguas.
Una matriz es una estructura de datos homogénea porque todos los elementos que contiene
son del mismo tipo de datos. A cualquier elemento de la matriz se puede obtener acceso
directamente mediante un índice. En .NET Framework, los índices de las matrices son de base
cero.

REPRESENTACIÓN INTERNA
En el código siguiente, la primera instrucción crea una variable de matriz y la segunda
inicializa la variable con una matriz de cuatro enteros:
int[] numbers;
numbers = new int[4];
Al principio, los números de la variable se establecen en null porque la matriz todavía no se
ha inicializado. Sin embargo, la segunda instrucción inicializa la matriz mediante la asignación
de un espacio de memoria contigua lo bastante grande para almacenar cuatro enteros en el
montón de memoria. La dirección inicial de la asignación de memoria se almacena en la

Figura 3-2
Representación interna de
una estructura de datos de
matriz

variable de matriz numbers, como se muestra en la figura 3-2. Todos los elementos de la
matriz se inicializan en este caso con el valor 0, que es el valor predeterminado para un entero.
A continuación, la variable numbers actúa como referencia a la ubicación de memoria asignada
a la matriz. El nombre de la matriz se puede usar para obtener acceso directamente a cada
uno de los elementos de la matriz. En .NET Framework, todas las matrices son de base cero;
es decir, al primer elemento de la matriz se obtiene acceso mediante el índice numbers[0], al
segundo mediante numbers[1] y así sucesivamente.
También es posible usar matrices multidimensionales. Podemos imaginarnos una matriz
bidimensional como una tabla en la que cada celda es un elemento de la matriz, que puede
direccionarse mediante los números de la fila y la columna a las que pertenece. Tanto
el número de fila como el número de columna se indizan con base cero. Por ejemplo, la
expresión table[2, 3] haría referencia a un elemento de la tercera fila y la cuarta columna de
una matriz denominada table.

OPERACIONES COMUNES
Las matrices admiten las siguientes operaciones:
• Asignación
• Acceso
Para trabajar con una matriz, en primer lugar se asigna la memoria. Para ello, es preciso crear
e inicializar la matriz como hemos mostrado anteriormente. Una vez realizada la asignación,
se puede obtener acceso a cualquier elemento de la matriz en cualquier orden que se desee
mediante una referencia directa a su índice. Por ejemplo, el código siguiente asigna el valor
10 al cuarto elemento de la matriz y, a continuación, asigna el doble de ese valor a la variable
calc:
number[3] = 10;
int calc = number[3] * 2;
72 | Lección 3

RENDIMIENTO Y USO
El contenido de una matriz se presenta como un bloque de memoria contiguo al que se puede
obtener acceso directamente mediante el índice de la matriz. Por lo tanto, leer una matriz y
escribir en ella son operaciones sumamente rápidas. Sin embargo, las matrices están limitadas
por sus requisitos de homogeneidad y tamaño fijo. Aunque se puede aumentar el tamaño de
una matriz, para hacerlo es preciso reasignar todos sus elementos y esta operación requiere
mucho tiempo.
Las matrices funcionan mejor cuando el número de elementos de la colección es una cantidad
predeterminada y se requiere un acceso veloz y directo a cada elemento.
En .NET Framework, se puede usar la clase ArrayList para eludir los requisitos de tamaño fijo
y homogeneidad de una matriz. ArrayList es un tipo de colección que puede contener objetos
de cualquier tipo de datos y ampliarse dinámicamente cuando sea necesario. Sin embargo,
ArrayList no resulta tan rápida de usar como una matriz.

Conceptos de las colas


Una cola es una colección de elementos en la que el primer elemento que se agrega
es el primero que se quita.

La estructura de datos de una cola imita las colas de la vida real. En una cola, los elementos
se procesan en el orden en que se agregaron a ella. En concreto, los elementos siempre se
agregan al final de la cola y se retiran del principio. Este tipo de procesamiento se denomina
de tipo primero en entrar, primero en salir (FIFO). La capacidad de una cola se refiere al
número de elementos que puede contener. Sin embargo, a medida que se agregan elementos
a la cola, su capacidad se aumenta automáticamente. Una cola es también una estructura de
datos heterogéneos, lo que significa que sus elementos pueden ser de diferentes tipos de datos.

REPRESENTACIÓN INTERNAL
Para evitar una excesiva reasignación de espacio de memoria y facilitar su administración,
las colas suelen implementarse internamente como matrices circulares de objetos, como se
muestra en la figura 3-3.

Figura 3-3
Representación interna de
una estructura de datos de
cola

Dentro de una cola, el índice del principio señala al primer elemento y el índice del final
señala al último elemento. En la figura 3-3, por ejemplo, el índice del principio señala a la
ubicación 2 de la cola. Como la cola es circular, siempre y cuando se realice el seguimiento de
los punteros del principio y el final no importará en qué ubicación comience la cola. Cuando
se quita un elemento, el principio se mueve al siguiente elemento de la cola. Cuando se agrega
un nuevo elemento, siempre aparece al final de la cola y el final señala al elemento recién
agregado. Las ranuras null de una cola (tales como las representadas en la figura 3-3) son los
lugares vacíos disponibles para llenarlos antes de que la cola requiera una reasignación de
memoria.
Conceptos generales del desarrollo de software | 73

.NET Framework proporciona una implementación de la estructura de datos de cola como


TOME NOTA
* parte de la clase Queue del espacio de nombres System.Collections. En los lenguajes de
Una versión genérica programación que no proporcionan una implementación de cola, es posible escribir una clase
de la clase Queue está Queue propia mediante una estructura de datos semejante a la matriz y simular las operaciones
disponible como parte de la cola.
del espacio de nombres
System.Collections.
Generic. Esta versión OPERACIONES COMUNES
genérica se usa para Una cola admite las siguientes operaciones comunes:
crear una cola de • Enqueue: la operación Enqueue (poner en cola) comprueba en primer lugar si existe
elementos que son del suficiente capacidad disponible en la cola para agregar un elemento más. En caso
mismo tipo de datos. afirmativo, el elemento se agrega al final de la cola. En caso negativo, se reasigna la
matriz en función de un factor de incremento especificado previamente y, a continuación,
se agrega el nuevo elemento a la cola.
• Dequeue: la operación Dequeue (quitar de la cola) retira el elemento actual del principio
de la cola y establece el principio de modo que señale al siguiente elemento.
• Peek: la operación Peek (leer información) permite ver el elemento actual que se encuen-
tra en la posición del principio sin quitarlo de la cola.
• Contains: la operación Contains (contiene) permite determinar si un elemento espe-
cífico existe en la cola.

RENDIMIENTO Y USO
Una cola es una estructura de datos de uso especial, adecuada principalmente para aplicaciones
en que se requiere procesar los elementos en el orden en que se reciben. Algunos ejemplos
de ello son las colas de impresión, los sistemas de mensajería y programadores de trabajos.
A diferencia de una matriz, una cola no puede usarse para obtener acceso a los elementos de
manera aleatoria. Las operaciones como Enqueue y Dequeue agregan y quitan realmente los
elementos de la cola.

Conceptos de las pilas


Una pila es una colección de elementos en la que el último elemento que se agrega
es el primero que se quita.

En contraposición a las colas, las pilas son estructuras de datos de tipo último en entrar,
primero en salir (LIFO). Podemos plantearnos una pila como una estructura semejante a una
serie de platos apilados sobre una mesa de un bufé; el último plato que se agrega es el primero
que se retira. La capacidad de la pila se refiere al número de elementos que puede contener.
Sin embargo, a medida que se agregan elementos a la pila, su capacidad se incrementa
automáticamente. Una pila es una estructura de datos heterogéneos, lo que significa que los
elementos que contiene pueden ser de diferentes tipos de datos.

REPRESENTACIÓN INTERNA
Al igual que una cola, una pila se suele implementar como un búfer circular a fin de evitar
una excesiva reasignación de espacio de memoria y facilitar su administración. Podemos
imaginarnos una pila con el mismo aspecto que se muestra en la figura 3-3, con la salvedad de
que el final es lo que ahora denominamos la parte superior de la pila y el principio es lo que
denominamos la parte inferior de la pila.
Los elementos nuevos siempre se agregan a la parte superior de la pila. Cuando esto sucede,
la parte superior de la pila comienza a señalar al elemento recién agregado. Los elementos
también se quitan de la parte superior de la pila; cuando eso sucede, la parte superior de la pila
se ajusta de modo que señale al siguiente elemento de la pila.
74 | Lección 3

.NET Framework proporciona una implementación de la estructura de datos de pila como


TOME NOTA
* parte de la clase Stack del espacio de nombres System.Collections. En los lenguajes de
Una versión genérica programación que no proporcionan una implementación de pila, es posible escribir una clase
de la clase Stack está Stack propia mediante una estructura de datos semejante a la matriz y simular las operaciones
disponible como parte de la pila.
del espacio de nombres
System.Collections.
Generic. Esta versión OPERACIONES COMUNES
genérica se usa para Una pila admite las siguientes operaciones comunes:
crear una pila de
• Push: la operación Push (insertar) comprueba en primer lugar si existe suficiente
elementos que son del
capacidad disponible en la pila para agregar un elemento más. En caso afirmativo, se
mismo tipo de datos.
agrega el elemento a la parte superior de la pila. En caso negativo, se reasigna la matriz
en función de un factor de incremento especificado previamente y, a continuación, se
agrega el nuevo elemento a la pila.
• Pop: la operación Pop (desapilar) elimina el elemento de la parte superior de la pila y
establece la parte superior de modo que señale al siguiente elemento de la pila.
• Peek: la operación Peek (leer información) permite ver el elemento actual en la posición
superior de la pila sin quitarlo de ella.
• Contains: la operación Contains (contiene) permite determinar si un elemento específico
existe en la pila.

RENDIMIENTO Y USO
Una pila es una estructura de datos de uso especial, adecuada principalmente para aplicaciones
en que se requiere procesar los elementos según el principio de primero en entrar, primero
en salir. Las pilas son estructuras útiles debido a sus aplicaciones en la administración de
la memoria en tiempo de ejecución, evaluación de expresiones, seguimiento de llamadas a
métodos, etc. A diferencia de las matrices, las pilas no se pueden usar para obtener acceso a los
elementos de forma aleatoria. Las operaciones como Push y Pop agregan y quitan realmente
los elementos de la pila.

Listas de vínculo

Una lista de vínculo es una colección de nodos organizados de modo que cada uno
de ellos contenga un vínculo al nodo siguiente de la secuencia.

Una lista de vínculo es una colección de nodos donde cada nodo contiene una referencia (o
vínculo) al nodo siguiente de la secuencia. A diferencia de una matriz, no es necesario que los
elementos de una lista de vínculo sean contiguos, de modo que esta última no requiere que se
reasigne el espacio de memoria de toda la lista para poder agregar más vínculos.

REPRESENTACIÓN INTERNA
En la memoria, una lista de vínculo puede visualizarse como una colección de nodos, como se
muestra en la figura 3-4.

Figura 3-4
Representación interna de
una estructura de datos de
lista de vínculo simple
Conceptos generales del desarrollo de software | 75

Cada nodo de una lista de vínculo contiene dos datos: la información correspondiente al
nodo y el vínculo al siguiente nodo. El primer nodo de la lista se denomina nodo principal.
Mediante el vínculo del nodo principal, se puede llegar al siguiente nodo y seguir atravesando
los nodos hasta que el último vínculo sea un valor null. A menudo, se usa el término final para
referirse a la lista a la que señala el primer nodo; es decir, se refiere a todo lo que aparece
después del nodo principal. Así pues, en la figura 3-4, el final es la lista de vínculo que
empieza en el nodo B.
Se pueden usar otras implementaciones de listas de vínculo en función de los requisitos. Por
ejemplo, en una lista de vínculo circular, el último nodo de la lista señala al primero, para
crear un círculo. En cambio, en una lista de doble vínculo, cada nodo contiene dos vínculos,
como se muestra en la figura 3-5.

Figura 3-5
Representación interna de
una estructura de datos de
lista de doble vínculo

En cada nodo de una lista de doble vínculo, un vínculo es una referencia adelantada que señala
al siguiente nodo de la secuencia y el otro es una referencia regresiva que señala al nodo
anterior de la secuencia. Como podemos imaginar, una lista de doble vínculo resulta fácil de
cruzar en cualquier dirección.
.NET Framework proporciona una clase LinkedList como parte del espacio de nombres
System.Collections.Generic. Esta clase implementa una lista de doble vínculo homogénea del
tipo de datos especificado. El desarrollador también puede escribir sus propias clases para
implementar un tipo diferente de lista de vínculo.

OPERACIONES COMUNES
Una lista de vínculo admite las siguientes operaciones comunes:
• Add: la operación Add (agregar o insertar) en una lista de vínculo consiste en cambiar los
vínculos, como se muestra en la figura 3-6. Supongamos que vamos a insertar un nuevo
nodo (con el valor Z) entre los nodos con los valores A y B. En primer lugar, es preciso
asignar memoria para el nuevo nodo y asignarle el valor Z a la sección de datos del nodo.
A continuación, será preciso copiar la sección de vínculo del nodo A a la sección de
vínculo del nodo Z, para que este último señale al nodo B. Por último, habrá que copiar

Figura 3-6
Adición de un nuevo nodo a
una lista de vínculo
76 | Lección 3

la dirección del nodo Z recién creado en la sección de vínculo del nodo A, para que este
empiece a señalar al nodo Z.
• Remove: de modo parecido a la operación Add, la operación Remove (quitar o eliminar)
también consiste en cambiar los vínculos. Por ejemplo, para eliminar el tercer nodo de la
figura 3-4, será preciso cambiar el vínculo del segundo nodo por un valor null. El tercer
nodo se convertirá en una ubicación de memoria sin referencia y, en última instancia, se
devolverá al bloque de memoria disponible.
• Find: la operación Find (buscar) halla el nodo con el valor dado en la lista de vínculo.
Para encontrar un valor, generalmente se comienza por el nodo principal y se comprueba
si el valor coincide. En caso negativo, se sigue el vínculo al siguiente nodo y se continúa
con la operación Find hasta alcanzar el final de la lista, lo que sucede cuando se encuen-
tra un vínculo null.

RENDIMIENTO Y USO
Una lista de vínculo no permite el acceso aleatorio a sus elementos. La única manera de
obtener un elemento consiste en empezar desde el nodo del principio y seguir los vínculos a
partir de él. En consecuencia, las listas de vínculo resultan lentas para recuperar datos. Sin
embargo, en las operaciones de inserción y eliminación, las listas de vínculo ofrecen una
velocidad excelente, porque para insertar o eliminar un nodo solo hay que cambiar un vínculo.
Por otro lado, las listas de vínculo no presentan ninguna capacidad máxima a partir de la cual
deba reasignarse su contenido.
De hecho, una lista de vínculo proporciona una manera alternativa de implementar las
estructuras de datos de cola y pila. Si los requisitos exigen un acceso frecuente a los datos pero
LISTO PARA CERTIFICACIÓN
rara vez será preciso insertar o eliminar datos, una matriz es la implementación de elección.
¿Comprende las estructuras
En cambio, si los requisitos exigen operaciones frecuentes de inserción y eliminación,
de datos comunes?
posiblemente sea preferible usar una lista de vínculo.
3.2

■ Conceptos de los algoritmos de ordenación

Los algoritmos de ordenación, tales como BubbleSort y QuickSort, organizan los


CONCLUSIÓN
elementos de una lista en un orden concreto. Conocer los conceptos de los algoritmos
de ordenación puede ayudarle a entender, analizar y comparar diferentes métodos de
solución de problemas.

Los algoritmos de ordenación son aquellos que organizan los elementos de una lista en un
orden determinado. Por ejemplo, podemos usarlos para ordenar una lista de alumnos de forma
ascendente en función de su apellido. En los albores del procesamiento de datos, la ordenación
era un problema importante al que se dedicaron muchos esfuerzos de investigación. En la
actualidad, encontramos la funcionalidad básica de ordenación ya integrada en las bibliotecas
y estructuras de datos más populares. Por ejemplo, en .NET Framework, podemos usar el
método Array.Sort para ordenar una matriz. Sin embargo, sigue siendo importante estudiar la
ordenación para comprender la resolución de problemas y el análisis de algoritmos.
En esta sección, estudiaremos dos algoritmos de ordenación de uso frecuente, BubbleSort y
QuickSort.

Conceptos de BubbleSort

El algoritmo BubbleSort usa una serie de operaciones de comparación e intercambio


para organizar los elementos de una lista en el orden correcto.
Conceptos generales del desarrollo de software | 77

BubbleSort funciona mediante la comparación de dos elementos para comprobar si están


desordenados. En el caso de que lo estén, intercambia sus posiciones. El algoritmo repite la
operación hasta que toda la lista está en el orden deseado. BubbleSort recibe este nombre
por su funcionamiento: a medida que el algoritmo progresa, los elementos de menor tamaño
ascienden hacia la superficie como si fueran burbujas (bubble, en inglés).
Vamos a visualizar BubbleSort con la ayuda de un ejemplo. Supongamos que deseamos
organizar todos los elementos de la lista siguiente en orden ascendente: (20, 30, 10, 40). Estos
elementos deben organizarse de menor a mayor. El algoritmo BubbleSort intenta resolver el
problema en una o varias pasadas; en cada una de ellas analiza la lista completa de elementos.
Si el algoritmo encuentra elementos desordenados, los intercambia. El algoritmo finaliza
cuando analiza la lista completa sin intercambiar ningún elemento. Si no se han producido
intercambios, significa que ningún elemento estaba desordenado, de modo que la lista está
ordenada de principio a fin.

Tabla 3-1
Primera pasada de Pasada Antes Después Comentarios
BubbleSort
1 20, 30, 10, 40 20, 30, 10, 40 El algoritmo compara los dos primeros
elementos (20 y 30); dado que están
en el orden correcto, no es necesario
intercambiarlos.
2 20, 30, 10, 40 20, 10, 30, 40 El algoritmo compara los dos
elementos siguientes (30 y 10);
puesto que están desordenados, se
intercambian.
3 20, 10, 30, 40 20, 10, 30, 40 El algoritmo compara los dos
elementos siguientes (30 y 40); como
están en el orden correcto, no es
necesario intercambiarlos.

Como se muestra en la tabla 3-1, al final del primer paso, BubbleSort ha realizado un
intercambio y existe la posibilidad de que los elementos sigan sin estar totalmente ordenados.
Por lo tanto, BubbleSort da otra pasada a la lista, como se muestra en la tabla 3-2.

Tabla 3-2
Segunda pasada de Pasada Antes Después Comentarios
BubbleSort
1 20, 10, 30, 40 10, 20, 30, 40 El algoritmo compara los dos primeros
elementos (20 y 10); dado que están
desordenados, se intercambian.
2 10, 20, 30, 40 10, 20, 30, 40 El algoritmo compara los dos
elementos siguientes (20 y 30); como
están en el orden correcto, no es
necesario intercambiarlos.
3 10, 20, 30, 40 10, 20, 30, 40 El algoritmo compara los dos
elementos siguientes (30 y 40); como
están en el orden correcto, no es
necesario intercambiarlos.
78 | Lección 3

Al final de la segunda pasada, BubbleSort ha realizado un intercambio más, así que todavía
no puede garantizar que la lista esté ordenada completamente. Por lo tanto, BubbleSort da otra
pasada a la lista, como se muestra en la tabla 3-3.

Tabla 3-3
Tercera pasada de Pasada Antes Después Comentarios
BubbleSort
1 10, 20, 30, 40 10, 20, 30, 40 El algoritmo compara los dos primeros
TOME NOTA
* elementos (10 y 20); dado que están
Cuando se usa en el orden correcto, no es necesario
BubbleSort, una intercambiarlos.
matriz se ordenará en 2 10, 20, 30, 40 10, 20, 30, 40 El algoritmo compara los dos
todos los casos en una elementos siguientes (20 y 30); como
pasada menos que el están en el orden correcto, no es
número de elementos. necesario intercambiarlos.
Así pues, si hay cuatro
elementos (como en el 3 10, 20, 30, 40 10, 20, 30, 40 El algoritmo compara los dos
escenario de ejemplo), elementos siguientes (30 y 40); como
la matriz se ordenará están en el orden correcto, no es
(con independencia del necesario intercambiarlos.
orden de partida) en tres
pasadas.
Al final de la tercera pasada, BubbleSort no ha realizado ningún intercambio. Esto garantiza
que ahora la lista está ordenada correctamente y el algoritmo puede finalizar.
En C#, el algoritmo BubbleSort se puede expresar mediante el método siguiente:
static int[] BubbleSort(int[] numbers)
{
  bool swapped;
  do
  {
    swapped = false;
     for (int i = 0; i < numbers.Length − 1; i++)
     {
        if (numbers[i] > numbers[i + 1])
        {
          //intercambio
           int temp = numbers[i + 1];
           numbers[i + 1] = numbers[i];
           numbers[i] = temp;
          swapped = true;
        }
      }
  } while (swapped == true);
  return numbers;
}
Conceptos generales del desarrollo de software | 79

Conceptos de QuickSort
El algoritmo QuickSort usa operaciones de particionamiento y comparación para
organizar los elementos de una lista en el orden correcto.

El algoritmo QuickSort usa la técnica de “divide y vencerás” para crear particiones de


forma continua en una lista hasta reducir el tamaño del problema tanto que apenas requiera
ordenación. En los pasos siguientes se explica este proceso con más detalle:
• Una lista de cero o uno siempre está ordenada en sí misma.
• Si la lista es mayor, se toma cualquiera de sus elementos como elemento de referencia.
A continuación, se divide la lista de tal manera que todos los elementos que son menores
o iguales que el elemento de referencia se coloquen en la lista de la izquierda y todos los
que son mayores se sitúen en la lista de la derecha. Ahora, la combinación de la lista de
la izquierda, el elemento de referencia y la lista de la derecha siempre estará ordenada si
lo están las listas de la izquierda y la derecha.
• El problema ha quedado dividido en dos listas de menor tamaño, la de la izquierda y la
de la derecha.
• Ambas se resuelven mediante la técnica descrita en los puntos anteriores.
• Por último, todas las listas pequeñas ya ordenadas se combinan para crear la lista
completa final ordenada.
En la siguiente tabla se explica el algoritmo QuickSort con un breve ejemplo.

Tabla 3-4
Visualización de QuickSort Pasada Datos que se van a ordenar Comentarios
1 50, 10, 30, 20, 40 S e comienza por una lista desordenada y se toma
un elemento de referencia; en este caso, 30.
2 20, 10  30    50, 40 Se crea una partición en la lista. Los elementos
menores que el elemento de referencia
se incluyen en la lista de la izquierda y
los mayores, en aquella de la derecha. A
continuación, para ordenar la lista de la
izquierda, se toma un elemento de referencia
(en este caso, el 10). De igual forma, para
ordenar la lista de la derecha, se toma un
elemento de referencia (en este caso, el 40)
para ordenarla.
3 -  10  20   30   -   40   50  E n la lista de la izquierda, 20 es mayor que
10; en la lista de la derecha, 50 es mayor que
40; por lo tanto, tanto 20 como 50 se llevan
a la lista de la derecha. Con ello se obtienen
listas de un solo número que, por definición,
siempre están ordenadas.
4 10, 20, 30, 40, 50 Todas las pequeñas listas ordenadas se
combinan para crear la lista ordenada final
completa.

Hasta ahora, podría parecer que el principal inconveniente del algoritmo QuickSort es la
cantidad de memoria adicional que se requiere para crear las pequeñas listas independientes.
Sin embargo, no es necesario crear estas listas independientes. Mediante una técnica
ligeramente modificada, las particiones de la matriz se pueden realizar in situ, como se
muestra en el siguiente listado de código:
static int Partition (int[] numbers, int left,
  int right, int pivotIndex)
80 | Lección 3

{
    int pivotValue = numbers[pivotIndex];
  // mover el elemento de referencia al final
  int temp = numbers[right];
  numbers[right] = numbers[pivotIndex];
  numbers[pivotIndex] = temp;
  // newPivot almacena el índice del primero
  // el número es mayor que el elemento de referencia
  int newPivot = left;
  for (int i = left; i < right; i++)
  {
    if (numbers[i] <= pivotValue)
    {
    temp = numbers[newPivot];
    numbers[newPivot] = numbers[i];
    numbers[i] = temp;
    newPivot++;
    }
  }
  //mover el elemento de referencia a su posición ordenada
  temp = numbers[right];
  numbers[right] = numbers[newPivot];
  numbers[newPivot] = temp;
  return newPivot;
}
Con esta técnica, primero se mueve el elemento de referencia al final de la matriz. Luego,
todos los elementos menores o iguales que él se mueven a la parte delantera de la matriz. Por
último, el elemento de referencia se sitúa justo antes del elemento mayor que sí mismo, con lo
que se crea una partición efectiva de la matriz.
Luego, QuickSort puede usar este algoritmo de particionamiento para dividir la lista, reducir el
problema a otros de menor tamaño y resolverlos recursivamente:
static int[] QuickSort(int[] numbers,
   int left, int right)
{
  if (right > left)
  {
    int pivotIndex = left + (right − left) / 2;
    //particionamiento de la matriz
    pivotIndex = Partition(
      numbers, left, right, pivotIndex);
    //ordenación de la partición izquierda
    QuickSort(
      numbers, left, pivotIndex − 1);
Conceptos generales del desarrollo de software | 81

    // ordenación de la partición derecha


    QuickSort(
      numbers, pivotIndex + 1, right);
  }
  return numbers;
LISTO PARA CERTIFICACIÓN }
¿Comprende los
Debido a su enfoque de particionamiento, el algoritmo QuickSort es mucho más rápido que
algoritmos de
BubbleSort.
ordenación comunes?
3.3

RESUMEN DE CONOCIMIENTOS

En esta lección hemos aprendido lo siguiente:


• La administración del ciclo de vida de las aplicaciones (ALM) se refiere a las
diversas actividades que giran en torno a un nuevo producto de software, desde su
concepción hasta el momento en que madura y, en última instancia, tal vez se retira.
• Las pruebas de software consisten en comprobar el software en relación con sus
requisitos. Las pruebas se llevan a cabo después de completar la mayor parte del
trabajo de desarrollo.
• Las estructuras de datos son técnicas que permiten organizar y almacenar datos
en la memoria del equipo. El modo en que se almacenan los datos afecta a su
recuperación y manipulación. Para comprender una estructura de datos no solo es
preciso entender su patrón de almacenamiento, sino también los métodos que se
usan para crear la estructura, obtener acceso a ella y manipularla.
• Una matriz es una colección de elementos del mismo tipo de datos que se almacenan
en ubicaciones de memoria contiguas y se direccionan mediante uno o varios índices.
• Una cola es una colección de elementos en la que el primer elemento que se agrega
es el primero que se quita.
• Una pila es una colección de elementos en la que el último elemento que se agrega
es el primero que se quita.
• Una lista de vínculo es una colección de nodos organizados de tal forma que cada
uno de ellos contiene un vínculo al siguiente nodo de la secuencia.
• El algoritmo BubbleSort usa una serie de operaciones de comparación e intercambio
para organizar los elementos de una lista en el orden correcto.
• El algoritmo QuickSort usa operaciones de particionamiento y comparación para
organizar los elementos de una lista en el orden correcto.

■ Evaluación de conocimientos
Rellene los espacios en blanco
Complete las oraciones siguientes escribiendo la palabra o palabras correctas en los
espacios en blanco proporcionados.
1. En las pruebas de ______, los evaluadores aplican sus conocimientos del funcionamiento
interno del sistema mientras lo comprueban.
2. Generalmente, con cada corrección, los evaluadores de software llevan a cabo una batería
de ______ para asegurarse de que cada funcionalidad de la cual se tenía constancia de
que funcionaba correctamente siga de ese modo.
82 | Lección 3

3. El algoritmo BubbleSort usa una serie de operaciones de ______ e ______ para organizar
los elementos de una lista en el orden correcto.
4. Un(a) ______ es una colección de elementos en la que el último elemento que se agrega
es el primero que se quita.
5. El ______ es el proceso de definición pormenorizada de los requisitos empresariales de
un sistema de software nuevo.
6. Una lista de vínculo es una colección de nodos organizados de tal forma que cada uno de
ellos contiene un(a) ____ al siguiente nodo de la secuencia.
7. La operación ______ agrega un elemento a la cola y la operación ______ quita un
elemento de ella.
8. El algoritmo QuickSort usa operaciones de ______ y comparación para organizar los
elementos de una lista en el orden correcto.
9. Un(a) ______ es responsable de analizar las necesidades empresariales y convertirlas en
requisitos que el equipo de desarrollo pueda satisfacer.
10. Las pruebas alfa y beta forman parte de las pruebas de ______ de un sistema.

Varias opciones
Rodee con un círculo la letra correspondiente a la mejor respuesta.
1. El producto que está desarrollando aún no está terminado, pero le gustaría distribuirlo a
un público más amplio de clientes para realizar pruebas y obtener comentarios. ¿En cuál
de los siguientes niveles de pruebas encajaría esta actividad?
a. Pruebas de integración
b. Pruebas del sistema
c. Pruebas de aceptación
d. Pruebas de regresión
2. Los evaluadores de una aplicación de software tienen acceso a su código fuente y planean
escribir casos de prueba que garanticen que los métodos devuelvan valores correctos. ¿En
cuál de los siguientes niveles de pruebas figuraría esta actividad?
a. Pruebas de integración
b. Pruebas unitarias
c. Pruebas alfa
d. Pruebas beta
3. ¿Cuál de las siguientes estructuras de datos permite el acceso directo a todos sus elemen-
tos?
a. Matriz
b. Pila
c. Cola
d. Lista de vínculo
4. ¿Cuál de las siguientes actividades del ciclo de vida de las aplicaciones usa el arquitecto
para crear los planos técnicos de un sistema?
a. Análisis de requisitos
b. Diseño
c. Desarrollo
d. Mantenimiento
5. En su aplicación, usa una estructura de datos de cola para manipular la información.
Necesita encontrar qué elemento de datos se procesará a continuación, pero no desea pro-
cesarlo aún. ¿Cuál de las siguientes operaciones de cola debe usar?
a. Enqueue
b. Dequeue
c. Peek
d. Contains
Introducción a la programación orientada a objetos | 83

6. Está desarrollando un programa que requiere realizar un seguimiento de las llamadas a


métodos. Solo se puede invocar un método a la vez. Sin embargo, una llamada al método
podrá invocar a su vez otros métodos. Cuando finaliza un método, devuelve el control al
método de llamada. ¿Qué estructura de datos debe usar para realizar el seguimiento de
estas llamadas a métodos?
a. Cola
b. Matriz
c. Lista de vínculo
d. Pila
7. Está desarrollando un programa que simula un procesador de trabajos. Con frecuencia,
los trabajos se presentan más rápido de lo que se pueden procesar, en cuyo caso deben
esperar a su turno para procesarlos. Debe asegurarse de que el trabajo que llegó primero
sea también el primero en procesarse. ¿Cuál de las siguientes estructuras de datos es la
más adecuada para este requisito?
a. Matriz
b. Cola
c. Lista de vínculo
d. Pila
8. Escribe el siguiente código en un programa:
int[] numbers = {2, 3, 1, 4};
numbers [2] = 4;
¿Cuál será el contenido de la matriz después de ejecutar la segunda instrucción?
a. {2, 4, 1, 4}
b. {2, 3, 4, 4}
c. {2, 4, 1, 2}
d. {4, 3, 1, 4}
9. Está desarrollando un programa que realiza operaciones de inserción y eliminación fre-
cuentes con los datos. Los requisitos exigen también la funcionalidad de obtener acceso a
los registros anterior y siguiente cuando el usuario haga clic en el botón correspondiente.
¿Cuál de las siguientes estructuras de datos es la más adecuada para estas necesidades?
a. Matriz
b. Lista de vínculo circular
c. Lista de vínculo
d. Lista de doble vínculo
10. Está desarrollando un programa que realiza operaciones de inserción y eliminación
frecuentes con los datos. Es preciso que se obtenga acceso a los elementos de datos como
una pila, con la funcionalidad de último en entrar, primero en salir. Su solución debe
requerir la menor cantidad de memoria posible. ¿Cuál de las siguientes estructuras de
datos es la más adecuada para estos requisitos?
a. Matriz
b. Lista de vínculo circular
c. Lista de vínculo
d. Lista de doble vínculo

■ Evaluación de competencias
Escenario 3-1: Uso de matrices
Está escribiendo un programa que usa una matriz bidimensional. La matriz tiene cuatro filas y
cinco columnas. Debe imprimir el elemento mayor de cada fila de la matriz. ¿Cómo se escribe
tal programa?
84 | Lección 3

Escenario 3-2: Uso de colas


Está escribiendo un programa que usa dos colas. Los datos de cada cola ya están organizados
en orden ascendente. Debe procesar el contenido de ambas colas de manera tal que la salida de
datos se muestre ordenada en la pantalla. ¿Cómo se escribe tal programa?

■ Evaluación de aptitudes
Escenario 3-3: Uso de pilas
Está escribiendo un programa que usa dos pilas. Los datos de cada pila ya están organizados
en orden descendente. Debe procesar el contenido de ambas pilas de manera tal que la salida
se muestre en la pantalla en orden ascendente. ¿Cómo se escribe tal programa?

Escenario 3-4: Uso de listas de vínculo


Está escribiendo un programa que almacena una lista de nombres de productos en una lista de
vínculo. El usuario especificará el nombre de un producto y el programa deberá comprobar si
la lista de vínculo contiene el producto dado o no. ¿Cómo se escribe tal programa?
Comprensión de las LECCIÓN 4
aplicaciones web
M AT R I Z D E C O N O C I M I E N T O S D E L A L E C C I Ó N

Conocimientos y conceptos Objetivo del examen MTA Número de objetivo del


examen MTA
Conceptos del desarrollo Conceptos del desarrollo 4.1
de páginas web de páginas web.
Conceptos del desarrollo Conceptos del desarrollo de 4.2
de aplicaciones ASP.NET aplicaciones web Microsoft ASP.NET.
Conceptos del hospedaje Conceptos del hospedaje 4.3
de sitios web IIS de sitios web.
Conceptos del desarrollo Conceptos de los servicios web. 4.4
de servicios web

TÉRMINOS CLAVE
administración de estado hospedaje de sitios web programación del lado servidor
administración de estado del Internet Information Protocolo simple de acceso a
lado cliente Services (IIS) objetos (SOAP)
administración de estado del JavaScript servicios web
lado servidor Lenguaje de marcado de sitio web
directorio virtual hipertexto (HTML) Web Service Description
hojas de estilos en programación del lado cliente Language (WSDL)
cascada (CSS)

Usted es desarrollador de software de una gran organización empresarial. Le han


encargado desarrollar una aplicación que se pueda usar a través de una red, como la
World Wide Web. Aunque se implementará en un servidor web Windows, los usuarios de
la aplicación usarán diversos sistemas operativos y exploradores web.

■ Conceptos del desarrollo de páginas web

Una página web es un documento que se presenta a través de la World Wide Web (WWW)
y que puede mostrarse en un explorador web. Las páginas web se desarrollan usando
CONCLUSIÓN el Lenguaje de marcado de hipertexto (HTML) y se almacenan en un servidor web.
Los exploradores web descargan el código HTML solicitado desde el servidor web y lo
representan en la pantalla del usuario.

85
86 | Lección 4

La World Wide Web (también denominada WWW o “la Web”) es un sistema de documentos
de hipertexto y otros recursos (como imágenes y vídeo) interconectados a los que se puede
obtener acceso a través de Internet. Para hacer posible la WWW, han de funcionar en
combinación varias tecnologías. En esta sección, analizaremos dos de estas tecnologías:
• Protocolo de transferencia de hipertexto (HTTP); y
• Lenguaje de marcado de hipertexto (HTML)
HTTP es el protocolo de comunicación subyacente que se usa en la World Wide Web. HTTP
proporciona el lenguaje común que usan los servidores y exploradores web para comunicarse.
HTTP usa un localizador uniforme de recursos (URL) para identificar de forma exclusiva y
direccionar cada recurso en Internet. Una dirección URL es esencialmente una dirección web
con este aspecto: http://www.microsoft.com/en/us/default.aspx. Cada dirección URL comienza
con un protocolo. En este ejemplo, el protocolo es HTTP. Seguramente observará también el
protocolo HTTPS (HTTP seguro) que se usa para las aplicaciones seguras en las que es preciso
cifrar los datos antes de transmitirlos a través de la red. Después del protocolo, la siguiente
parte de la dirección URL es la dirección del servidor web (en este caso, www.microsoft.com),
seguida de la ubicación del recurso dentro del servidor web (/en/us/) y, por último, el recurso
solicitado en sí (default.aspx). Todos los documentos, imágenes, vídeos y otros recursos de la
web se identifican mediante una dirección URL.
Cuando un explorador envía una solicitud HTTP de una página web a un servidor web (tanto
la página como el servidor se identifican mediante una dirección URL), el servidor prepara
una respuesta HTTP para el explorador. Esta respuesta especifica el contenido y el diseño de la
página web.

Los términos “Internet” y “la Web” a menudo se usan indistintamente, pero en realidad son
distintos y no deben confundirse. Internet es un sistema de comunicaciones de datos global
*
TOME NOTA que proporciona conectividad entre equipos. En cambio, la Web es uno de los diversos
servicios disponibles en Internet que permite a los usuarios obtener acceso a recursos con
hipervínculos.

El lenguaje que el servidor y explorador web usan para describir una página web es el
Lenguaje de marcado de hipertexto (HTML). HTML es un lenguaje basado en texto que usa
varias etiquetas de marcado que describen el modo en que se muestra el contenido. HTML
permite hacer referencia a imágenes, vídeos y otros objetos en un archivo, a fin de crear
páginas web multimedia. HTML también puede incrustar scripts (por ejemplo, JavaScript) que
afectan al comportamiento de las páginas web y se pueden usar para incluir hojas de estilos en
cascada (CSS) que definen el formato y el diseño del contenido de una página. El explorador
lee el código HTML y representa los resultados en la pantalla.
Una página web puede contener hipervínculos a otros recursos, tales como imágenes y vídeos.
Cada uno de estos recursos se identifica mediante su propia dirección URL. Así pues, para
representar una página en su totalidad, el explorador realizará solicitudes HTTP adicionales
con objeto de obtener estos recursos y mostrarlos como parte de la página web.
En las siguientes secciones, conoceremos mejor los diversos componentes que conforman una
página web, tales como HTML, CSS y JavaScript.

Conceptos de HTML

El Lenguaje de marcado de hipertexto (HTML) es el lenguaje que usan los exploradores


y servidores web para describir una página web.

El propósito de HTML es proporcionar un lenguaje estándar para describir páginas web, de tal
forma que los diversos exploradores web lo entiendan y muestren la página correspondiente.
HTML es un lenguaje basado en texto, lo que significa que es posible escribir y editar páginas
Comprensión de las aplicaciones web | 87

HTML con cualquier editor de texto. Cuando se envía HTML a un explorador web, se envía el
TOME NOTA
* texto completo de la página. De hecho, la mayoría de los exploradores permiten ver el código
HTML es un lenguaje fuente HTML de una página web.
basado en el texto por
lo que se refiere a la El código HTML consta de un conjunto de etiquetas (también denominadas elementos HTML)
escritura del código. que definen la estructura y el contenido de una página. Por ejemplo, la etiqueta <html>
HTML proporciona especifica el principio de un documento HTML. Las etiquetas HTML siempre van entre
etiquetas para integrar corchetes angulares y se usan en parejas. En concreto, cada etiqueta inicial tiene una etiqueta
imágenes, audio, vídeo final correspondiente. Las etiquetas finales contienen una barra diagonal que las identifica
y muchos otros tipos de como tales. Por ejemplo, la etiqueta final de <html> es </html>.
contenido multimedia Una página HTML tiene dos partes diferentes: un encabezado y un cuerpo. El encabezado
e interactivo en una se incluye entre las etiquetas <head> y </head> y se usa para proporcionar un título para
página web. el documento y vínculos a los elementos externos que se usen en la página, tales como los
archivos CSS y JavaScript. El cuerpo va incluido entre las etiquetas <body> y </body> y se
usa para proporcionar la estructura y contenido completos de la página que se mostrará en un
TOME NOTA
* explorador web.
En este ejemplo, observe
que el documento A continuación se muestra un ejemplo de etiqueta HTML que muestra una imagen:
HTML no contiene la <img height="400px" width="400px"
imagen propiamente
dicha. En cambio, alt="Mimas Cassini" src=
la etiqueta <img> "http://upload.wikimedia.org/wikipedia/commons/b/bc/Mimas_Cassini.jpg"/>
especifica la dirección Observe que la etiqueta <img> especifica atributos adicionales. Por ejemplo, el atributo src
URL de la imagen, especifica la ubicación del archivo de imagen y los atributos height y width especifican las
que el explorador dimensiones que se deberán aplicar al representar la imagen en un explorador.
descarga por separado y
representa como parte de Ahora, vamos a estudiar otro ejemplo de etiqueta HTML:
la página.
<a href="http://en.wikipedia.org/wiki/Mimas_(moon)">
Luna de Saturno</a>
En este caso, <a> es la etiqueta de anclaje, que se usa para crear hipervínculos en una página
web. El atributo href asociado a esta etiqueta especifica la dirección URL de destino y el texto
contenido en la etiqueta de anclaje es el que se muestra como vínculo.

En esta lección no se abarcan todos los elementos HTML. Para obtener más información
*
TOME NOTA
sobre ellos, busque “elementos HTML” en MSDN.

En el ejercicio se ilustran los pasos necesarios para crear un documento HTML.

TRABA JO CON HTML

PREPÁRESE. Para crear un documento HTML, lleve a cabo estas acciones:


1. Abra Visual Studio. Cree un nuevo proyecto basado en la plantilla Aplicación web vacía
de ASP.NET. Asigne al proyecto el nombre WorkingWithHTML y asigne a la solución el
nombre Lesson04.
2. Seleccione Proyecto > Agregar nuevo elemento y, a continuación, seleccione la
plantilla Página HTML. Asigne al archivo el nombre default.htm.
3. Sustituya el código predeterminado del archivo HTML por el siguiente:
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
  <title>Saturn's Moon</title>
</head>
88 | Lección 4

<body>
<h1>Mimas Cassini</h1>
La etiqueta img se usa para mostrar la imagen de una
<a href="http://en.wikipedia.org/wiki/Mimas_(moon)">
  Luna de Saturno</a>: <br />
<img height="400px" width="400px"
  alt="Mimas Cassini"
  src="http://goo.gl/3BeK"/>
</body>
</html>
4. Seleccione Depurar > Iniciar depuración (o presione F5). Se abrirá la página default.
htm en un explorador web. La salida debe ser similar a la figura 4-1, donde se observa
cómo funcionan las etiquetas <img> y <a>.

Figura 4-1
Página HTML sencilla que
contiene una imagen y un
hipervínculo

Conceptos de las hojas de estilos en cascada

Las hojas de estilos en cascada (CSS) permiten almacenar la información acerca del
estilo y el formato de una página web en un espacio separado del código HTML. Esta
separación hace más fácil actualizar la apariencia de su sitio web. Visual Studio incluye
herramientas para crear hojas de estilos y ver su vista previa.

CSS es un lenguaje que describe información sobre cómo se muestra una página web. Al
representar las páginas web en el explorador, HTML especifica lo que se mostrará y las hojas
de estilos en cascada (CSS) especifican cómo se mostrará ese material. Por ejemplo, HTML
puede especificar que el documento tiene un título H1 con un texto determinado y CSS puede
especificar la fuente y el color que se aplicarán a ese título.
CSS permite separar el diseño de una página web de su contenido. Esta separación permite
cambiar uno de ellos sin que afecte al otro. Combinar el contenido y el estilo dificulta el
Comprensión de las aplicaciones web | 89

mantenimiento de un sitio web. Por ejemplo, supongamos que deseamos cambiar el color
y la fuente de todos los títulos H1 del sitio web. Una forma de hacerlo podría ser abrir un
editor de HTML y modificar cada archivo del sitio web donde se use la etiqueta H1. Podría
ser una solución aceptable si el sitio web solo tuviese una o dos páginas. Pero ¿y si tiene más,
por ejemplo, 50 o 100? Imagínese lo que supondría cambiar manualmente todas las páginas.
Si este tipo de cambios se solicitan con frecuencia, el proceso de desarrollo web resultará
TOME NOTA
* aburrido y proclive a cometer errores. Si lo pensamos, ¿existe un modo de garantizar que no se
Cuando se usa con
haya omitido ninguna etiqueta H1?
eficacia, las CSS
son una excelente Afortunadamente, con CSS es posible incluir toda la información de estilos en un archivo
herramienta para separado y conectarlo a todas las páginas del sitio web. Así, una vez configurado el archivo
aumentar la coherencia CSS, es posible modificar cualquier estilo (por ejemplo, el color y la fuente de los títulos H1)
y la facilidad de con solo cambiarlo en el archivo CSS; este único cambio afectará a todas las páginas del sitio
mantenimiento de todo web.
el sitio.
DISEÑO DE HOJAS DE ESTILOS EN CASCADA
El lenguaje CSS se basa en texto y es fácil de leer y entender. A continuación se muestra un
ejemplo de una página HTML que define estilos CSS:
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
  <title>Conceptos de CSS</title>
  <style type="text/css">
    body
    {
      grosor de fuente: Verdana;
      font-size: 9pt;
    }
    div
    {
      color:Red;
    }
    .block
    {
      background-color: Yellow;
      border-color: Blue;
      border-width: thin;
      border-style: outset;
      font-family: Arial;
    }
  </style>
</head>
<body>
  Ejemplo de texto del cuerpo <br />
  <div>Ejemplo de texto DIV</div>
  <div class="block">Ejemplo de texto DIV
    con la clase block</div>
  <span class="block">Ejemplo de texto SPAN
    con la clase block</span>
</body>
</html>
90 | Lección 4

Tenga en cuenta que las definiciones de CSS deben estar dentro del elemento <style> y bajo
el elemento <head>. Este código CSS concreto define dos estilos de elemento y un estilo de
clase. El primer estilo se aplica al elemento HTML body y especifica que todo el texto de ese
elemento debe usar la fuente Verdana con un tamaño de letra de 9 puntos. El segundo estilo
de elemento especifica que el texto del elemento DIV debe escribirse en rojo. Por último, se
define una clase denominada “block”. Las definiciones de clase de CSS llevan un punto (“.”)
como prefijo. El contenido de todos los elementos HTML que usen esta clase se mostrará con
fondo amarillo y borde. Cuando esta página concreta aparezca en un explorador, su aspecto
deberá ser el que se muestra en la figura 4-2.

Figura 4-2
Formato HTML con hojas de
estilos en cascada

En la figura, observe que el texto resaltado aparece como resultado de la clase block. Sin
embargo, la clase CSS block no especifica el color del texto. En la primera línea de texto
resaltado, la clase block se aplica al elemento DIV; en la segunda línea de texto resaltado, la
clase block se aplica al elemento SPAN. En el primer caso, como la clase block se aplica a un
texto DIV, el estilo de color del elemento DIV se propaga a la representación final.
En el ejemplo anterior, el archivo CSS se escribió dentro del archivo HTML. Suele resultar
más útil escribir el código CSS en su propio archivo independiente y, después, vincular el
archivo HTML a este archivo CSS. Aprenderemos a hacerlo en el siguiente ejercicio.

TRABA JO CON ARCHIVOS CSS

PREPÁRESE. Para escribir un archivo CSS y vincularlo a un archivo HTML, siga este
procedimiento:
1. Agregue un nuevo proyecto basado en la plantilla Aplicación web vacía de ASP.NET a la
solución Lesson04. Asigne al proyecto el nombre UnderstandingCSS.
2. Seleccione Proyecto > Agregar nuevo elemento. Seleccione la plantilla Hoja de estilos.
Asigne al archivo el nombre styles.css. Sustituya el código predeterminado del archivo
por el siguiente:
body
{
  grosor de fuente: Verdana;
  font-size: 9pt;
}
div
{
  color:Red;
}
Comprensión de las aplicaciones web | 91

.block
{
  background-color: Yellow;
  border-color: Blue;
  border-width: thin;
  border-style: outset;
  font-family: Arial;
}
3. Seleccione Proyecto > Agregar nuevo elemento y, a continuación, seleccione la
plantilla Página HTML. Asigne al archivo el nombre default.htm. Sustituya el código
predeterminado del archivo por el siguiente:
<!DOCTYPE html PUBLIC
"–//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1–
  transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
  <link rel="STYLESHEET"
    type="text/css" href="styles.css" />
  <title>Conceptos de CSS</title>
</head>
<body>
  Ejemplo de texto del cuerpo <br />
  <div>Ejemplo de texto DIV</div>
  <div class="block">Ejemplo de texto DIV
    con la clase block</div>
  <span class="block">Ejemplo de texto SPAN
    con la clase block</span>
</body>
</html>
4. Seleccione Depurar > Iniciar depuración (o presione F5). La página default.htm se
TOME NOTA
* abrirá en un explorador web; la salida debe ser similar a la figura 4-2 (presentada
Cuando las CSS se
almacenan en archivos anteriormente).
separados, el explorador Como se muestra en el ejercicio de ejemplo, el elemento HTML <link> se usa para vincular un
del usuario descargará y archivo CSS a una página HTML:
guardará estos archivos
localmente. Por lo tanto, <link rel="STYLESHEET"
se pueden usar en varias   type="text/css" href="styles.css" />
páginas sin necesidad
de descargarlos otra El elemento <link> siempre se coloca dentro del elemento <head> y el atributo href especifica
vez. Esto reduce la dirección del archivo CSS que se va a usar. Para vincular varias páginas al mismo archivo
las transferencias CSS, deberá incluir el elemento <link> dentro de cada página HTML.
innecesarias de datos. Visual Studio incluye un diseñador de estilos integrado que le ayudará a diseñar nuevos
estilos CSS o modificar los ya existentes. Al abrir un archivo .css, aparece un nuevo menú
denominado Estilos. Desde este menú, se puede crear un nuevo estilo seleccionando Estilos >
Agregar regla de estilo. También puede modificar el estilo seleccionado actualmente; para ello,
elija la opción Estilos > Generar estilo. Esta opción abre el cuadro de diálogo Modificar estilo,
como se muestra en la figura 4-3.
92 | Lección 4

Figura 4-3
Cuadro de diálogo Modificar
estilo

Conceptos de JavaScript

JavaScript es un lenguaje de scripting del lado cliente que se ejecuta en los exploradores
web para ayudar a crear páginas web mucho más interactivas de lo que es posible usando
solamente HTML. JavaScript se usa en millones de páginas web y es compatible con
todos los exploradores modernos.

JavaScript se usa para aportar capacidad de respuesta a los sitios web e interactividad a las
páginas web. Para ello, JavaScript ejecuta el código en el lado cliente (el explorador web)
y minimiza las idas y venidas innecesarias al servidor web. Tomemos como ejemplo a un
usuario que tiene que especificar en una página web sus datos personales, tales como su
nombre, dirección de correo electrónico y número de teléfono. Un requisito común consiste
en realizar la validación de los datos para asegurarse de que los campos de entrada no estén
vacíos y de que la dirección de correo electrónico y el número de teléfono del usuario se
hayan especificado con el formato correcto. Sin JavaScript, sería preciso enviar el formulario
al servidor, que validaría los datos y devolvería los resultados al cliente. Esta transmisión de
información tarda tiempo y degrada la experiencia del usuario. Sin embargo, una solución
JavaScript puede realizar este tipo de validación de datos desde el propio explorador, con lo
que mejora la experiencia del usuario.
Como hemos mencionado anteriormente, el código JavaScript se ejecuta localmente en el
explorador web (el cliente), no en el servidor web. Por este motivo, en ocasiones nos referimos
a JavaScript como un “lenguaje de scripting del lado cliente” y denominamos la programación
con JavaScript “programación del lado cliente”.
El comportamiento en tiempo de ejecución del código del lado cliente depende del explorador
que lo ejecute. Sin embargo, este comportamiento es independiente de la tecnología de
servidor y del marco de programación. Por consiguiente, para el código JavaScript ejecutado
en un explorador web, no importa si la página web se generó mediante ASP.NET o PHP ni si
la presenta un servidor web Windows o Linux.
Los lenguajes de programación JavaScript y C# usan una sintaxis influenciada por el
lenguaje de programación C. Sin embargo, JavaScript y C# son muy diferentes en la forma
de ejecutarse. En concreto, JavaScript lo ejecuta el explorador web y el código JavaScript se
interpreta, no se compila como ocurre con C#.
Todo el código JavaScript debe incluirse dentro del elemento <script>. El elemento <script>
suele ir dentro del elemento <head>, aunque no es obligatorio que sea así. Pueden existir
Comprensión de las aplicaciones web | 93

Muchos sitios web modernos ofrecen una experiencia sumamente interactiva equiparable
a la de las aplicaciones de escritorio. Dichos sitios se pueden desarrollar mediante la
programación Ajax. Ajax es la abreviatura de “Asynchronous JavaScript and XML”
*
TOME NOTA
(JavaScript y XML asincrónicos). Ajax toma muchos recursos de JavaScript a fin de
proporcionar aplicaciones web con gran capacidad de respuesta. El marco ASP.NET AJAX
permite implementar la funcionalidad de Ajax en páginas web ASP.NET.

varios elementos <script> en una misma página. Para ver cómo funciona JavaScript, pruebe
con el ejercicio siguiente.

TRABA JO CON JAVASCRIPT

PREPÁRESE. Para empezar a trabajar con JavaScript, lleve a cabo las siguientes tareas:
1. Agregue un nuevo proyecto basado en la plantilla Aplicación web vacía de ASP.NET a la
solución Lesson04. Asigne al proyecto el nombre UnderstandingJavaScript.
2. Seleccione Proyecto > Agregar nuevo elemento y, a continuación, seleccione la
plantilla Página HTML. Asigne al archivo el nombre default.htm. Sustituya el código
predeterminado del archivo por el siguiente:
<!DOCTYPE html PUBLIC
"–//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1–
  transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
  <title>Conceptos de JavaScript</title>
  <script type="text/javascript"
    language="javascript">
    username = prompt("Escriba su nombre");
    message = "Hola, " + username 1+
     ". Su nombre tiene ";
    nameLen = username.length;
    if (nameLen > 5)
     message = message + "más de ";
    else if (nameLen < 5)
     message = message + "menos de ";
    else
     message = message + "exactamente ";
    message = message + "5 caracteres.";
    alert(message);
  </script>
</head>
<body>
</body>
</html>
94 | Lección 4

3. Seleccione Depurar > Iniciar depuración (o presione F5). Se abrirá la página


default.htm en un explorador web. Observe que el código JavaScript le pide que
especifique su nombre. Una vez lo ha hecho, un cuadro de diálogo muestra un
mensaje, que varía según la longitud de su nombre, como se muestra en las
figuras 4-4 y 4-5.
Figura 4-4
Mensaje de usuario de
JavaScript

Figura 4-5
Cuadro de diálogo de
JavaScript

Como sucede con los archivos CSS, el código JavaScript también puede incluirse en un
archivo separado y vinculado a un archivo HTML mediante el elemento de script, como se
muestra a continuación:
<script src="SampleScript.js">
</script>
En este caso, el archivo SampleScript.js contiene todo el código JavaScript y el elemento
script establece un vínculo a este archivo mediante el atributo src. Almacenar el código
JavaScript en archivos externos ofrece varias ventajas:
TOME NOTA
* • Facilita el mantenimiento: si se usa el mismo código JavaScript en todas las páginas de
Aunque todos los un sitio web, es posible almacenar ese código en una página central en lugar de repetirlo
exploradores modernos en todas ellas. De este modo, cuando sea preciso modificar el código JavaScript, solo
admiten JavaScript, habrá que cambiarlo en un lugar.
pueden establecerse de • Mejora el rendimiento: almacenar el código JavaScript en un archivo separado reduce
modo que JavaScript el tamaño de la página web. Además, los exploradores pueden descargar y almacenar en
esté desactivado. Puede caché el archivo JavaScript externo para que no se vuelva a descargar a menos que se
usar un elemento modifique.
<noscript> para mostrar
un mensaje específico Visual Studio incluye compatibilidad plena de IntelliSense con el código JavaScript. Incluso
a los usuarios que los controles ASP.NET, como el control TreeView o los controles de validación, usan
optan por no ejecutar JavaScript siempre que es posible para representar el contenido dinámicamente.
JavaScript.
Conceptos de la programación del lado cliente comparada con la
programación del lado servidor
Si un programa es del lado cliente o del lado servidor depende de dónde se ejecute en
última instancia.

La programación del lado cliente se refiere a los programas que se ejecutan totalmente en el
equipo local de un usuario. Ejemplos de programas del lado cliente son la aplicación Windows
Forms y el código JavaScript que se ejecuta en un explorador web. Los programas del lado
cliente no consumen recursos del servidor.
Por otra parte, la programación del lado servidor se refiere a programas que se ejecutan
íntegramente en un servidor y que consumen los recursos de cálculo del servidor. En este caso,
los únicos recursos del cliente que se usan son aquellos que intervienen en la recuperación de
los resultados de procesamiento del servidor. Las aplicaciones web y los servicios web son
Comprensión de las aplicaciones web | 95

ejemplos de programación del lado servidor. Este tipo de programación usa tecnologías del
lado servidor, como ASP.NET, PHP o Ruby on Rails.
En los últimos tiempos, están cobrando popularidad las aplicaciones híbridas, que usan
programación del lado cliente y del lado servidor. Por ejemplo, se pueden diseñar aplicaciones
de cliente inteligente que se ejecutan localmente en equipos cliente pero usan los servicios web
LISTO PARA CERTIFICACIÓN para llevar a cabo determinadas tareas. De hecho, las aplicaciones Ajax usan una combinación
¿Comprende cómo se de programación del lado servidor y de código del lado cliente para crear aplicaciones web
usan HTML, JavaScript interactivas con una gran capacidad de respuesta.
y CSS para desarrollar
páginas web? ASP.NET permite crear aplicaciones que se ejecutan íntegramente en el servidor o aplicaciones
4.1 Ajax híbridas que proporcionan interfaces rápidas con gran capacidad de respuesta pero
almacenan la mayor parte de sus datos en la Web.

■ Conceptos del desarrollo de aplicaciones ASP.NET

ASP.NET es la parte de .NET Framework que permite desarrollar formularios Web


Forms programables y servicios web. Al igual que sucede con cualquier aplicación
CONCLUSIÓN .NET Framework, las aplicaciones ASP.NET se pueden desarrollar en cualquier lenguaje
compatible con .NET Common Language Runtime (CLR), como Visual Basic y C#.

La infraestructura ASP.NET se compone de dos partes principales:


• Un conjunto de clases e interfaces que permite la comunicación entre el explorador y
el servidor web. Estas clases se organizan en el espacio de nombres System.Web.
• Un proceso en tiempo de ejecución, también denominado proceso de trabajo ASP.
NET (aspnet_wp.exe), que controla las solicitudes web de recursos de ASP.NET.
En un nivel superior, una aplicación web ASP.NET se ejecuta mediante una serie de solicitudes
y mensajes de respuesta HTTP entre el explorador cliente y el servidor web. Este proceso
ocurre de la siguiente manera:
1. El usuario solicita un recurso de un servidor web escribiendo una dirección URL
en el explorador web. El explorador envía una solicitud HTTP al servidor web de
destino.
2. El servidor web analiza la solicitud HTTP y busca un proceso que pueda ejecutarla.
3. El resultado de la solicitud HTTP se devuelve al explorador cliente en forma de
respuesta HTTP.
4. El explorador lee la respuesta HTTP y la presenta en una página web para el usuario.
Este proceso se ilustra en la figura 4-6.

Figura 4-6
Comunicación entre un
cliente y un servidor web
96 | Lección 4

Como desarrollador, debe saber lo que ocurre entre bambalinas cuando un servidor web
ejecuta una solicitud de una página ASP.NET. En los siguientes pasos se describe este proceso:
1. Cuando Internet Information Service (IIS) recibe una solicitud HTTP, usa la
extensión de archivo para determinar qué programa de la Interfaz de programación
de aplicaciones para servidores de Internet (ISAPI) debe ejecutar para procesar la
solicitud. Cuando lo que se solicita es una página ASP.NET, pasa la solicitud al
archivo DLL de ISAPI que controla las solicitudes de páginas ASP.NET, que es
aspnet_isapi.dll.
2. El proceso aspnet_isapi.dll pasa la solicitud al proceso de trabajo de ASP.NET
(aspnet_wp.exe), que satisface la solicitud.
3. El proceso de trabajo de ASP.NET compila el archivo .aspx en un ensamblado
y da las instrucciones al Common Language Runtime (CLR) para que ejecute el
ensamblado.
4. Cuando el ensamblado se ejecuta, usa los servicios de varias clases en la biblioteca de
clases de .NET Framework para realizar su trabajo y generar mensajes de respuesta
para el cliente solicitante.
5. El proceso de trabajo de ASP.NET recopila las respuestas generadas por la ejecución
de la página web, crea un paquete de respuesta y lo pasa al proceso aspnet_isapi.dll.
6. aspnet_isapi.dll reenvía el paquete de respuesta a IIS que, a su vez, lo pasa al equipo
cliente solicitante.
Antes de la ejecución, cada página ASP.NET se convierte en una clase. Esta clase deriva la
mayor parte de su funcionalidad de la clase System.Web.UI.Page. La clase Page proporciona
varias propiedades importantes, tales como Request, Response, Session y Server.

La clase Page proporciona varios métodos y propiedades importantes que controlan


cómo se procesa una solicitud de página. Para obtener una lista completa de métodos y
*
TOME NOTA
propiedades, visite http://msdn.microsoft.com/en-us/library/system.web.ui.page.aspx.

Conceptos del modelo de eventos y del ciclo de vida de las páginas ASP.NET
Durante su ejecución, una página ASP.NET atraviesa varias fases de procesamiento
diferenciadas. Cada una de estas fases a su vez atraviesa varios pasos de procesamiento
específicos, tales como inicialización, carga, ejecución del código de controlador de
eventos y representación.

A medida que se ejecuta, la página pasa por las diversas fases de procesamiento. La página
también activa varios eventos a los que es posible adjuntar un controlador de eventos para
poder ejecutar código personalizado en las diferentes fases del procesamiento de la página.
De hecho, los desarrolladores de ASP.NET deben conocer bien el ciclo de vida de las
páginas, para poder escribir un código que se ejecute exactamente en las fases deseadas del
procesamiento de la página.
En la tabla 4.1 se enumeran las distintas fases del ciclo de vida y los eventos asociados a ellas.

En un típico formulario de contacto, se especifica información y se presiona el botón de


envío. Al enviar esta página, esta puede procesar los datos enviados para realizar algunas
acciones, como almacenar la información en una base de datos o enviar un mensaje de
correo electrónico. En muchos casos, la página inicial se muestra de nuevo, con una
*
TOME NOTA
confirmación de que se ha enviado el formulario. Cuando la información se publica en la
misma página web para procesarla, tiene lugar un postback. El postback es distinto de la
carga inicial de la página, porque la página recibe información adicional (por ejemplo, datos
de formulario) como parte del postback.
Comprensión de las aplicaciones web | 97

Tabla 4-1
Fases importantes del ciclo de vida de las páginas ASP.NET

Fase Significado Eventos asociados


Solicitud de página Cuando se recibe una solicitud de una página, comienza el ciclo de vida
de la página. En este punto, ASP.NET decide si la página se puede
proporcionar directamente desde la memoria caché o si es preciso
analizarla y compilarla.
Inicio La fase inicial consiste en determinar si la solicitud es un postback o PreInit
una nueva solicitud. Varias propiedades, tales como Request, Response,
IsPostBack y UICulture se establecen en esta fase.
Inicialización Durante la fase de inicialización, todos los controles en la página se Init
inicializan y quedan disponibles. Un controlador del evento Init es el
mejor lugar para situar el código que debe ejecutarse antes de
continuar procesando la página.
Carga Si la solicitud es un postback, la fase de carga se usa para restaurar las Carga
propiedades de control con información del estado de vista y del estado
de control. Un método que controla el evento Load es el mejor lugar
donde almacenar el código de inicialización para los controles específicos
de esta página.
Administración de Si la solicitud es un postback, se llama a los controladores de eventos
eventos de postback de control durante esta fase. A continuación, se validan los valores
de entrada y se establece la propiedad IsValid para la clase Page.
Prerrepresentación E sta fase señala que la página está a punto de representar su contenido. PreRender
Un controlador del evento PreRender es la última oportunidad de
modificar la salida de la página antes de enviarla al cliente.
Representación En esta fase, la página llama al método Render para cada control y
rellena la respuesta que se enviará al explorador web.
Unload  urante la fase de descarga, se envía la respuesta al cliente y se realiza
D Unload
la limpieza de la página. Durante esta limpieza, se descartan las
propiedades de página, como Request y Response.

Cuando deseamos controlar un evento, debemos escribir código que registre con el evento
un método que lo controle (también denominado controlador de eventos). Esto suele hacerse
mediante el patrón común de registro de eventos que se usa en .NET Framework:
objeto.evento += new EventHandler(controladorEventos);
En esta expresión, reemplazamos objeto por el nombre del objeto que expone el evento, evento
por el nombre del evento y controladorEventos por el nombre del método que controla el
evento.
Sin embargo, cabe destacar que ASP.NET proporciona seis métodos especiales reconocidos
como controladores de eventos de forma predeterminada y para los que no se requiere
el código de registro anterior. Se trata de los métodos con nombres especiales Page_Init,
Page_Load, Page_DataBind, Page_PreRender y Page_Unload. Estos métodos se tratan como
controladores de eventos para los eventos correspondientes expuestos por la clase Page.
Estas conexiones de eventos automáticos se controlan mediante el atributo AutoEventWireup
de la directiva @Page. De forma predeterminada, el valor de este atributo es true, lo que
significa que estos métodos con nombres especiales están conectados automáticamente a sus
correspondientes eventos.
98 | Lección 4

CONCEPTOS DEL CICLO DE VIDA DE LAS PÁGINAS ASP.NET

PREPÁRESE. Para ver cómo se ejecutan los diferentes eventos de la clase Page, realice las
siguientes acciones:
1. Cree un nuevo proyecto basado en la plantilla Aplicación web vacía de ASP.NET en la
solución Lesson04. Asigne al proyecto el nombre PageEvents.
2. Seleccione Proyecto > Agregar nuevo elemento. Seleccione la plantilla Formulario
Web Forms. Asigne al archivo el nombre WebForm1.aspx.
3. En el formato HTML de la página (WebForm1.aspx), asegúrese de que el atributo
AutoEventWireup de la directiva @Page esté establecido en true:
<%@ Page Language="C#" AutoEventWireup="true"
CodeBehind="WebForm1.aspx.cs"
Inherits="PageEvents.WebForm1" %>
4. Haga clic en la ventana de código y seleccione Ver código en el menú contextual para
cambiar a la vista de código. Reemplace el código del archivo de código subyacente
(WebForm1.aspx.cs) por lo siguiente:
using System;
namespace PageEvents
{
  public partial class WebForm1
    : System.Web.UI.Page
  {
    protected void Page_Load
      (object sender, EventArgs e)
    {
      Response.Write
        ("Message from Page_Load. <br/>");
    }
    protected void Page_Init
      (object sender, EventArgs e)
    {
      Response.Write
        ("Message from Page_Init. <br/>");
    }
    protected void Page_PreRender
      (object sender, EventArgs e)
    {
      Response.Write
        ("Message from Page_PreRender. <br/>");
    }
    protected void Page_PreInit
      (object sender, EventArgs e)
    {
      Response.Write
        ("Mensaje de Page_PreInit. <br/>");
    }
  }
}
Comprensión de las aplicaciones web | 99

5. Seleccione Depurar > Iniciar depuración (o presione F5). La página default.htm se


abrirá en un explorador web, como se muestra en la figura 4-7.

Figura 4-7
Formulario Web Forms en
que se muestra el orden de
ejecución de eventos de una
página ASP.NET

En el ejercicio del ejemplo, observe que se usan los caracteres <% y %> para insertar bloques
de código en el formato HTML de una página. El código contenido en estos bloques insertados
se ejecuta durante la fase de representación de la página. Dentro de los bloques de código
insertado, se usa la sintaxis <%=expresión> para resolver una expresión y devolver su valor en
el bloque. Por ejemplo, vamos a fijarnos en el bloque de código siguiente:
<i><% = DateTime.Now.ToShortDateString() %></i>
Al ejecutarlo, este código mostrará la fecha actual en cursiva:
12/01/2010
La directiva @Page especifica varios atributos que controlan cómo ASP.NET representará
una página. Por ejemplo, en este ejercicio, los atributos de la directiva @Page especifican lo
siguiente:
• C# es el lenguaje de programación de esta página web (Language="C#")
• los eventos de la página se conectan automáticamente (AutoEventWireup=true)
• el nombre del archivo de código que contiene la clase asociada con la página
(CodeBehind="WebForm1.aspx.cs")
• el nombre de clase de la página que se hereda (Inherits="PageEvents.WebForm1")

Conceptos de la administración de estado


La administración de estado es un aspecto importante de las aplicaciones web, debido a
la naturaleza desconectada de HTTP. Para administrar el estado existen técnicas del lado
cliente y del lado servidor.

La administración de estado es el proceso de mantener el estado de una página web en


las idas y venidas a través de la red. Los valores de las variables y controles conforman
colectivamente el estado de una página web.
ASP.NET proporciona varias técnicas para preservar la información de estado durante los
sucesivos postbacks de una página. En función de dónde se consuman los recursos, estas
técnicas se pueden agrupar en términos generales en dos categorías: del lado cliente o del lado
servidor.
100 | Lección 4

INTRODUCCIÓN A LA ADMINISTRACIÓN DE ESTADO DEL LADO CLIENTE


La administración de estado del lado cliente usa código HTML y la funcionalidad del
explorador web para almacenar la información de estado en el equipo cliente. Las siguientes
técnicas se usan para almacenar información de estado en el lado cliente:
• Cadenas de consulta: en este caso, el estado se mantiene incluyendo los datos en un
conjunto de pares clave-valor en la porción correspondiente a la cadena de consulta de la
dirección URL de una página. Por ejemplo, la siguiente dirección URL lleva integrada un
par clave (q)-valor (television) de cadena de consulta:
http://www.bing.com/search?q=television. Para recuperar el valor de la clave en una
página ASP.NET, use la expresión Request.QueryString["q"]. QueryString es una
propiedad del objeto Request y obtiene la colección de todas las variables de cadena de
consulta.
• Cookies: las cookies son pequeños paquetes de información que el explorador almacena
localmente en el equipo del usuario. Las cookies se suelen usar para almacenar las
preferencias del usuario y el contenido del carro de la compra, así como para ofrecer a
los usuarios una experiencia de exploración personalizada en visitas posteriores a una
página web. La clase HttpCookie representa una cookie en el código. El código siguiente
muestra cómo establecer una cookie en el equipo cliente:
  HttpCookie cookie =
    new HttpCookie("Name", "Bob");
  cookie.Expires = DateTime.Now.AddMinutes(10);
  Response.Cookies.Add(cookie);
Del mismo modo, el siguiente fragmento de código muestra cómo leer una cookie:
  if (Request.Cookies["Name"] != null)
  {
    name = Request.Cookies["Name"].Value;
  }
• Campos ocultos: los campos ocultos contienen información que no se muestra en una
página web pero sí forma parte del código HTML de la página. Los campos ocultos
pueden crearse mediante el elemento HTML <input type="hidden">. El control de
servidor HTML HtmlInputHidden de ASP.NET también se asigna a este elemento
HTML.
• ViewState: ViewState es el mecanismo que ASP.NET usa para mantener el estado de los
controles durante los sucesivos postbacks de una página. Para facilitar esta labor, cuando
ASP.NET ejecuta una página, recolecta el valor de todos los controles nonpostback
que se modificaron en el código y les da formato en una sola cadena codificada. Esta
cadena se almacena en un campo oculto en un control denominado __VIEWSTATE.
De forma predeterminada, ViewState está habilitado en las aplicaciones ASP.NET.
Puede deshabilitar ViewState para un control determinado estableciendo la propiedad
EnableViewState del control en false:
  <asp:GridView ID="GridView1"
    runat="server" EnableViewState="false" />
También puede deshabilitar ViewState para la página estableciendo el atributo
EnableViewState de la directiva @Page en false:
  <%@ Page EnableViewState="false" %>
Por último, puede deshabilitar ViewState para toda la aplicación agregando la siguiente
línea al archivo web.config:
  <pages enableViewState="false" />
Comprensión de las aplicaciones web | 101

INTRODUCCIÓN A LA ADMINISTRACIÓN DEL LADO SERVIDOR


La administración de estado de lado servidor usa recursos del servidor para almacenar la
información de estado. El uso de técnicas de lado servidor elimina la posibilidad de que un
usuario intente modificar indebidamente el código del lado cliente o leer los datos de sesión.
Sin embargo, almacenar y procesar la información de sesión en un servidor aumenta la carga
que ha de soportar y exige que este disponga de recursos adicionales para proporcionar las
páginas web.
ASP.NET admite la administración de estado del lado servidor en dos niveles:
• Estado de sesión: una aplicación ASP.NET crea una sesión única para cada usuario
que envía una solicitud a la aplicación. ASP.NET identifica claramente cada una de
estas sesiones mediante el envío de un identificador de sesión único a la dirección URL
solicitante. Este identificador de sesión se transmite como una cookie o se inserta en la
dirección URL, según la configuración de la aplicación. La posibilidad de identificar
de forma exclusiva y relacionar las solicitudes se puede usar para almacenar datos
específicos de la sesión, lo que también se denomina el estado de sesión de la aplicación
web. Un ejemplo común de estado de sesión consiste en almacenar el contenido del carro
de la compra del usuario mientras explora un comercio web.

El estado de sesión se puede configurar para almacenarlo en otro servidor o en un servidor


SQL. Esto resulta útil cuando la solicitud de un usuario se puede procesar en cualquiera
de los muchos servidores de una granja de servidores web. Una granja de servidores web
*
TOME NOTA
es una colección de servidores web que se usan colectivamente para proporcionar un sitio
web. Las granjas de servidores web son necesarias para admitir el tráfico en los sitios web
que gozan de mayor popularidad.

• Estado de aplicación: el estado de aplicación se usa para almacenar los datos usados
en una aplicación. Se puede obtener fácilmente acceso al estado de aplicación mediante
la propiedad Application de la clase Page. Esta propiedad proporciona acceso al objeto
HttpApplicationState que almacena el estado de aplicación como una colección de pares
clave-valor.
En el ejercicio siguiente se muestra cómo usar el estado de sesión. En el ejercicio se usan dos
formularios Web Forms. WebForm1.aspx obtiene un nombre de usuario y lo almacena en el
estado de sesión. A continuación, el formulario transfiere al usuario a WebForm2.aspx, que
recupera el nombre de usuario de la sesión.

USO DEL ESTADO DE SESIÓN

PREPÁRESE. Para usar el estado de sesión, realice los siguientes pasos:


1. Agregue un nuevo proyecto basado en la plantilla Aplicación web vacía de ASP.NET a la
solución Lesson04. Asigne al proyecto el nombre UsingSessionState.
2. Seleccione Proyecto > Agregar nuevo elemento. Seleccione la plantilla Formulario
Web Forms. Asigne al archivo el nombre WebForm1.aspx.
3. Cambie el formato HTML de WebForm1.aspx a lo siguiente:
<%@ Page Language="C#" AutoEventWireup="true"
   CodeBehind="WebForm1.aspx.cs"
   Inherits="UsingSessionState.WebForm1" %>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
  <title></title>
</head>
102 | Lección 4

<body>
  <form id="form1" runat="server">
  <div>
    <asp:Label ID="Label1" runat="server"
      Text="Escriba su nombre:" /><br />
    <asp:TextBox ID="TextBox1" runat="server" />
    <br /><br />
    <asp:Button ID="Button1" runat="server"
      Text="Enviar" onclick="Button1_Click" />
  </div>
  </form>
</body>
</html>
4. Haga clic en la ventana de código y seleccione Ver código en el menú contextual para
cambiar al archivo de código subyacente (WebForm1.aspx.cs). Reemplace el código de
ese archivo por lo siguiente:
using System;
namespace UsingSessionState
{
public partial class WebForm1
  : System.Web.UI.Page
{
   protected void Page_Load
   (object sender, EventArgs e)
   {
      if (Session["Name"] != null)
        Response.Redirect("WebForm2.aspx");
    }

    protected void Button1_Click


      (object sender, EventArgs e)
    {
      Session.Add("Name", TextBox1.Text);
      Response.Redirect("WebForm2.aspx");
    }
  }
}
5. Agregue un nuevo formulario Web Forms (WebForm2.aspx) al proyecto. Cambie el
formato de la página a lo siguiente:
<%@ Page Language="C#" AutoEventWireup="true"
  CodeBehind="WebForm2.aspx.cs"
  Inherits="UsingSessionState.WebForm2" %>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
  <title></title>
Comprensión de las aplicaciones web | 103

</head>
<body>
  <form id="form1" runat="server">
  <div>
    <asp:Label ID="Label1" runat="server" /> <br />
    <asp:Button ID="Button1" runat="server"
      Text="Borrar sesión"
      onclick="Button1_Click" />
  </div>
  </form>
</body>
</html>
6. Cambie el código del archivo de código subyacente (WebForm2.aspx.cs) del formulario
de modo que sea como el siguiente:
using System;
namespace UsingSessionState
{
  public partial class WebForm2
    : System.Web.UI.Page
  {
    protected void Page_Load(
      object sender, EventArgs e)
    {
      if (Session["Name"] != null)
        Label1.Text = String.Format(
"Bienvenido, {0}", Session["Name"]);
      else
        Response.Redirect("WebForm1.aspx");
    }
    protected void Button1_Click(
      object sender, EventArgs e)
    {
      Session.Remove("Name");
      Response.Redirect("WebForm1.aspx");
    }
  }
}
7. Seleccione Depurar > Iniciar depuración (o presione F5). Se abrirá la página
WebForm1.aspx en un explorador web, como se muestra en la figura 4-8. Escriba
un nombre y haga clic en el botón "Enviar". En esta página se almacena el nombre
especificado en el estado de sesión.
104 | Lección 4

Figura 4-8
En esta página se almacena
el nombre especificado en el
estado de sesión

LISTO PARA CERTIFICACIÓN


8. A continuación, se le transferirá a WebForm2.aspx, como se muestra en la figura 4-9.
¿Comprende los conceptos WebForm2.aspx recupera el nombre de usuario del estado de sesión. En la misma
básicos del desarrollo ventana del explorador (de tal forma que continúe en la misma sesión), intente
de aplicaciones web obtener acceso a WebForm1.aspx. Tenga en cuenta que, mientras la sesión contenga
Microsoft ASP.NET? una entrada correspondiente al nombre, se le redirigirá a WebForm2.aspx. Haga clic
4.2 en el botón Borrar sesión. Se borrará la sesión y se le transferirá a WebForm1.aspx.

Figura 4-9
En esta página se recupera el
nombre mostrado del estado
de sesión

■ Conceptos del hospedaje de sitios web IIS

El hospedaje de sitios web consiste en configurar un servidor web con los archivos de
CONCLUSIÓN código y la configuración correctos para que los usuarios remotos puedan obtener acceso
satisfactoriamente a una aplicación web.

Las aplicaciones ASP.NET deben implementarse en un servidor web de Internet Information


Services (IIS). IIS forma parte integrante de los sistemas operativos Windows Server y
proporciona la funcionalidad de hospedaje de sitios web.
Implementar una aplicación ASP.NET resulta sencillo porque ASP.NET proporciona la
implementación de xcopy. Gracias a ello, para implementar un sitio web ASP.NET en un
servidor web basta con copiar los archivos en las ubicaciones correctas. Esto se lleva a cabo
mediante el comando xcopy de Windows o con una aplicación de Protocolo de transferencia
de archivos (FTP).

Algunas aplicaciones web complejas pueden requerir la implementación de archivos DLL


en la memoria caché global de ensamblados (GAC). En tales situaciones, puede ser preciso
TOME NOTA
* crear un paquete de Windows Installer para efectuar la implementación, en lugar de usar
xcopy o FTP.
Comprensión de las aplicaciones web | 105

Conceptos de Internet Information Services


Internet Information Services (IIS) es un servidor web que permite hospedar
aplicaciones web en el sistema operativo Windows. Un servidor IIS usa los conceptos de
sitios, aplicaciones y directorios virtuales.

IIS se puede usar para hospedar varios sitios web y compartir información con los usuarios a
través de Internet o de una intranet. IIS aplica una relación jerárquica entre sitios, aplicaciones
y directorios virtuales que constituye un bloque de creación básico para hospedar contenido en
línea.
IIS se puede administrar mediante el Administrador de IIS, una herramienta incluida en el
sistema operativo Windows. Esta herramienta, como se muestra en la figura 4-10, proporciona
una interfaz gráfica de usuario para configurar sitios web, aplicaciones y directorios virtuales.
La captura de pantalla de la figura 4-10 se ha tomado en un equipo que ejecuta Windows 7.
La interfaz de usuario del Administrador de IIS es diferente en Windows XP.

Figura 4-10
Interfaz del Administrador de
IIS en un equipo que ejecuta
Windows 7

Creación de directorios virtuales y sitios web


Un sitio web es un contenedor de aplicaciones y directorios virtuales. Un directorio
virtual es un alias que se asigna a un directorio físico en el servidor web.

Un sitio web es un contenedor de aplicaciones y directorios virtuales a los que se puede


obtener acceso mediante una dirección web. Por ejemplo, la dirección URL
www.northwind.com puede señalar a un sitio web que contenga numerosos directorios
virtuales, tales como “pedidos” y “cuentas”, a cada uno de los cuales se puede obtener acceso
en combinación con la dirección del sitio web; por ejemplo, mediante www.northwind.com/
pedidos y www.northwind.com/cuentas.
Un servidor web no expone la dirección física y ubicación reales de los archivos al exterior.
En cambio, usa un sistema de alias que se asignan a los directorios físicos. Estos alias también
se denominan directorios virtuales. Los directorios virtuales forman parte de la dirección URL,
106 | Lección 4

como se muestra en el ejemplo anterior. Cuando IIS recibe una solicitud de una dirección URL
de este tipo, asigna el directorio virtual a la ubicación física de los archivos. En el ejercicio
siguiente se muestra cómo crear un directorio virtual.

CREACIÓN DEL DIRECTORIO VIRTUAL

PREPÁRESE. Para crear un directorio virtual mediante el Administrador de IIS, realice los
pasos siguientes:
1. Abra el Administrador de IIS. Para abrir el Administrador de IIS en Windows 7, escriba
IIS en el menú Inicio y, a continuación, haga clic en el acceso directo Administrador
de IIS. Para obtener acceso al Administrador de IIS en Windows XP, vaya a Inicio >
Ejecutar, escriba “inetmgr” y haga clic en el botón Aceptar.
2. Expanda los nodos del panel izquierdo (consulte la figura 4-10) y seleccione el nodo
Sitio web predeterminado.
3. Haga clic con el botón secundario en el nodo Sitio web predeterminado y seleccione
la opción Agregar directorio virtual en el menú contextual. En Windows XP, el
comando será Nuevo > Directorio virtual. En este punto, se abrirá en la pantalla el
Asistente para crear un directorio virtual.
4. En el cuadro de diálogo Agregar directorio virtual, especifique un alias y una ruta de
acceso física, como se muestra en la figura 4-11. A continuación, haga clic en Aceptar.

Figura 4-11
Cuadro de diálogo Agregar
directorio virtual

Implementación de aplicaciones web


La implementación de sitios web simples se lleva a cabo copiando los archivos en la
ubicación correcta. Para instalar un sitio web complejo, puede ser preciso usar Windows
Installer.

Existen principalmente dos maneras de implementar archivos en un sitio web:


• Mediante xcopy o FTP: gran cantidad de aplicaciones web y servicios web solamente
requieren que los archivos se copien en el servidor web. Estos sitios y servicios no
requieren ninguna acción especial (como reiniciar los servicios IIS, registrar los
componentes en el Registro de Windows, etc.). La implementación mediante xcopy o
LISTO PARA CERTIFICACIÓN
FTP es idónea en estos casos.
¿Comprende los conceptos
básicos del hospedaje web • Mediante Windows Installer: Windows Installer puede llevar a cabo varias acciones
con el servidor web IIS? personalizadas durante el proceso de implementación. Por lo tanto, puede usarse para
4.3 implementar sitios web complejos que requieren crear automáticamente directorios
virtuales, reiniciar servicios, registrar componentes, etc.
Comprensión de las aplicaciones web | 107

■ Conceptos del desarrollo de servicios web

Un servicio web es un componente de software al que se puede obtener acceso a través de


una red mediante protocolos de red estándar, como HTTP. Los servicios web se describen
CONCLUSIÓN
mediante Web Service Description Language (WSDL).

Los servicios web proporcionan un modo de interactuar con los objetos de programación
ubicados en equipos remotos. La característica especial de los servicios web es que todas las
comunicaciones entre sus clientes y servidores se lleva a cabo mediante mensajes en lenguaje
de marcado extensible (XML) que se transmiten a través del Protocolo de transferencia de
hipertexto (HTTP).
Mediante el uso de estas tecnologías estándar, los objetos remotos se pueden publicar y
consumir en sistemas que de otro modo serían incompatibles. Por ejemplo, un objeto remoto
escrito en C# y publicado como servicio web en un servidor web Windows se puede procesar
mediante código Java ejecutado en un equipo Linux.
Antes de entrar en los detalles de la creación y el consumo de los servicios web, vamos a
familiarizarnos con dos tecnologías esenciales que hacen posibles los servicios web:
• Protocolo simple de acceso a objetos (SOAP)
• Web Services Description Language (WSDL)

Introducción a SOAP
SOAP es el protocolo de intercambio de información estructurada en comunicaciones de
servicios web entre dos equipos remotos.

SOAP es el protocolo que define el modo en que los equipos remotos intercambian mensajes
durante una comunicación de servicios web. SOAP usa XML para el formato de los mensajes
y HTTP para transmitirlos. El uso de SOAP para las comunicaciones presenta dos ventajas
principales. En primer lugar, puesto que el formato de los mensajes es XML, resultan más
fáciles de entender en los sistemas no compatibles. En segundo lugar, como estos mensajes se
transmiten mediante el omnipresente protocolo HTTP, suelen poder obtener acceso a cualquier
equipo de Internet sin quedar bloqueados en los cortafuegos.
Este es un paquete SOAP típico enviado desde un cliente a un servicio web:
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope
xmlns:xsi=http://www.w3.org/2001/XMLSchema–instance
xmlns:xsd=http://www.w3.org/2001/XMLSchema
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
 <soap:Body>
  <ToLower xmlns="http://northwindtraders.com">
<inputString>CADENA DE MUESTRA</inputString>
  </ToLower>
 </soap:Body>
</soap:Envelope>
108 | Lección 4

Si nos fijamos en el ejemplo, observaremos algunos de los elementos evidentes de este paquete
SOAP:
• El paquete consta de un sobre (envelope) que contiene un cuerpo (body); cada uno de
estos elementos se identifica mediante una etiqueta XML específica.
• El cuerpo consiste en el nombre del método que se invoca. En este paquete SOAP, el
nombre del método es ToLower y toma un solo parámetro denominado inputString con
un valor dado.
Este es el paquete de respuesta del servidor:
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
 <soap:Body>
  <ToLowerResponse
    xmlns="http://northwindtraders.com">
<ToLowerResult>cadena de muestra</ToLowerResult>
  </ToLowerResponse>
 </soap:Body>
</soap:Envelope>
En el paquete de respuesta, el elemento XML ToLowerResponse es el resultado de la
invocación del método en el servidor.

Introducción a WSDL
WSDL es un lenguaje basado en XML para describir servicios web.

TOME NOTA
* WSDL son las siglas de Web Services Description Language (lenguaje de descripción de
Un servicio web puede servicios web) y proporciona un estándar que permite a un servicio web informar a su cliente
existir sin un archivo sobre qué tipo de mensajes aceptará y qué resultados se devolverán. Un archivo WSDL actúa
WSDL, pero es preciso como la interfaz pública de un servicio web e incluye la siguiente información:
conocer el mensaje • los tipos de datos que puede procesar;
SOAP entrante exacto
que el servicio web • los métodos que expone;
espera recibir para poder • las direcciones URL a través de las que se puede obtener acceso a los métodos.
usar dicho servicio.

Creación de servicios web


En esta sección, aprenderemos a crear y publicar un servicio web.

En esta sección, aprenderemos a crear y un servicio web sencillo denominado TextWebService


que expone dos métodos, ToLower y ToUpper. Estos métodos convierten una cadena
determinada a mayúsculas y minúsculas, respectivamente. Aunque se trata de un ejemplo
sencillo, abarca todos los aspectos de la creación de un servicio web que pueden requerir una
lógica de procesamiento más compleja.
Comprensión de las aplicaciones web | 109

CREACIÓN DE UN SERVICIO WEB

PREPÁRESE. Para crear un servicio web, realice las siguientes acciones:


1. Agregue un nuevo proyecto basado en la plantilla Aplicación web vacía de ASP.NET a la
solución Lesson04. Asigne al proyecto el nombre TextWebService, como se muestra en
la figura 4-12.
Figura 4-12
Seleccione la plantilla
Aplicación web vacía de
ASP.NET

2. Seleccione Proyecto > Agregar nuevo elemento en el menú contextual. Seleccione la


plantilla Servicio Web, como se muestra en la figura 4-13. Asigne al servicio web el
nombre TextWebService.asmx.
Figura 4-13
Seleccione la plantilla
Servicio Web

3. Cambie el código predeterminado de la clase TextWebService en el archivo


TextWebService.asmx.cs como se muestra a continuación:
[WebService(Namespace = "http://northwindtraders.com/")]
[WebServiceBinding(ConformsTo
  = WsiProfiles.BasicProfile1_1)]
public class TextWebService:
 System.Web.Services.WebService
110 | Lección 4

{
  [WebMethod]
  public string ToUpper(string inputString)
  {
    return inputString.ToUpper();
  }
  [WebMethod]
  public string ToLower(string inputString)
  {
    return inputString.ToLower();
  }
}
4. Seleccione Depurar > Compilar TextWebService para compilar el proyecto y
TOME NOTA
* asegurarse de que no hay ningún error. Ahora, el servicio web está listo para su uso.
Puede incluir el nombre
de dominio de su En el código anterior, hay algunos aspectos importantes que cabe destacar. En primer
empresa en el espacio de lugar, observe que cada clase que se expone como servicio web XML debe tener el atributo
nombres para distinguir WebService. El atributo WebService tiene una propiedad Namespace que toma de forma
sus servicios web de predeterminada el valor https://tempuri.org/. Aunque durante el desarrollo es aceptable usar
aquellos publicados por este valor, el valor del espacio de nombres debe cambiarse antes de publicar el servicio web.
otras empresas. De hecho, cada servicio web individual debe tener un espacio de nombres exclusivo para que
las aplicaciones cliente lo distingan de los demás servicios web.
Cada método que se expone desde el servicio web debe tener además el atributo WebMethod.
Los métodos marcados con atributos WebMethod se denominan también “métodos web”. Los
dos métodos que se usan en este ejercicio convierten una cadena determinada a mayúsculas y
minúsculas, respectivamente.
Para probar un servicio web sencillo como TextWebService, creado anteriormente, solo se
necesita un explorador web. Puede seleccionar métodos para invocarlos, pasar parámetros
y revisar los valores devueltos desde el propio explorador, como se muestra en el siguiente
ejercicio.

PRUEBA DE UN SERVICIO WEB

PREPÁRESE. Para probar un servicio web, realice las siguientes tareas:


1. Abra el proyecto TextWebService creado en el ejercicio anterior. Seleccione Depurar >
Iniciar depuración. Se abrirá un explorador con la página de prueba del servicio web,
como se muestra en la figura 4-14.
Figura 4-14
Página de prueba del servicio
web
Comprensión de las aplicaciones web | 111

2. En la página de prueba, haga clic en el vínculo descripción de servicios. De esta


manera, podrá ver el código WSDL de este servicio web. Haga clic en el botón Atrás
para volver a la página de prueba.
3. Observe que todos los métodos web aparecen como vínculos en la página de prueba.
Para invocar un método web concreto, haga clic en su vínculo. Después de hacerlo,
debería aparecer una página en la que probar el método web seleccionado, como se
muestra en la figura 4-15.
Figura 4-15
Página de prueba de un
método web

4. En cada página de prueba de un método web se muestran el código SOAP y los demás
mensajes que el servicio web entiende. También hay un formulario que permite
especificar los parámetros del método web y probarlo. Especifique una cadena de
entrada de prueba y haga clic en el botón Invocar. El resultado debería aparecer en la
página siguiente, como se muestra en la figura 4-16.
Figura 4-16
Valor devuelto por la prueba
del servicio web

5. Pruebe los dos métodos. Cuando haya terminado, cierre el explorador web.
112 | Lección 4

Como se ha observado en el ejercicio, al hacer clic en el botón Invocar, la página de


prueba construye los paquetes SOAP adecuados para que el servicio web los procese y, a
continuación, muestra los resultados devueltos por el servicio web.

Consumo de servicios web


En esta sección, aprenderemos a obtener acceso a los servicios web desde una aplicación cliente.

En esta misma lección, hemos aprendido a invocar un servicio web desde la página de
prueba del servicio web. En esta sección, aprenderemos a llamar a un servicio web mediante
programación desde una aplicación cliente ASP.NET.

ACCESO A UN SERVICIO WEB DESDE UNA APLICACIÓN CLIENTE

PREPÁRESE. Para obtener acceso a un servicio web desde una aplicación cliente, realice los
siguientes pasos:
1. Agregue un nuevo proyecto a la solución Lesson04 basado en la plantilla Aplicación
web ASP.NET. Asigne al proyecto el nombre TextWebServiceClient.
2. Haga clic con el botón secundario en el nombre del proyecto en la ventana Explorador
de soluciones y, a continuación, seleccione la opción Agregar referencia web en el
menú contextual. En el cuadro de diálogo Agregar referencia web, escriba la dirección
URL del servicio creado en el ejercicio anterior y presione Intro. (También puede
copiar la dirección URL de la barra de direcciones del explorador.) Esta acción carga la
lista de operaciones disponibles en el servicio web, como se muestra en la figura 4-17.

Figura 4-17
Cuadro de diálogo Agregar
referencia web

3. En el cuadro de diálogo Agregar referencia web, cambie el nombre de la referencia


web a textWebService y haga clic en el botón Agregar referencia. Se agregará una
referencia web al proyecto, como se muestra en la figura 4-18.
Comprensión de las aplicaciones web | 113

Figura 4-18
Nodo de referencias web del
proyecto

4. Cambie el código de Default.aspx como se muestra a continuación.


<%@ Page Title="Home Page" Language="C#"
  AutoEventWireup="true"
  CodeBehind="Default.aspx.cs"
  Inherits="TextWebServiceClient._Default" %>
<html>
  <head><title>TextWebService Client
  </title></head>
 <body>
  <form runat="server">
<h2>Formulario de prueba de TextWebService</h2>
     <p>
      <asp:TextBox ID="TextBox1"
       runat="server"
       Text="enter text" />
      <br />
      <asp:Button ID="Button1"
       runat="server"
Text="Invocar métodos del servicio"
       onclick="Button1_Click" />
     </p>
     <p>
<strong>Resultados:</strong><br />
Método ToLower:
      <asp:Label ID="toLowerLabel"
       runat="server"
       Text="Label" ForeColor="Green" />
      <br />
114 | Lección 4

Método ToUpper:
      <asp:Label ID="toUpperLabel"
       runat="server"
       Text="Label" ForeColor="Green" />
     </p>
  </form>
 </body>
</html>
5. Abra la vista Diseño de Default.aspx y haga doble clic en el control Button. Se agregará
el código del controlador de eventos Click. Modifique el código como se muestra a
continuación:
TOME NOTA
* protected void Button1_Click(
Al invocar un método
de un servicio web,   object sender, EventArgs e)
puede usar un método {
sincrónico o asincrónico.   var webService =
El método asincrónico
puede ser conveniente     new textWebService.TextWebService();
para aumentar la   toLowerLabel.Text =
capacidad de respuesta     webService.ToLower(TextBox1.Text);
de la aplicación cliente.   toUpperLabel.Text =
    webService.ToUpper(TextBox1.Text);
}
6. Seleccione Depurar > Iniciar depuración para ejecutar la aplicación web. Escriba texto
de muestra y haga clic en el botón Invocar métodos de servicio. Deberían aparecer los
resultados de TextWebService, como se muestra en la figura 4-19.

Figura 4-19
Valor devuelto por el servicio
web

En el ejercicio anterior, al agregar una referencia web, Visual Studio crea un proxy local que
representa el servicio remoto. El proxy simplifica la comunicación con el servicio web porque
acepta los mensajes, los reenvía al servicio web y devuelve los resultados del servicio web.
Este proxy se puede usar fácilmente para crear objetos desde el servicio web e invocar
métodos. En consecuencia, resulta similar trabajar con objetos remotos o con objetos locales.
Comprensión de las aplicaciones web | 115

Cuando se crea una referencia web, Visual Studio lee el archivo WSDL apropiado para
LISTO PARA CERTIFICACIÓN
determinar qué clases y métodos están disponibles en el servidor remoto. Cuando se llama
¿Comprende los conceptos
a un método para un objeto remoto, .NET Framework traduce la llamada y los resultados a
básicos del desarrollo de
mensajes SOAP y los transmite sin que usted intervenga en absoluto.
servicios web?
4.4

RESUMEN DE CONOCIMIENTOS

En esta lección hemos aprendido lo siguiente:


• Una página web es un documento que se presenta a través de la World Wide Web
(WWW) y mostrarse en un explorador web.
• El Lenguaje de marcado de hipertexto (HTML) es el lenguaje que usan los
exploradores y servidores web para describir una página web.
• Las hojas de estilos en cascada (CSS) permiten almacenar la información acerca del
estilo y el formato en un espacio separado del código HTML. Esta separación facilita
la actualización de los sitios web. Visual Studio incluye herramientas para crear hojas
de estilos y ver su vista previa.
• JavaScript es un lenguaje de scripting del lado cliente que se ejecuta en un
explorador web para ayudar a crear páginas web mucho más interactivas de lo que
es posible usando solamente HTML.
• Las técnicas de administración de estado del lado cliente, como las cadenas de
consulta, las cookies, los campos ocultos y ViewState, usan HTML y las funciones de
los exploradores web para almacenar información de estado en los equipos cliente.
• Las técnicas de administración de estado del lado servidor, como el estado de sesión
y el estado de aplicación, usan los recursos del servidor para administrar el estado.
• Internet Information Services (IIS) es un servidor web que permite hospedar
aplicaciones web en el sistema operativo Windows. Un servidor IIS usa los conceptos
de sitios, aplicaciones y directorios virtuales.
• Los servicios web proporcionan una manera de invocar objetos remotos mediante
tecnologías estándar como XML y HTTP.
• SOAP es el protocolo que define el modo en que los equipos remotos intercambian
mensajes durante una comunicación de servicios web. SOAP usa XML para el formato
de los mensajes y HTTP para transmitirlos.
• WSDL proporciona un estándar que permite a un servicio web informar a su cliente
de qué tipos de mensajes aceptará y qué resultados se devolverán.

■ Evaluación de conocimientos
Rellene los espacios en blanco
Complete las oraciones siguientes escribiendo la palabra o palabras correctas en los
espacios en blanco proporcionados.
1. En la etiqueta de anclaje HTML (<a>), el atributo _________ especifica la dirección URL
del destino.
2. Puede poner código CSS en un archivo separado y vincularlo a una página web mediante
el uso del elemento HTML _________.
116 | Lección 4

3. El código JavaScript de una página web se ejecuta en el _________.


4. Puede usar un elemento _________ para mostrar un mensaje específico a los usuarios
cuando su explorador no está ejecutando JavaScript.
5. Puede deshabilitar ViewState en el nivel de página estableciendo en false el atributo
_________ de la directiva @Page en la página ASP.NET.
6. El estado de la _________ se usa para almacenar datos que se usan globalmente en toda
una aplicación, en contraposición al estado de _________, que almacena los datos de una
sesión de usuario.
7. A una aplicación web se obtiene acceso mediante un nombre de _________, en lugar de
un nombre de carpeta física.
8. Debe marcar las clases con el atributo _________ para exponerlas como servicio web.
9. De todos los métodos de una clase de servicio web, solo los que están marcados con
atributos _________ se exponen como métodos del servicio web.
10. SOAP usa _________ para el formato de los mensajes y _________ para transmitirlos.

Varias opciones
Rodee con un círculo la letra correspondiente a la mejor respuesta.
1. Ha escrito el siguiente código para su página web:
<html>
  <head>
<title>Página de muestra</title>
    <style type="text/css">
    div
    {
      grosor de fuente: Verdana;
      font-size: 9pt;
    }
    </style>
  </head>
  <body>
    <div style=
      "font-weight: bold; font-size: 12pt;">
Texto de muestra</div>
  </body>

</html>
¿Cuál sería el estilo del texto mostrado como parte del elemento <div>?
a. Font family: Verdana; font weight: bold; font size: 12pt
b. Font family: Verdana; font weight: bold; font size: 9pt
c. Font family: Verdana; font size: 12pt
d. Font family: Verdana; font size: 9pt
Comprensión de las aplicaciones web | 117

2. Está desarrollando un sitio web de mapas que permite a los usuarios explorar mapas
interactivamente mediante acciones como panorámicas y acercamiento. Desea que el
sitio web sea dinámico y accesible en la mayor parte de los exploradores modernos.
Sin embargo, no desea que los usuarios tengan que instalar complementos adicionales
para usar su sitio web. ¿Cuál de las siguientes tecnologías debería usar para mostrar
los mapas?
a. HTML
b. Tecnología de programación del lado servidor como ASP.NET
c. Adobe Flash
d. JavaScript
3. Su página ASP.NET contiene una variable de nivel de página del tipo Customer.
Desea conservar el valor de esta variable a través de los postback de la página,
pero no necesita esta variable en ninguna otra página de la aplicación. ¿Cuál de las
siguientes técnicas de administración de estado es la mejor manera de lograrlo?
a. Cadenas de consulta
b. Cookies
c. ViewState
d. Sesión
4. Está desarrollando una aplicación web para un banco de Internet. La aplicación
permite a los usuarios obtener acceso a su información de cuenta y transacciones
desde el interior de un explorador web. Cuando un usuario inicie una sesión en la
aplicación web, usted desea mostrar el nombre de usuario y el balance de la cuenta
en todas las páginas de la aplicación hasta que el usuario cierre la sesión. También
desea que esta aplicación esté a salvo de usuarios malintencionados. ¿Cuál de las
siguientes técnicas de administración de estado debe usar?
a. Cookies
b. ViewState
c. ViewState con cifrado
d. Sesión
5. Está desarrollando un formulario Web Forms para mostrar información
meteorológica. Cuando un usuario solicita el formulario Web Forms, este debe
realizar una inicialización para cambiar su apariencia y asignar valores a algunos
controles. ¿Dónde debería poner el código?
a. En el controlador del evento PreInit de la clase Page
b. En el controlador del evento Init de la clase Page
c. En el controlador del evento Load de la clase Page
d. En el controlador del evento PreRender de la clase Page
6. Desea mostrar valores de las expresiones de C# en una página ASP.NET. ¿Cuál de los
siguientes tipos de bloques de código debería usar para delimitar la expresión?
a. <script runat="server">…</script>
b. <script>…</script>
c. <%= … %>
d. <form>…</form>
7. Ha desarrollado una aplicación de planilla de horas trabajadas que usarán todos los
empleados de su empresa. Ha usado ASP.NET para desarrollar esta aplicación y la
ha implementado en el servidor web de la empresa. ¿Qué deben instalar todos los
empleados de la empresa en sus equipos para poder obtener acceso a la aplicación de
la planilla?
a. .NET Framework Redistributable
b. .NET Framework Software Development Kit
c. Visual Studio
d. Un explorador web
118 | Lección 4

8. La aplicación cliente llama a un servicio web que realiza cálculos complejos que tardan
mucho tiempo. Un usuario se queja de que, mientras se devuelven los resultados, la
interfaz de usuario deja de actualizarse momentáneamente. ¿Qué enfoque debe adoptar
para solucionar este problema?
a. Se debe instalar un procesador mejor en el servidor web.
b. Se debe instalar un procesador mejor en el equipo cliente.
c. Se debe actualizar la conexión a Internet a una más rápida.
d. Se deben usar llamadas asincrónicas para invocar el servicio web.
9. Ha creado un servicio web ASP.NET que convierte una divisa en otra. Uno de los
métodos del servicio web se define con el siguiente código:
public double Convert(double amount,
  string from, string to)
{
// código para realizar la conversión de divisa
}
Los usuarios del servicio web notifican que, si bien pueden establecer una referencia
al servicio web, el método Convert no está disponible para ellos. ¿Cuál puede ser el
problema?
a. El archivo .asmx del servicio web no está disponible en el servidor web.
b. La clase del servicio web no está marcada con el atributo WebService.
c. El método Convert no está marcado con el atributo WebMethod.
d. Los servicios web solo pueden exponer métodos que devuelven valores de texto.
10. Está trabajando en dos proyectos de Visual Studio. El primer proyecto es un servicio
web que devuelve un objeto DataSet perteneciente al espacio de nombres System.Data.
El segundo proyecto tiene acceso al servicio web creado por el primer proyecto. ¿Qué
proyecto de este escenario requiere una referencia al espacio de nombres System.Data?
a. El proyecto de servicio web
b. El proyecto de cliente que obtiene acceso al servicio web
c. Tanto el proyecto de cliente como el proyecto del servicio web
d. Ni el proyecto de cliente ni el proyecto del servicio web

■ Evaluación de competencias
Escenario 4-1: Uso de JavaScript y HTML
Está desarrollando una página web que proporciona una interfaz de usuario interactiva. Decide
mostrar una imagen en la página. Cuando el usuario mueve el mouse sobre la imagen, se
sustituye la imagen original por una imagen nueva. A continuación, cuando el mouse sale del
área de la imagen, la imagen original se muestra otra vez. Desea lograr este comportamiento
mediante código JavaScript del lado cliente y código HTML. ¿Cómo se crea una página web
que funcione como hemos descrito?

Escenario 4-2: Uso de cadenas de consulta


Está desarrollando una parte de un sitio web que permite a los usuarios especificar su nombre
y dirección de correo electrónico para suscribirse a un boletín de correo electrónico. La
solución consta de dos páginas web. La primera página recopila el nombre de usuario y la
dirección de correo electrónico y después transfiere el control a una segunda página. La
segunda página acepta el nombre y la dirección de correo electrónico como parámetros de
cadena de consulta y muestra un mensaje de confirmación. Debe escribir el código de estas
dos páginas. ¿Qué código debe escribir para cumplir este requisito?
Comprensión de las aplicaciones web | 119

■ Evaluación de aptitudes
Escenario 4-3: Llamada a un servicio web de forma asincrónica
La clase proxy generada por Visual Studio para un servicio web incluye métodos para
llamar al servicio web tanto sincrónica como asincrónicamente. De forma predeterminada,
la aplicación usa el método sincrónico. Si prefiere la invocación asincrónica, debe llamar a
la versión asincrónica del método. Las versiones asincrónicas no esperan a que el servicio
web devuelva una respuesta y usan un mecanismo de devolución de llamada para obtener
una respuesta cuando está lista. La invocación asincrónica de un servicio web puede ayudar
a incrementar la capacidad de respuesta de las aplicaciones cliente. Desea llamar al método
ToLower del servicio TextWebServices creado anteriormente de forma asincrónica. ¿Qué
código escribiría para invocar asincrónicamente un servicio web?

Escenario 4-4: Uso del estado de sesión


Está desarrollando una parte de un sitio web que permite a los usuarios especificar su nombre
y dirección de correo electrónico para suscribirse a un boletín de correo electrónico. La
solución consta de dos páginas web. La primera página recopila el nombre de usuario y la
dirección de correo electrónico, los agrega al estado de sesión y transfiere el control a una
segunda página. La segunda página recupera el nombre y la dirección de correo electrónico del
estado de sesión y muestra un mensaje de confirmación. Debe escribir el código de estas dos
páginas. ¿Qué código debe escribir para cumplir este requisito?
5 LECCIÓN
Comprensión de
las aplicaciones de
escritorio
M AT R I Z D E C O N O C I M I E N T O S D E L A L E C C I Ó N

Conocimientos y conceptos Objetivo del examen MTA Número de objetivo del


examen MTA
Conceptos de los objetos Conceptos de las aplicaciones 5.1
de Windows Forms.
Conceptos de los valores Conceptos de las aplicaciones 5.2
y las referencias basadas en consola.
Comprensión de la encapsulación Conceptos de los servicios de Windows. 5.3

TÉRMINOS CLAVE
aplicación basada en consola delegados parámetros de línea de
Aplicaciones de interfaz de eventos comandos
múltiples documentos (MDI) herencia visual servicio de Windows
aplicaciones de Windows instalador
Forms

Usted es desarrollador de software de una gran organización empresarial. Debe


desarrollar una aplicación que se integre estrechamente con el escritorio de Windows del
usuario y proporcione una interfaz de usuario similar a la que presentan las populares
aplicaciones de escritorio de la plataforma Windows. La aplicación debe ser funcional,
tanto cuando esté conectada a la red como cuando no lo esté. La aplicación también debe
poder comunicarse con dispositivos como escáneres portátiles e impresoras.

■ Conceptos de las aplicaciones de Windows Forms

Las aplicaciones de Windows Forms son aplicaciones de cliente inteligentes que


constan de uno o varios formularios que muestran una interfaz visual al usuario. Estas
CONCLUSIÓN aplicaciones se integran bien con el sistema operativo, usan dispositivos conectados y
pueden funcionar con o sin conexión a Internet.

120
Comprensión de las aplicaciones de escritorio | 121

Diseño de un formulario de Windows Forms

Un formulario de Windows Forms es una superficie visual que puede mostrar gran
variedad de controles, tales como menús, botones y cuadros de texto. Visual Studio
proporciona un Diseñador de Windows Forms con funcionalidad de arrastrar y colocar
que puede usar para crear fácilmente sus aplicaciones.

TOME NOTA
* Para diseñar formularios de Windows Forms, primero debe decidir qué controles desea
Un control es un colocar en el formulario. Los formularios de Windows Forms proporcionan una amplia
elemento de interfaz colección de controles comunes que se pueden usar directamente para crear una excelente
de usuario particular interfaz de usuario. Si la funcionalidad que precisa no está disponible en uno de los controles
que acepta entradas comunes existentes, puede crear un control personalizado o bien comprárselo a un proveedor
del usuario o muestra independiente.
salidas al usuario.
Puede usar la funcionalidad que aporta el Diseñador de Windows Forms de Visual Studio
para colocar y organizar rápidamente los controles conforme a sus requisitos. Visual Studio
proporciona fácil acceso a los controles disponibles a través de su cuadro de herramientas,
como se muestra en la figura 5-1.
Figura 5-1
Cuadro de herramientas de
Visual Studio

Un formulario y sus componentes suelen responder a las acciones de los usuarios, tales como
pulsaciones de teclado o movimientos del mouse. Estas acciones se denominan eventos. Gran
parte del código que se escribe como desarrollador de formularios de Windows Forms está
orientado a la captura de estos eventos y su control mediante la creación de una respuesta
adecuada. Por ejemplo, en el ejercicio siguiente, crearemos un formulario de Windows Forms
que muestra el valor de fecha seleccionado por el usuario.

CREACIÓN DE UN FORMULARIO DE WINDOWS FORMS


PREPÁRESE. Inicie Microsoft Visual Studio. Luego, realice las siguientes acciones:
1. Cree un nuevo proyecto basado en la plantilla Aplicación de Windows Forms, como se
muestra en la figura 5-2. Asigne al proyecto el nombre WindowsFormsDesign.
122 | Lección 5

Figura 5-2
Cuadro de diálogo Nuevo proyecto de Visual Studio

2. El proyecto de aplicación de formularios de Windows Forms se cargará con un


formulario predeterminado (Form1.cs) abierto en la vista del diseñador. La vista
del diseñador permite trabajar visualmente con el formulario. Por ejemplo, puede
organizar los controles sobre la superficie del formulario y establecer sus propiedades.
Puede obtener acceso a los controles disponibles desde la ventana Cuadro de
herramientas. Si la ventana Cuadro de herramientas no está visible, seleccione
Ver > Cuadro de herramientas para mostrarla. A continuación, en el Cuadro de
herramientas, arrastre un control DateTimePicker y un control Label, colóquelos sobre
la superficie del diseñador y organícelos como se muestra en la figura 5-3.

Figura 5-3
Formulario de Windows
Forms con un control
DateTimePicker y un control
Label

3. En la vista del diseñador, seleccione el control Label y, mediante la ventana de


propiedades, establezca su propiedad Text en una cadena vacía.
4. También en la vista del diseñador, haga doble clic en el control DateTimePicker. Esta
acción conecta al controlador de eventos predeterminado del evento ValueChanged
del control DateTimePicker y cambia la vista del diseñador a la de código. A
continuación, modifique el código predeterminado del controlador de eventos de la
siguiente manera:
private void dateTimePicker1_ValueChanged
     (object sender, EventArgs e)
{
  label1.Text =
   dateTimePicker1.Value.ToLongDateString();
}
Comprensión de las aplicaciones de escritorio | 123

5. Seleccione Depurar > Iniciar depuración (o presione F5) para ejecutar el proyecto. En
TOME NOTA
* la interfaz de usuario, seleccione una nueva fecha y compruebe que esta aparece en el
En este ejercicio, hemos
control Label.
usado los nombres
predeterminados de En este ejercicio, observe que, la primera vez que se muestra el formulario, el control Label
los controles. En los está establecido en una cadena vacía. Después, al cambiar la selección de fecha manipulando
formularios complejos el control DateTimePicker, el valor de fecha seleccionado se establece como el texto del
con más controles, control Label.
siempre es conveniente
asignar a los controles
nombres más Conceptos del modelo de eventos de Windows Forms
significativos.
El control de eventos desempeña una función primordial en la programación basada
en interfaz de usuario, pues permite responder a los diversos eventos que se activan
como consecuencia de las acciones del usuario y, de este modo, hace que los programas
sean interactivos. El modelo de eventos de Windows Forms usa delegados de .NET
Framework para vincular los eventos a sus controladores de eventos respectivos.

En las aplicaciones de Windows Forms, cada formulario y control expone un conjunto


predefinido de eventos. Cuando se produce un evento, se invoca el código del controlador
de eventos asociado. Por ejemplo, en el ejercicio anterior, al hacer doble clic en el control
DateTimePicker para agregar código al controlador de eventos, Visual Studio genera el
siguiente código para asociar el controlador de eventos al evento:
this.dateTimePicker1.ValueChanged +=
  new System.EventHandler(
  this.dateTimePicker1_ValueChanged);
TOME NOTA
*
Un delegado puede Aquí, ValueChanged es el evento del control DateTimePicker que queremos capturar. Así, se
enlazarse a cualquier crea una nueva instancia del delegado de tipo EventHandler y el método dataTimePicker1_
método cuya signatura ValueChanged se pasa al controlador de evento. El método dataTimePicker1_ValueChanged es
coincida con la del el método en el que se escribe realmente el código controlador de eventos.
controlador de eventos. El diseñador de Visual Studio genera este código automáticamente. Encontrará este código en
el archivo de código subyacente para el diseñador (Form1.Designer.cs), dentro de una región
de código titulada Código generado por el Diseñador de Windows Forms.
Otro aspecto más que es importante observar es que la sintaxis de adición de un delegado usa
el +operador =. Esto se debe a que .NET Framework admite los delegados de multidifusión,
que permiten que un delegado esté enlazado a más de un método, lo que hace posibles las
notificaciones de uno a varios cuando se desencadena un evento.

Uso de la herencia visual

La Herencia visual permite volver a usar la funcionalidad y los diseños existentes en


formularios de Windows Forms.

Uno de los principios básicos de la programación orientada a objetos es la herencia. Cuando


una clase hereda de una clase base, deriva su funcionalidad básica de la clase base. Por
supuesto, siempre se puede extender la clase derivada para proporcionar funcionalidad
adicional y que sea más útil.
124 | Lección 5

Un formulario de Windows Forms, en esencia, es simplemente otra clase; por consiguiente,


la herencia se aplica también a él. Sin embargo, cuando se aplica herencia a un formulario de
Windows Forms, se heredan todas las características visuales de un formulario, como tamaño,
color y cualquier control colocado en el formulario. También puede manipular visualmente
cualquiera de las propiedades que se heredan de la clase base. Por lo tanto, la herencia de
formularios de Windows Forms se suele denominar herencia visual. En el siguiente ejercicio,
vamos a crear un formulario de Windows Forms mediante la herencia visual de un formulario
existente.

CREACIÓN DE UN FORMULARIO DE WINDOWS FORMS MEDIANTE LA HER-


ENCIA VISUAL
PREPÁRESE. Inicie Microsoft Visual Studio y abra el proyecto de aplicación de Windows
existente denominado WindowsFormsDesign. A continuación, siga este procedimiento:
1. Abra Form1.designer.cs y cambie los modificadores de acceso de los controles label1 y
dateTimePicker1 de private a protected, como se muestra a continuación:
protected System.Windows.Forms.Label label1;
protected System.Windows.Forms.DateTimePicker
  dateTimePicker1;
2. Seleccione Proyecto > Agregar formularios de Windows Forms para agregar un
nuevo formulario de Windows Forms basado en la plantilla Formulario heredado.
Puede buscar rápidamente esta plantilla escribiendo su nombre en el cuadro de
búsqueda, como se muestra en la figura 5-4. Asigne al formulario heredado el nombre
InheritedForm.cs. (Tenga en cuenta que la plantilla Formulario heredado no está
disponible en las ediciones de Visual Studio Express. Si usted usa la edición Express,
cree un formulario normal de Windows Forms denominado InheritedForm.cs y
continúe en el paso 4.)

Figura 5-4
Plantilla Formulario
heredado
Comprensión de las aplicaciones de escritorio | 125

3. Haga clic en el botón Agregar. A continuación, en el cuadro de diálogo Selector de


herencia, seleccione Form1 en el espacio de nombres WindowsFormsDesign, como se
muestra en la figura 5-5, y haga clic en el botón Aceptar.

Figura 5-5
Cuadro de diálogo Selector
de herencia

4. Seleccione la vista de código de InheritedForm; observará que la clase InheritedForm


hereda de Form1, como se muestra a continuación. Si no ha usado la plantilla
Formulario heredado en el paso 2, deberá modificar manualmente el código para
agregar el código de herencia (se muestra en negrita):
public partial class InheritedForm
 : WindowsFormsDesign.Form1
{
    public InheritedForm()
    {
     InitializeComponent();
  }
}

5. En la vista del diseñador de InheritedForm, establezca la propiedad Text en Inherited


Form.
6. También en la vista del diseñador, haga doble clic en InheritedForm. Esta acción
asocia un controlador de eventos del evento Load del formulario y cambia la vista del
diseñador a la de código. En la vista de código, cambie el código predeterminado del
controlador de eventos de la siguiente manera:
private void InheritedForm_Load(
  object sender, EventArgs e)
{
  label1.Text =
   dateTimePicker1.Value.ToLongDateString();
}
126 | Lección 5

7. Abra Program.cs y modifique el método Main como se muestra a continuación para


asegurarse de que InheritedForm se inicie al ejecutar la aplicación:
[STAThread]
static void Main()
{
  Application.EnableVisualStyles();
  Application
   .SetCompatibleTextRenderingDefault(false);
  Application.Run(new InheritedForm());
}

8. Seleccione Depurar > Iniciar depuración (o presione F5) para ejecutar el proyecto.
Cuando InheritedForm se carga, se muestra la fecha seleccionada actualmente en el
control Label. Esto no sucedía en el formulario Form1 creado anteriormente, donde
inicialmente el control Label estaba vacío.
El formulario InheritedForm demuestra que se puede obtener toda la funcionalidad de Form1
con solo heredar el formulario. Una vez que ha cambiado de private a protected el modificador
de acceso de los controles miembros de Form1, label1 y dateTimePicker1, ya es posible
tener acceso a ellos desde el formulario heredado. En este ejercicio también se muestra cómo
extender la funcionalidad del formulario base en un formulario heredado.

Conceptos de las aplicaciones de interfaz de múltiples documentos (MDI)

Las aplicaciones de interfaz de múltiples documentos (MDI) son aquellas en que varias
ventanas secundarias residen en una sola ventana principal.

Las aplicaciones MDI permiten que varias ventanas compartan un solo menú de aplicación
y una sola barra de herramientas. Las aplicaciones MDI suelen tener un menú denominado
Ventana que permite a los usuarios administrar varias ventanas secundarias y ofrece
características como cambiar entre ventanas secundarias y organizar las ventanas secundarias.
Por ejemplo, la figura 5-6 muestra Microsoft Excel 2010 en modo MDI.

Figura 5-6
Microsoft Excel 2010 como
aplicación MDI
Comprensión de las aplicaciones de escritorio | 127

Las aplicaciones MDI contrastan con las aplicaciones de interfaz de un único documento
(SDI), donde cada ventana contiene su propio menú y barra de herramientas. Las aplicaciones
SDI dependen del sistema operativo para proporcionar la funcionalidad de administración de
TOME NOTA
* ventanas. Por ejemplo, en Windows, puede cambiar entre varias ventanas mediante el uso de la
Puede resultar barra de tareas de Windows.
complicado implementar Entre los diseñadores de interfaces de usuario existe diversidad de opiniones sobre cuál de
la compatibilidad con las interfaces de aplicación funciona mejor. En términos generales, las SDI se consideran más
varios monitores en adecuadas para usuarios noveles y las MDI, para usuarios avanzados. Muchas aplicaciones
las aplicaciones MDI, populares como Microsoft Word y Microsoft Excel admiten tanto SDI como MDI. Word y
porque la ventana Excel se instalan de forma predeterminada como aplicaciones SDI, pero proporcionan a los
principal tiene que usuarios la opción de cambiar entre SDI y MDI. Por ejemplo, en Word 2010 y Excel 2010,
abarcar todos los usted puede cambiar al modo MDI desactivando la opción “Mostrar todas las ventanas en la
monitores del usuario. barra de tareas” en el menú Opciones.

CREACIÓN DE UNA APLICACIÓN MDI


PREPÁRESE. Inicie Microsoft Visual Studio y cree un nuevo proyecto de aplicación de
formulario de Windows Forms denominada MDIApplication. A continuación, siga este
procedimiento:
1. Seleccione la ventana de propiedades de Form1 y establezca la propiedad Text en MDI
Application y la propiedad IsMdiContainer en True.
2. Seleccione el control MenuStrip del cuadro de herramientas y agréguelo al formulario.
Agregue un elemento de menú de nivel superior &Ventana y, a continuación, agregue
&Nueva ventana y &Organizar en el siguiente nivel. En el menú Organizar, agregue
tres opciones, &Cascada, &Horizontal y &Vertical, como se muestra en la figura 5-7.

Figura 5-7
Adición de opciones de
menú
128 | Lección 5

El signo & que aparece delante de un carácter en el texto de un menú no se muestra


tal cual; su finalidad es establecer el carácter que será la tecla de método abreviado del
menú. Por ejemplo, el menú &Ventana puede invocarse presionando Alt+V. Las teclas de
*
TOME NOTA
método abreviado no serán evidentes hasta que el usuario presione la tecla Alt. Un ajuste
del sistema operativo Windows controla si las teclas de método abreviado estarán siempre
visibles.

3. Para el control MenuStrip, establezca la propiedad MdiWindowListItem en el nombre


del menú Ventana (windowToolStripMenuItem de forma predeterminada).
4. En el Explorador de soluciones, haga clic con el botón secundario en el proyecto y
seleccione Agregar > Formulario de Windows Forms. Agregue un nuevo formulario de
Windows Forms denominado ChildForm.
5. Haga doble clic en el formulario secundario y agregue el siguiente código para contro-
lar el evento Load:
private void ChildForm_Load(
  object sender, EventArgs e)
{
  Text = DateTime.Now.ToString();
}

6. En el formulario principal, haga doble clic en el elemento de menú Ventana > Nueva
ventana y agregue el siguiente controlador de eventos para su evento Click:
private void newWindowToolStripMenuItem_Click(
  object sender, EventArgs e)
{
ChildForm child = new ChildForm();
child.MdiParent = this;
child.Show();
}

7. En el formulario principal, haga doble clic en Ventana > Organizar, Ventana > Cascada,
Ventana > Organizar, Ventana > Horizontal y Ventana > Organizar, Ventana > Vertical,
respectivamente, y agregue los siguientes controladores de eventos para sus eventos
Click:
private void cascadeToolStripMenuItem_Click(
  object sender, EventArgs e)
{
  LayoutMdi(MdiLayout.Cascade);
}
private void horizontalToolStripMenuItem_Click(
  object sender, EventArgs e)
{
  LayoutMdi(MdiLayout.TileHorizontal);
}
private void verticalToolStripMenuItem_Click(
  object sender, EventArgs e)
{
  LayoutMdi(MdiLayout.TileVertical);
}
Comprensión de las aplicaciones de escritorio | 129

8. Seleccione Depurar > Iniciar depuración (o presione F5) para ejecutar el proyecto.
Seleccione Ventana > Nueva ventana para crear varias ventanas secundarias nuevas.
Cambie entre las ventanas secundarias. Observe que solo hay una instancia de la apli-
cación en la barra de tareas de Windows. Ahora, use las opciones del menú Ventana
> Organizar para organizar las ventanas secundarias. Por ejemplo, una aplicación con
tres ventanas secundarias podría presentar el aspecto de la imagen que se muestra en
la figura 5-8 cuando las ventanas secundarias estén organizadas horizontalmente.
Figura 5-8
Una aplicación MDI con
tres ventanas secundarias
organizadas horizontalmente

Vamos a revisar algunos de los métodos y las propiedades importantes que hemos usado en
este ejercicio. En primer lugar, para el formulario principal, la propiedad IsMdiContainer
se establece en true. Esta propiedad indica que el formulario es un contenedor de varios
formularios secundarios MDI. Por consiguiente, para cada formulario secundario, se establece
la propiedad MdiParent a fin de especificar el formulario contenedor principal.
A continuación, se establece la propiedad MdiWindowListItem de MenuStrip con objeto de
indicar qué elemento de menú se usará para mostrar la lista de ventanas secundarias MDI. Una
vez establecida esta propiedad, el elemento de menú mostrará una lista de todas las ventanas
secundarias y, además, permitirá cambiar entre ellas. Como resultado del código del método
LISTO PARA CERTIFICACIÓN ChildForm_Load, la barra de título de cada formulario muestra la fecha y hora del instante en
¿Comprende cómo que se cargó el formulario.
desarrollar aplicaciones de Por último, el método LayoutMdi se usa en los elementos de menú del menú Ventana para
Windows Forms? organizar las ventanas secundarias. El método acepta un parámetro del tipo de enumeración
5.1 MdiLayout. El valor de la enumeración determina si las ventanas secundarias deben
organizarse en mosaico horizontal o vertical, en cascada o mostrarse como iconos.

■ Conceptos de las aplicaciones basadas en consola

Las aplicaciones basadas en consola no cuentan con una interfaz gráfica de usuario
CONCLUSIÓN
y usan una ventana de consola de modo de texto para interactuar con el usuario. Estas
aplicaciones son más adecuadas para tareas que requieren una interfaz de usuario
mínima o ninguna.
Como su nombre indica, una aplicación de consola se ejecuta desde la ventana de consola. La
TOME NOTA
* entrada a esta aplicación se puede proporcionar mediante parámetros de línea de comandos;
Para habilitar la lectura o bien, la aplicación puede leer interactivamente los caracteres de la ventana de consola.
o escritura en la consola Del mismo modo, la salida de una aplicación de consola se escribe también en la ventana de
desde una aplicación comandos. Puede habilitar la lectura o escritura en la consola mediante la creación de una
de Windows Forms, aplicación que use la plantilla Aplicación de consola de Visual Studio.
establezca el tipo de También puede usar aplicaciones basadas en consola para crear comandos que se ejecuten
salida del proyecto en desde la línea de comandos. Por ejemplo, puede aprovechar las canalizaciones y los filtros
aplicación de consola proporcionados por el sistema operativo para pasar la salida de un comando como entrada de
en las propiedades del otro comando; con esta combinación de comandos simples se crean otros más eficaces.
proyecto.
130 | Lección 5

Trabajo con parámetros de línea de comandos

En esta sección, aprenderemos a aceptar parámetros de línea de comandos de una


aplicación de consola.

En el siguiente ejercicio se crea una aplicación de consola simple que acepta el nombre de un
archivo de texto como argumento de línea de comandos y muestra el contenido de ese archivo.

CREACIÓN DE UNA APLICACIÓN DE CONSOLA


PREPÁRESE. Inicie Microsoft Visual Studio. A continuación, siga este procedimiento:
1. Cree un nuevo proyecto basado en la plantilla Aplicación de consola, como se muestra
en la figura 5-9. Asigne al proyecto el nombre DisplayFile.

Figura 5-9
Plantilla Aplicación de
consola

2. En Program.cs, modifique el código del método Main como se muestra a continuación:


static void Main(string[] args)
{
  if (args.Length < 1)
    return;
  string[] lines = File.ReadAllLines(args[0]);
  foreach (string item in lines)
  {
    Console.WriteLine(item);
  }
}

3. Agregue la siguiente directiva using al archivo:


using System.IO;
4. Seleccione Compilar > Compilar solución (o presione F6) para compilar el proyecto.
Comprensión de las aplicaciones de escritorio | 131

5. Cree un archivo de texto mediante Visual Studio o el Bloc de notas, escriba algún texto
de muestra y guarde el archivo como Sample.txt en la misma carpeta que el archivo
ejecutable. (El archivo ejecutable se crea de forma predeterminada en la carpeta
bin\debug bajo la carpeta del proyecto.)
6. Abra un símbolo del sistema y vaya a la ruta de acceso del archivo EXE del proyecto.
Ejecute el siguiente comando:
DisplayFile sample.txt
LISTO PARA CERTIFICACIÓN
Este comando debe mostrar el contenido del archivo de texto en la ventana de
¿Comprende cómo
comandos.
desarrollar aplicaciones
basadas en consola? 7. Como alternativa, también puede pasar el argumento de línea de comandos desde
5.2 Visual Studio mediante la ventana de propiedades del proyecto, como se muestra en
la figura 5-10. Para ver la ventana de propiedades del proyecto, seleccione la opción
de menú Proyecto > Propiedades de DisplayFile.
Figura 5-10
Establecimiento de las
opciones de inicio en la
ventana de propiedades del
proyecto

■ Conceptos de los servicios de Windows

Un servicio de Windows es una aplicación que se ejecuta en segundo plano y no cuenta


CONCLUSIÓN con ninguna interfaz de usuario.

Por su naturaleza, los servicios de Windows son idóneos para crear programas de ejecución
prolongada que se ejecutan en segundo plano y no proporcionan directamente ninguna
interacción con el usuario. Un servicio de Windows se puede iniciar, pausar, reiniciar
y detener. También se puede definir un servicio de Windows de manera que se inicie
automáticamente al arrancar el equipo.
Algunos ejemplos de servicios de Windows son un servidor web que escucha las solicitudes
entrantes y envía una respuesta, o la cola de impresión de un sistema operativo que
proporciona servicios de impresión a los programas de aplicación.
132 | Lección 5

Los servicios desempeñan una función importante en la arquitectura de las aplicaciones


empresariales. Por ejemplo, puede tenerse un servicio que escucha los pedidos entrantes e
inicia un flujo de trabajo de procesamiento de pedidos cada vez que se recibe uno.

Dado que un servicio de Windows se puede ejecutar en segundo plano, no necesita que un
usuario haya iniciado sesión para poder funcionar. Los servicios de Windows se ejecutarán
TOME NOTA
* en su propia sesión de Windows en el contexto de seguridad especificado. Aun así, según
qué permisos se necesiten, se puede especificar una cuenta de usuario en la que ejecutar el
servicio.

Creación de un servicio de Windows

Para crear un servicio de Windows en Visual Studio, use la plantilla de aplicación


Servicio de Windows. Tenga en cuenta que el servicio de Windows debe haberse
instalado previamente para poder usarlo.
TOME NOTA
*
Visual Studio Express Todos los servicios de Windows deben derivarse de la clase ServiceBase. Esta clase base
Edition no proporciona proporciona la estructura y funcionalidad básicas para la creación de un servicio de Windows.
plantillas para crear Puede invalidar los métodos OnStart, OnStop, OnPause y OnContinue de la clase base para
proyectos de servicio de agregar su propia lógica personalizada que se ejecute en respuesta a los cambios en los estados
Windows. Por lo tanto, del servicio.
se requiere una versión En el ejercicio siguiente se muestra cómo crear un servicio de Windows simple que escribe
de Visual Studio distinta mensajes en el registro de eventos de la aplicación. Los registros de eventos son la parte de
de la edición Express Windows que las tareas y aplicaciones del sistema operativo que se ejecutan en segundo plano
para completar los usan para registrar mensajes de errores o informativos de otro tipo. En Windows se definen
ejercicios en que se usan tres registros de eventos de forma predeterminada: del sistema, de la aplicación y de seguridad.
proyectos de servicios Las aplicaciones suelen usar el registro de eventos de la aplicación para registrar sus mensajes.
de Windows. Puede usar el Visor de eventos de Windows para ver los mensajes de los registros de eventos.

CREACIÓN DE UN SERVICIO DE WINDOWS


PREPÁRESE. Inicie Microsoft Visual Studio. A continuación, siga este procedimiento:

Figura 5-11
Selección de la plantilla
de proyecto Servicio de
Windows
Comprensión de las aplicaciones de escritorio | 133

1. Cree un nuevo proyecto basado en la plantilla Servicio de Windows. Asigne al proyecto


el nombre FirstService, como se muestra en la figura 5-11.
2. Seleccione la ventana de propiedades de Service1 y establezca las propiedades
(Name) y ServiceName en “FirstService”.
3. En el Explorador de soluciones, cambie el nombre del archivo Service1.cs por
FirstService.cs. Abra Program.cs y compruebe que las referencias a Service1 se han
cambiado a FirstService.
4. Seleccione la ventana de propiedades del servicio y establezca las propiedades
CanPauseAndContinue y CanShutdown en True.
5. Abra el diseñador de FirstService y agréguele un componente EventLog desde el
cuadro de herramientas. El componente EventLog permite conectar con los registros
de eventos.
6. Consulte el código de FirstService y modifique el constructor como se muestra a
continuación. En este código, primero creamos un origen del evento denominado
FirstService. Este origen del evento se usa para distinguir los mensajes generados
por una aplicación concreta entre todos los demás mensajes del registro de eventos.
A continuación, establecemos la propiedad Source del componente del registro de
eventos en el nombre del origen del evento. La propiedad Log del componente de
registro de eventos, eventLog1, se usa para especificar el registro de eventos que se
usa para registrar los mensajes:
public FirstService()
{
  InitializeComponent();
  if (!EventLog.SourceExists(“FirstService”))
  {
     EventLog.CreateEventSource(
       “FirstService”, “Application”);
  }
  eventLog1.Source = “FirstService”;
  eventLog1.Log = "Application";
}

7. Agregue el código siguiente a los métodos de cambio de estado del servicio para
definir su comportamiento. El método WriteEntry del componente de registro de
eventos, eventLog1, se usa para escribir un mensaje en un registro de eventos. En el
método se puede especificar el tipo de mensaje. Por ejemplo, el mensaje puede ser
un mensaje de error, un mensaje de advertencia o solo un dato:
protected override void OnStart(string[] args)
{
  eventLog1.WriteEntry(
"Iniciando el servicio",
   EventLogEntryType.Information, 1001);
}
protected override void OnStop()
{
  eventLog1.WriteEntry(
"Deteniendo el servicio",
134 | Lección 5

   EventLogEntryType.Information, 1001);
}
protected override void OnPause()
{
  eventLog1.WriteEntry(
"Pausando el servicio",
   EventLogEntryType.Information, 1001);
}
protected override void OnContinue()
{
  eventLog1.WriteEntry(
"Continuando el servicio",
   EventLogEntryType.Information, 1001);
}
protected override void OnShutdown()
{
  eventLog1.WriteEntry(
"Apagando el servicio",
   EventLogEntryType.Information, 1001);
}

8. Seleccione Compilar > Compilar solución (o presione F6) para compilar el proyecto.
En este caso, el código de FirstService invalida los métodos OnStart, OnStop, OnPause,
OnContinue y OnShutdown para escribir mensajes en el registro de eventos. Sin embargo,
no todos los servicios requieren invalidar estos métodos. La necesidad de invalidarlos o no
depende del valor de las propiedades CanPauseAndContinue y CanShutdown del servicio de
Windows.
El método WriteEntry del registro de eventos toma el mensaje de escribir en el registro, el tipo
de entrada del registro de eventos (información, error, advertencia, etc.) y un Id. de evento, que
es un identificador específico de la aplicación que se usa para identificar el evento.
El servicio de Windows FirstService está listo, pero para poder usarlo antes es preciso
instalarlo en la base de datos del servicio de Windows. Para ello, hay que agregar un instalador
del servicio al proyecto del servicio de Windows. En el siguiente ejercicio se muestra cómo.

ADICIÓN DE UN INSTALADOR A UN SERVICIO DE WINDOWS


PREPÁRESE. Inicie Microsoft Visual Studio. A continuación, siga este procedimiento:
1. Abra el proyecto FirstService creado en el ejercicio anterior. Haga clic con el botón
secundario en la superficie del diseñador de FirstService.cs y seleccione la opción
Agregar instalador en el menú contextual.
2. Esta acción agrega al proyecto un nuevo archivo ProjectInstaller.cs. Abra el diseñador
de ProjectInstaller.cs. Debería observar que se han agregado dos componentes al
diseñador, como se muestra en la figura 5-12.

Figura 5-12
Vista del diseñador de
ProjectInstaller.cs
Comprensión de las aplicaciones de escritorio | 135

3. Obtenga acceso a las propiedades de serviceProcessInstaller1component y cambie la


propiedad Account a LocalService.
4. A continuación, obtenga acceso a las propiedades de serviceInstaller1component.
Cambie la propiedad DisplayName a FirstService y la propiedad Description a “Un ser-
vicio de prueba simple”. Observe que el valor de la propiedad StartType se establece
de forma predeterminada en Manual.
5. Seleccione Compilar > Compilar solución (o presione F6) para compilar el proyecto. El
servicio de Windows ha quedado listo para instalarlo.

La propiedad StartType de la clase ServiceInstaller indica cómo y cuándo se ha iniciado


un servicio. La propiedad StartType puede tener tres valores posibles: el valor Manual, que
es también el valor predeterminado, indica que es preciso iniciar el servicio manualmente;
*
TOME NOTA
el valor Automatic indica que el servicio se iniciará automáticamente cuando se inicie
Windows; el valor Disabled indica que no se puede iniciar el servicio.

Al agregar un instalador a un proyecto de servicio de Windows, se agregan al proyecto las


clases ServiceProcessInstaller y ServiceInstaller. La clase ServiceProcessInstaller realiza
TOME NOTA
* tareas de instalación que son comunes a todos los servicios de Windows de una aplicación.
Para minimizar los Esto incluye configurar la cuenta de inicio de sesión del servicio de Windows. La clase
riesgos de seguridad, ServiceInstaller, por su parte, realiza las tareas de instalación que son específicas de un único
es conveniente evitar servicio de Windows, tales como establecer ServiceName y StartType.
el uso de la cuenta La propiedad Account de la clase ServiceProcessInstaller especifica el tipo de cuenta
LocalSystem para bajo la que se ejecutan los servicios. La propiedad Account es del tipo de enumeración
ejecutar servicios de ServiceAccount, cuyos valores posibles son LocalService, LocalSystem, NetworkService y
Windows, a no ser que User. El valor LocalSystem especifica una cuenta con privilegios elevados, mientras que la
el servicio requiera cuenta LocalService actúa como un usuario sin privilegios.
privilegios de seguridad
más elevados para Un archivo ejecutable que contiene el código para las clases del instalador del servicio puede
funcionar. instalarse mediante el uso de la herramienta de línea de comandos Installer (installutil.exe). En
el siguiente ejercicio se muestra cómo instalar una aplicación de servicio de Windows en la
base de datos del servicio de Windows.

INSTALACIÓN DE UN SERVICIO DE WINDOWS


PREPÁRESE. Para instalar un servicio de Windows, realice los siguientes pasos:
1. Ejecute un símbolo del sistema de Visual Studio como administrador. Para obtener
acceso al símbolo del sistema, vaya a Inicio > Todos los programas > Visual Studio
> Visual Studio Tools y elija Símbolo del sistema de Visual Studio. Para ejecutar un
programa como administrador en Windows, haga clic con el botón secundario en el
acceso directo del programa y seleccione la opción Ejecutar como administrador en el
menú contextual.
2. Cambie al directorio de salida del proyecto FirstService. Este es el directorio donde se
encuentra el archivo ejecutable.
136 | Lección 5

3. Ejecute el siguiente comando; deben aparecer unos resultados parecidos a los


mostrados en la figura 5-13:
installutil FirstService.exe

Figura 5-13
Uso de installutil.exe

4. El servicio de Windows FirstService ha quedado instalado.


TOME NOTA
*
Para instalación un La aplicación del servicio de Windows está almacenada ahora en la base de datos del servicio
servicio de Windows de Windows. Antes, cuando usted agregamos ServiceInstaller para FirstService, establecimos
se requiere acceso al la propiedad StartType del componente serviceInstaller1 en Manual. En consecuencia,
Registro de Windows. tendremos que iniciar manualmente el servicio cuando sea necesario. En el siguiente ejercicio
Por lo tanto, asegúrese se muestra cómo iniciar, pausar, continuar y detener un servicio de Windows.
de ejecutar installUtil.
exe como administrador.
TRABA JO CON UN SERVICIO DE WINDOWS
PREPÁRESE. Abra la ventana Administración de equipos; para ello, haga clic con el botón
TOME NOTA
* secundario en Mi PC y seleccione Administrar en el menú contextual. A continuación,
Para desinstalar un siga este procedimiento:
servicio de Windows,
1. En la ventana Administración de equipos, expanda la sección Servicios y Aplicaciones
use InstallUtil.exe con la
opción -u. y seleccione Servicios. Debe aparecer una lista de todos los servicios instalados en el
equipo, como se muestra en la figura 5-14.

Figura 5-14
La sección de servicios
permite trabajar con los
servicios instalados
Comprensión de las aplicaciones de escritorio | 137

2. Seleccione el servicio FirstService y haga clic en el hipervínculo Iniciar, como se


muestra en la figura 5-14. Debe aparecer un cuadro de diálogo que indica progreso,
como se muestra en la figura 5-15. Al iniciar el servicio, su estado cambia a Iniciado.

Figura 5-15
Mensaje Control de servicio
mostrado al iniciar un
servicio

3. Expanda el nodo Visor de eventos y seleccione el registro de aplicación de Windows.


Debe aparecer un mensaje de FirstService que diga “Iniciando el servicio”, como se
muestra en la figura 5-16.

Figura 5-16
Registro de aplicación de
Windows

4. Vuelva a la lista de servicios e intente pausar, reanudar o detener FirstService.


LISTO PARA CERTIFICACIÓN
Compruebe el registro de eventos de la aplicación para comprobar que se muestran
¿Comprende cómo
desarrollar servicios de
los mensajes apropiados.
Windows? En los últimos ejercicios, hemos visto cómo crear, instalar y usar un servicio de Windows.
5.3 También hemos aprendido a agregar mensajes mediante programación al registro de eventos
de la aplicación de Windows.

RESUMEN DE CONOCIMIENTOS

En esta lección hemos aprendido lo siguiente:


• Un formulario de Windows Forms es una superficie visual que puede mostrar varios
de controles, como cuadros de texto, botones y menús. Visual Studio proporciona
un Diseñador de Windows Forms con funcionalidad de arrastrar y colocar que puede
usar para crear aplicaciones.
• En Windows Forms, cada formulario y control expone un conjunto predefinido
de eventos. Cuando se produce un evento, se invoca el código del controlador de
eventos asociado. El modelo de eventos de Windows Forms usa delegados de .NET
Framework para vincular los eventos a sus controladores de eventos respectivos.
138 | Lección 5

• La herencia visual permite volver a usar la funcionalidad y los diseños existentes en
formularios de Windows Forms.
• Las aplicaciones de interfaz de múltiples documentos (MDI) son aquellas en que
varias ventanas secundarias residen en una sola ventana principal.
• Las aplicaciones basadas en consola no cuentan con una interfaz gráfica de usuario y
usan una ventana de consola de modo de texto para interactuar con el usuario. Estas
aplicaciones son más adecuadas para tareas que requieren una interfaz de usuario
mínima o ninguna.
• Los servicios de Windows son idóneos para crear aplicaciones de ejecución prolonga-
da que se ejecutan en segundo plano y no presentan ninguna interfaz de usuario.
• Puede crear servicios de Windows mediante la plantilla Servicios de Windows de
Visual Studio.
• Para poder usar un servicio de Windows, es preciso instalarlo antes en el Registro de
Windows. Para ello, agregue el componente Installer a la aplicación del servicio de
Windows. Esto permite instalar el servicio de Windows mediante una herramienta de
instalación como InstallUtil.exe.

■ Evaluación de conocimientos
Rellene los espacios en blanco
Complete las oraciones siguientes escribiendo la palabra o las palabras correctas en los
espacios en blanco proporcionados.
1. Use la propiedad _________ de la clase ServiceInstaller para especificar un
comentario breve que explique el propósito del servicio.
2. La propiedad _________ de la clase _________ indica el tipo de cuenta en que se
ejecutará un servicio de Windows.
3. La propiedad _________ de la clase EventLog se usa para especificar el nombre de
aplicación que se usará al escribir en un registro de eventos.
4. _________ permite volver a usar la funcionalidad y los diseños existentes en
formularios de Windows Forms.
5. Las aplicaciones _________ son aquellas en que varias ventanas secundarias residen
en una misma ventana principal.
6. Un(a) _________ es idóneo(a) para crear aplicaciones de ejecución prolongada que
se ejecutan en segundo plano y no presentan ninguna interfaz de usuario.
7. _________ no cuentan con una interfaz gráfica de usuario y usan una ventana de
consola de modo de texto para interactuar con el usuario.
8. Las aplicaciones de _________ proporcionan su propia funcionalidad de
administración de ventanas, mientras que las aplicaciones de _________ dependen
del sistema operativo para la administración de las ventanas.
9. Un delegado puede enlazarse a cualquier método cuya signatura coincida con la de
________.
10. Los(Las) _________ se pueden enlazar a más de un método, lo que hace posibles las
notificaciones de uno a varios cuando se desencadena un evento.
Comprensión de las aplicaciones de escritorio | 139

Varias opciones
Rodee con un círculo la letra correspondiente a la mejor respuesta.
1. Tiene que diseñar un servicio de Windows que no se pueda pausar. ¿Cuál de las
siguientes opciones le ayudará a realizar esta tarea?
a. Establecer la propiedad CanPauseAndContinue del servicio de Windows en False.
b. Establecer la propiedad CanPauseAndContinue del servicio de Windows en True.
c. Establecer la propiedad CanStart del servicio de Windows en True, pero establecer
la propiedad CanShutdown en False.
d. No invalidar los métodos OnPause y OnContinue en el servicio de Windows.
2. Ha desarrollado un servicio de Windows. Tiene que instalarlo para instalar su funcio-
nalidad. ¿Cuál de las siguientes opciones debe elegir para llevar a cabo esta tarea?
a. Usar el Explorador de servidores de Visual Studio.
b. Usar el nodo Servicios de la ventana Administración de equipos.
c. Usar InstallUtil.exe.
d. Usar gacutil.exe.
3. Ha desarrollado un servicio de Windows. Este servicio se tiene que ejecutar como
usuario sin privilegios, para minimizar cualquier posibilidad de riesgos de seguridad.
¿Cuál de las siguientes cuentas debe usar para ejecutar este servicio de Windows?
a. LocalSystem
b. NetworkService
c. LocalService
d. User (cuya propiedad UserName se establece en un miembro del rol de adminis-
trador)
4. Está diseñando una aplicación de servicio de Windows que contiene un solo servicio
de Windows. Desea que este servicio se inicie automáticamente al reiniciar el equipo.
¿Cuál de las siguientes clases debería usar para especificar esta opción?
a. ServiceBase
b. ServiceInstaller
c. ServiceProcessInstaller
d. ServiceController
5. Necesita cambiar la pantalla y el comportamiento de un formulario de Windows
Forms para que pueda contener varias ventanas secundarias. ¿Qué debe hacer?
a. Establecer la propiedad IsMdiContainer del formulario en True.
b. Establecer la propiedad MdiParent de todas las ventanas secundarias.
c. Establecer la propiedad MdiChild del formulario.
d. Establecer la propiedad IsMdiChild del formulario.
6. Está desarrollando un formulario de Windows Forms que responde a los eventos del
mouse. Al mover el mouse, debe invocar el método Form1_HandleMouse. El código
que escriba no debe afectar a ningún código de control de eventos existente. ¿Qué
instrucción debe usar para asociar el controlador de eventos al evento?
a.
this.MouseDown = new MouseEventHandler
      (Form1_HandleMouse);
b.
this.MouseMove = new MouseEventHandler
      (Form1_HandleMouse);
c.
this.MouseDown += new MouseEventHandler
      (Form1_HandleMouse);
140 | Lección 5

d.
this.MouseMove += new MouseEventHandler
      (Form1_HandleMouse);

7. Está desarrollando un formulario de Windows Forms con una interfaz de múltiples


documentos (MDI). Debe escribir código que organice las ventanas secundarias ver-
ticalmente dentro de la región de cliente del formulario MDI principal. ¿Cuál de las
siguientes instrucciones debe usar?
a.
LayoutMdi(MdiLayout.TileVertical);
b.
LayoutMdi(MdiLayout.Cascade);
c.
MdiLayout(LayoutMdi.TileVertical);
d.
MdiLayout(LayoutMdi.Cascade);

8. Está desarrollando una aplicación que se ejecutará desde la línea de comandos. ¿Cuál
de los siguientes métodos usaría para la salida de la línea de comandos?
a. Console.Read
b. Console.Write
c. File.Read
d. File.Write
9. Desea desarrollar una aplicación que muestre una superficie visual que pueda mostrar
gran variedad de controles, como cuadros de texto, botones y menús. La aplicación
también debe permitir que varias ventanas secundarias residan en una ventana princi-
pal única. ¿Cuál de los siguientes tipos de aplicación debe desarrollar?
a. Una aplicación basada en consola
b. Una aplicación de servicio de Windows
c. Una aplicación de interfaz de un único documento (SDI)
d. Una aplicación de interfaz de múltiples documentos (MDI)
10. Está extendiendo una aplicación existente de Windows. Desea crear un nuevo formu-
lario que derive sus características visuales (lo que incluye tamaño, color y algunos
controles) de un formulario creado anteriormente. ¿Qué técnica debería usar para
crear el nuevo formulario?
a. Herencia visual
b. Encapsulación visual
c. Abstracción visual
d. Polimorfismo visual

■ Evaluación de competencias
Escenario 5-1: Uso de la herencia visual
Tiene que crear un formulario de Windows Forms similar al que creó en el ejercicio de
VisualInheritance. Sin embargo, esta vez el requisito es que el color de fondo de este
formulario coincida con el color seleccionado del escritorio del usuario. ¿Cómo se puede
desarrollar este formulario?

Escenario 5-2: Control del evento MouseDown


Está desarrollando un juego que permite a los usuarios impactar una zona objetivo en un
formulario de Windows Forms con su mouse. Debe desarrollar un formulario experimental que
muestre las coordenadas X e Y de la ubicación donde el usuario hizo clic en la barra de título
del formulario. ¿Cómo se puede lograr esto?
Comprensión de las aplicaciones de escritorio | 141

■ Evaluación de aptitudes
Escenario 5-3: Trabajo con entrada de consola
Está desarrollando un programa que manipula texto. Debe escribir una aplicación basada
en consola que acepta texto del usuario y que lo convierte a mayúsculas. ¿Qué código debe
escribir para cumplir con este requisito?

Escenario 5-4: Uso de la utilidad de red (net.exe)


La utilidad de símbolo del sistema net.exe viene instalada con Windows. Esta utilidad le
permite ejecutar varios comandos de redes, lo que incluye el control de los servicios de
Windows. Desea usar net.exe para trabajar con el servicio de Windows FirstService que se
creó anteriormente. ¿Qué medidas debe tomar para pausar, detener e iniciar un servicio de
Windows mediante la utilidad net.exe?
6 LECCIÓN
Comprensión de
bases de datos
M AT R I Z D E C O N O C I M I E N T O S D E L A L E C C I Ó N

Conocimientos y conceptos Objetivo del examen MTA Número de objetivo del


examen MTA
Conceptos de los objetos Conceptos de los sistemas de 6.1
administración de bases de
datos relacionales
Conceptos de los valores Conceptos de los métodos 6.2
y las referencias de consulta de bases de datos.
Comprensión de la encapsulación Conceptos de los métodos de 6.3
conexión de bases de datos.

TÉRMINOS CLAVE
aplicaciones desconectadas diseño de bases de datos procedimiento almacenado
archivos planos relacionales procedimientos almacenados
atributo elemento parametrizados
base de datos instrucciones de procesamiento segunda forma normal (2FN)
base de datos relacional integridad de bases de datos sistema de administración de
clave principal Lenguaje de consulta bases de datos (DBMs)
DataSet estructurado (SQL) tercera forma normal (3FN)
dependencia funcional Lenguaje de marcado
extensible (XML)
diagramas de relación entre
entidades (ERD) normalización
primera forma normal (1FN)

Usted es un desarrollador de software de la empresa Northwind Corporation. Como parte


de su trabajo, interactúa con datos sobre clientes, productos, proveedores y pedidos y los
procesa. Su trabajo conlleva interactuar con bases de datos relacionales como Microsoft
SQL Server. Sin embargo, también trabaja con datos almacenados en otros formatos, tales
como archivos planos, archivos XML y datos en memoria. Para ser eficaz en su trabajo,
tiene que saber cómo conectarse a diversos orígenes de datos, así como recuperar y
actualizar datos de esos orígenes.

■ Conceptos de las bases de datos relacionales

Una base de datos relacional es una colección de datos interrelacionados basados en el


CONCLUSIÓN
modelo relacional desarrollado por E. F. Codd. Este modelo define entidades de datos
diferenciadas, sus atributos y las relaciones entre ellas.
142
Comprensión de bases de datos | 143

Comprensión de las bases de datos

Una base de datos es una colección organizada de datos interrelacionados que se


administran como una sola unidad.

Una base de datos permite almacenar, mantener y recuperar datos importantes. Si una base
de datos está diseñada correctamente, la pueden usar varias aplicaciones y varios usuarios.
Un sistema de administración de bases de datos (DBMS), por su parte, es un software que
organiza las bases de datos y proporciona características tales como almacenamiento, acceso
a datos, seguridad, copia de seguridad, etc. Algunos DBMS conocidos son, por ejemplo,
Microsoft SQL Server, Microsoft Access, Oracle y MySql.
Los sistemas de administración de bases de datos se pueden implementar de acuerdo con
diferentes modelos. De estos modelos, el relacional es el más popular. En el modelo relacional,
los datos se organizan en tablas, cada una de las cuales puede tener varias filas. Los DBMS
basados en modelos relacionales se denominan DBMS relacionales (RDBMS). SQL Server,
Access, Oracle y MySql son RDBMS.
Otros sistemas de administración de bases de datos se basan en diferentes modelos. Por
ejemplo, los DBMS de objetos (ODBMS) se basan en el modelo de objetos, en el cual
los datos se almacenan como una colección de objetos. Sin embargo, en esta lección nos
centraremos únicamente en las bases de datos relacionales más populares.
Los DBMS relacionales usan el Lenguaje de consulta estructurado (SQL) para recuperar
y manipular los datos. Los sistemas de administración de bases de datos relacionales más
conocidos proporcionan compatibilidad con la versión estándar de SQL, lo que le permitirá
usar sus conocimientos en distintos sistemas de bases de datos relacionales.

Conceptos de las bases de datos relacionales

Una base de datos relacional organiza los datos en tablas bidimensionales que
constan de filas y columnas.

Una base de datos relacional organiza la información en tablas. Una tabla es una lista de filas
y columnas, conceptualmente similar a una hoja de cálculo de Microsoft Excel. A las filas
también se las denomina registros o tuplas y a las columnas, campos. La columna o campo
especifica el tipo de datos que se almacenará para cada registro de la tabla. Por ejemplo, los
pedidos de clientes se pueden almacenar en una tabla denominada Orders (Pedidos) en que
cada fila represente un único pedido. En esta tabla, se pueden usar columnas, como OrderDate
(Fecha pedido), para especificar que un valor válido es del tipo de datos correcto. En la figura
6-1 se muestra un ejemplo de tabla de pedidos.

Figura 6-1
Tabla de pedidos de una
base de datos relacional
144 | Lección 6

Conceptos del diseño de bases de datos relacionales

El diseño de bases de datos relacionales es el proceso que consiste en determinar cuál es


la estructura de una base de datos relacional apropiada para satisfacer los requisitos de la
empresa.

Los datos de una organización son uno de sus activos más importantes. Por lo tanto, garantizar
la integridad de la base de datos debe ser uno de los principios rectores al diseñarla. Por
integridad entendemos que los datos de la base de datos sean exactos y coherentes en todo
momento.
El proceso de diseño de bases de datos consta de los siguientes pasos:
1. Desarrollar una declaración de objetivos de la base de datos: identifica el propósito
de la base de datos, cómo se usará y quién la usará. En este paso se marca la pauta para el
resto del proceso de diseño.
2. Determinar los datos que se desea almacenar: identifica todos los tipos de datos que
deben almacenarse en la base de datos. Generalmente, esta información se recopila
durante la tarea de análisis de requisitos, mediante diagramas de relación entre entidades.
3. Dividir los datos en tablas y columnas: identifica las tablas y la información que se
desea almacenar en ellas.
4. Elegir las claves principales: una clave principal es una columna o conjunto de
columnas que identifica de forma exclusiva cada fila de datos de una tabla.
5. Identificar las relaciones: identifica cómo se relacionan los datos de una tabla con los de
otra. Por ejemplo, para cada cliente de una tabla denominada Customers (Clientes), puede
haber muchos pedidos en la tabla Orders (Pedidos); esta relación se denomina relación de
uno a varios.
6. Aplicar el proceso de normalización: aplica las reglas de normalización de datos para
asegurarse de que se resuelvan todos los problemas que pueden afectar a la integridad
de los datos. Aprenderemos más sobre el proceso de normalización más adelante en esta
lección.
Una vez que se ha establecido el propósito de una base de datos, los siguientes pasos (del 2
al 5) se pueden realizar durante el modelado de relación entre entidades. A continuación, el
último paso de la normalización puede aplicarse a la salida de este modelo.

Conceptos de los diagramas de relación entre entidades

Los diagramas de relación entre entidades (ERD) se usan para modelar las entidades,
sus atributos y las relaciones entre ellas. Los diagramas de relación entre entidades
pueden ayudarle a determinar qué datos es preciso almacenar en una base de datos.

El modelado de relación entre entidades es un proceso que se usa para crear el modelo de
datos conceptual de un sistema; los diagramas de relación entre entidades son las herramientas
gráficas de modelado gráfico que permiten realizar este proceso. Los bloques de creación
básicos de un ERD son la entidad, el atributo y la relación:
• Entidad: una entidad es una construcción de un objeto físico o un concepto. Algunos
ejemplos de entidades son un pedido, un cliente, un empleado, etc. Una entidad suele
designarse por el sustantivo que representa.
• Atributo: los atributos son las propiedades específicas de una entidad. Por ejemplo,
si la entidad es Order, algunos atributos útiles pueden ser OrderNumber, OrderDate,
ShipDate y ShipVia (respectivamente, Número pedido, Fecha pedido, Fecha envío y
Transportista). Del mismo modo, si la entidad es Empleado, algunos atributos útiles
pueden ser EmployeeId, LastName, FirstName, Title y HireDate (respectivamente, Id.
empleado, Apellidos, Nombre, Cargo y Fecha contratación). Cada entidad debe contar
con un conjunto de atributos que lo identifican de forma exclusiva y se denominan clave
principal de la entidad. Por ejemplo, OrderNumber es un atributo que identifica de forma
exclusiva un pedido, por lo que es una clave principal de la entidad Order (Pedido).
Comprensión de bases de datos | 145

• Relación: una relación es una asociación entre las entidades. Por ejemplo, Takes (Acepta)
es una relación entre las entidades Employee (Empleado) y Order (Pedido) (es decir,
Employee Takes Order, que significa Empleado Acepta Pedido).
Tenga en cuenta que los ERD no muestran entidades ni relaciones individuales. Por ejemplo,
puede haber miles de entidades Order y cientos de entidades Customer (Cliente). Así pues, en
estos diagramas se muestran conjuntos de entidades y de relaciones; por ejemplo, los miles de
entidades Order pueden constituir un único conjunto de entidades. De hecho, cuando aparece
Order o Customer en un ERD, generalmente se refiere a un conjunto de entidades, no a una
entidad individual.
Los ERD usan algunas convenciones de diseño. En concreto:
• Un rectángulo representa un conjunto de entidades.
• Una elipse representa un atributo.
• Un rombo representa un conjunto de relaciones.
• Las líneas continuas vinculan los conjuntos de entidades a los conjuntos de
relaciones y a los atributos.
En la figura 6-2 se muestra un ejemplo de ERD. En este diagrama, los dos conjuntos de
entidades son Customer y Order. Los atributos asociados con el cliente son ID (Identificador),
Name (Nombre) y City (Ciudad). Los atributos asociados con Order son OrderID, OrderDate
y ShipDate (respectivamente, Id. pedido, Fecha pedido y Fecha envío). Los atributos que
constituyen una clave principal están subrayados. Además, como se muestra en la figura, la
relación entre Customer y Order es Places (Realiza).
Figura 6-2
Diagrama de relación entre
entidades

En un ERD, se puede clasificar una relación como una relación de uno a uno, de uno a varios
o de varios a varios. En la figura 6-2, la línea que conecta la relación Places con el conjunto
de entidades Customer tiene la etiqueta “1”, mientras que la línea que conecta Places con el
conjunto de entidades Order tiene la etiqueta “N”. Este es un ejemplo de una relación de uno a
varios. En esta relación, un cliente puede realizar muchos pedidos, pero un pedido solo puede
tener asociado un cliente.

ASIGNACIÓN DE ERD A UNA BASE DE DATOS RELACIONAL


Para convertir un ERD en una base de datos relacional, es preciso realizar estos pasos:
1. Asignar las entidades: comience por crear una tabla para cada conjunto de entidades
del diagrama. Los atributos se convertirán en columnas. Asegúrese de establecer el o
los atributos de claves principales en la o las columnas de clave principal de la tabla.
2. Asignar la relación: a continuación, se asigna la relación de uno a varios; para
ello, asegúrese de que la tabla de lado N de la relación contiene la columna de clave
principal de la tabla del lado 1 de la relación. En el caso de la figura 6-2, esto puede
lograrse mediante la adición de una columna CustomerID (Id. cliente) a la tabla
Order y asignársela a la columna ID de la tabla Customer. En el contexto de la tabla
Order, CustomerID también se denomina clave externa. Al agregar esta columna
a la tabla Order, es posible responder a preguntas como “¿Cuáles son todos los
pedidos realizados por un cliente determinado?” y “Quién es el cliente de un pedido
concreto?”
146 | Lección 6

Cuando se asigna a una base de datos relacional, el ERD de la figura 6-2 genera las siguientes
tablas:
Customers

ID Name City
1001 Jane Doe Berlín
1002 John Doe Tokio
1003 Howard Steel Sidney

Orders

OrderID CustomerId OrderDate ShipDate


101 1001 10/1/2010 10/7/2010
102 1002 10/5/2010 10/10/2010
103 1001 10/4/2010 10/10/2010

Conceptos de la normalización de datos

El proceso de normalización de datos asegura que el diseño de una base de datos se


encuentre exento de problemas que puedan causar una pérdida de la integridad de los datos.

En análisis de relación entre entidades ayuda a asegurarse de haber identificado los elementos
de datos correctos para la base de datos. Luego, a través del proceso de normalización
de datos, se aplica un conjunto de reglas de normalización para asegurarse de que se ha
establecido el diseño de base de datos correcto; es decir, se comprueba si las columnas
pertenecen a las tablas correctas con objeto de asegurarse de que la base de datos esté libre de
problemas no deseados.
Por ejemplo, como parte del análisis de relación entre entidades, se podría descubrir una tabla
denominada Books (Libros) con las siguientes columnas:

Books

BookId BookName CategoryId CategoryName


1 Cooking 1001 Cocina
2 Mystery & Thriller 1002 Misterio y suspense
3 Business 1003 Empresa
4 Mystery & Thriller 1002 Misterio y suspense

Sin embargo, este diseño de la tabla Books presenta tres problemas:


• Anomalía de inserción: una anomalía de inserción es una situación en que no se pueden
insertar datos nuevos en una base de datos debido a una dependencia no relacionada.
Por ejemplo, si desea que la base de datos contenga un nuevo CategoryId (Id. categoría)
y CategoryName (Nombre categoría) para los libros de historia, el diseño actual no lo
permitirá a menos que previamente disponga de un libro de historia que incluir en esa
categoría.
Comprensión de bases de datos | 147

• Anomalía de eliminación: una anomalía de eliminación es una situación en que eliminar


un dato provoca la pérdida no intencionada de otros datos. Por ejemplo, si se elimina
la entrada BookId 3 (Id. libro 3) de la tabla Books, se perdería el hecho de que también
existió el valor Business en CategoryName.
• Anomalía de actualización: una anomalía de actualización es una situación en que
la actualización de un solo valor de datos requiere que se actualicen varias filas. Por
TOME NOTA
* ejemplo, supongamos que hemos decidido cambiar la categoría Mystery & Thriller por,
La normalización puede simplemente, Mystery. Con el diseño de tabla actual, será preciso cambiar el nombre
ayudarle a asegurarse de de categoría de todos los libros de esa categoría. También existe el riesgo de que, si se
que el diseño de la base actualiza el nombre de la categoría en una fila, pero no en las demás, los datos de la base
de datos sea correcto, de datos presenten incoherencias.
pero no garantiza que
lo sean también los Todos estos problemas se pueden solucionar siguiendo el proceso de normalización. Existen
elementos de datos de cinco formas normales que se usan en este proceso; sin embargo, en esta lección analizaremos
partida. únicamente las tres primeras, porque en la mayoría de los casos no se necesita más.

CONCEPTOS DE LA PRIMERA FORMA NORMAL


Para que una tabla se ajuste a la primera forma normal (1FN), ninguna de las columnas de la
tabla debe tener varios valores en la misma fila de datos. Por ejemplo, si la tabla Customers
almacena los datos como se muestra a continuación, esta tabla no es conforme con 1FN,
porque la columna PhoneNumber contiene más de un valor por fila.
Customer

Id FirstName LastName PhoneNumber


TOME NOTA
*
Generalmente se aplica 1 Jane Doe (503) 555-6874
la convención general
de subrayar el nombre 2 John Doe (509) 555-7969,
de las columnas de una (509) 555-7970
tabla que forman parte 3 Howard Steel (604) 555-3392,
de la clave principal.
(604) 555-3393

Para que esta tabla sea conforme con 1FN, es preciso dividirla en dos:

Cliente

Id FirstName LastName
1 Jane Doe
2 John Doe
3 Howard Steel

CustomerPhones

Id PhoneNumber
1 (503) 555-6874
2 (509) 555-7969
2 (509) 555-7970
3 (604) 555-3392
3 (604) 555-3393
148 | Lección 6

Ahora, tanto la tabla Customers como la tabla CustomerPhones (Teléfonos clientes) cumplen
con 1FN. Ambas tablas tienen una clave principal (el Id. de la primera tabla y la combinación
de Id. y PhoneNumber en la segunda tabla) que establece una relación entre ellas. Para
cualquier Id. de un cliente, puede encontrar todos los números de teléfono que le pertenecen
sin ninguna confusión. Por otro lado, LastName no es una clave principal porque puede haber
entradas de apellidos duplicadas.

Crear columnas repetitivas, como PhoneNumber1 y PhoneNumber2 para normalizar la tabla


Customer no sería una solución aceptable, porque la primera forma de normalización no
*
TOME NOTA
permite estas columnas repetitivas.

CONCEPTOS DE LA SEGUNDA FORMA NORMAL


Para que una tabla se ajuste a la segunda forma normal (2FN), primero debe cumplir los
requisitos de 1FN. Además, 2FN exige que todas las columnas no clave sean funcionalmente
dependientes de la clave principal completa.
Para comprender 2FN, antes es preciso entender la dependencia funcional. Tomemos el
ejemplo de la tabla Customers anterior. En la tabla Customers, la columna Id. es la clave
principal porque identifica de forma exclusiva cada fila. Las columnas FirstName y LastName
son columnas no clave, porque no forman parte de la clave principal. Tanto FirstName como
LastName son funcionalmente dependientes de Id. porque, para un valor determinado de Id.,
siempre hallaremos un valor de FirstName y LastName correspondiente sin ambigüedades.
No hay ninguna columna no clave en la tabla Customers que no dependa funcionalmente de la
clave principal. Por consiguiente, las tablas Customers y CustomerPhones satisfacen 2FN.

2FN solo se aplica a las tablas que tienen claves principales compuestas (es decir, cuando
varias columnas tomadas juntas conforman la clave principal). Los valores combinados de
*
TOME NOTA todos los campos de una clave principal compuesta deben ser únicos. Si una tabla satisface
1FN y tiene una sola columna en su clave principal, entonces la tabla también se ajusta a
2FN.

En cambio, vamos a fijarnos en la siguiente tabla:

Orders

OrderId CustomerId OrderDate CustomerName


101 1 10/1/2010 Jane Doe
102 2 10/5/2010 John Doe
103 1 10/4/2010 Jane Doe

En ella, las columnas OrderId (Id. pedido) y CustomerId (Id. cliente) identifican
conjuntamente una fila exclusiva y, por lo tanto, constituyen una clave principal compuesta.
Sin embargo, la columna OrderDate solo depende funcionalmente de OrderId y la columna
CustomerName solo depende de CustomerId. Esto infringe 2FN, porque las columnas no clave
son funcionalmente dependientes solo de una parte de la clave principal.
Una manera posible de modificar la tabla Orders de modo que se ajuste a 2FN es sacar
CustomerName de la tabla y tener solo tres columnas (OrderId, CustomerId y OrderDate),
de tal forma que únicamente OrderId constituya la clave principal. En esta solución, tanto
CustomerId como OrderDate dependen funcionalmente de OrderId, en consecuencia,
satisfacen 2FN.
Comprensión de bases de datos | 149

CONCEPTOS DE LA TERCERA FORMA NORMAL


La tercera forma normal (3FN) exige que se satisfaga 2FN y que no exista ninguna
dependencia funcional entre atributos no clave. Es decir, cada atributo no clave debe depender
exclusivamente de la clave principal y de nada más. Por ejemplo, vamos a estudiar la siguiente
tabla:
Items

ItemId SupplierId ReorderFax


101 100 (514) 555-2955
102 11 (514) 555-9022
103 525 (313) 555-5735

Aquí, ItemId (Id. artículo) es la clave principal. Sin embargo, ReorderFax (Fax reclamación)
es un número de fax del proveedor y, por lo tanto, depende funcionalmente de SupplierId (Id.
proveedor). Para satisfacer el requisito de 3FN, esta tabla debe descomponerse en dos tablas:
Items (Artículos) (ItemId, SupplierId) y Supplier (Proveedor) (SupplierId, ReorderFax).

Items

ItemId SupplierId
101 100
102 11
103 525

Supplier

LISTO PARA CERTIFICACIÓN SupplierId ReorderFax


¿Comprende los conceptos 100 (514) 555-2955
básicos de los sistemas de
administración de bases 11 (514) 555-9022
de datos relacionales?
525 (313) 555-5735
6.1

■ Conceptos de los métodos de consulta de bases de datos

Los datos constituyen el núcleo de numerosas aplicaciones empresariales. Como


desarrollador, probablemente dedicará buena parte de su tiempo a tareas relacionadas
CONCLUSIÓN con los datos. En esta sección, aprenderemos a usar el Lenguaje de consulta
estructurado (SQL) y los procedimientos almacenados de SQL Server para seleccionar,
insertar, actualizar y eliminar datos.
SQL es el lenguaje que usa la mayoría de los sistemas de bases de datos para administrar
la información de sus bases de datos. Los comandos SQL permiten recuperar y actualizar
datos. Los comandos SQL también permiten crear y administrar objetos de base de datos,
como las tablas. Podemos considerar que SQL es un lenguaje de programación para bases de
datos relacionales. Sin embargo, SQL es de naturaleza declarativa, en oposición al carácter
imperativo de la mayoría de los lenguajes de programación habituales.
150 | Lección 6

En SQL, le decimos a la base de datos lo que tiene que hacer y es la propia base de datos
la que debe averiguar cómo hacerlo; por ejemplo, podemos pedirle a la base de datos que
seleccione las 10 primeras filas de una tabla. Comparemos este proceder con un lenguaje de
programación imperativo como C#, en el que hay que especificar con todo detalle el trabajo
que debe realizar. Por ejemplo, en este caso, habría que crear un bucle que se ejecute diez
veces, configurar e inicializar variables, mover punteros de registros, etc.
SQL es un estándar de ANSI (American National Standards Institute), pero los diversos
proveedores de bases de datos han implementado sus propias extensiones del SQL estándar. La
implementación de SQL de Microsoft SQL Server se denomina Transact-SQL (T-SQL).
Existen dos modos principales de enviar T-SQL a SQL Server. Se pueden usar instrucciones
SQL ad hoc, que se ejecutan directamente, o bien procedimientos almacenados. Los
procedimientos almacenados son colecciones de instrucciones SQL y lógica de programación
que se almacenan en el servidor de bases de datos como objetos con nombre.

Trabajo con consultas SQL

Las instrucciones SELECT, INSERT, UPDATE y DELETE son los cuatro tipos
principales de instrucciones SQL que se usan para manipular datos de SQL Server.

El uso de consultas ad hoc de SQL es una manera flexible de trabajar con bases de datos de
SQL Server. En esta parte de la lección, aprenderemos los conceptos básicos de los cuatro
tipos principales de instrucciones SQL que le ayudan a manipular datos de SQL Server:
• Las instrucciones SELECT permiten recuperar los datos almacenados en una base de
datos.
• Las instrucciones INSERT permiten agregar nuevos datos a una base de datos.
• Las instrucciones UPDATE permiten modificar los datos existentes en una base de
datos.
• Las instrucciones DELETE permiten borrar datos de una base de datos.
CONEXIÓN A UNA BASE DE DATOS DE SQL SERVER

Para poder manipular la información de una base de datos de SQL Server, previamente
deberá conectarse a ella.

En este ejercicio, aprenderemos a trabajar con una base de datos de Microsoft SQL Server. Si
no dispone de acceso a una versión reciente de SQL Server, puede descargar SQL Server 2008
Express gratis desde www.microsoft.com/express/database. En este ejercicio se usa la base
de datos de ejemplo de SQL Server denominada Northwind. Esta base de datos no se instala
de forma predeterminada con SQL Server, pero puede descargar el archivo de base de datos
siguiendo las instrucciones en www.msdn.com/es-es/library/ms143221.aspx.
Complete el siguiente ejercicio para conectarse a la base de datos Northwind con Visual Studio
y usarla.

CONEXIÓN A LA BASE DE DATOS NORTHWIND

PREPÁRESE. Antes de comenzar con el siguiente procedimiento, asegúrese de iniciar


Microsoft Visual Studio.
1. Abra la ventana Explorador de servidores. Seleccione el nodo Conexiones de datos
y haga clic en el botón Conectar a base de datos de la barra de herramientas del
Explorador de servidores.
En Visual Studio Express Edition, la ventana del Explorador de servidores se denomina
*
TOME NOTA
Explorador de bases de datos y se abre seleccionando Ver > Otras ventanas > Explorador de
bases de datos.
Comprensión de bases de datos | 151

2. En el cuadro de diálogo Agregar conexión, busque el archivo de la base de datos


Northwind (northwnd.mdf), como se muestra en la figura 6-3.

Figura 6-3
Conexión a la base de datos
Northwind

3. Use Autenticación de Windows como modo de autenticación y haga clic en el botón


Probar conexión para asegurarse de que puede conectarse a la base de datos. Por
último, haga clic en el botón Aceptar para agregar la conexión a la base de datos.
4. Una vez establecida la conexión, la base de datos está disponible como conexión en
el nodo Conexiones de datos del Explorador de servidores. Expanda la base de datos
para ver las tablas, los procedimientos almacenados y otros objetos de la base de
datos, como se muestra en la figura 6-4.
Figura 6-4
Acceso a la base de datos
Northwind mediante el
Explorador de servidores
152 | Lección 6

5. Haga clic con el botón secundario en el nodo NORTHWND.MDF y seleccione


Propiedades. Debe aparecer la ventana Propiedades que se muestra en la figura 6-5.
En esta ventana, observe la propiedad Cadena de conexión. Usará el valor de esta
propiedad para conectarse a la base de datos Northwind desde una aplicación C#.

Figura 6-5
Ventana Propiedades de la
base de datos Northwind

PAUSA. En el próximo ejercicio, obtendremos acceso a los datos desde la base de datos
Northwind.

EJECUCIÓN DE CONSULTAS SQL

Existen varios modos de comunicarse con SQL Server para llevar a cabo consultas de
base de datos.

Hay muchas maneras de enviar consultas a un servidor SQL Server. Por ejemplo, podemos
usar cualquiera de las siguientes:
• Entorno de desarrollo integrado (IDE) de Visual Studio
• Aplicación C#
• Analizador de consultas SQL
• Utilidad de símbolo del sistema osql
Observe que el Analizador de consultas SQL y las utilidades de símbolo del sistema osql son
herramientas instaladas con SQL Server.

EJECUCIÓN DE CONSULTAS DESDE VISUAL STUDIO

PREPÁRESE. Para usar el IDE de Visual Studio y las aplicaciones C# para ejecutar consultas
SQL, siga estos pasos:
1. Seleccione la base de datos Northwind en el Explorador de servidores. Haga clic con
el botón secundario en la base de datos y seleccione Nueva consulta. Esta acción abre
un diseñador de consultas y muestra el cuadro de diálogo Agregar tabla. Seleccione la
tabla Customers (Clientes) y haga clic en Agregar. Haga clic en Cerrar en el cuadro de
diálogo Agregar tabla.
2. En el panel de SQL del diseñador de consultas (que es la zona que muestra el texto de
la consulta), modifique la instrucción SQL de la manera siguiente:
SELECT * FROM Customers
3. En el menú Visual Studio, seleccione la opción Diseñador de consultas > Ejecutar SQL
o haga clic en el botón Ejecutar SQL de la barra de herramientas. La instrucción SQL
se enviará al servidor SQL Server para su ejecución y se mostrarán unos resultados
parecidos a los de la figura 6-6.
Comprensión de bases de datos | 153

Figura 6-6
Diseñador de consultas de
Visual Studio

El diseñador de consultas de Visual Studio muestra hasta cuatro paneles. De arriba abajo, los
paneles son:
• Panel de diagrama: este panel muestra las tablas implicadas en la consulta y las
relaciones entre ellas, así como todas las columnas que contienen las tablas.
• Panel de criterios: el panel de criterios muestra las columnas que se han seleccionado en
la consulta, así como información adicional de clasificación y filtrado.
• Panel de SQL: este panel muestra la instrucción SQL real que se ejecutará.
• Panel de resultados: este panel muestra los resultados (si los hay) después de ejecutar la
consulta.
La barra de herramientas del diseñador de consultas incluye botones que puede usar para
ocultar o mostrar cualquiera de estos cuatro paneles. En el ejercicio siguiente, solamente
necesitaremos los paneles de SQL y de resultados.

EJECUCIÓN DE CONSULTAS DESDE UNA APLICACIÓN C#

PREPÁRESE. Para ejecutar consultas desde aplicaciones C#, haga lo siguiente:


1. Cree un nuevo proyecto de aplicación de Windows denominado QueryCS.
2. Al formulario de Windows Forms, agregue un control TextBox, un control Button
y un control DataGridView. Establezca la propiedad MultiLine de TextBox en True.
Establezca la propiedad Text del control Button en Execute SQL.
3. Haga doble clic en el control Button para generar un controlador de eventos para su
evento Click. Modifique el controlador de eventos como se muestra a continuación:
private void button1_Click(
  object sender, EventArgs e)
{
  if (textBox1.TextLength > 0)
  {
   SelectData(textBox1.Text);
  }
}
154 | Lección 6

4. Agregue el método siguiente a la clase. Asegúrese de cambiar la cadena de conexión


para que coincida con la ruta local del archivo de base de datos de su equipo:
private void SelectData(string selectCommandText)
{
  try
  {
    // Cambie la cadena de conexión
    // de modo que coincida con su sistema.
    string selectConnection =
    @"Data Source=.\SQLEXPRESS;" +
    @"AttachDbFilename=" +
    @"c:\SqlSampleDB\NORTHWND.MDF;" +
    @"Integrated Security=True;" +
    @"Connect Timeout=30;User Instance=True";
    SqlDataAdapter dataAdapter =
      new SqlDataAdapter(
       selectCommandText, selectConnection);
    DataTable table = new DataTable();
    dataAdapter.Fill(table);
    dataGridView1.DataSource = table;
  }
  catch (Exception ex)
  {
    MessageBox.Show(ex.Message);
  }
}
5. Agregue las siguientes directivas using al código:
using System.Data;
  using System.Data.SqlClient;
Seleccione Depurar > Iniciar depuración para ejecutar el proyecto. Escriba una
consulta SQL válida y haga clic en el control Button. Debe aparecer la salida que se
muestra en la figura 6-7.

Figura 6-7
Ejecución de consultas desde
una aplicación C#
Comprensión de bases de datos | 155

El código de este ejercicio implementa un método SelectData que inicializa un objeto


SqlDataAdapter y lo usa para rellenar un objeto DataTable. A continuación, se enlaza
DataTable como origen de datos del componente DataGridView. El objeto SqlDataAdapter
actúa como canalización entre SQL Server y DataTable para recuperar los datos. El método
Fill cambia los datos en el objeto DataTable para que coincidan con los datos del origen de
datos. La instrucción selectCommandText se usa para identificar los datos en el origen de
datos.

SELECCIÓN DE DATOS

La instrucción SELECT se usa para recuperar datos de una o más tablas de la base de
datos.

La instrucción SELECT suele adoptar la forma siguiente:


SELECT lista_de_campos
FROM lista_de_tablas
WHERE cláusula_where
GROUP BY cláusula_group_by
HAVING cláusula_having
ORDER BY cláusula_order_by
Cada una de estas líneas de código de la instrucción SELECT se denomina “cláusula”. Las
cláusulas SELECT y FROM son obligatorias, pero el resto son opcionales. Por ejemplo, a
continuación se muestra una instrucción SQL que contiene solo las cláusulas obligatorias:
SELECT OrderId, CustomerId
FROM Orders
Si desea enumerar todos los campos de una tabla, también puede usar los siguientes accesos
directos en lugar de enumerar explícitamente todos los campos:
SELECT *
FROM Orders
Además, puede seleccionar información de varias tablas; por ejemplo:
Select OrderId, Customers.CustomerId, ContactName
From Orders, Customers
Customers.CustomerId se denomina “nombre completo” porque especifica tanto el nombre de
la tabla como el nombre del campo. Esto es necesario porque tanto la tabla Orders (Pedidos)
como la tabla Customers (Clientes) incluyen este campo, de modo que es preciso indicar a
SQL Server a qué tabla concreta nos referimos.
Si ejecutamos esta consulta, obtendremos muchos más registros de los esperados. Esto sucede
porque, aunque hemos indicado a SQL Server qué tablas debe incluir, no hemos indicado
ninguna información acerca de cómo se relacionan esas tablas. En consecuencia, SQL Server
construye el conjunto de resultados de modo que incluya todas las filas de la tabla Customer
para cada fila de la tabla Orders. Este tipo de combinación se denomina “combinación
cruzada” y, en este caso, no resulta muy útil.
Una consulta más útil, por supuesto, sería aquella que haga coincidir cada pedido con su
cliente correspondiente. La palabra clave INNER JOIN puede ayudarle a hacerlo así, como se
muestra en la siguiente consulta:
SELECT OrderID, Customers.CustomerId, ContactName
FROM Orders INNER JOIN Customers
ON Orders.CustomerId = Customers.CustomerId
156 | Lección 6

Esta consulta indica a SQL Server que tome cada fila de la tabla Orders y la haga coincidir
con todas las filas de la tabla Customers en que el valor de CustomerId del pedido sea igual
al valor de CustomerId del cliente. Dado que CustomerId es exclusivo en la tabla Customers,
esto equivale a incluir una sola fila para cada pedido en el conjunto de resultados. En este
caso, el conjunto de resultados tendrá tantas filas como la tabla Orders.
Pero ¿qué sucede si solamente queremos ver algunas de las filas de la tabla? En esta situación,
podemos usar la cláusula WHERE. La cláusula WHERE evalúa cada fila para comprobar si se
TOME NOTA
* cumple una condición y decide si la incluirá en el conjunto de resultados. Por ejemplo:
El delimitador estándar SELECT *
para el texto y las fechas
en SQL Server es la FROM Orders
comilla simple. WHERE ShipCountry = 'Canada'
Aquí, la cláusula WHERE busca en todas las filas de la tabla Orders para comprobar si
ShipCountry (País envío) tiene el valor exacto “Canada” (Canadá). En caso afirmativo, la fila
se incluye en el conjunto de resultados; en caso negativo, no se incluye.
También podemos combinar varias condiciones en una sola cláusula WHERE. Por ejemplo:
SELECT *
FROM Orders
WHERE (ShipCountry = 'Canada')
AND (OrderDate >= '01/01/97')
AND (OrderDate <= '01/31/97')
Aquí, las condiciones WHERE filtran los pedidos cuyo ShipCountry es “Canada” y cuya fecha
es “January 1997” (Enero de 1997).
De forma predeterminada, SQL no garantiza que los resultados se muestren en un orden
determinado. Sin embargo, podemos usar la cláusula ORDER BY para asegurarnos de que
los datos deseados se devuelvan en un orden concreto. Por ejemplo, para mostrar una lista de
pedidos ordenados por su fecha de realización, podemos usar la siguiente consulta:
SELECT *
FROM Orders
WHERE (ShipCountry = 'Canada')
AND (OrderDate >= '01/01/97')
AND (OrderDate <= '01/31/97')
ORDER BY OrderDate
Podemos modificar el orden mediante las palabras clave ASC (en orden ascendente) o DESC
(en orden descendente). El orden predeterminado es el ascendente. Por lo tanto, la consulta
siguiente muestra los pedidos más recientes al principio:
SELECT *
FROM Orders
WHERE (ShipCountry = 'Canada')
AND (OrderDate >= '01/01/97')
AND (OrderDate <= '01/31/97')
ORDER BY OrderDate DESC
Comprensión de bases de datos | 157

Es bastante frecuente que las aplicaciones empresariales soliciten datos agregados o resumidos.
Estos requisitos pueden satisfacerse mediante la cláusula GROUP BY y las funciones de
agregado. Por ejemplo, podemos usar la siguiente consulta para encontrar a qué países se
envían la mayor parte de los pedidos:
SELECT ShipCountry, COUNT(ShipCountry) AS OrderCount
FROM Orders
GROUP BY ShipCountry
ORDER BY OrderCount DESC
Esta consulta mostrará el nombre de cada país, seguido del número total de pedidos enviados a
ese país. La cláusula ORDER BY ordena el resultado y coloca a los países con más pedidos en
la parte superior de la lista.
Podemos imaginarnos que la cláusula GROUP BY crea “depósitos”; en este caso, uno por cada
país. A medida que el motor de la base de datos examina cada registro, lo coloca en el depósito
apropiado. Una vez finalizado este proceso, el motor de base de datos cuenta el número de
registros que ha colocado en cada depósito y muestra en la salida una fila para cada uno de
ellos. En la figura 6-8 se muestra el comienzo del resultado de esta consulta.

Figura 6-8
Uso de la cláusula GROUP BY
para resumir información

En la instrucción SQL anterior, Count es una función de agregado; es decir, devuelve un


resultado basado en un grupo de filas. T-SQL admite varias funciones de agregado distintas.
Algunas de las más frecuentes son:
• Count: devuelve el número de registros
• Sum: devuelve el valor total de una columna dada
• Avg: devuelve el valor promedio de una columna dada
• Min: devuelve el valor mínimo de una columna dada
• Max: devuelve el valor máximo de una columna dada

ACTUALIZACIÓN DE DATOS

La instrucción UPDATE se usa para actualizar la información en las tablas de la base de


datos.

Otra instrucción SQL útil es UPDATE. La finalidad de una instrucción UPDATE es actualizar
o modificar datos. Por ejemplo, podemos actualizar un campo de un registro de la tabla
Customers mediante la siguiente consulta:
UPDATE Customers
SET ContactName = 'Maria Anderson'
WHERE CustomerId = 'ALFKI'
158 | Lección 6

En esta consulta, la palabra clave SET indica a SQL Server qué columnas debe actualizar y la
TOME NOTA
* palabra clave WHERE indica qué filas se van a actualizar. En la tabla Customers, CustomerId
En una instrucción es una clave principal que identifica de forma exclusiva una sola fila. Por lo tanto, esta
UPDATE, la cláusula instrucción UPDATE puede actualizar como máximo una fila.
SET es obligatoria y
solo se puede especificar Sin embargo, cabe destacar que no estamos limitados a actualizar un único registro. Por el
una vez. contrario, si la cláusula WHERE selecciona varios registros, todos ellos se actualizarán:
UPDATE Customers
SET Country = 'United States'
TOME NOTA
* WHERE Country = 'USA'
Se recomienda
encarecidamente revisar También podemos actualizar más de un campo a la vez con una instrucción UPDATE, como
con todo cuidado la en el ejemplo siguiente:
cláusula WHERE UPDATE Customers
para cada instrucción
SET ContactName = 'Maria Anderson',
UPDATE. Si no
presta atención, podría CITY = 'Tokyo'
actualizar los datos WHERE CustomerId = 'ALFKI'
en más filas de las
deseadas.

INSERCIÓN DE DATOS

La instrucción INSERT se usa para agregar una o más filas a una tabla de la base de
datos.

El comando INSERT enumera los campos de la tabla de destino seguidos por un conjunto
de valores que se insertarán en estos campos. Por ejemplo, la siguiente instrucción INSERT
inserta una fila en la tabla Order Details (Detalles de pedidos):
INSERT INTO [Order Details]
(OrderId, ProductId, UnitPrice, Quantity, Discount)
VALUES (10248, 2, 19.00, 2, 0)
Los corchetes son obligatorios cuando los nombres de las tablas o los campos contienen
espacios. En este caso, el primer conjunto de paréntesis contiene una lista de columnas y el
segundo, los valores que se deben insertar. Si un campo tiene un valor predeterminado, puede
ser null o es un campo de identidad, podemos dejarlo fuera de la lista de campos, como en el
ejemplo siguiente:
INSERT INTO [Order Details]
(OrderId, ProductId, UnitPrice, Quantity)
VALUES (10249, 2, 19.00, 2)
Esta instrucción funciona aunque no se haya especificado ningún valor para el campo Discount
(Descuento). Además, esta instrucción nos permite reorganizar la lista de campos siempre y
cuando reorganicemos la lista de valores del mismo modo:
INSERT INTO [Order Details]
(ProductId, OrderId, UnitPrice, Quantity)
VALUES (2, 10250, 19.00, 2)
La instrucción INSERT no se limita a insertar un único registro. De hecho, hay un segundo
formato que inserta los resultados de una instrucción SELECT en la tabla de destino. Por
ejemplo, esta consulta inserta un producto de cada proveedor en la tabla Products (Productos):
INSERT INTO Products
(SupplierId, ProductName, CategoryId)
SELECT SupplierId, 'Almond', 7
FROM Suppliers
Comprensión de bases de datos | 159

Esta consulta genera los resultados de la instrucción SELECT y, a continuación, incluye cada
una de las filas devueltas por las instrucciones SELECT en la tabla de destino. Por supuesto,
las columnas deben coincidir correctamente también en este caso.

ELIMINACIÓN DE DATOS

La instrucción DELETE se usa para quitar información de las tablas de la base de datos.

La instrucción DELETE elimina los datos de una tabla. Para practicar y evitar que se eliminen
los datos de la misma base de datos, puede copiar una tabla mediante una instrucción
SELECT, como en el ejemplo siguiente:
SELECT * INTO CustomersCopy
FROM Customers
Esta instrucción selecciona todos los registros de la tabla Customers y los copia en una tabla
nueva denominada CustomersCopy (Copia clientes).
Para eliminar una fila de datos de la tabla CustomersCopy, usamos la siguiente instrucción
DELETE:
DELETE FROM CustomersCopy
WHERE CustomerId = 'ALFKI'
Es preciso extremar las precauciones porque, si omitimos la cláusula WHERE, eliminaremos
todos los datos de la tabla:
DELETE FROM CustomersCopy

Trabajo con procedimientos almacenados

Un procedimiento almacenado es un conjunto de instrucciones SQL almacenadas


en una base de datos. Los procedimientos almacenados se pueden usar en varias
aplicaciones.
Al contrario que las consultas ad hoc, los procedimientos almacenados se almacenan
permanentemente en un servidor SQL Server. Podemos considerarlos el equivalente en SQL de
los métodos de C#.
Los procedimientos almacenados presentan dos ventajas principales. En primer lugar, puede
usarlos para guardar instrucciones SQL complejas para ejecutarlos en el futuro. En segundo
lugar, SQL Server compila los procesos almacenados de manera que se ejecuten más
rápidamente que las consultas ad hoc. En esta sección de la lección, aprenderemos a crear y
ejecutar procedimientos almacenados.

CREACIÓN Y EJECUCIÓN DE PROCEDIMIENTOS ALMACENADOS


El comando CREATE PROCEDURE se puede usar para crear un nuevo procedimiento
almacenado.
Puede usar la palabra clave CREATE PROCEDURE de T-SQL para crear un procedimiento
almacenado. Puede ejecutar la instrucción CREATE PROCEDURE desde cualquier interfaz
que permite especificar y ejecutar T-SQL.
160 | Lección 6

CREACIÓN DE UN PROCEDIMIENTO ALMACENADO DESDE VISUAL STUDIO

PREPÁRESE. Para crear un procedimiento almacenado desde Visual Studio, realice las
siguientes acciones:
1. Abra el Explorador de servidores y seleccione la base de datos Northwind. Haga clic
con el botón secundario en el nodo Procedimiento almacenado y seleccione la opción
Agregar nuevo procedimiento almacenado.
2. En el diseñador de procedimientos almacenados, sustituya el texto del documento por el
siguiente código:
CREATE PROCEDURE GetCustomersFromFrance
AS
  SELECT * FROM Customers
  Where Country = 'France'
RETURN
TOME NOTA
* 3. Guarde el procedimiento almacenado. El procedimiento almacenado se agregará a la base
Puede usar la de datos.
instrucción ALTER 4. Para ejecutar el procedimiento almacenado, haga clic en él con el botón secundario
PROCEDURE para en el Explorador de servidores y seleccione Ejecutar. El resultado del procedimiento
modificar la definición almacenado debe mostrarse en la ventana de salida.
de un procedimiento 5. También puede ejecutar este procedimiento almacenado desde el proyecto QueryCS que
almacenado existente. creó anteriormente. Aquí, en lugar de una instrucción SQL, solo hay que escribir el nombre
del procedimiento almacenado y hacer clic en el botón Ejecutar SQL. El resultado del
procedimiento almacenado se mostrará en el formulario de Windows Forms.

TRABAJO CON PROCEDIMIENTOS ALMACENADOS PARAMETRIZADOS

Los procedimientos almacenados parametrizados permiten pasar argumentos en tiempo


de ejecución a SQL Server.

La capacidad de pasar parámetros aumenta significativamente la potencia de los


procedimientos almacenados. Los valores de los parámetros se pueden proporcionar en tiempo
de ejecución a los procedimientos almacenados.
Supongamos que desea averiguar las ventas totales de un cliente determinado en la base de
datos Northwind. En esta situación, debe ser posible especificar el CustomerId en tiempo de
ejecución.

CREACIÓN DE UN PROCEDIMIENTO ALMACENADO PARAMETRIZADO

PREPÁRESE. Para crear un procedimiento almacenado parametrizado, realice las siguientes


acciones:
1. Abra el Explorador de servidores y seleccione la base de datos Northwind. Haga
clic con el botón secundario en el nodo Procedimiento almacenado y seleccione la
opción Agregar nuevo procedimiento almacenado.
2. En el diseñador de procedimientos almacenados, sustituya el texto del documento por
el siguiente código:
CREATE PROCEDURE dbo.GetCustomerSales
  (
  @CustomerId char(5),
  @TotalSales money OUTPUT
  )
Comprensión de bases de datos | 161

AS
  SELECT @TotalSales = SUM(Quantity * UnitPrice)
  FROM (Customers INNER JOIN Orders
  ON Customers.CustomerId = Orders.CustomerId)
  INNER JOIN [Order Details]
  ON Orders.OrderId = [Order Details].OrderId
  WHERE Customers.CustomerId = @CustomerId
RETURN
3. Guarde el procedimiento almacenado. El procedimiento almacenado se agregará a la
base de datos.
En este procedimiento almacenado, tanto @CustomerId como @TotalSales son parámetros.
@CustomerId es un parámetro de entrada; debe proporcionar un valor para este parámetro al
ejecutar el procedimiento almacenado. @TotalSales es un parámetro de salida; devuelve un
valor desde el procedimiento almacenado. Al ejecutar este procedimiento almacenado desde
Visual Studio, se abre un cuadro de diálogo que pide que se especifique el valor de todos los
parámetros, como se muestra en la figura 6-9.
Figura 6-9
El cuadro de diálogo Ejecutar
procedimiento almacenado
solicita los valores de los
parámetros

Para ejecutar este procedimiento almacenado, especifique ALFKI como valor de @CustomerId
y NULL como valor de @TotalSales. Al hacer clic en el botón Aceptar, el valor calculado del
parámetro de salida, @TotalSales, se muestra en la ventana de salida.
Sin embargo, un procedimiento almacenado parametrizado no se puede ejecutar desde el
proyecto QueryCS, porque su código no acepta parámetros.

EJECUCIÓN DE PROCEDIMIENTOS ALMACENADOS PARAMETRIZADOS


DESDE C#

PREPÁRESE. Para ejecutar procedimientos almacenados parametrizados desde C#, realice las
siguientes tareas:
1. Cree un nuevo proyecto de aplicación de Windows denominado ParameterizedSP.
2. Coloque un control Label en el formulario y establezca su propiedad Text
en “Id. cliente:”. Coloque un control TextBox junto a él y asígnele el nombre
CustomerIdTextBox. A continuación, coloque un control Button y establezca su
propiedad Name en GetTotalSalesButton y su propiedad Text propiedad en “Obtener
ventas totales”. Por último, coloque un control Label en el formulario y asígnele el
nombre TotalSalesLabel. Organice los controles para lograr una apariencia similar a la
de la figura 6-10.
162 | Lección 6

3. Haga doble clic en el control Button para generar un controlador de eventos para su
evento Click. Modifique el controlador de eventos como se muestra a continuación:
private void GetTotalSalesButton_Click(
    object sender, EventArgs e)
{
  TotalSalesLabel.Text = String.Format(
    "Ventas totales: {0}",
    GetTotalSales(CustomerIdTextBox.Text));
}
4. Agregue el método siguiente a la clase. Asegúrese de cambiar la cadena de conexión
para que coincida con la ruta local del archivo de base de datos de su equipo:
private double GetTotalSales(string customerId)
{
  double totalSales = −1;
  try
  {
    // Cambie la cadena de conexión
    // de modo que coincida con su sistema.
     string connectionString =
    @"Data Source=.\SQLEXPRESS;" +
    @"AttachDbFilename=" +
    @"c:\SqlSampleDB\NORTHWND.MDF;" +
    @"Integrated Security=True;" +
    @"Connect Timeout=30;User Instance=True";
     SqlConnection connection =
       new SqlConnection(connectionString);
     SqlCommand command =
       connection.CreateCommand();
     command.CommandType =
       CommandType.StoredProcedure;
     command.CommandText = "GetCustomerSales";
     command.Parameters.AddWithValue(
       "@CustomerId", customerId);
     command.Parameters.AddWithValue(
       "@TotalSales", null);
     command.Parameters["@TotalSales"].DbType
       = DbType.Currency;
     command.Parameters["@TotalSales"].Direction
       = ParameterDirection.Output;
     connection.Open();
     command.ExecuteNonQuery();
     totalSales = Double.Parse(
Comprensión de bases de datos | 163

       command.Parameters["@TotalSales"]
       .Value.ToString());
     connection.Close();
  }
  catch (Exception ex)
  {
    MessageBox.Show(ex.Message);
  }
  return totalSales;
}
5. Agregue las siguientes directivas using al código:
using System.Data;
using System.Data.SqlClient;
Seleccione Depurar > Iniciar depuración para ejecutar el proyecto. Especifique un Id.
de cliente válido. Debe aparecer la salida que se muestra en la figura 6-10.

Figura 6-10
Ejecución de procedimientos
almacenados parametrizados
desde una aplicación C#

En el código, los parámetros se representan mediante objetos SqlParameter. El código


establece el valor del parámetro @CustomerId, ejecuta el objeto SqlCommand correspondiente
al procedimiento almacenado y, a continuación, recupera la propiedad Value del parámetro @
TotalSales.

Si agrega una nueva fila a una tabla con una columna de identidad, puede usar la variable
@@IDENTITY de SQL Server para recuperar el valor de la columna de identidad
*
TOME NOTA
correspondiente a la fila recién creada.

El código anterior tiene las siguientes líneas:


connection.Open();
command.ExecuteNonQuery();
totalSales = Double.Parse(
  command.Parameters["@TotalSales"]
  .Value.ToString());
connection.Close();
En este caso, en primer lugar abrimos la conexión de la base de datos, hacemos lo necesario
con ella y, a continuación, la cerramos. El objeto que contiene las referencias a la conexión
de la base de datos usa gran cantidad de recursos del sistema y, por lo tanto, resulta costoso
ejecutarlo. Por consiguiente, se recomienda cerrar este objeto tan pronto como se ha terminado
de usarlo. Si la conexión no se cierra, creamos una pérdida de memoria en el programa que
puede afectar a su rendimiento.
164 | Lección 6

C# también proporciona una instrucción using que nos puede ayudar a asegurarnos de que
TOME NOTA
* los objetos costosos, tales como las conexiones de base de datos, se cierren automáticamente
El objeto que se usa con cuando hemos terminado de usarlos. A continuación se muestra una versión alternativa del
la instrucción using debe código anterior que usa la instrucción using para cerrar automáticamente la conexión de bases
implementar la interfaz de datos:
IDisposable.
// eliminación de objetos mediante la instrucción using
using (connection)
LISTO PARA CERTIFICACIÓN {
¿Comprende los diversos
  connection.Open();
métodos de consulta de
bases de datos?   command.ExecuteNonQuery();
6.2   totalSales = Double.Parse(
    command.Parameters["@TotalSales"]
LISTO PARA CERTIFICACIÓN     .Value.ToString());
¿Comprende los }
métodos de conexión
de bases de datos? Observe que la instrucción using define un ámbito para el objeto de conexión. Cuando el
6.3 código llega al final de ese ámbito, el objeto de conexión se cierra automáticamente y se
liberan todos los recursos.

■ Conceptos de los métodos de conexión de bases de datos

Las aplicaciones empresariales pueden requerir datos en varios formatos. Por ejemplo,
CONCLUSIÓN es posible que debamos trabajar con archivos planos, archivos XML y objetos en
memoria.

.NET Framework proporciona clases que están optimizadas para funcionar con archivos
planos, archivos XML y objetos en memoria. Los datos almacenados en archivos planos se
pueden controlar mediante las clases del espacio de nombres System.IO. Para trabajar con
datos XML, se pueden usar las clases del espacio de nombres System.Xml. Por último, para
trabajar con objetos en memoria como DataSet, se usan las clases del espacio de nombres
System.Data. En las secciones siguientes aprenderemos cómo trabajar con cada uno de estos
formatos de datos.

Trabajo con archivos planos

Un archivo plano es una tabla de la base de datos que se almacena en un archivo de


disco independiente.

Un archivo plano suele contener una fila de datos por línea y sus columnas están separadas por
delimitadores, como comas, o tienen una longitud fija. Los datos de un archivo plano pueden
ser de texto o binarios. Estos archivos se denominan “archivos planos” para distinguirlos de
otras formas de almacenamiento más estructuradas, como las bases de datos relacionales y los
archivos XML.
Históricamente, antes del advenimiento de las bases de datos modernas, los archivos planos
eran una forma popular de almacenar y organizar la información. Siguen siendo útiles hoy
en día, aunque solamente en algunas situaciones y no como bases de datos de uso general.
Algunos de los lugares donde se usan archivos planos son el sistema operativo, los archivos
de configuración de aplicaciones, al realizar transferencias de datos a sistemas remotos y al
migrar datos entre sistemas incompatibles.
La entrada y salida basada en archivos de .NET Framework gira en torno a los conceptos de
las secuencias y las memorias auxiliares. Una secuencia es un flujo de datos sin procesar;
la memoria auxiliar es el origen o destino de la secuencia. Una memoria auxiliar puede ser
un archivo de disco, memoria, conexión de red, etc. Encontrará clases para trabajar con las
secuencias y las memorias auxiliares en el espacio de nombres System.IO.
Comprensión de bases de datos | 165

Como hemos mencionado anteriormente, el formato de los archivos planos puede ser de texto
o binario. Los archivos de texto se organizan con frecuencia como líneas de texto separadas
por caracteres de fin de línea. Las clases StreamReader y StreamWriter proporcionan una
manera fácil de manipular dichos archivos de texto.
Los archivos binarios almacenan su contenido como una secuencia de bytes. Aunque los
archivos binarios no son legibles como los archivos de texto, permiten almacenar gran
variedad de datos, tales como imágenes, sonidos, vídeo, etc. Para interpretar el contenido de
un archivo binario siempre se necesita un programa informático. Las clases BinaryReader y
BinaryWriter proporcionan una manera fácil de manipular los archivos binarios.
En el siguiente ejercicio, seleccionaremos columnas de la tabla Customers y las escribiremos
en un archivo de texto. Más tarde, abriremos este archivo de texto y mostraremos su contenido
en la ventana de consola.

LECTURA Y ESCRITURA EN UN ARCHIVO DE TEXTO

PREPÁRESE. Para leer y escribir en un archivo de texto, haga lo siguiente:


1. Cree un nuevo proyecto de aplicación de consola denominado WorkingWithTextFiles.
2. Agregue el siguiente código a la clase Program. Deberá corregir la ruta de acceso a la
base de datos Northwind en el código:
static void Main(string[] args)
{
  string myDocumentsPath =
     Environment.GetFolderPath(
     Environment.SpecialFolder.MyDocuments);
  CopyDataToTextFile(myDocumentsPath
     + @"\CustomerList.txt");
  DisplayTextFile(myDocumentsPath
     + @"\CustomerList.txt");
}
static private void CopyDataToTextFile(
 string fileName)
{
  try
  {
      // Cambie la cadena de conexión
      // de modo que coincida con su sistema.
      string connectionString =
     @"Data Source=.\SQLEXPRESS;" +
     @"AttachDbFilename=" +
     @"c:\SqlSampleDB\NORTHWND.MDF;" +
     @"Integrated Security=True;" +
     @"Connect Timeout=30;User Instance=True";
      SqlConnection connection =
       new SqlConnection(connectionString);
      SqlCommand command =
       connection.CreateCommand();
166 | Lección 6

      command.CommandText =
       "SELECT CustomerId, CompanyName,"
       + "ContactName, Phone FROM Customers";
     using (connection)
     {
       connection.Open();
       SqlDataReader reader =
        command.ExecuteReader();
       using (StreamWriter sw =
        new StreamWriter(fileName))
       {
          while (reader.Read())
          {
           string customerRow =
          String.Format("{0}, {1}, {2}, {3}",
          reader.GetValue(0),
          reader.GetValue(1),
          reader.GetValue(2),
          reader.GetValue(3));
          sw.WriteLine(customerRow);
        }
      }
    }
  }
  catch (Exception ex)
  {
    Console.WriteLine(ex.Message);
  }
}
static void DisplayTextFile(string fileName)
{
  try
  {
    using (StreamReader sr =
      new StreamReader(fileName))
    {
      string line;
      while ((line = sr.ReadLine()) != null)
      {
        Console.WriteLine(line);
      }
    }
  }
Comprensión de bases de datos | 167

  catch (Exception ex)


  {
    Console.WriteLine(ex.Message);
  }
}
3. Agregue las siguientes directivas using al código:
using System.Data.SqlClient;
  using System.IO;
4. Genere y ejecute el programa. Compruebe que el nombre de archivo CustomerList.
txt aparece en la carpeta Mis documentos y asegúrese de que se hayan escrito los
datos del cliente. Compruebe también la salida de la ventana de consola respecto al
contenido del archivo.
El código de este ejercicio abre en primer lugar un nuevo objeto StreamWriter y llama a su
método WriteLine varias veces para escribir texto en un archivo de texto. A continuación,
crea un objeto StreamReader para leer el texto del archivo recién creado mediante el método
ReadLine. Cuando no queda ningún dato por leer, el objeto ReadLine devuelve un valor null.
El código usa este valor para determinar cuándo terminar la lectura del archivo de texto.

Trabajo con XML

El Lenguaje de marcado extensible (XML) es un formato basado en texto que se usa


para representar datos estructurados.

En XML, puede almacenar tanto datos y como metadatos (información sobre los datos
almacenados). Por ejemplo, el siguiente código XML representa los datos de dos clientes:
<?xml version="1.0" encoding="utf-8"?>
<!--Customer List-->
<Customers>
  <Customer Id="ALFKI">
    <CompanyName>Alfreds Futterkiste</CompanyName>
    <Phone>030-0074321</Phone>
  </Customer>
  <Customer Id="EASTC">
    <CompanyName>Eastern Connection</CompanyName>
    <Phone>(171) 555-0297</Phone>
  </Customer>
</Customers>
Incluso sin saber nada acerca de XML, podemos entender el contenido de este archivo
con solo mirarlo. XML consta de etiquetas (contenidas entre corchetes angulares) y datos.
Las etiquetas siempre aparecen en pares, de tal forma que a cada etiqueta de apertura le
corresponde una de cierre. Por ejemplo, <Customers> es una etiqueta de apertura y </
Customers> es la etiqueta de cierre correspondiente.
La primera línea de un documento XML es la declaración XML:
<?xml version="1.0" encoding="utf-8"?>
Las etiquetas XML que comienzan por <? se denominan instrucciones de procesamiento. Esta
instrucción de procesamiento nos indica que este es un documento XML, que se ajusta a las
especificaciones de la versión 1.0 de XML y que usa el conjunto de caracteres UTF-8 para sus
elementos de datos.
168 | Lección 6

El conjunto comprendido por una etiqueta de apertura, su etiqueta de cierre correspondiente


y el contenido que hay entre ellas se denomina elemento. Por ejemplo, a continuación se
muestra un elemento XML del documento anterior:
<Phone>030-0074321</Phone>
Este fragmento de código define un elemento denominado Phone cuyo valor es 030-0074321.
Los elementos se pueden anidar, pero no pueden superponerse. Por ejemplo, el siguiente
código XML no es válido porque los elementos CompanyName y Phone se superponen:
<Customer Id="EASTC">
    <CompanyName>Eastern Connection<Phone>
    </Phone>(171) 555-0297</CompanyName>
  </Customer>
</Customers>
Los documentos XML presentan una naturaleza jerárquica. Cada documento XML contiene un
elemento raíz único que contiene todos los demás nodos. Por lo tanto, podemos visualizar un
documento XML como un árbol de nodos.
Los elementos pueden contener atributos. Un atributo es un dato que describe más detalles de
un elemento. Por ejemplo:
<Customer Id="ALFKI">
En este caso, el elemento Customer incluye un atributo cuyo nombre es Id y cuyo valor es
ALFKI.
Por último, un documento XML puede contener comentarios. Los comentarios comienzan por
los caracteres <!-- y finalizan por los caracteres -->.
XML suele ser mucho más complejo de lo que se trata en esta sección. Sin embargo, estos
conceptos básicos son suficientes para entender la mayoría de los documentos XML que un
desarrollador tendrá que estudiar hasta que comience a trabajar con XML en profundidad.
Hay muchas maneras de trabajar con datos XML. Las clases que funcionan con datos XML
se organizan en el espacio de nombres System.Xml. Esta parte de la lección se centra en las
siguientes clases de uso común:
• XmlReader y XmlWriter: estas clases proporcionan una manera rápida, sin caché y
solo hacia delante de leer o escribir datos XML.
• XmlDocument: La clase XmlDocument es una representación en memoria de los
datos XML y permite navegar por el documento XML y editarlo.
En el ejercicio siguiente, se usa la clase XmlReader para leer el nombre del archivo XML
Customers.xml de forma secuencial y solo hacia delante.

LECTURA DE UN ARCHIVO XML

PREPÁRESE. Para leer de un archivo XML, haga lo siguiente:


1. Cree un nuevo proyecto de aplicación de consola denominado
WorkingWithXmlReader.
2. Agregue el siguiente código al método Main de la clase Program:
using (XmlReader reader =
 XmlReader.Create("Customers.xml"))
{
  while (reader.Read())
  {
Comprensión de bases de datos | 169

    if (reader.IsStartElement())
    {
      switch (reader.Name)
      {
        case "CompanyName":
          if (reader.Read())
          {
            Console.Write(
            "Nombre de la empresa: {0}, ",
             reader.Value);
          }
          break;
        case "Phone":
          if (reader.Read())
          {
            Console.WriteLine(
             "Teléfono: {0}", reader.Value);
          }
          break;
      }
    }
  }
}
3. A continuación, agregue la siguiente directiva using al programa:
using System.Xml;
4. Ahora, agregue un nuevo archivo XML denominado Customers.xml al proyecto.
Asegúrese de que el archivo xml contenga los siguientes datos:
<?xml version="1.0" encoding="utf-8"?>
<!--Customer List-->
<Customers>
  <Customer Id="ALFKI">
    <CompanyName>Alfreds Futterkiste</CompanyName>
    <Phone>030-0074321</Phone>
  </Customer>
  <Customer Id="EASTC">
    <CompanyName>Eastern Connection</CompanyName>
    <Phone>(171) 555-0297</Phone>
  </Customer>
</Customers>
Compile el programa. Copie el archivo Customers.xml en la carpeta del archivo
ejecutable del programa. Ejecute el programa. Debe aparecer una lista de todos los
nombres y números de teléfono de las empresas.
170 | Lección 6

El código de este ejercicio crea en primer lugar una nueva instancia de XmlReader mediante
el método XmlReader.Create. Esto inicia una excepción si no se encuentra el archivo. El
programa terminará cuando el método XmlReader.Read no tenga nada que leer. Puede usar
propiedades como Name y Value para obtener acceso a diversas partes de XML.

Trabajo con DataSet

DataSet es una representación en memoria de datos relacionales.

DataSet es una representación en memoria de datos relacionales. Al igual que una base de
datos, DataSet puede tener tablas, relaciones y restricciones de integridad de datos, tales como
restricciones únicas o de clave externa. Un objeto DataSet suele crearse al recuperar datos
de un origen de datos, como una base de datos. Una vez creado, podemos trabajar con todos
los datos de DataSet aunque el vínculo al origen de datos no está disponible temporalmente.
Cuando se produzcan cambios en los datos, solo se actualizará la copia en memoria de los
datos. La conexión al origen de datos solo se requiere cuando hay que actualizar el origen de
datos con los cambios del objeto DataSet. DataSet resulta muy útil para crear aplicaciones
desconectadas. Las aplicaciones desconectadas son aquellas que pueden continuar
funcionando sin una conexión constante a los recursos de red, como las bases de datos.
Todas las clases relacionadas con DataSet forman parte del espacio de nombres System.
Data. Un objeto DataSet se crea mediante la clase DataSet. DataSet consta de una colección
de objetos DataTable. Un objeto DataTable es exactamente igual que una tabla de una base
de datos relacional. El objeto DataTable tiene una colección de objetos DataColumn que
representan las columnas de la tabla. Las filas del objeto DataTable se representan mediante la
colección DataRow.
DataAdapter es un puente de conexión entre el origen de datos y el objeto DataSet.
DataAdapter almacena los comandos y las conexiones de datos necesarios para conectarse al
origen de datos. DataAdapter también proporciona comandos que permiten recuperar datos del
origen de datos y actualizar este último con los cambios pertinentes.
.NET Framework proporciona tres clases DataAdapter para trabajar con diferentes tipos de
orígenes de datos:
• La clase OdbcDataAdapter se usa para trabajar con orígenes de datos ODBC. La
clase OdbcDataAdapter forma parte del espacio de nombres System.Data.Odbc.
• La clase OleDbDataAdapter se usa para trabajar con orígenes de datos OLEDB. La
clase OleDbDataAdapter forma parte del espacio de nombres System.Data.OleDb.
• La clase SqlDataAdapter se usa para trabajar con bases de datos de SQL Server. La
clase SQLDataAdapter forma parte del espacio de nombres System.Data.SqlClient.
En una aplicación típica que crea y actualiza un objeto DataSet, tendremos que llevar a cabo
los siguientes pasos:

También puede conectar a una base de datos de SQL Server mediante el uso de las clases
OdbcAdapter y OleDbAdapter. Sin embargo, la clase SQLDataAdapter está optimizada
*
TOME NOTA
para SQL Server. Por lo tanto, cuando se trabaja con SQL Server, es preferible usar la clase
SQLDataAdapter.

1. Construir y llenar cada objeto DataTable de DataSet con los datos del origen de datos
mediante el uso de un objeto DataAdapter.
Comprensión de bases de datos | 171

2. Cambiar los datos de los objetos DataTable individuales mediante la adición,


actualización o eliminación de objetos DataRow.
3. Invocar el método AcceptChanges para el objeto DataSet. Este método se conecta
a los orígenes de datos originales y los actualiza con todos los cambios realizados
en el objeto DataSet desde que se cargó o desde la última vez que se llamó a
AcceptChanges. Como alternativa, puede llamar al método RejectChanges para
cancelar todos los cambios realizados en DataSet desde que se cargó o desde la
última vez que se llamó a AcceptChanges.
En el ejercicio siguiente, se usan las clases mencionadas hasta el momento para leer los
datos de la base de datos Northwind de SQL Server, crear con ellos un objeto DataSet y, a
continuación, recorrer en iteración la tabla Customer para mostrar los números de pedido de
cada cliente.

LECTURA DE UN OBJETO DATASET EN MEMORIA

PREPÁRESE. Para leer un objeto DataSet en memoria, haga lo siguiente:


1. Cree un nuevo proyecto de aplicación de consola denominado WorkingWithDataSet.
2. Reemplace el código de la clase Program por el código siguiente. Asegúrese de
cambiar la cadena de conexión para que coincida con la ruta local del archivo de base
de datos de su equipo:
static void Main(string[] args)
{
  WorkingWithDataSet();
}
static void WorkingWithDataSet()
{
  string cString = @"Data Source=.\SQLEXPRESS;"
    + @"AttachDbFilename=B:\SqlSampleDB\NORTHWND.MDF;"
    + "Integrated Security=True;"
    + "Connect Timeout=30;User Instance=True";
    SqlConnection northwindConnection =
      new SqlConnection(cString);
    string customerCommandText =
        "SELECT * FROM Customers";
    SqlDataAdapter customerAdapter =
        new SqlDataAdapter(
        customerCommandText, northwindConnection);
    string ordersCommandText =
        "SELECT * FROM Orders";
  SqlDataAdapter ordersAdapter =
        new SqlDataAdapter(
            ordersCommandText, northwindConnection);
172 | Lección 6

DataSet customerOrders = new DataSet();


customerAdapter.Fill(
    customerOrders, "Customers");
ordersAdapter.Fill(
    customerOrders, "Orders");
DataRelation relation =
    customerOrders.Relations.Add("CustomerOrders",
    customerOrders.Tables["Customers"]
        .Columns["CustomerID"],
    customerOrders.Tables["Orders"]
        .Columns["CustomerID"]);
foreach (DataRow customerRow in
    customerOrders.Tables["Customers"].Rows)
{
    Console.WriteLine(customerRow["CustomerID"]);
    foreach (DataRow orderRow in
        customerRow.GetChildRows(relation))
        Console.WriteLine("\t" +
            orderRow["OrderID"]);
}
  Console.WriteLine(
“Presione cualquier tecla para continuar . . .");
  Console.ReadKey();
}
3. Agregue la siguiente directiva using al programa:
using System.Data;
using System.Data.SqlClient;
4. Seleccione Proyecto > Establecer como proyecto de inicio para establecer el proyecto
como proyecto de inicio de la solución.
5. Seleccione Depurar > Iniciar depuración (o presione F5) para ejecutar el programa.
Tenga en cuenta que la ventana de consola enumera todos los clientes de la tabla
Customers. Cada CustomerID va seguido del OrderID correspondiente a ese cliente.
El código de este ejercicio primero crea un objeto DataSet con dos objetos DataTable,
Customers y Orders. El objeto DataSet también crea un objeto DataRelation que establece la
LISTO PARA CERTIFICACIÓN relación entre Customers y la tabla Orders en la columna CustomerID. Esta relación permite
¿Comprende los diversos llamar al método GetChildRow para una fila de cliente a fin de recuperar las filas de pedido
métodos de conexión de correspondientes a cada cliente.
bases de datos?
6.3

Un objeto DataSet puede leer y escribir datos como documentos XML. Para escribir datos
como XML, use el método WriteXml de la clase DataSet. Para leer datos del documento
TOME NOTA
* XML, use el método ReadXml de la clase DataSet.
Comprensión de bases de datos | 173

RESUMEN DE CONOCIMIENTOS

En esta lección hemos aprendido lo siguiente:


• Una base de datos relacional organiza la información en tablas. Una tabla es una lista
de filas y columnas.
• El diseño de bases de datos relacionales es el proceso que consiste en determinar
cuál es la estructura de una base de datos relacional apropiada para satisfacer los
requisitos de la empresa.
• Los diagramas de relación entre entidades se usan para modelar las entidades, sus
atributos y las relaciones entre ellas. Los diagramas de relación entre entidades
pueden ayudarle a determinar qué datos es preciso almacenar en una base de datos.
• El proceso de normalización de datos asegura que el diseño de una base de datos se
encuentre exento de problemas que puedan causar una pérdida de la integridad de
los datos. La mayoría de los problemas de diseño se puede resolver asegurándose de
que las tablas satisfagan los requisitos de la tercera forma normal.
• El Lenguaje de consulta estructurado (SQL) proporciona instrucciones, tales como
SELECT, INSERT, UPDATE y DELETE, para trabajar con datos relacionales.
• Un procedimiento almacenado es un conjunto de instrucciones SQL almacenadas
en una base de datos. Los procedimientos almacenados se pueden usar en varias
aplicaciones.
• Las clases XmlReader y XmlWriter proporcionan una manera rápida, sin caché y
solo hacia delante de leer o escribir datos XML. La clase XmlDocument es una
representación en memoria de los datos XML y permite navegar por el documento
XML y editarlo.
• La clase DataSet es una representación en memoria de datos relacionales. La clase
DataAdapter es un puente de conexión entre el origen de datos y el objeto DataSet.
DataAdapter almacena los comandos y las conexiones de datos necesarios para
conectarse al origen de datos.

■ Evaluación de conocimientos
Rellene los espacios en blanco
Complete las oraciones siguientes escribiendo la palabra o palabras correctas en los
espacios en blanco proporcionados.
1. Para que una tabla se ajuste a la _______________, ninguna de las columnas de la tabla
debe tener varios valores en la misma fila de datos.
2. Además, la _______________ exige que todas las columnas no clave sean
funcionalmente dependientes de la clave principal completa.
3. La _______________ exige que no exista ninguna dependencia funcional entre atributos
no clave.
4. Los bloques de creación básicos de un diagrama de relación entre entidades son la
_______________, el _______________ y la _______________.
5. La cláusula _______________ de una instrucción SELECT evalúa cada fila para
comprobar si se cumple una condición y decide si la incluirá en el conjunto de resultados.
6. El objeto que se usa con la instrucción using debe implementar la interfaz
_______________.
7. La instrucción _______________ de T-SQL se puede usar para crear un procedimiento
almacenado.
174 | Lección 6

8. En el proceso de _______________, se aplica una serie de reglas que aseguran que el


diseño de la base de datos facilite la integridad de datos y el mantenimiento en el futuro.
9. Encontrará las clases para trabajar con secuencias y memorias auxiliares en el espacio de
nombres _______________.
10. El formato _______________ es un formato jerárquico de representación de datos.

Varias opciones
Rodee con un círculo la letra correspondiente a la mejor respuesta.
1. La aplicación tiene que almacenar la imagen del producto en un archivo de disco. Desea
reducir al mínimo el tamaño de este archivo de disco. ¿Cuál de los siguientes objetos
debe usar para escribir el archivo?
a. FileStream
b. StreamWriter
c. BinaryWriter
d. XmlWriter
2. El programa C# tiene que devolver el número total de clientes de una base de datos. El
programa se usará varias veces al día. ¿Cuál es la forma más rápida de devolver esta
información desde el programa?
a. Escribir una consulta SQL y usar el método SqlCommand.ExecuteScalar para ejecutar
la consulta.
b. Crear un procedimiento almacenado para devolver el número total de clientes;
a continuación, usar el método SqlCommand.ExecuteScalar para ejecutar el
procedimiento almacenado.
c. Escribir una consulta SQL y usar el método SqlDataAdapter.Fill para ejecutar la
consulta.
d. Crear un procedimiento almacenado para devolver el número total de clientes; a
continuación, usar el método SqlDataAdapter.Fill para ejecutar el procedimiento
almacenado.
3. Debe modificar los registros de una tabla Products marcando ciertos productos como
descontinuados. Sin embargo, debe hacerlo solo cuando tanto el valor de UnitsInStock
como el de UnitsOnOrder sea cero. ¿Cuál de las siguientes instrucciones SQL se debe
usar?
a. INSERT
b. SELECT
c. UPDATE
d. DELETE
4. Debe actualizar los campos Region de los clientes de Japón. Escribe la siguiente
instrucción SQL UPDATE:
UPDATE Customers
SET Region = 'EastAsia'
Al llevar a cabo una consulta en una base de datos de prueba, descubre que hay más
registros afectados de los que esperaba. Es preciso corregir la instrucción SQL. ¿Qué
debe hacer?
a. Agregar una cláusula WHERE a la instrucción UPDATE.
b. Agregar una cláusula SET adicional a la instrucción UPDATE.
c. Agregar una cláusula GROUP BY a la instrucción UPDATE.
d. Agregar una cláusula HAVING a la instrucción UPDATE.
5. Está desarrollando una aplicación que tiene que recuperar una lista de clientes de una
base de datos de SQL Server. La aplicación debe recorrer la lista secuencialmente una
vez, mientras procesa cada registro de cliente. ¿Cuál de las siguientes clases debe usar
para contener la lista de clientes a fin de lograr el máximo rendimiento?
a. DataSet
b. DataTable
c. DataView
d. SqlDataReader
Comprensión de bases de datos | 175

6. La aplicación que está desarrollando tiene que leer datos de un archivo plano que incluye
elementos tales como una clave de tipo integer de cinco dígitos, seguida de un nombre de
cliente de 20 caracteres, seguido de dos campos de fecha y hora. ¿Cuál de las siguientes
clases debe usar?
a. FileStream
b. StreamReader
c. BinaryReader
d. DataReader
7. Está desarrollando una aplicación que deberá copiar datos de una vista de SQL Server en
un DataSet. Asigna al objeto DataSet el nombre dsData. ¿Cuál de los siguientes métodos
debe usar para copiar los datos?
a. Fill
b. InsertCommand
c. SelectCommand
d. Update
8. Está desarrollando una aplicación para administrar los clientes y sus pedidos. ¿Cuál de
las siguientes situaciones no es una buena candidata para implementarla en su aplicación
mediante procedimientos almacenados?
a. Recuperación de la lista de todos los clientes de la base de datos.
b. Recuperación de la lista de todos los pedidos de clientes específicos.
c. Inserción de un nuevo pedido en la tabla Orders.
d. Creación de consultas ad hoc por parte del administrador de la base de datos.
9. Su aplicación se conecta a una base de datos de SQL Server que contiene una tabla
denominada Employees con las siguientes columnas:
EmployeeID (int, identity)
EmployeeType (char(1))
EmployeeDate (datetime)
Debe escribir una consulta que elimine todas las filas de la tabla cuando el valor de
EmployeeType sea C o T. No desea eliminar las demás filas. ¿Qué instrucción debe usar?
a. DELETE FROM Employees
WHERE EmployeeType LIKE '[CT]'
b. DELETE FROM Employees
WHERE EmployeeType LIKE '[C-T]'
c. DELETE FROM Employees
WHERE EmployeeType LIKE 'C' OR 'T'
d. DELETE * FROM Employees
WHERE EmployeeType IN ('C', 'T')
10. Su aplicación incluye un objeto SqlDataAdapter denominado sqlDataAdapter que se
conecta a la tabla Employees. La aplicación, que se basa en este SQLDataAdapter,
también incluye un objeto DataSet denominado dsEmployees. ¿Qué línea de código debe
usar para cargar los datos de la base de datos en el objeto DataSet?
a. dsEmployees = sqlDataAdapter.Fill("Employees");
b. sqlDataAdapter.Fill("dsEmployees", "Employees");
c. sqlDataAdapter.Fill(dsEmployees);
d. sqlDataAdapter.Fill(dsEmployees, "Employees");
176 | Lección 6

■ Evaluación de competencias
Escenario 6-1: Creación de un diagrama de relación entre entidades
Una empresa tiene un número de empleados y cada empleado se puede asignar a uno o más
proyectos. Además, cada proyecto puede tener uno o más empleados trabajando en ellos.
Dibuje un diagrama de relación entre entidades para esta situación.

Escenario 6-2: Creación de un procedimiento almacenado


A menudo necesita generar una lista de clientes de un determinado país. Debido a esto, decide
crear un procedimiento almacenado que acepta el nombre del país como parámetro y devuelve
todos los clientes de ese país. ¿De qué modo haría esto?

■ Evaluación de aptitudes
Escenario 6-3: Normalización de tablas
Está convirtiendo un diagrama de relación entre entidades en tablas. Idea el siguiente diseño
de tabla:

Books

BookId BookName CategoryId CategoryName


1 Cooking Light 1001 Cooking

2 Prophecy 1002 Mystery & Thriller

3 Shift 1003 Business

4 The Confession 1002 Mystery & Thriller

Debe aplicar reglas de normalización para garantizar la integridad de los datos. ¿Cómo
garantizaría que la tabla Books sea conforme con la tercera forma normal?

Escenario 6-4: Creación y control de eventos


Está trabajando en una aplicación que requiere que usted guarde la información del cliente de
la tabla Customers de la base de datos Northwind en un archivo XML. Este archivo XML se
usará en varias tareas de integración de datos. Debe asegurarse de que el nodo raíz de XML
se denomine Customers. El nodo raíz tendrá un nodo Customer para cada cliente de la tabla
Customers. ¿Cómo realizaría esta tarea?
Apéndice A
Aspectos fundamentales del desarrollo
de software: Examen 98-361

Dominio de objetivos Número de competencia Número de lección


Conceptos de la programación básica
Conceptos del almacenamiento y los tipos de datos de los equipos. 1.1 1, 2
Conceptos de las estructuras de decisión informáticas. 1.2 1
Identificación de los métodos apropiados para controlar la repetición. 1.3 1
Conceptos del control de errores. 1.4 1
Conceptos de la programación orientada a objetos
Conceptos de los aspectos fundamentales de las clases. 2.1 2
Conceptos de la herencia. 2.2 2
Conceptos del polimorfismo. 2.3 2
Conceptos de la encapsulación. 2.4 2
Conceptos generales del desarrollo de software
Conceptos de la administración del ciclo de vida de las aplicaciones. 3.1 3
Interpretación de las especificaciones de las aplicaciones. 3.2
Conceptos de los algoritmos y las estructuras de datos. 3.3 3
Conceptos de las aplicaciones web
Conceptos del desarrollo de páginas web. 4.1 4
Conceptos del desarrollo de aplicaciones web Microsoft ASP.NET. 4.2 4
Conceptos del hospedaje de sitios web. 4.3 4
Conceptos de los servicios web. 4.4 4
Conceptos de las aplicaciones de escritorio
Conceptos de las aplicaciones de Windows Forms. 5.1 5
Conceptos de las aplicaciones basadas en consola. 5.2 5
Conceptos de los servicios de Windows. 5.3 5
Conceptos de las bases de datos
Conceptos de los métodos de consulta de las bases de datos relacionales. 6.1 6
Conceptos de los métodos de consulta de las base de datos. 6.2 6
Conceptos de los métodos de conexión de las bases de datos. 6.3 6

177
Índice

&, signo, 128 operadores, 10–11


@@IDENTITY, 163 procedimientos almacenados, ejecución a partir de, 161-164
@Page, directiva, 99 tipos de datos, 8–9
<html>, etiqueta, 87 using, instrucción, 164
<img>, etiqueta, 87 variables, 8
<link>, elemento, 91 Aplicaciones de consola, 129–131
<script>, elemento, 93 Aplicaciones de Windows Forms
+=operador, 42 creación, 121–123
<?, 167 definición, 120
herencia visual, 123–126
Interfaz de múltiples documentos (MDI), 126–129
A modelo de eventos, 123
Account, propiedad, 135 Aplicaciones desconectadas, 170
Administración de estado Aplicaciones web, implementación, 106
cadenas de consulta, 100 Aplicaciones, escritorio
campos ocultos, 100 basadas en consolas, 129–131
cookies, 100 Servicio de Windows, 131–137
definición, 99 Windows Forms, 120–129
estado de aplicación, 101 Application, propiedad, 101
estado de sesión, 101–104 Archivos binarios, 165
lado cliente, 100 Archivos de texto, lectura y escritura, 165–167
lado servidor, 101 Archivos planos
ViewState, 100 definición, 164
Administración de versiones, 68 archivo de texto, lectura y escritura, 165–167
Administración del ciclo de vida de las aplicaciones (ALM) As, operador, 53
administración de versiones, 68 Asignación de memoria, 45–47
análisis de requisitos, 66–67 ASP.NET
desarrollo de software, 67 @Page, directiva, 99
proceso de diseño, 67 administración de estado, 99–104
pruebas de software, 68–70. Véase también Pruebas ciclo de vida de las páginas, 96–99
Ajax, 93 controladores de eventos, 97
Algoritmo de ordenación desarrollo de aplicaciones, 95–104
BubbleSort, 76–78 infraestructura, 95
QuickSort, 79–81 Page, clase, 96
Algoritmo. Véase también Algoritmo de ordenación Page, clase, eventos, ejecución, 98–99
definición, 2 postback, 96, 97
diagramas de flujo, 2–3 proceso de solicitud de página, 96
tablas de decisión, 3–4 proceso de solicitud/respuesta de HTTP, 95
Anomalía de actualización, 147 Atributo, 168
Anomalía de eliminación, 147
Anomalía de inserción, 146 B
aplicaciones de C# Base de datos, 143
carácter imperativo, 150 Bases de datos de SQL Server
constantes, 8 conexión, 150–152
consultas, ejecución a partir de, 153–155 consultas, aplicaciones de C#, ejecución a partir de, 153–155
escritura, 5 consultas, Visual Studio, ejecución a partir de, 152–153
estructura, 6–8 Bases de datos relacionales. Véase también Relacionales, bases de
estructuras de control, 17–22 datos
matrices, 9–10 BubbleSort, 76–78
métodos, 11

179
180  |  Índice

C Desarrollo de páginas web


Cadenas de consulta, 100 hojas de estilo en cascada (CSS), 88–92
Campos ocultos, 100 HTML, 86–88
case, instrucción, 15 JavaScript, 92–94
Clase sellada, 50, 51 programación, del lado cliente o del lado servidor, 94–95
Clase Descriptores de acceso, 36
abstracta, creación, 50–51 Diagramas de flujo, 2–3
creación, 33–34 Diagramas de relación entre entidades (ERD)
definición, 7, 33 atributo, 144
derivada, creación, 49 base de datos relacional, asignación, 145–146
modificador de acceso, 34 definición, 144
clase, base entidad, 144
herencia, 48–49 relación, 145
new, palabra clave, 55–56 Directorio virtual, 105–106
override, palabra clave, 55–56 Do-while, bucle, 19
Clases abstractas
creación, 50–51 E
definición, 50 Elemento, 168
Clave principal, 144 Encapsulación, 33, 47–48
Código binario, 4 Enqueue, 73
Colas Espacios de nombres, 42–43
definición, 72 Estado de aplicación, 101. Véase también Administración de estado
operadores, 73 Estado de sesión, 101–104. Véase también Administración de
rendimiento y uso, 73 estado
representación interna, 72 Estructuras de datos
CompareTo, 57 colas, 72–73
Consola, 129 listas de vínculo, 74–76
Constantes, 8 matrices, 70–72
Constructores, 35 pilas, 73–74
Consultas, SQL. Véase también Lenguaje de consulta estructurado Estructuras de decisión
(SQL) definición, 11
Aplicación de C#, ejecución a partir de, 153-154 if, instrucción, 11–13
Visual Studio, ejecución a partir de, 152–153 if-else, instrucción, 13–15
Contains, 73, 74 switch, instrucción, 15–17
Controladores de eventos, 97 Estructuras de repetición
Conversión do-while, bucle, 19–20
as, operador, 53 for, bucle, 20–21
definición, 52 foreach, bucle, 21–22
entre tipos, 52–53 método recursivo, 23
is, operador, 53 recursión, 22
Cookies, 100 while, bucle, 17–19
CREATE PROCEDURE, 159–160 EventArgs, clase, 41
EventHandler, delegado, 41
D Eventos
DataAdapter, clase, 170 definición, 40, 121
DataSet Page, clase, ejecución, 98–99
definición, 170 publicación y suscripción, 41–42
objeto, lectura, 171–172 Excepciones
DataSet, clase, 170, 172 control, 24–25
default, instrucción, 15 definición, 24
Delegados, 40, 123 try-catch-finally, instrucción, 25–26
DELETE, instrucción, 150, 159 Expresión de terminación, 19
Dependencia funcional, 148
Dequeue, 73 F
Derivada, clase finally, bloque, 25
herencia, 48–50 Firma, 34
new, palabra clave, 55–56 For, bucle, 20
override, palabra clave, 55–56 Foreach, bucle, 21
FTP, 106
Índice  181

G funciones de agregado, 157


Get, descriptor de acceso, 36 INSERT, instrucción, 150, 158–159
instrucciones ad-hoc, 150
H SELECT, instrucción, 150, 155–157
Herencia visual, 123–126 UPDATE, instrucción, 150, 157–158
Herencia Lenguaje de marcado de hipertexto (HTML)
as, operador, 53 definición, 86
clase abstracta, 50–51 documento, creación, 87–88
clase base, 48 encabezado y cuerpo, 87
clase derivada, 48–50 etiquetas, 87
clase sellada, 50, 51 propósito, 86–87
conversión entre tipos, 52–53 Lenguaje de marcado extensible (XML). Véase XML
de la clase object, 51–52 Listas de vínculo
definición, 48 definición, 74
is, operador, 53 operaciones, 75–76
Hojas de estilo en cascada (CSS) rendimiento y uso, 76
archivo, vincular un archivo HTML, 90–91 representación interna, 74–75
definición, 88 Localizador uniforme de recursos (URL), 86
diseño, 89
Hospedaje de sitios web M
Aplicaciones web, implementación, 106 Main, método, 7–8, 11
definición, 104 Matrices
directorios virtuales, creación, 105–106 acceso, 71
Internet Information Services (IIS), 104–105 asignación, 71
Sitios web, creación, 104 C#, aplicaciones, 9–10
HttpCookie, clase, 100 definición, 9, 70
operaciones, 71
I rendimiento y uso, 72
IComparable, 56–58 representación interna, 71
If, instrucción, 11 Memoria de la pila de llamadas, 47
If-else, instrucción, 13 Memoria del montón, 47
Inicializador, 19 Método recursivo, 23
INSERT, instrucción, 150, 158–159 Métodos de conexión de bases de datos
Instalador de Windows, 106 archivos planos, 164–167
Instalador, 135 DataSet, 170–173
Instancia, 33 XML, 167–170
Instrucciones de procesamiento, 167 Métodos de consulta de las bases de datos Véase Lenguaje de
Integridad de bases de datos, 144 consulta estructurado (SQL)
Interfaces Métodos
definición, 56 definición, 11
icomparable, 56–58 InitFields, 34–35
Interfaz de múltiples documentos (MDI), 126–129 objetos, 34–35
Internet Information Services (IIS), 104–106 return, instrucciones, 34, 35
Internet o Web, 86 signaturas, 34
is, operador, 53 Miembros estáticos
creación, 43–44
definición, 43
J
this, palabra clave, 44
JavaScript
Modificadores de acceso, 34, 37, 48
Ajax, 93
N
definición, 92
Namespace, propiedad, 110
en archivos externos, ventajas, 94
New, palabra clave, 35, 55–56
trabajo con, 93–94
Nombre de clase completo, 7
Normalización de datos
L definición, 146
Lenguaje de alto nivel, 4 primera forma normal, 147–148
Lenguaje de consulta estructurado (SQL) segunda forma normal, 148
carácter declarativo, 149–150 tercera forma normal, 149
DELETE, instrucción, 150, 159
182  |  Índice

O Propiedades
Objetos creación, 36–37
clases, creación, 33–34 de implementación automática, 37–38
constructores, 35 definición, 36
conversión entre tipos, 52–53 descriptores de acceso, 36
creación, 35–36 solo escritura, 37
DataSet en memoria, lectura, 171 solo lectura, 37
definición, 33, 35 Protocolo de transferencia de hipertexto (HTTP), 86, 95, 107
delegados, 40 Protocolo simple de acceso a objetos (SOAP)
espacios de nombres, 42–43 definición, 107
eventos, 40–42 elementos, 108
métodos, 34–35 Prueba de bucle, 19
miembros estáticos, 43–44 Pruebas de aceptación, 70
new, palabra clave, 35 Pruebas de caja blanca, 69
propiedades de implementación automática, 37–38 Pruebas de caja negra, 69
propiedades, creación, 36–37 Pruebas de integración, 69–70
this, palabra clave, 38–39 Pruebas de regresión, 70
Operadores binarios, 10 Pruebas de software. Véase Pruebas
Operadores ternarios, 10 Pruebas del sistema, 70
Operadores unarios, 10 Pruebas unitarias, 69
Operadores Pruebas
+=, 42 aceptación, 70
definición, 10 caja blanca, 69
precedencia en C#, 10 caja negra, 69
override, palabra clave, 55–56 integración, 69–70
métodos, 69
P niveles, 69–70
Parámetros de línea de comandos, 129 regresión, 70
Peek, 73, 74 Servicios web, 110–112
Pensamiento orientado a objetos, 33 sistema, 70
Pilas unitarias, 69
operaciones, 74 Push, 74
rendimiento y uso, 74
representación interna, 73–74 Q
Polimorfismo QueryString, propiedad, 100
definición, 53 QuickSort, 79–81
uso, 54–55
Pop, 74 R
Postback, 96, 97 Recursión, 22
Primera forma normal, 147–148 Relación de uno a uno, 145
Procedimientos almacenados parametrizados, 160–164 Relación de uno a varios, 144, 145
Procedimientos almacenados Relación de varios a varios, 145
creación y ejecución, 159–160 Relacionales, bases de datos
definición, 159 conceptos, 143
parametrizados, creación, 160–161 definición, 142
parametrizados, ejecución a partir de C#, 161–164 diagramas de relación entre entidades, 144–146
Visual Studio, creación a partir de, 160 diseño, 144
Proceso de diseño, 67 normalización de datos, 146–149
Programa, 4 tablas, 143
Programación del lado cliente, 94–95
Programación del lado servidor, 94–95 S
Programación orientada a objetos Segunda forma normal, 148
encapsulación, 47–48 SELECT, instrucción, 150, 155–157
herencia, 48–53 ServiceInstaller, clase, 135
interfaces, 56–58 ServiceProcessorInstaller, clase, 135
objetos, 33–44 Servicios de Windows
polimorfismo, 53–56 creación, 132–134
valores y referencias, 44–47 definición, 131
Propiedades de implementación automática, 37–38 ejemplos, 131
Índice  183

instalación, 135–136 V
instalador, adición al, 134–135 Value, palabra clave, 37
trabajo con, 136–137 Variables, 8
Servicios web ViewState, 100
aplicación cliente, acceso desde, 112–114 Visual Studio
creación, 108–110 consultas, ejecución a partir de, 152–153
definición, 107 Diseñador de consultas, 153
pruebas, 110–112 Instalador del Servicio de Windows, adición, 134–135
SOAP, 107–108 Plantilla del Servicio de Windows, 132–134
WebMethod, atributo, 110 Servicio de Windows, instalación, 135–136
Set, descriptor de acceso, 36
Sistema de administración de bases de datos (DBMS), 143 W
Sistema de numeración binario, 4 WebMethod, atributo, 101
Sitios web, 104–105 WebService, atributo, 101
SQL. Véase Lenguaje de consulta estructurado (SQL) While, bucle
StartType, propiedad, 135 definición, 17
Static, palabra clave, 43 partes, 19
Structs, 44–45 World Wide Web, 86
Switch, bloque, 15 WSDL, 108
Switch, instrucción, 15
X
T xcopy, 106
Tablas de decisión, 3–4 XML
Tablas, 143, 146–149 archivos, lectura, 168–170
Tercera forma normal, 149 atributos, 168
This, palabra clave, 38–39, 44 definición, 167
Tipos de datos, 8–9 elementos, 168
Tipos de referencia, 44–45, 46–47 etiquetas, 167
Tipos de valor, 44, 45, 46 XmlDocument, 168
Try, bloque, 25 XmlReader, 168
Try-catch-finally, instrucción, 25–26 XmlWriter, 168
T-SQL. Véase Lenguaje de consulta estructurado (SQL)

U
UPDATE, instrucción, 150, 157–158
Using, directiva, 7
Using, instrucción, 164
Notas
Notas
Notas
Notas
Notas
Notas
Notas
Notas
Notas
Notas

También podría gustarte