“half the battle is knowing what problem to solve” la

12
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 [email protected] Actualización: 02 de agosto de 2007 02/08/2007 Franco Guidi Polanco (PUCV-EII) 2 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) 02/08/2007 Franco Guidi Polanco (PUCV-EII) 3 De Problemas a Soluciones Análisis: entender el problema y sus requerimientos Diseño: determinar un modelo que nos permita resolver el problema. Implementación: determinar la forma de representar el modelo que describe el problema (y la solución): 02/08/2007 Franco Guidi Polanco (PUCV-EII) 4 Los Requerimientos Los requerimientos: son incompletos usualmente están equivocados son engañosos (y los usuarios también) no cuentan la historia completa Por lo tanto, los requerimientos siempre cambian

Upload: others

Post on 16-Oct-2021

5 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: “Half the battle is knowing what problem to solve” La

La Programación Orientada a Objetos:Introducción

Prof. Franco Guidi PolancoEscuela de Ingeniería Industrial

Pontificia Universidad Católica de Valparaíso, [email protected]

Actualización: 02 de agosto de 2007

02/08/2007Franco Guidi Polanco (PUCV-EII) 2

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/

02/08/2007Franco Guidi Polanco (PUCV-EII) 3

De Problemas a Soluciones

Análisis: entender el problema y sus requerimientos

Diseño: determinar un modelo que nos permita resolver el problema.

Implementación: determinar la forma de representar el modelo que describe el problema (y la solución):

02/08/2007Franco Guidi Polanco (PUCV-EII) 4

Los Requerimientos

Los requerimientos:son incompletosusualmente están equivocadosson engañosos (y los usuarios también) no cuentan la historia completa

Por lo tanto, los requerimientos siempre cambian

Page 2: “Half the battle is knowing what problem to solve” La

02/08/2007Franco Guidi Polanco (PUCV-EII) 5

El Desarrollo de Proyectos

Lo que propuso el comité de proyecto

Lo que se especificócomo requerimiento

Lo que diseñó el analista

Lo que desarrollaronlos programadores

Lo que se instalóal usuario

Lo que necesitabael usuario

1 2 3

4 5 6

02/08/2007Franco Guidi Polanco (PUCV-EII) 6

Metodologías y Modelos

La Ingeniería de Software provee:

Metodologías de desarrollo.Desarrollo en cascadaProceso Unificadoetc.

Modelos para soportar el desarrolloEspecificación estructurada (DFDs, MER, etc.)UMLetc.

Lenguajes para la implementaciónC, C++Javaetc.

Se estudiaránen detalle

en curso de Modelamiento

de Sistemas

The Beatles

Cecilia Serrano(Miss Chile 1979)

Teleserie de Cara al Mañana(1982)

Grease

Antes de la Programación Orientada a Objetos

1a Teletón (1978) 02/08/2007Franco Guidi Polanco (PUCV-EII) 8

Divide et Impera: Descomposición Funcional

“Divide et Impera”

Descomposición en funciones: el analista descompone el problema en una serie de pasos que permiten resolverlo.

Los pasos son refinados sucesivamente, hasta llegar a funciones elementales.

¿Costo?

Page 3: “Half the battle is knowing what problem to solve” La

02/08/2007Franco Guidi Polanco (PUCV-EII) 9

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}...

02/08/2007Franco Guidi Polanco (PUCV-EII) 10

La Encapsulación como Agrupación de Funciones

La encapsulación permite la agrupación de ideas relacionadas en una unidad, la que posteriormente puede ser referida por un solo nombre.

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.

02/08/2007Franco Guidi Polanco (PUCV-EII) 11

Descomposición Funcional: Reutilización de Código

..i=1mientras i<=10 hacer{ si a[i]=10 entonces a[i]=0i=i+1}..i=1mientras i<=10 hacer{ si b[i]=10 entonces b[i]=0i=i+1}..i=1mientras i<=10 hacer{ si c[i]=10 entonces c[i]=0i=i+1}.

..HacerCeros(a)...HacerCeros(b)...HacerCeros(c)...Procedimiento HacerCeros(x:arreglo)i=1mientras i<=10 hacer{ si x[i]=10 entonces x[i]=0i=i+1}

