Monografias.com > Sin categoría
Descargar Imprimir Comentar Ver trabajos relacionados

Técnicas Generales de Diseño Software (página 2)




Enviado por Pablo Turmero



Partes: 1, 2, 3

Monografias.com
11
TÉCNICAS DE DISEÑO FUNCIONAL DESCENDENTE: DISEÑO ESTRUCTURADO
El flujo de transacción es aplicable cuando el flujo de datos se puede descomponer en varias líneas separadas. El análisis consiste en identificar el centro de transacción a partir del cual se ramifican las líneas de flujo a las regiones correspondientes a cada una de las transacciones

Monografias.com
12
TÉCNICAS DE DISEÑO FUNCIONAL DESCENDENTE: DISEÑO ESTRUCTURADO. EJ. GESTIÓN DE BIBLIOTECA

Monografias.com
13
TÉCNICAS DE DISEÑO BASADO EN ABSTRACCIONES
La idea es que los módulos corresponden a funciones o a tipos abstractos de datos.
Los lenguajes que dan más facilidades para la implementación son los orientados a objetos
TÉCNICAS DE DISEÑO BASADO EN ABSTRACCIONES: DESCOMPOSICIÓN MODULAR BASADA EN ABSTRACCIONES
Se trata de ampliar el lenguaje de programación con nuevas operaciones y tipos de datos definidos por el usuario, de forma que se simplifique la escritura de los niveles superiores del programa, basándose en módulos que realicen estas operaciones
Podemos identificar los tipos abstractos correspondientes a un número
complejo y a una ecuación de 2° grado y definir sobre dichos tipos abstractos las siguientes operaciones:
Ecuación de 2° grado: Número complejo:
Leer ecuación Escribir
Escribir ecuación Sumar, Restar, etc..
Obtener raíces Raíz cuadrada
La estructura modular del programa sería:

Monografias.com
14
TÉCNICAS DE DISEÑO BASADO EN ABSTRACCIONES: MÉTODO DE ABBOTT
A partir de la descripción o especificación de los módulos es posible identificar las palabras o términos que puedan corresponder a elementos significativos del diseño:
Tipos de datos, que aparecen como sustantivos genéricos
Atributos, son sustantivos en general
Operaciones, tienen la forma de verbos o nombres de acciones
Se subrayan en la descripción las palabras significativas haciendo una lista de nombres y otra de verbos u operaciones. Hay que eliminar los términos irrelevantes o los sinónimos de palabras ya aparecidas

Monografias.com
15
TÉCNICAS DE DISEÑO ORIENTADAS A OBJETOS
Es esencialmente igual al diseño basado en abstracciones, añadiendo la herencia y el polimorfismo.
En la descomposición modular del sistema cada módulo contiene la descripción de una clase de objetos o de varias clases relacionadas entre sí.
PASOS:
Estudiar y comprender el problema a resolver
Desarrollar en líneas generales uan posible solución, al menos informal
Formalizar dicha estrategía en términos de clases, objetos y sus relaciones:
Identificar los objetos, sus atributos y sus componentes
Identificar las operaciones sobre los objetos y asociarlas a la clase adecuada
Aplicar herencia donde convenga
Describir cada operación en función de las otras, y subsanar posibles omisiones
Asignar clases y objetos a los módulos del sistema

Monografias.com
16
TÉCNICAS DE DISEÑO DE DATOS
Muchas aplicaciones necesitan almacenar información de forma permanente y la mejor forma de hacerlo es crear una base de datos subyacente
Podemos enfocar la organización de la base de datos de 3 formas:
Nivel externo Esquemas de usuario
Nivel conceptual Esquemas lógicos
Nivel interno Esquemas físicos
El nivel externo corresponde a la visión del usuario, en la fase de análisis de pasa al nivel conceptual, que establece la organización de los datos, y finalmente en la etapa de diseño se pasa al nivel interno.
DISEÑO DE BASES DE DATOS RELACIONALES, en este modelo la eficiencia se basa en:
Las FORMAS NORMALES, que tienden a evitar las redundancias en los datos almacenados
FN1, la información asociada a cada columna de la tabla es un único valor, y no una colección
FN2, si hay una clave primaria que distingue e identifica cada fila, el resto de los datos dependen de toda la clave primaria
FN3, el valor de cada columna que no es clave primaria depende directamente de la clave primaria. Se puede conseguir si se separan las tablas.
Los INDICES, que mejoran la velocidad de acceso a los datos

