La Programación Orientada a Objetos

Anuncio
La Programación Orientada a Objetos:
Introducción
Prof. Franco Guidi Polanco
Escuela de Ingeniería Industrial
Pontificia Universidad Católica de Valparaíso, Chile
fguidi@ucv.cl
De Problemas a Soluciones
“Half the battle is knowing what problem to
solve”
Data Structures and Algorithms
(A.A. Aho, J.E. Hopcroft & J.D. Ullman)
De http://pbfcomics.com/
Franco Guidi Polanco (PUCV-EII)
02-06-14
2
De Problemas a Soluciones
v Análisis: entender el problema y sus
requerimientos
v Diseño: determinar un modelo que nos permita
resolver el problema.
v Implementación: determinar la forma de
representar el modelo que describe el problema (y
la solución):
Franco Guidi Polanco (PUCV-EII)
02-06-14
3
Los Requerimientos
v Los requerimientos:
§  son incompletos
§  usualmente están equivocados
§  son engañosos (y los usuarios
también)
§  no cuentan la historia completa
v Por lo tanto, los requerimientos
siempre cambian
Franco Guidi Polanco (PUCV-EII)
02-06-14
4
El Desarrollo de Proyectos
que propuso el
1 Lo
comité de proyecto
que se especificó
2 Lo
como requerimiento
que desarrollaron
4 Lo
los programadores
5
Franco Guidi Polanco (PUCV-EII)
Lo que se instaló
al usuario
02-06-14
3
Lo que diseñó
el analista
que necesitaba
6 Lo
el usuario
5
Metodologías y Modelos
La Ingeniería de Software provee:
v Metodologías de desarrollo.
§  Desarrollo en cascada
§  Proceso Unificado
§  etc.
v Modelos para soportar el desarrollo
Se estudiarán
en detalle
en curso de
Modelamiento
de Sistemas
§  Especificación estructurada (DFDs, MER, etc.)
§  UML
§  etc.
v Lenguajes para la implementación
§  C, C++
§  Java
§  etc.
Franco Guidi Polanco (PUCV-EII)
02-06-14
6
Antes de la Programación
Orientada a Objetos
Divide et Impera: Descomposición Funcional
v “Divide et Impera”
v Descomposición en funciones:
el analista descompone el
problema en una serie de pasos
que permiten resolverlo.
v Los pasos son refinados
sucesivamente, hasta llegar a
funciones elementales.
v ¿Costo?
Franco Guidi Polanco (PUCV-EII)
02-06-14
8
Descomposición Funcional
...
ingresarDatos(datos);
calcularMedia(datos, media);
calcularDE(datos, de);
mostrarResultados(media, de);
...
procedimiento ingresarDatos(datos:arreglo)
{
i=0;
mientras i <= 10 hacer
{
leer datos[i]
i = i + 1;
}
}
procedimiento calcularMedia(datos:arreglo, media:float)
{
i=0;
suma = 0;
mientras i <= 10 hacer
{
suma = suma + datos[i]
i = i + 1;
}
media = suma / 10
}
...
Franco Guidi Polanco (PUCV-EII)
02-06-14
9
La Encapsulación como Agrupación de Funciones
v La encapsulación permite la agrupación de ideas
relacionadas en una unidad, la que posteriormente puede
ser referida por un solo nombre.
v El concepto surgió en la década del ’40 con la invención de
la subrutina: los programadores se dieron cuenta de que
un mismo patrón de instrucciones se podía repetir muchas
veces en un programa.
Franco Guidi Polanco (PUCV-EII)
02-06-14
10
Descomposición Funcional: Reutilización de
Código
Programa original
.
.
i=1
mientras i<=10
{
si a[i]=10
i=i+1
}
.
.
i=1
mientras i<=10
{
si b[i]=10
i=i+1
}
.
.
i=1
mientras i<=10
{
si c[i]=10
i=i+1
}
.
Programa con subrutina
.
.
HacerCeros(a)
.
.
.
HacerCeros(b)
.
.
.
HacerCeros(c)
.
.
.
hacer
entonces a[i]=0
hacer
entonces b[i]=0
Procedimiento
HacerCeros(x:arreglo)
i=1
mientras i<=10 hacer
{
si x[i]=10 entonces x[i]=0
i=i+1
hacer
entonces c[i]=0
Franco Guidi Polanco (PUCV-EII)
}
02-06-14
11
Ventajas de Funciones o Subrutinas
v Ahorro de memoria de computador (código fuente de
programas más corto).
v Código fuente más “entendible”: una subrutina agrupa un
conjunto de instrucciones en un “concepto” que una
persona puede considerar y manejar como una sola idea
(en el ejemplo, HacerCeros).
Franco Guidi Polanco (PUCV-EII)
02-06-14
12
Lenguajes de Programación
v Antes de la POO los lenguajes de programación
eran procedimentales.
NOTA:
NO LO INTENTE
Aproximación:
Imagine
programar en
Java, usando sólo
métodos
estáticos, con
instancias de
clases que no
tengan métodos.
Franco Guidi Polanco (PUCV-EII)
02-06-14
13
Reutilización antes de la POO: Tipos Abstractos de
Datos
ADT
(Abstract
Data Type)
Tipo de dato
(No provisto por
el lenguaje de
programación)
+
Operaciones
Por separado, pero asociadas.
Franco Guidi Polanco (PUCV-EII)
02-06-14
14
La Programación
Orientada a Objetos
La Programación Orientada a Objetos (POO)
v El paradigma de la Orientación a Objetos es sucesor de la
descomposición funcional
v Se centra en el concepto de Objeto:
Objeto = Datos + Métodos
(Definición tradicional)
v Los objetos:
§ 
§ 
§ 
§ 
son responsables de si mismos.
“saben” de qué tipo son.
conocen su propio estado (datos).
contienen el código que les permite actuar.
Franco Guidi Polanco (PUCV-EII)
02-06-14
16
POO versus Descomposición Funcional
v El modelo de programación funcional mantenía
centralizadas las responsabilidades:
§  Una cena en la cual un garzón pide a cada comensal lo que se
servirá, y luego les trae los platos solicitados.
v El modelo de programación OO
provee delegación de
responsabilidades:
§  Una cena en la cual a los comensales
se les indica la distribución del buffet.
Ellos se sirven a su propio gusto.
Franco Guidi Polanco (PUCV-EII)
02-06-14
17
¿Cómo identificar Objetos?
v En problemas pequeños una técnica sencilla se
basa en la identificación de sustantivos y verbos :
§  Los sustantivos pueden ser objetos
§  Los verbos pueden ser métodos
Franco Guidi Polanco (PUCV-EII)
02-06-14
18
Objetos
v Una buena forma de concebir un objeto es pensar en él
como una entidad con responsabilidades. Las
responsabilidades determinan el comportamiento del
objeto.
v Debe existir una forma para comunicar a un objeto qué
debe hacer.
v Esta comunicación se logra por medio del conjunto de
métodos que un objeto ofrece para que otros puedan
invocar.
v El conjunto de estos métodos se denomina interfaz pública
del objeto.
Franco Guidi Polanco (PUCV-EII)
02-06-14
19
Visión de Objetos
v Martin Fowler identifica tres perspectivas para describir los
objetos:
§  Nivel conceptual: un objeto es un conjunto de responsabilidades.
§  Nivel especificación: un objeto es un
conjunto de métodos
(comportamientos), que pueden ser
invocados por otros objetos o por si
mismos.
§  Nivel implementación: un objeto es
código y datos, e interacciones
computaconales entre ellos.
Martin Fowler
Franco Guidi Polanco (PUCV-EII)
02-06-14
20
Perspectivas para Describir Sistemas OO
Nivel Conceptual
Análisis
Nivel Especificación
Codificación (Lenguajes de
programación e.g. Java, C++, C#, etc.)
Franco Guidi Polanco (PUCV-EII)
02-06-14
Diseño (Lenguajes de
modelamiento e.g. UML)
Nivel Implementación
21
Perspectivas para Describir Sistemas OO: Ejemplo
v Sistema de docencia, que mantiene datos de
alumnos y registra sus inscripciones en cursos.
Nivel Conceptual
Nivel Especificación
Nivel Implementación
Franco Guidi Polanco (PUCV-EII)
02-06-14
22
Ejemplo: Nivel Conceptual
Responsabilidades:
v Alumno:
§  Mantener datos de un alumno (rol y nombre). Debe validar el rol
del alumno.
v Curso:
§  Mantener datos de un curso (nombre)
§  Mantener la lista de los alumnos que se inscriben en el curso,
verificando que estos no se repitan al momento de agregarlos.
§  Retornar alumnos, buscándolos por rol del alumno.
Franco Guidi Polanco (PUCV-EII)
02-06-14
23
Ejemplo: Nivel Especificación
v Clase Alumno:
§ 
§ 
§ 
§ 
public
public
public
public
setRol(numero: int, verificador: int)
setNombre( nombre: String)
getRol(): String
getNombre(): String
v Clase Curso:
§  public setNombre(nombre: String)
§  public addAlumno(alumno:Alumno):boolean
§  public getAlumno(rol: String):Alumno
Franco Guidi Polanco (PUCV-EII)
02-06-14
24
Ejemplo: Nivel Implementación
public class Alumno{
private String rol, nombre;
public void setRol(int numero, int verificador){
if( sumaDigitos(numero) == verificador )
this.rol = rol +”-”+verificador;
}
public void setNombre(Sting nombre){
this.nombre = nombre;
public class Curso{
}
private String nombre;
public String getRol(){
private Vector alumnos;
return rol;
}
public void setNombre(String nombre){
public String getNombre(){
this.nombre = nombre;
return nombre;
}
}
public boolean addAlumno(Alumno alumno){
private int sumaDigitos(int numero){if( getAlumno( alumno.getRol() )== null ){
...
alumnos.add( alumno );
}
return true;
}
}
return false;
}
public Alumno getAlumno(String rol){
...
}
}
Franco Guidi Polanco (PUCV-EII)
02-06-14
25
¿Es necesario tomar precauciones, si el análisis
inicial está bien hecho?
!
“All systems change during their life cycles. This
must be borne in mind when developing systems
expected to last longer than the first version.”
Ivar Jacobson.
“Object Oriented Software Engineering a Use Case
Driven Approach”,
Addison Wesley, 1992,
Franco Guidi Polanco (PUCV-EII)
02-06-14
26
POO y Encapsulación
v Tradicionalmente se asocia a “ocultamiento de
datos” (estado) de un objeto.
v Sin embargo, se refiere además a ocultamiento de:
§ 
§ 
§ 
§ 
implementación de métodos
tipo, clases derivadas
detalles de diseño
reglas de instanciación
Franco Guidi Polanco (PUCV-EII)
02-06-14
27
Encapsulación como Ocultamiento de Datos
v Ejemplo:
public class Punto{
private int coordA, coordB;
public void setXY(int x, int y){
coordA = x;
coordB = y;
}
public int getX(){
return coordA;
}
public int getY(){
return coordB;
}
}
Franco Guidi Polanco (PUCV-EII)
02-06-14
El “contexto” de la
clase Punto no
tiene visibilidad de
cómo ésta
almacena sus
datos.
Consecuencia:
Puede modificarse
el conjunto de
variables de la
clase Punto, sin
que esto afecte su
contexto.
28
Encapsulación en la Implementación de Métodos
v Ejemplo:
public class Angle{
private double angle;
public void setAngle(double a){
angle = a;
}
public double getSin(){
// Cálculo mediante series de
// Taylor
...
}
}
Franco Guidi Polanco (PUCV-EII)
02-06-14
El “contexto” de la
clase Angle no
tiene visibilidad
del algoritmo de
cálculo del seno
del ángulo
Consecuencia:
Puede modificarse
la implementación
del método sin
afectar al contexto.
29
Encapsulación del Tipo
v Ejemplo
El “contexto” de
las figuras no tiene
visibilidad de cuál
de ellas está
exactamente
utilizando.
Figura
Contexto
Rombo
+dibujar()
+rellenar()
+ocultar()
Franco Guidi Polanco (PUCV-EII)
+dibujar()
+rellenar()
+ocultar()
Cuadrado
Círculo
+dibujar()
+rellenar()
+ocultar()
+dibujar()
+rellenar()
+ocultar()
02-06-14
Consecuencia:
El contexto puede
implementar una
lógica común para
utilizar cualquiera
de las figuras (o
cualquier nueva
subclase).
30
Encapsulación de Detalles de Diseño
v Ejemplo
Banco
Contexto
+recibirCliente()
+atenderSiguiente()
Cola
Cajero
+agregar()
+sacar()
+atender()
Franco Guidi Polanco (PUCV-EII)
02-06-14
El “contexto” de la
clase Banco no
tiene visibilidad de
las clases que
soportan sus
operaciones.
Consecuencia:
Puede modificarse
la “arquitectura”
del Banco sin
afectar el contexto.
31
Encapsulación de Reglas de Instanciación
v Ejemplo
public class LeonardoDaVinci{
private static LeonardoDaVinci instance;
private LeonardoDaVinci(){}
public static LeonardoDaVinci getLeonardo(){
if( instance == null )
instance = new LeonardoDaVinci();
}
return instance;
}
public String writeName(){
return “odranoeL”;
}
...
El “contexto” de la
clase no tiene
visibilidad de la
lógica de
instanciación de
objetos
LeonardoDaVinci.
¿Consecuencias?
}
Franco Guidi Polanco (PUCV-EII)
02-06-14
32
Encapsulación y Diseño
v Ante especificaciones variables y sistemas
que evolucionan...
... ¿podemos lograr un buen
diseño?
v Sí, encontrando qué cosas pueden variar en
el diseño y
Franco Guidi Polanco (PUCV-EII)
encapsulándolas
02-06-14
?
33
Encapsulación y Diseño
v Muchos patrones de diseño (soluciones a
problemas comunes de diseño) utilizan la
encapsulación de tipos para crear capas de
separación entre objetos.
v La separación se crea asignando
referencias a clases abstractas o
interfaces.
v Esto permite modificar alguno de los
“lados” de la capa de separación, sin
afectar a la otra.
Franco Guidi Polanco (PUCV-EII)
02-06-14
34
El principio “abierto-cerrado”
v  En el libro Object Oriented Software
Construction de 1988, Bertrand Meyer
propuso el “Open-Closed Principle” (OCP)
v “Las entidades de software (clases,
módulos, funciones, etc.) deberían
estar abiertos para extensión y
cerrados para modificaciones.”
Bertrand Meyer
v  En otras palabras, el software debe ser diseñado para soportar la adición
de nuevas funcionalidades, sin que esto comporte modificaciones en
aquellas existentes.
v  No es siempre posible seguir completamente este principio.
Franco Guidi Polanco (PUCV-EII)
02-06-14
35
El principio “abierto-cerrado”
v Síntomas de un mal diseño (cuando no se cumple este
principio):
§  Al modificar un módulo de software, los cambios se propagan a
otros módulos.
v Por lo tanto:
§  Se deben diseñar módulos que nunca cambiarán.
§  Si los requerimientos cambian, se debe extender el comportamiento
de tales módulos, agregando nuevo código, no modificando aquél
existente.
v La base de este principio está en los conceptos de:
§  Abstracción
§  Polimorfismo
Franco Guidi Polanco (PUCV-EII)
02-06-14
36
El principio “abierto-cerrado”
v Los módulos desarrollados bajo este principio
tienen dos características:
§  Están “abiertos para extensión”: el comportamiento del
módulo puede ser extendido, a fin de lograr un nuevo
comportamiento, impusto por nuevos requerimientos de
la misma o de otra aplicación.
§  Están “cerrados para modificaciones”: el código fuente
de un módulo existente no debe ser alterado.
Franco Guidi Polanco (PUCV-EII)
02-06-14
37
El principio “abierto-cerrado”
v Aquí no se respeta el principio:
Personaje
public void pinta(Personaje p){
if( seRequierePintar ){
if( p instance of Héroe)
pintaHeroe((Héroe) p);
else if(p instance of Enemigo)
pintaEnemigo((Enemigo) p);
}
…
}
Héroe
Enemigo
Dibujador
pinta(Personaje p)
pintaHéroe(Héroe p)
pintaEnemigo(Enemigo p)
v ¿Qué pasa si es necesario agregar un nuevo tipo de
personaje (ej. un Mago)?
Franco Guidi Polanco (PUCV-EII)
02-06-14
38
El principio “abierto-cerrado”
v Aquí si es respetado el principio:
Personaje
Dibujador
pinta()
pinta(Personaje p)
Héroe
public void pinta(Personaje p){
if( seRequierePintar )
p.pinta();
…
}
pinta()
Enemigo
pinta()
v Es posible agregar nuevos objetos a pintar (agregando una
subclase de Personaje), sin modificar el código ya existente
Franco Guidi Polanco (PUCV-EII)
02-06-14
39
Consecuencias del principio “abierto–cerrado”
v “Regla” de diseño: Establecer visibilidad “privada”
a variables de instancia.
v Los conceptos de abstracción y polimorfismo del
principio abierto-cerrado están asociados a la
especificación de jerarquías de herencia.
v ¿Hay algo que decir respecto de las jerarquías de
herencia? (Veamos el principio de sustitución de
Liskov)
Franco Guidi Polanco (PUCV-EII)
02-06-14
40
El principio de sustitución de Liskov
v  Barbara Liskov, en “Data Abstraction and Hierarchy”, SIGPLAN Notices,
23, 5 (May 1988) estableció lo que hoy se conoce como el “Liskov
Substitution Principle” (LSP):
v “Las funciones que utilizan punteros
o referencias a clases de base, deben
ser capaces de utilizar subclases de
éstas, sin necesidad de conocerlas”
v  Esto es:
§  Cualquier propiedad que sea cierta para una
súperclase, debe serlo también para sus
subclases.
§  Un cliente de una clase debe funcionar
correctamente con cualquier subclase de ésta
última.
Franco Guidi Polanco (PUCV-EII)
02-06-14
Barbara Liskov
41
El principio de sustitución de Liskov
v Ejemplo:
Programador
Vehículo
Terrestre
Aéreo
Bus
Tren
v La clase Programador debe funcionar correctamente con la
clase Vehículo, o con cualquier subclase de ella
Franco Guidi Polanco (PUCV-EII)
02-06-14
42
El principio de sustitución de Liskov
v El LSP se violaría ante la presencia de situaciones como la
siguiente:
Programador
Vehículo
programa(vehiculo v)
Terrestre
Aéreo
public void programa(Vehículo v){
if( v instance of Bus ){
throw new InvalidException();
else
programaAutomático(v);
}
}
Franco Guidi Polanco (PUCV-EII)
02-06-14
Bus
Tren
43
El principio de “inversión de dependencia”
v  El “Dependency Inversion Principle” (DIP) establece cómo implementar
los objetivos enunciados por el OCP y el LSP.
v “Los módulos de alto nivel no deberían depender de los
módulos de bajo nivel. Ambos deberían depender de
abstracciones.
v Las abstracciones no deberían depender de detalles. Los
detalles deberían depender de abstracciones.”
Kandinsky
Franco Guidi Polanco (PUCV-EII)
Klee
02-06-14
44
El principio de “inversión de dependencia”
v Propone la estategia de depender de abstracciones
(interfaces, funciones abstractas y/o clases
abstractas), en vez de depender de funciones y
clases concretas.
Franco Guidi Polanco (PUCV-EII)
02-06-14
45
El principio de “inversión de dependencia”
v Aquí no se cumple el DIP:
public void copiar(LectorTeclado l, EscritorDisco e){
while( !l.eof){
byte b = l.leer();
e.escribir( b );
}
}
Copiador
LectorTeclado
Franco Guidi Polanco (PUCV-EII)
EscritorDisco
02-06-14
v  La lógica general del
copiador tiene
“cableada” la acción
sobre un LectorTeclado
y un EscritorDisco
v  ¿Posibilidad de reutilizar
el código del Copiador?
46
El principio de “inversión de dependencia”
v Aquí sí se cumple:
public void copiar(Lector l, Escritor e){
while( !l.eof){
byte b = l.leer();
e.escribir( b );
}
}
Copiador
Lector
LectorTeclado
Franco Guidi Polanco (PUCV-EII)
Escritor
EscritorDisco
02-06-14
47
Después de la OO... ¿qué?
v Los objetos ofrecen una interfaz pública por medio de la cual
otros objetos invocan sus comportamientos.
v Los objetos son inherentemente reactivos: su
comportamiento es gatillado por la acción (externa) de otro
objeto.
v Nuevo paradigma: agentes de software.
v Los agentes de software son unidades de software con
objetivos y responsabilidades.
v Los agentes de software exhiben comportamiento proactivo:
un agente actúa por cuenta propia sobre el ambiente y sobre
otros agentes para alcanzar sus objetivos.
Franco Guidi Polanco (PUCV-EII)
02-06-14
48
Descargar