Un
proceso de desarrollo de software tiene como propósito la producción eficaz y
eficiente de un producto software que reúna los requisitos del cliente. Dicho
proceso, en términos globales se muestra en la Figura.
Este
proceso es intensamente intelectual, afectado por la creatividad y juicio de
las personas involucradas. Aunque un proyecto de desarrollo de software es
equiparable en muchos aspectos a cualquier otro proyecto de ingeniería, en el
desarrollo de software hay una serie de desafíos adicionales, relativos
esencialmente a la naturaleza del producto obtenido. A continuación se explican
algunas particularidades asociadas al desarrollo de software y que influyen en
su proceso de construcción.
Un producto software en sí es complejo, es
prácticamente inviable conseguir un 100% de confiabilidad de un programa por
pequeño que sea. Existe una inmensa combinación de factores que impiden una
verificación exhaustiva de las todas posibles situaciones de ejecución que se
puedan presentar (entradas, valores de variables, datos almacenados, software
del sistema, otras aplicaciones que intervienen, el hardware sobre el cual se
ejecuta, etc.).
Un producto software es intangible y por lo
general muy abstracto, esto dificulta la definición del producto y sus
requisitos, sobre todo cuando no se tiene precedentes en productos software
similares. Esto hace que los requisitos sean difíciles de consolidar
tempranamente. Así, los cambios en los requisitos son inevitables, no sólo después de entregado en
producto sino también durante el proceso de desarrollo.
En esencia,
un componente es una pieza de código pre-elaborado que encapsula alguna
funcionalidad expuesta a través de interfaces estándar. Los componentes son los
"ingredientes de las aplicaciones", que se juntan y combinan para
llevar a cabo una tarea. Es algo muy similar a lo que podemos observar en el
equipo de música que tenemos en nuestra sala. Cada componente de aquel aparato
ha sido diseñado para acoplarse perfectamente con sus pares, las conexiones son
estándar y el protocolo de comunicación está ya preestablecido. Al unirse las
partes, obtenemos música para nuestros oídos.
El paradigma
de ensamblar componentes y escribir código para hacer que estos componentes
funcionen se conoce como Desarrollo de Software Basado en Componentes. El uso
de este paradigma posee algunas ventajas:
1. Reutilización
del software. Nos lleva a alcanzar un mayor nivel de reutilización de software.
2. Simplifica
las pruebas. Permite que las pruebas sean ejecutadas probando cada uno de los
componentes antes de probar el conjunto completo de componentes ensamblados.
3. Simplifica
el mantenimiento del sistema. Cuando existe un débil acoplamiento entre
componentes, el desarrollador es libre de actualizar y/o agregar componentes
según sea necesario, sin afectar otras partes del sistema.
4. Mayor
calidad. Dado que un componente puede ser construido y luego mejorado
continuamente por un experto u organización, la calidad de una aplicación
basada en componentes mejorará con el paso del tiempo.
De la misma
manera, el optar por comprar componentes de terceros en lugar de
desarrollarlos, posee algunas ventajas:
1. Ciclos de
desarrollo más cortos. La adición de una pieza dada de funcionalidad tomará
días en lugar de meses ó años.
2. Mejor ROI.
Usando correctamente esta estrategia, el retorno sobre la inversión puede ser
más favorable que desarrollando los componentes uno mismo.
3. Funcionalidad mejorada. Para usar un
componente que contenga una pieza de funcionalidad, solo se necesita entender
su naturaleza, más no sus detalles internos. Así, una funcionalidad que sería
impráctica de implementar en la empresa, se vuelve ahora completamente
asequible.
Las características siguientes son las más
importantes:
·Abstracción: Denota las características esenciales de un
objeto, donde se capturan sus comportamientos.Cada objeto en el sistema sirve
como modelo de un "agente" abstracto que puede realizar trabajo,
informar y cambiar su estado, y "comunicarse" con otros objetos en el
sistema sin revelar cómo se implementan estas características. Los procesos,
las funciones o los métodos pueden también ser abstraídos y cuando lo están,
una variedad de técnicas son requeridas para ampliar una abstracción.El proceso
de abstracción permite seleccionar las características relevantes dentro de un
conjunto e identificar comportamientos comunes para definir nuevos tipos de
entidades en el mundo real. La abstracción es clave en el proceso de análisis y
diseño orientado a objetos, ya que mediante ella podemos llegar a armar un
conjunto de clases que permitan modelar la realidad o el problema que se quiere
atacar.
·Encapsulamiento: Significa reunir a todos los elementos que
pueden considerarse pertenecientes a una misma entidad, al mismo nivel de
abstracción. Esto permite aumentar la cohesión de los
componentes del sistema. Algunos autores confunden este concepto con el
principio de ocultación, principalmente porque se suelen emplear conjuntamente.
·Modularidad: Se denomina Modularidad a la propiedad que
permite subdividir una aplicación en partes más pequeñas (llamadas módulos),
cada una de las cuales debe ser tan independiente como sea posible de la
aplicación en sí y de las restantes partes. Estos módulos se pueden compilar
por separado, pero tienen conexiones con otros módulos. Al igual que la
encapsulación, los lenguajes soportan la Modularidad de diversas formas.
·Principio de ocultación: Cada
objeto está aislado del exterior, es un módulo natural, y cada tipo de objeto
expone una interfaz a otros objetos que específica cómo pueden interactuar con
los objetos de la clase. El aislamiento protege a las propiedades de un objeto
contra su modificación por quien no tenga derecho a acceder a ellas, solamente
los propios métodos internos del objeto pueden acceder a su estado. Esto
asegura que otros objetos no pueden cambiar el estado interno de un objeto de
maneras inesperadas, eliminando efectos secundarios e interacciones
inesperadas. Algunos lenguajes relajan esto, permitiendo un acceso directo a
los datos internos del objeto de una manera controlada y limitando el grado de
abstracción. La aplicación entera se reduce a un agregado o rompecabezasde
objetos.
·Polimorfismo: Comportamientos diferentes, asociados a objetos
distintos, pueden compartir el mismo nombre, al llamarlos por ese nombre se
utilizará el comportamiento correspondiente al objeto que se esté usando. O
dicho de otro modo, las referencias y las colecciones de objetos pueden
contener objetos de diferentes tipos, y la invocación de un comportamiento en
una referencia producirá el comportamiento correcto para el tipo real del
objeto referenciado. Cuando esto ocurre en "tiempo de ejecución",
esta última característica se llama asignación tardía o asignación dinámica.
Algunos lenguajes proporcionan medios más estáticos (en "tiempo de
compilación") de polimorfismo, tales como las plantillas y la sobrecarga
de operadores de C++.
·Herencia: Las clases no están aisladas, sino que se relacionan entre sí,
formando una jerarquía de clasificación. Los objetos heredan las propiedades y
el comportamiento de todas las clases a las que pertenecen. La herencia organiza
y facilita el polimorfismo y el encapsulamiento permitiendo a los objetos ser
definidos y creados como tipos especializados de objetos preexistentes. Estos
pueden compartir (y extender) su comportamiento sin tener que volver a
implementarlo. Esto suele hacerse habitualmente agrupando los objetos en clases
y estas en árboles o enrejados que reflejan un comportamiento común. Cuando un
objeto hereda de más de una clase se dice que hay herencia múltiple.
·Recolección de basura: La recolección de basura o garbage collector es
la técnica por la cual el entorno de objetos se encarga de destruir
automáticamente, y por tanto desvincular la memoria asociada, los objetos que
hayan quedado sin ninguna referencia a ellos. Esto significa que el programador
no debe preocuparse por la asignación o liberación de memoria, ya que el
entorno la asignará al crear un nuevo objeto y la liberará cuando nadie lo esté
usando. En la mayoría de los lenguajes híbridos que se extendieron para
soportar el Paradigma de Programación Orientada a Objetos como C++ u Object Pascal, esta característica no existe y la memoria debe
desasignarse manualmente.
Componentes
fundamentales del Enfoque Orientado a Objetos.
·Clase:
Definiciones de las propiedades y comportamiento de un tipo de objeto concreto.
La instanciación es la lctura de estas definiciones y la creación de un objeto
a partir de ellas.
·Herencia: (Por ejemplo, herencia de la clase C a la clase
D) Es la facilidad mediante la cual la clase D hereda en ella cada uno de los
atributos y operaciones de C, como si esos atributos y operaciones hubiesen
sido definidos por la misma D. Por lo tanto, puede usar los mismos métodos y
variables publicas declaradas en C. Los componentes registrados como
"privados" (private) también se heredan, pero como no pertenecen a la
clase, se mantienen escondidos al programador y sólo pueden ser accedidos a
través de otros métodos públicos. Esto es así para mantener hegemónico el ideal
de OOP.
·Objeto: Entidad provista de un conjunto de propiedades o atributos (datos) y
de comportamiento o funcionalidad (métodos) los mismos que consecuentemente
reaccionan a eventos. Se corresponde con los objetos reales del mundo que nos
rodea, o a objetos internos del sistema (del programa). Es una instancia a una
clase.
·Método: Algoritmo asociado a un objeto (o a una clase de objetos), cuya
ejecución se desencadena tras la recepción de un "mensaje". Desde el
punto de vista del comportamiento, es lo que el objeto puede hacer. Un método
puede producir un cambio en las propiedades del objeto, o la generación de un
"evento" con un nuevo mensaje para otro objeto del sistema.
·Evento: Es un suceso en el sistema (tal como una
interacción del usuario con la máquina, o un mensaje enviado por un objeto). El
sistema maneja el evento enviando el mensaje adecuado al objeto pertinente.
También se puede definir como evento, a la reacción que puede desencadenar un
objeto, es decir la acción que genera.
·Mensaje: Una comunicación dirigida a un objeto, que le
ordena que ejecute uno de sus métodos con ciertos parámetros asociados al
evento que lo generó.
·Propiedad
o atributo: Contenedor de un
tipo de datos asociados a un objeto (o a una clase de objetos), que hace los
datos visibles desde fuera del objeto y esto se define como sus características
predeterminadas, y cuyo valor puede ser alterado por la ejecución de algún
método.
·Estado
interno: Es una variable que se declara privada, que puede
ser únicamente accedida y alterada por un método del objeto, y que se utiliza
para indicar distintas situaciones posibles para el objeto (o clase de
objetos). No es visible al programador que maneja una instancia de la clase.
·Componentes
de un objeto: Atributos, identidad, relaciones y métodos.
·Identificación de un
objeto: Un objeto se representa por medio de una tabla
o entidad que esté compuesta por sus atributos y funciones correspondientes.
El Enfoque Orientado a Objeto se basa en cuatro principios que constituyen la
base de todo desarrollo orientado a objetos. Estos principios son: la
Abstracción, el Encapsulamiento, la Modularidad y la Herencia.
Fundamento
1: Abstracción
Es el principio de ignorar aquellos aspectos de un fenómeno observado que no
son relevantes, con el objetivo de concentrarse en aquellos que si lo son. Una
abstracción denota las características esenciales de un objeto (datos y
operaciones), que lo distingue de otras clases de objetos. Decidir el conjunto
correcto de abstracciones de un determinado dominio, es el problema central del
diseño orientado a objetos.
Los mecanismos de abstracción son usados en el EOO para extraer y definir del
medio a modelar, sus características y su comportamiento. Dentro del EOO son
muy usados mecanismos de abstracción: la Generalización, la Agregación y la
clasificación.
La generalización
es el mecanismo de abstracción mediante el cual un conjunto de clases de
objetos son agrupados en una clase de nivel superior (Superclase), donde
las semejanzas de las clases constituyentes (Subclases) son enfatizadas, y
las diferencias entre ellas son ignoradas. En consecuencia, a través de la
generalización, la superclase almacena datos generales de las subclases, y
las subclases almacenan sólo datos particulares.La especialización es lo
contrario de la generalización. Por ejemplo; La clase Médico es una
especialización de la clase Persona, y a su vez, la clase Pediatra es una
especialización de la superclase Médico.
La agregación es el
mecanismo de abstracción por el cual una clase de objeto es definida a
partir de sus partes (otras clases de objetos). Mediante agregación se
puede definir por ejemplo un computador, por descomponerse en: la CPU, la
ULA, la memoria y los dispositivos periféricos. El contrario de agregación
es la descomposición.
La clasificación
consiste en la definición de una clase a partir de un conjunto de objetos
que tienen un comportamiento similar. La ejemplificación es lo contrario a
la clasificación, y corresponde a la instanciación de una clase, usando el
ejemplo de un objeto en particular.
Fundamento
2: Encapsulamiento
Es la propiedad del EOO que permite ocultar al
mundo exterior la representación interna del objeto. Esto quiere decir que el
objeto puede ser utilizado, pero los datos esenciales del mismo no son
conocidos fuera de él. La idea central del encapsulamiento es esconder los
detalles y mostrar lo relevante. Permite el ocultamiento de la información
separando el aspecto correspondiente a la especificación de la implementación;
de esta forma, distingue el "qué hacer" del "cómo hacer".
La especificación es visible al usuario, mientras que la implementación se le
oculta. El encapsulamiento en un sistema orientado a objeto se representa en
cada clase u objeto, definiendo sus atributos y métodos con los siguientes modos
de acceso:
Público (+): Atributos
o Métodos que son accesibles fuera de la clase. Pueden ser llamados por
cualquier clase, aun si no está relacionada con ella.
Privado (-):
Atributos o Métodos que solo son accesibles dentro de la implementación de
la clase.
Protegido (#): Atributos
o Métodos que son accesibles para la propia clase y sus clases hijas
(subclases).
Los atributos y los métodos que son públicos constituyen la interfaz de la
clase, es decir, lo que el mundo exterior conoce de la misma.Normalmente lo
usual es que se oculten los atributos de la clase y solo sean visibles los
métodos, incluyendo entonces algunos de consulta para ver los valores de los
atributos. El método constructor (Nuevo, New) siempre es Público.
Fundamento
3: Modularidad
Es la
propiedad que permite tener independencia entre las diferentes partes de un
sistema. La modularidad consiste en dividir un programa en módulos o partes,
que pueden ser compilados separadamente, pero que tienen conexiones con otros
módulos. En un mismo módulo se suele colocar clases y objetos que guarden una
estrecha relación. El sentido de modularidad está muy relacionado con el
ocultamiento de información.
Fundamento
4: Herencia
Es el proceso mediante el cual un objeto de una clase adquiere
propiedades definidas en otra clase que lo preceda en una jerarquía de
clasificaciones.Permite la definición de un nuevo objeto a partir de
otros, agregando las diferencias entre ellos (Programación Diferencial),
evitando repetición de código y permitiendo la reusabilidad.
Las clases heredan los datos y métodos de la superclase. Un método
heredado puede ser sustituido por uno propio si ambos tienen el mismo nombre.
La herencia puede ser simple (cada clase tiene sólo una superclase) o múltiple
(cada clase puede tener asociada varias superclases). La clase Docente y la
clase Estudiante heredan las propiedades de la clase Persona (superclase,
herencia simple). La clase Preparador (subclase) hereda propiedades de la clase
Docente y de la clase Estudiante (herencia múltiple).
Fundamento
5: Polimorfismo
Es una propiedad del EOO que permite que un método tenga múltiples
implementaciones, que se seleccionan en base al tipo objeto indicado al
solicitar la ejecución del método. El polimorfismo operacional o Sobrecarga
operacional permite aplicar operaciones con igual nombre a diferentes clases o
están relacionados en términos de inclusión. En este tipo de polimorfismo, los
métodos son interpretados en el contexto del objeto particular, ya que los
métodos con nombres comunes son implementados de diferente manera dependiendo
de cada clase.
Por ejemplo, el área de un cuadrado, rectángulo y círculo, son
calculados de manera distinta; sin embargo, en sus clases respectivas puede
existir la implementación del área bajo el nombre común Área. En la práctica y
dependiendo del objeto que llame al método, se usará el código correspondiente.
Ejemplos:
Superclase: Clase Animal
Subclases: Clases Mamífero, Ave, Pez.
Se puede definir un método Comer en cada subclase, cuya implementación cambia
de acuerdo a la clase invocada, sin embargo el nombre del método es el mismo.
Mamifero.Comer ≠ Ave.Comer ≠ Pez.Comer
Otro ejemplo de polimorfismo es el operador +. Este operador tiene dos
funciones diferentes de acuerdo al tipo de dato de los operandos a los que se
aplica. Si los dos elementos son numéricos, el operador + significa suma
algebraica de los mismos, en cambio si por lo menos uno de los operandos es un
String o Carácter, el operador es la concatenación de cadenas de caracteres.
Este
programa permite definir los distintos Tipos de Componentes que serán
utilizados para la carga de los productos de stock.A esta opción se accede desde el menú
principal Stock, luegoCostosde Produccióny dentro de éste seleccionandoTipos de Componentes.
Esta
opción permite definir los distintos tipos de componentes que utilizarán el
sistema. Para ello se deberán completar los siguientes datos:
Código de Tipo de Componente
Código numérico que identifica el tipo de componente.
Descripción
Nombre del tipo de componente.
Cantidad
Cantidad del tipo de componente.
Medida
Unidad de medida en la que se expresa la cantidad.
Limpiar
Limpia los valores ingresados en los cuadros de texto.
Observación
Permite asignar comentarios u observaciones.
Variable
Variable que se utiliza para el cálculo.
Orden
Orden en el que se realizará el cálculo interno para el tipo de
componente.
No suma
Suma para Costo
Fórmula
Expresión utilizada para el cálculo interno. Las fórmulas deben estar
previamente definidas en su mantenimiento.
Condicionante
Expresión empleada como condición para la ejecución de la fórmula
indicada.
1. El software
se desarrolla o construye; no se manufactura en el sentido clásico.
A pesar de
que existen similitudes entre el desarrollo del software y la manufactura del
hardware, las dos actividades serian diferentes en lo fundamental. En ambas la
alta calidad se alcanza por medio del buen diseño, la fase de manufactura del
hardware puede incluir problemas de calidad existentes en el software.
2.
El software no se desgasta.
El software
es inmune a los males ambientales que desgasten el hardware. Por lo tanto la
curva de tasas de fallas para el software debería tener la forma de la “curva
idealizada”. Los defectos sin descubrir causan tasas de fallas altas en las
primeras etapas de vida de un programa. Sin embargo, los errores se corrigen y
la curva se aplana: el software no se desgasta, pero si se deteriora.
3. A pesar de que la industria tiene una
tendencia hacia la construcción por componentes, la mayoría del software aun se
construye a la medida.
Un
componente de software se debe diseñar e implementar de forma que puede
utilizarse en muchos programas diferentes.
Los
componentes reutilizables modernos encapsulan tanto los datos como el proceso
se aplican a estos, lo que permite al ingeniero de software crear nuevas
aplicaciones nuevas a partir de partes reutilizables.
La gran cantidad de
organizaciones de desarrollo de software implementan metodologías para el
proceso de desarrollo. Muchas de estas organizaciones pertenecen a la industria
armamentística, que en los Estados Unidos necesita un certificado basado en su
modelo de procesos para poder obtener un contrato.
El estándar
internacional que regula el método de selección, implementación y monitoreo del
ciclo de vida del software es ISO 12207.
Durante décadas se ha perseguido la meta de
encontrar procesos reproducibles y predecibles que mejoren la productividad y
la calidad. Algunas de estas soluciones intentan sistematizar o formalizar la
aparentemente desorganizada tarea de desarrollar software. Otros aplican
técnicas de gestión de proyectos para la creación del software. Sin una gestión
del proyecto, los proyectos de software corren el riesgo de demorarse o
consumir un presupuesto mayor que el planeado. Dada la cantidad de proyectos de
software que no cumplen sus metas en términos de funcionalidad, costes o tiempo
de entrega, una gestión de proyectos efectiva es algo que amenudo falta.
Planificacion
La importante tarea a la hora de crear un producto de software es obtener los requisitos
o el analisis de los requisitos. Los clientes suelen tener una idea más bien
abstracta del resultado final, pero no sobre las funciones que debería cumplir
el software. Una vez que se hayan recopilado los requisitos del cliente, se
debe realizar un análisis del ámbito del desarrollo. Este documento se conoce
como especificación funcional.
Implementación,
pruebas y documentación.
La implementacion es
parte del proceso en el que los ingenieros de software programan el código para
el proyecto.
Las pruebas de
software son parte esencial del proceso de desarrollo del software. Esta parte
del proceso tiene la función de detectar los errores de software lo antes
posible.
La documentacion del
diseño interno del software con el objetivo de facilitar su mejora y su
mantenimiento se realiza a lo largo del proyecto. Esto puede incluir la
documentación de un API, tanto interior como exterior.
Despliegue y
mantenimiento.
El despliegue comienza
cuando el código ha sido suficientemente probado, ha sido aprobado para su
liberacion y ha sido distribuido en el entorno de producción.
Entrenamiento y
soporte para el software es de suma importancia y algo que muchos
desarrolladores de software descuidan. Los usuarios, por naturaleza, se oponen
al cambio porque conlleva una cierta inseguridad, es por ello que es
fundamental instruir de forma adecuada a los futuros usuarios del software.
El mantenimiento y
mejora del software de un software con problemas recientemente desplegado puede
requerir más tiempo que el desarrollo inicial del software. Es posible que haya
que incorporar código que no se ajusta al diseño original con el objetivo de
solucionar un problema o ampliar la funcionalidad para un cliente. Si los
costes de mantenimiento son muy elevados puede que sea oportuno rediseñar el
sistema para poder contener los costes de mantenimiento.