Monografias.com
17
TÉCNICAS DE DISEÑO DE DATOS: DISEÑO DE LAS ENTIDADES
En el modelo relacional cada entidad del modelo E-R se traduce en una tabla por cada clase de entidad, con una fila por cada elemento de esa clase y una columna por cada atributo de esa entidad.
Entre las entidades relacionadas se puede incluir una columna con un número de referencia o identificador que las relaciona, sirve como clave primaria.
En el modelo E-R todas las relaciones se consideran de asociación, y la manera de trasladar esto a las tablas depende de la cardinalidad de la relación. La relación se convierte en una tabla que contiene referencias a las tablas de las entidades relacionadas, así como los atributos de la relación (cale para cualquier cardinalidad, incluso N:N). Si es 1:N es posible incluir los datos de la relación en la tabla con cardinalidad 1. Si la cardinalidad es 1:1 se pueden fundir las tablas de las dos entidades.

Monografias.com
18
CODIFICACIÓN DEL DISEÑO
Nos vamos a referir a las últimas fases del ciclo de vida: codificación, pruebas de unidades, integración y pruebas de sistema.
Cuando alguna de las pruebas no resulta positiva es necesario repetir la codificación o la integración y probar de nuevo.
La fase de codificación constituye el núcleo central en cualquiera de los modelos y tiene una importancia fundamental ya que elabora los programas fuente.
Previamente a la codificación es necesario elegir el lenguaje que se empleará así como la metodología de programación. También se pueden establecer en el equipo unas normas y un estilo de programación común, lo que mejorará la coordinación y facilitará el trabajo. Además se consigue facilitar el mantenimiento y mejorar la reusabilidad del software.
Cuando el resultado de las pruebas no sea satisfactorio será necesario modificar el código, lo que podrá introducir nuevos errores. Si la programación es estructurada será más fácil localizar la disfunción y la posterior modificación y las pruebas del código, dónde podemos introducir puntos de test.

Monografias.com
19
LENGUAJES DE PROGRAMACIÓN
Aunque los lenguajes han evolucionado mucho desde los años 50 todavía están más próximos a la máquina que al pensamiento humano. Los lenguajes suelen adoptar los avances metodológicos que se producen en el desarrollo del software. Ej.: C y C++
DESARROLLO HISTÓRICO, muchos han sido desarrollados con fines experimentales y muy pocos han llegado a ser utilizados industrialmente:
1ª GENERACIÓN: muy próximos al lenguaje máquina
Ensamblador, asocia a cada instrucción de la máquina un nemónico
2ª GENERACIÓN: no dependen de la CPU, se programa de manera simbólica, en “alto nivel”.
FORTRAN (FORula TRANslator), para aplicaciones científicas
COBOL, para procesamiento de información. Supone el 70 %
ALGOL, da gran importancia a la tipificación de datos
BASIC, sencillo y fácil de aprender. Desarrollado para el PC.
3ª GENERACIÓN: programación estructurada con declaración de tipos. Los últimos van asociados a otros paradigmas.
PASCAL, fue diseñado para la enseñanza de la programación estructurada. Tipificación rígida y no contempla la codificación por separado
MÓDULA-2, descendiente de pascal, se incorpora la estructura de módulo. Se mejora modularidad, concurrencia, abstracción y ocultación
C, desarrollado para la codificación del UNIX. Flexible y potente. No hay restricciones sobre las operaciones con distintos tipos.
ADA, descendiente de pscal, mucho más potente y complejo. Incorpora modularidad, abstracción, ocultación, concurrencia y sincronización entre tareas.
SMALLTALK, precursos de los lenguajes orientados a objetos
C++, incorpora en C los mecanismos de la POO: ocultación, clases, herencia y polimorfismo.
EIFFEL, permite la definición de clases genéricas, herencia múltiple y polimorfismo.
LISP, lenguaje funcional usado en IA y sistemas expertos. Basado en listas admite recursividad. Maneja bien los símbolos
PROLOG, lenguaje lógico en que se construye una base de conocimiento basada en reglas a partir de la cual podemos inferir nuevos hechos o reglas.
4ª GENERACIÓN: mayor grado de abstracción. Se agrupan en:
BASES DE DATOS; como SQL permiten acceder y manipular la información.
GENERADORES DE PROGRAMAS, son eficientes en un dominio de aplicaciones limitado. La mayoría producen aplicaciones de gestión y la salida va en cobol, aunque se han desarrollado herramientas CASE que generan programas en C++ o ADA.
CÁLCULO, hojas de cálculo, herramientas de simulación y diseño para el control, etc.
OTROS: herramientas para la especificación y verificación formal de programas, lenguajes de simulación, de prototipos, etc.