Programa con subrutinaPrograma original

02/08/2007Franco Guidi Polanco (PUCV-EII) 12

Ventajas de Funciones o Subrutinas

Ahorro de memoria de computador (código fuente de programas más corto).

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).

Page 4: “Half the battle is knowing what problem to solve” La

02/08/2007Franco Guidi Polanco (PUCV-EII) 13

Lenguajes de Programación

Antes de la POO los lenguajes de programación eran procedimentales.

Aproximación:

Imagine programar en Java, usando sólo métodos estáticos, con instancias de clases que no tengan métodos.

NOTA:NO LO INTENTE

02/08/2007Franco Guidi Polanco (PUCV-EII) 14

ADT(AbstractData Type)

Tipo de dato(No provisto por

el lenguaje deprogramación)

+ Operaciones

Por separado, pero asociadas.

Reutilización antes de la POO: Tipos Abstractos de Datos

La Programación Orientada a Objetos

Derrumbe Muro Berlín (09/09/1989)

Cecilia BoloccoMiss Universo (1987)

Tragedia Transbordador Challenger(1986)

Pulp FictionQ. Tarantino (1994)

Tim Berners-Lee(CERN-1989)

02/08/2007Franco Guidi Polanco (PUCV-EII) 16

La Programación Orientada a Objetos (POO)

El paradigma de la Orientación a Objetos es sucesor de la descomposición funcional

Se centra en el concepto de Objeto:

Objeto = Datos + Métodos

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.

(Definición tradicional)

Page 5: “Half the battle is knowing what problem to solve” La

02/08/2007Franco Guidi Polanco (PUCV-EII) 17

POO versus Descomposición Funcional

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.

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.

02/08/2007Franco Guidi Polanco (PUCV-EII) 18

¿Cómo identificar Objetos?

En problemas pequeños una técnica sencilla se basa en la identificación de sustantivos y verbos :

Los sustantivos pueden ser objetosLos verbos pueden ser métodos

02/08/2007Franco Guidi Polanco (PUCV-EII) 19

Objetos

Una buena forma de concebir un objeto es pensar en él como una entidad con responsabilidades. Las responsabilidades determinan el comportamiento del objeto.Debe existir una forma para comunicar a un objeto qué debe hacer.Esta comunicación se logra por medio del conjunto de métodos que un objeto ofrece para que otros puedan invocar. El conjunto de estos métodos se denomina interfaz públicadel objeto.

02/08/2007Franco Guidi Polanco (PUCV-EII) 20

Visión de Objetos

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

Page 6: “Half the battle is knowing what problem to solve” La

02/08/2007Franco Guidi Polanco (PUCV-EII) 21

Perspectivas para Describir Sistemas OO

Nivel Conceptual

Nivel Especificación

Nivel Implementación

Análisis

Diseño (Lenguajes de modelamiento e.g. UML)

Codificación (Lenguajes de programación e.g. Java, C++, C#, etc.)

02/08/2007Franco Guidi Polanco (PUCV-EII) 22

Perspectivas para Describir Sistemas OO: Ejemplo

Sistema de docencia, que mantiene datos de alumnos y registra sus inscripciones en cursos.

Nivel Conceptual

Nivel Especificación

Nivel Implementación

02/08/2007Franco Guidi Polanco (PUCV-EII) 23

Ejemplo: Nivel Conceptual

Responsabilidades:

Alumno:Mantener datos de un alumno (rol y nombre). Debe validar el rol del alumno.

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.

02/08/2007Franco Guidi Polanco (PUCV-EII) 24

Ejemplo: Nivel Especificación

Clase Alumno:

public setRol(numero: int, verificador: int)public setNombre( nombre: String)public getRol(): Stringpublic getNombre(): String

Clase Curso:

public setNombre(nombre: String)public addAlumno(alumno:Alumno):booleanpublic getAlumno(rol: String):Alumno

Page 7: “Half the battle is knowing what problem to solve” La

02/08/2007Franco Guidi Polanco (PUCV-EII) 25

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 String getRol(){return rol;

}public String getNombre(){return nombre;

}private int sumaDigitos(int numero){...

}}