Monografias.com
20
PRESTACIONES DE LOS LENGUAJES: ESTRUCTURAS DE CONTROL
se incluyen aquí, además de las características propias de la programación estructurada, el manejo de excepciones y la concurrencia.
Programación estructurada: secuencia, iteración y selección (verdadero-falso y por casos)
Manejo de excepciones: errores humanos, fallos hardware, errores software, datos de entrada vacíos, valores fuera de rango, etc. (estructuras exception when y raise).
Concurrencia, tareas simultáneas, sincronización, comunicación e interbloqueos. Los lenguajes han implementado la posibilidad de lanzar tareas concurrentes de distintas formas:
CORRUTINAS, tienen una estructura semejante a subprogramas pero con una transferencia del control más flexible. El avance en la ejecución de las corrutinas se produce según el avance entre ellas.
FORK-JOIN, es la propuesta de UNIX.
COBEGIN-COEND, entre estas palabras se inician todas las tareas y se finalizan. Es posible el anidamiento.
PROCESOS; cada tarea se declara como un proceso y estos y se ejecutan concurrentemente. En algunos casos es posible lanzar dinámicamente nuevos procesos una vez iniciado el programa.
PARA LA COMUNICACIÓN ENTRE TAREAS.
VARIABLES COMPARTIDAS
SEMÁFOROS
REGIONES CRÍTICAS
MONITORES
PASO DE MENSAJES
CSP
LLAMADA A PROCEDIMIENTOS REMOTOS
REDENZVOUS, DE ADA

Monografias.com
21
PRESTACIONES DE LOS LENGUAJES: ESTRUCTURAS DE DATOS
DATOS SIMPLES. Para los eneros hay que tener en cuenta el rango posible y para los de coma flotante la precisión. En ocasiones también permiten el manejo de complejos.
Otros tipos simples son char y string, para el manejo de cadenas. Los tipos enumerados también pueden resultar útiles, un tipo enumerado muy frecuente son los booleanos.
En ocasiones los lenguajes permiten utilizar subrangos.
DATOS COMPUESTOS, son combinaciones de datos simples y compuestos ya definidos. Pueden ser homogéneos como los ARRAYS y heterogéneos como los RECORDS o STRUCTS.
Para el manejo de estructuras dinámicas de datos muchos lenguajes incluyen punteros
CONSTANTES, en los lenguajes modernos se pueden declarar constantes simbólicas, sin indicar directamente su valor numérico.
COMPROBACIÓN DE TIPOS, se pueden distinguir 5 niveles:
Nivel 0: sin tipos, no es posible declarar nuevos tipos y todos los datos deben pertenecer a tipos predefinidos
Nivel 1: tipado automático, el compilador decide cuál es el tipo más adecuado para cada dato.
Nivel 2: tipado débil, el compilador hace inferencias sobre los tipos y solo son posibles determinadas conversiones
Nivel 3: tipado semirígido, todos los datos deben ser declarados con su tipo
Nivel 4: tipado fuerte, aquí además de declarar los tipos, el programador está obligado a hacer explícita cualquier conversión de tipos.
ABSTRACCIONES Y OBJETOS.
ABSTRACCIONES FUNCIONALES
TIPOS ABSTRACTOS DE DATOS
OBJETOS
MOODULARIDAD. Se requiere la compilación por separado. Además se introducen de forma redundante la declaración y la definición de cada módulo, para permitir al compilador hacer comprobaciones acerca de la consistencia. C y modula-2 lo tienen, pero pascal es monolítico.