public class Curso{private String nombre;private Vector alumnos;public void setNombre(String nombre){this.nombre = nombre;

}public boolean addAlumno(Alumno alumno){if( getAlumno( alumno.getRol() )== null ){

alumnos.add( alumno );return true;

}return false;

}public Alumno getAlumno(String rol){

...}

}02/08/2007Franco Guidi Polanco (PUCV-EII) 26

¿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,

02/08/2007Franco Guidi Polanco (PUCV-EII) 27

POO y Encapsulación

Tradicionalmente se asocia a “ocultamiento de datos” (estado) de un objeto.

Sin embargo, se refiere además a ocultamiento de:

implementación de métodostipo, clases derivadasdetalles de diseñoreglas de instanciación

02/08/2007Franco Guidi Polanco (PUCV-EII) 28

Encapsulación como Ocultamiento de Datos

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;}

}

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.

Page 8: “Half the battle is knowing what problem to solve” La

02/08/2007Franco Guidi Polanco (PUCV-EII) 29

Encapsulación en la Implementación de Métodos

Ejemplo:

public class Angle{private double angle;public void setAngle(double a){

angle = a;}public double getSin(){

// Cálculo mediante series de// Taylor...

}}

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.

02/08/2007Franco Guidi Polanco (PUCV-EII) 30

Encapsulación del Tipo

Ejemplo

Figura

+dibujar()+rellenar()+ocultar()

Rombo

+dibujar()+rellenar()+ocultar()

Cuadrado

+dibujar()+rellenar()+ocultar()

Círculo

+dibujar()+rellenar()+ocultar()

Contexto

El “contexto” de las figuras no tiene visibilidad de cuál de ellas está exactamente utilizando.

Consecuencia:El contexto puede implementar una lógica común para utilizar cualquiera de las figuras (o cualquier nueva subclase).

02/08/2007Franco Guidi Polanco (PUCV-EII) 31

Encapsulación de Detalles de Diseño

Ejemplo

Banco

+recibirCliente()+atenderSiguiente()

Cola

+agregar()+sacar()

Cajero

+atender()

Contexto

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.

02/08/2007Franco Guidi Polanco (PUCV-EII) 32

Encapsulación de Reglas de Instanciación

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?

Ejemplo

Page 9: “Half the battle is knowing what problem to solve” La

02/08/2007Franco Guidi Polanco (PUCV-EII) 33

Encapsulación y Diseño

Ante especificaciones variables y sistemas que evolucionan...

... ¿podemos lograr un buen diseño?

Sí, encontrando qué cosas pueden variar en

el diseño y encapsulándolas

02/08/2007Franco Guidi Polanco (PUCV-EII) 34

Encapsulación y Diseño

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.

La separación se crea asignando referencias a clases abstractas o interfaces.

Esto permite modificar alguno de los “lados” de la capa de separación, sin afectar a la otra.

02/08/2007Franco Guidi Polanco (PUCV-EII) 35

El principio “abierto-cerrado”

En el libro Object Oriented Software Construction de 1988, Bertrand Meyerpropuso el “Open-Closed Principle” (OCP)

“Las entidades de software (clases, módulos, funciones, etc.) deberían estar abiertos para extensión y cerrados para modificaciones.”

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.

No es siempre posible seguir completamente este principio.

Bertrand Meyer

02/08/2007Franco Guidi Polanco (PUCV-EII) 36

El principio “abierto-cerrado”

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.

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.

La base de este principio está en los conceptos de:AbstracciónPolimorfismo

Page 10: “Half the battle is knowing what problem to solve” La

02/08/2007Franco Guidi Polanco (PUCV-EII) 37

El principio “abierto-cerrado”

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.

02/08/2007Franco Guidi Polanco (PUCV-EII) 38

El principio “abierto-cerrado”

Aquí no se respeta el principio:

Dibujador

Héroe Enemigo

pinta(Personaje p)pintaHéroe(Héroe p)pintaEnemigo(Enemigo p)

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);

}…

}

¿Qué pasa si es necesario agregar un nuevo tipo de personaje (ej. un Mago)?