Monografias.com
22
CRITERIOS DE SELECCIÓN DEL LENGUAJE
El lenguaje es uno de los elementos más importantes de cualquier desarrollo y tiene una influencia decisiva en la depuración y el mantenimiento dela aplicación. Criterios:
IMPOSICIÓN DEL CLIENTE, a veces para disminuir los costes de desarrollo y mantenimiento que se producen cuando una empresa utiliza lenguajes diferentes.
TIPO DE APLICACIÓN, hay lenguajes orientados a un campo de aplicación concreto.
Aplicaciones tiempo real críticas -> ensamblador
Gestión -> cobol
Área científico-técnica -> Fortran, Pascal, C
Inteligencia artificial -> Lisp, Prolog
Orientado a objeots ->> Eifel, C++
DISPONIBILIDAD Y ENTORNO, hay que comprobar los compiladores existentes para la plataforma elegida. Estudio comparativo de eficiencia con un programa de prueba. Herramientas del entorno de desarrollo: editor, montador, depurador, control versiones, manejo de librerías, etc.
EXPERIENCIA PREVIA, aprovechar la experiencia aumenta el rendimiento y disminuye las posibilidades de error. La formación supone una fuerte inversión.
RESUABILIDAD, organización de librerías que faciliten la búsqueda y almacenamiento de módulos reutilizables.
TRANSPORTABILIDAD, depende del lenguaje
USO DE VARIOS LENGUAJES, no es aconsejable a no ser que las distintas partes sean más fáciles de desarrollar en lenguajes concretos. Hay que tener en cuenta la compatibilidad de los compiladores

Monografias.com
23
ASPECTOS METODOLÓGICOS
Estos aspectos pueden mejorar la codificación bajo determinados puntos de vista: claridad, manejo de errores eficiencia y transportabilidad.
Normas y estilo, para conseguir un trabajo del equipo homogéneo. Ejemplos:
Formato y contenido del as cabeceras de cada módulo
Formato y contenido para los comentarios
Uso del indentado
Elección de nombre y uso de mayúsculas
Restricciones sobre el tamaño del os módulos, evitar anidamiento excesivo, no usar goto, etc.
Manejo de errores. Las causas de los errores pueden estar en el hardware o en el software, incluso de pueden producir por la introducción de datos incorrectos.
DEFECTO, incorrección en el software. Pueden permanecer ocultos hasta que no se ejecutan determinadas partes del programa
FALLO, elemnto del programa que no funciona correctamente, produciendo un resultado erróneo
ERROR, estado no válido de un programa al que se llega como consecuencia de un fallo.
Al codificar podemos adoptar distintas actitudes ante los errores:
NO CONSIDERAR LOS ERRORES, no es realista esta postura
PREVENCIÓN DE ERRORES, consiste en detectar los fallos antes de que provoquen un error. Hay que evitar la propagación de errores y tener siempre a la salida un resultado correcto o una señal de fallo.
RECUPERACIÓN DE ERRORES, Cuando no es posible depurar todos los fallos es necesario hacer un tratamiento de errores para devolver al programa a un estado válido y evitar que el error se propague
Detección del error
Recuperación del error. Se pueden usar dos esquemas en general:
RECUPERACIÓN HACIA DELANTE, hay que programas un mecanismo de excepciones para que cuando se detecte el error se corrija el estado y se continúe correctamente la ejecución.
RECUPERACIÓN HACIA ATRÁS, corrige el estado no válido restaurando el programa a un estado correcto anterior,
Una transacción es una operación que puede terminar con éxito o con fallo, en cuyo caso se aborta y se restaura el estado de antes de comenzar dicha transacción.

Monografias.com
24
ASPECTOS METODOLÓGICOS: EFICIENCIA Y TRANSPORTABILIDAD
La potencia de cálculo y la cantidad de memoria disponible en los computadores actuales hacer preferible la claridad en el código que la EFICIENCIA.
EFICIENCIA EN MEMORIA, en la fase de diseño se estudian las posibles alternativas y se opta por el algoritmo que optimiza el uso dela memoria.
EFICIENCIA DE TIEMPO, es importante en el desarrollo de sistemas de tiempo real muy críticos. A veces se mejora la eficiencia de tiempo a costa de ocupar más memoria. En el diseño se estudian las alternativas y se adopta el algoritmo más rápido. Técnicas de codificación para aumentar la eficiencia de tiempo:
Tabular cálculo complejos
Expansión en línea, emplear macros en vez de subrutinas
Simplificar las expresiones aritméticas y lógicas
Sacar fuera de los bucles lo que no sea necesario repetir
Usar estructuras de datos de acceso rápido
Evitar operaciones en coma flotante, mejor en coma fija
Evitar conversiones innecesarias de tipos
TRANSPORTABILIDAD DEL SOFTWARE, no solo es rentable a corto plazo para obtener versiones para diferentes plataformas, a medio y largo plazo facilita el mantenimiento y la adaptación de la aplicación a las nuevas arquitecturas.
Los factores para la transportabilidad son:
Utilización de estándares
Aislar las peculiaridades, colocándolas en módulos separados. Se procurará evitar aquellos elementos no consolidados y que pueden estar sujetos a futuros cambios o revisiones.
Las peculiaridades de los distintos tipos de computadores depende de la arquitectura y del sistema operativo utilizado.

Monografias.com
25
TÉCNICAS DE PRUEBAS
Para garantizar su calidad es necesario someter al programa a diversas pruebas para garantizar su funcionamiento correcto.
Se deben hacer pruebas a cada módulo, según avanza la codificación del proyecto. Finalmente se harán las pruebas de integración entre módulos y las pruebas de sistema
OBJETIVOS, el principal objetivo es conseguir que el programa funcione incorrectamente para ir depurando los errores y que se descubran los efectos. Para elaborar los casos de prueba:
Una buena prueba encuentra los errores y no los encubre
Para determinar si hubo error es necesario conocer el resultado correcto
Deben participar codificador y diseñador
Al corregir un error se pueden introducir otros nuevos
No es posible demostrar la ausencia de defectos mediante pruebas
No son posibles las pruebas exhaustivas. Con el menor esfuerzo posible hay que detectar el máximo nº de defectos, en especial los más graves.
Las pruebas se realizan en un entorno de ejecución controlado, para asegurar la estabilidad en los pruebas y automatizar en lo posible este proceso.

Monografias.com
26
TÉCNICAS DE PRUEBAS DE UNIDADES: CAJA NEGRA
Las técnicas de pruebas de unidades siguen dos estrategias fundamentales:
PRUEBAS DE CAJA NEGRA, se ignora por completo la estructura interna del programa y se comprueba la corrección de entradas y salidas del programa.

Lo importante es la elaboración de los casos de prueba con el objetivo de descubrir los errores e incorrecciones. Métodos:
PARTICIÓN EN CLASES DE EQUIVALENCIA, se trata de ividir el espacio de ejecución del programa en varios subestapacios o clases equivalentes desde el punto de vista del a caja negra. Hay que:
Determinar las clases equivalentes apropiadas
Establecer pruebas para cada clase de equivalencia, con datos de entrada válidos y no válidos. Se repiten las pruebas hasta cubrir todos los casos válidos de todas las clases.
ANÁLISIS DE VALORES LÍMITE, los errores tienden a aparecer al operar en las fronteras. Directrices para la elaboración de casos de pruebas:
Entradas, probar los valores del límite y justo fuera del límite
Salidas, probar los valores del límite y justo fuera del límite
Memoria, probar tamaños nulos, límite superior y superior al límite de todas las estructuras de datos del programa
Recursos, probar límites. Si terminales=30, probar 0, 20 y 31
Otros, probar los valores límite y establecer las pruebas
COMPARACIÓN DE VERSIONES, se desarrollan varias versiones software para resolver la especificación del módulo y se comparan los resultados con el fin de detectar errores.
EMPLEO DELA INTUICIÓN, la intuición y la experiencia puede mejorar los casos de prueba, también es conveniente que participen expertos ajenos al desarrollo.

Monografias.com
27
TÉCNICAS DE PRUEBAS DE UNIDADES: CAJA TRANSPARENTE
Se tiene en cuenta la estructura interna del módulo. Los casos de prueba deben conseguir que:
Todas las decisiones se ejecuten en uno y otro sentido
Todos los bucles se ejecuten en los supuestos más diversos posibles
Todas las estructuras de datos se modifiquen y consulten alguna vez
La complejidad de los módulos dificulta realizar exhaustivas pruebas de caja transparente. Conviene que participen expertos con un conocimiento amplio de las estructura del programa. Métodos:

CUBRIMIENTO LÓGICO, consiste en no dejar ninguna sección del código sin ejecutar en pruebas. Se llama camino básico a cualquier recorrido sobre el diagrama de flujo que nos permita llegar al final desde el punto de entrada.
Hay que determinar el conjunto de caminos básicos que recorran todas las líneas de flujo del programa al menos una vez.
Nº máximo de caminos = Nº predicados + 1
En un segundo nivel de casos de prueba se trata de que se ejecuten todas las combinaciones de caminos básicos por parejas
A otros niveles se generan casos de pruebas para que se ejecuten un nº significativo de combinaciones de caminos básicos

PRUEBAS DE BUCLES, que son elemento esencial en cualquier programa. Casos:
Bucles con nº no acotado de repeticiones, probar 0, 1, 2, bastantes y muchas iteraciones.
Bucles con nº máximo de repeticiones, probar 0, 1, 2 bastantes, M-1, M y M+1 iteraciones
Bucles anidados, el nº de pruebas para comprobar todas las situaciones crece.
EMPLEO DE LA INTUICIÓN, conocer con detalle la estructura del módulo y tener experiencia.

Monografias.com
28
TÉCNICAS DE PRUEBAS DE UNIDADES: CAJA TRANSPARENTE
Diagramas de flujo con 3 y con 4 predicados lógicos simples

Monografias.com
29
ESTIMACIÓN DE ERRORES NO DETECTADOS
Resulta imposible demostrar que un módulo carece de defectos, pero podemos hacer una estimación estadísitca de erratas que permanecen sin detectar:
Anotar el nº de errores que se producen inicialmente al pasar los casos de prueba.
Corregir el módulo hasta que sdesaparezcan todos esos errores
Introducir en el módulo, de forma aleatoria un nº razonable de errores
Someter al módulo nuevamente a los casos de prueba y ver el nº de errores que se detectan
De esta forma podemos estimar el nº de errores que han permanecido sin ser detectados en el programa
En función de los resultados se valorará la necesidad de preparar nuevos casos de prueba.

Monografias.com
30
ESTRATEGIAS DE INTEGRACIÓN
Se integran los módulos del sistema para conformar el sistema completo. Causas de error:
Desacuerdos en el interfaz entre módulos
Interacción indebida entre módulos
Imprecisiones acumuladas
Estrategias básicas para la integración:
INTEGRACIÓN BIG BANG, en un único paso se integran todos los módulos, de forma que todos los defectos se manifiestan a la vez. Solo recomendable para sistemas pequeños.
INTEGRACIÓN DESCENDENTE, se parte de un módulo principal P, que se prueba con “módulos de andamiaje”, los cuales van siendo sustituidos por los verdaderos de forma progresiva por niveles. Los módulos de andamiaje;
No hacen nada y solo sirven para comprobar el interfaz
Imprimen un mensaje de seguimiento, con información de la llamada
Suministran un resultado fijo
Suministran un resultado aleatorio
Suministran un resultado tabulado u obtenido con un algoritmo simplificado
El trabajo de elaborar estos módulos puede ser aprovechado para hacer un prototipo y mostrar al cliente un avance del programa. Inconvenientes:
Impide el trabajo en paralelo en las pruebas
Es difícil buscar los casos de pruebas especiales o dirigidas a los últimos módulos integrados
INTEGRACIÓN ASCENDENTE, se codifican por separado y en paralelo todos los módulos del nivel más bajo. Para probarlos se codifican módulos gestores o conductores que los hacen funcionar independientemente o en combinaciones sencillas. Las ventajas son:
Facilita el trabajo en paralelo
Facilita el ensayo de situaciones especiales
La Integración Sandwich consiste en realizar integración ascendente con los módulos de nivel más bajo y descendente con los de nivel más alto.

Partes: 1, 2, 3
 Página anterior Volver al principio del trabajoPágina siguiente 

Nota al lector: es posible que esta página no contenga todos los componentes del trabajo original (pies de página, avanzadas formulas matemáticas, esquemas o tablas complejas, etc.). Recuerde que para ver el trabajo en su versión original completa, puede descargarlo desde el menú superior.

Todos los documentos disponibles en este sitio expresan los puntos de vista de sus respectivos autores y no de Monografias.com. El objetivo de Monografias.com es poner el conocimiento a disposición de toda su comunidad. Queda bajo la responsabilidad de cada lector el eventual uso que se le de a esta información. Asimismo, es obligatoria la cita del autor del contenido y de Monografias.com como fuentes de información.

Categorias
Newsletter