02/08/2007Franco Guidi Polanco (PUCV-EII) 39

El principio “abierto-cerrado”

Aquí si es respetado el principio:

Dibujador

Héroe Enemigo

pinta(Personaje p)

Personaje

public void pinta(Personaje p){if( seRequierePintar )

p.pinta();…

}

pinta() pinta()

Es posible agregar nuevos objetos a pintar (agregando una subclase de Personaje), sin modificar el código ya existente

pinta()

02/08/2007Franco Guidi Polanco (PUCV-EII) 40

Consecuencias del principio “abierto–cerrado”

“Regla” de diseño: Establecer visibilidad “privada” a variables de instancia.

Los conceptos de abstracción y polimorfismo del principio abierto-cerrado están asociados a la especificación de jerarquías de herencia.

¿Hay algo que decir respecto de las jerarquías de herencia? (Veamos el principio de sustitución de Liskov)

Page 11: “Half the battle is knowing what problem to solve” La

02/08/2007Franco Guidi Polanco (PUCV-EII) 41

El principio de sustitución de Liskov

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):

“Las funciones que utilizan punteros o referencias a clases de base, deben ser capaces de utilizar subclases de éstas, sin necesidad de conocerlas”

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. Barbara Liskov

02/08/2007Franco Guidi Polanco (PUCV-EII) 42

El principio de sustitución de Liskov

Ejemplo:

Programador

Aéreo Terrestre

Vehículo

Bus Tren

La clase Programador debe funcionar correctamente con la clase Vehículo, o con cualquier subclase de ella

02/08/2007Franco Guidi Polanco (PUCV-EII) 43

El principio de sustitución de Liskov

El LSP se violaría ante la presencia de situaciones como la siguiente:

Programador

Aéreo Terrestre

Vehículo

Bus Tren

public void programa(Vehículo v){if( v instance of Bus ){

throw new InvalidException();else

programaAutomático(v);}

}

programa(vehiculo v)

02/08/2007Franco Guidi Polanco (PUCV-EII) 44

El principio de “inversión de dependencia”

El “Dependency Inversion Principle” (DIP) establece cómo implementar los objetivos enunciados por el OCP y el LSP.

“Los módulos de alto nivel no deberían depender de los módulos de bajo nivel. Ambos deberían depender de abstracciones.Las abstracciones no deberían depender de detalles. Los detalles deberían depender de abstracciones.”

KleeKandinsky

Page 12: “Half the battle is knowing what problem to solve” La

02/08/2007Franco Guidi Polanco (PUCV-EII) 45

El principio de “inversión de dependencia”

Propone la estategia de depender de abstracciones (interfaces, funciones abstractas y/o clases abstractas), en vez de depender de funciones y clases concretas.

02/08/2007Franco Guidi Polanco (PUCV-EII) 46

El principio de “inversión de dependencia”

Aquí no se cumple el DIP:

Copiador

LectorTeclado EscritorDisco

public void copiar(LectorTeclado l, EscritorDisco e){while( !l.eof){

byte b = l.leer();e.escribir( b );

}}

La lógica general del copiador tiene “cableada” la acción sobre un LectorTeclado y un EscritorDisco ¿Posibilidad de reutilizar el código del Copiador?

02/08/2007Franco Guidi Polanco (PUCV-EII) 47

El principio de “inversión de dependencia”

Aquí sí se cumple:

Lector Escritor

Copiador

LectorTeclado EscritorDisco

public void copiar(Lector l, Escritor e){while( !l.eof){

byte b = l.leer();e.escribir( b );

}}

02/08/2007Franco Guidi Polanco (PUCV-EII) 48

Después de la OO... ¿qué?

Los objetos ofrecen una interfaz pública por medio de la cual otros objetos invocan sus comportamientos.

Los objetos son inherentemente reactivos: su comportamiento es gatillado por la acción (externa) de otro objeto.

Nuevo paradigma: agentes de software.

Los agentes de software son unidades de software con objetivos y responsabilidades.

Los agentes de software exhiben comportamientoproactivo: un agente actúa por cuenta propia sobre el ambiente y sobre otros agentes para alcanzar sus objetivos.