Title: Tcnicas avanzadas de programacin Fundamentos de programacin orientada a objetos
1Técnicas avanzadas de programaciónFundamentos
de programación orientada a objetos
2Índice
- Introducción
- Generalización o abstracción
- Encapsulamiento
- Modularidad
- Jerarquía
3Introducción
4Qué es un método?
- No basta tener ingenio, lo principal es
aplicarlo bien (Descartes, Discurso del método) - Objetivos
- Principios (axiomas)
- Reglas de formación (notación).
- Reglas de transformación (lo que se debe hacer
para cumplir los principios). - Modelo de proceso (metarreglas que indican el
orden de actividades)
Primero, no admitir como verdadera cosa alguna
que no supiese con evidencia .... No comprender
en mis juicios nada más que lo que se presentase
tan clara y distintamente, que no hubiese ninguna
ocasión de ponerlo en duda Dividir cada una de
las dificultades que examine en cuantas partes
fuese posible y en cuantas requiere su mejor
solución Conducir ordenadamente mis
pensamientos empezando por los objetos más
simples y más fáciles de conocer, para ir
ascendiendo poco a poco, gradualmente, hasta el
conocimiento de los más compuestos Hacer en
todo unos recuentos tan integrales y unas
revisiones tan generales que llegase a estar
seguro de no omitir nada (Descartes, Discurso
del método)
5Cambio de mentalidad
Procedimiento 1
Datos
Paradigma tradicional
Procedimiento 2
Objeto
Objeto
Métodos
Métodos
Paradigma orientado a objetos
Datos
Datos
Objeto
Métodos
Datos
6Objetivos de la ingeniería (I)
- Corrección el software realiza la especificación
de requisitos - Robustez capacidad de reaccionar ante
condiciones excepcionales - Extensible (facilidad de mantenimiento) poder
cambiarlo en función de modificaciones de los
requisitos. Para ello, es muy importante usar
principios de calidad en el diseño modularidad,
encapsulamiento, etc. - Reutilizable poder ser utilizado en otras
aplicaciones
7Objetivos de la ingeniería (II)
- Facilidad de uso tanto si el usuario es un
consumidor final (se habla de interfaces
amistosos), como si es otro programador. En este
último sentido una buena especificación de
servicios, API o Application Programing
Interface, ahorra costes de mantenimiento y
reutilización. - Portabilidad usable en diversos entornos.
- Integrable (compatibilidad) posibilidad de
compartir datos con otras aplicaciones
(integración de datos o integración por medio de
conexión) - Verificable facilidad para poner a prueba la
aplicación
8Principios y reglas de la ingeniería OO
- Para cumplir los objetivos tenemos que aplicar
principios. Cada principio se realiza mediante la
aplicación de reglas - 1. Generalización o abstracción. Reglas
- Mantener la coherencia de clases
- Mantener la coherencia de métodos
- Generalizar los tipos de datos y métodos
- Amplia cobertura del servicio
- Minimizar la información global
- Gestión de excepciones
- Precaución con la optimización
- 2. Encapsulamiento. Reglas
- Encapsular las clases
- Ocultar estructuras y algoritmos internos
- 3. Modularidad. Reglas
- Minimizar el acoplamiento.
- Comprensibilidad y trazabilidad.
- Arquitectura en capas.
- 4. Jerarquía. Reglas
- Definir orden de herencia sin abusar de la
profundidad - Definir orden de composición
9Principios y objetivos
Generalización Centrarnos en lo genérico y
eliminar u ocultar detalles (el cómo)
Menor coste
Encapsulamiento Utilizamos los servicios de un
objeto a través de su interfaz externo
CORRECCION ROBUSTEZ EXTENSIBILIDAD REUSABILIDAD
Modularidad Descomponemos de forma lógica
Jerarquía Ordenamos por niveles de herencia y
composición
Mayor calidad
10Generalización o abstracción
11Generalización mantener la coherencia (I)
- Toda clase debe aspirar a ser una representación
genérica de una entidad del dominio del problema
o del dominio de la aplicación. Genérica o
abstracta no significa que hace de todo, sino que
cumple su papel de forma genérica. Las siguientes
reglas nos permiten hacer software lo más
genérico posible - Mantener la coherencia o cohesión de la clase
una clase tiene un rol (papel o función) o un
conjunto de roles lógicamente relacionados. Si
tiene varios roles que no están relacionados
resulta incoherente. Buenos ejemplos - class ventana_configuración ....
- class control_acceso_usuario ....
- Pero no
- class calculador_e_interfaz_ de calculo ...
- class de_todo_un_poco ...
12Generalización mantener la coherencia (II)
- Mantener la coherencia de los métodos tratemos
de hacer un componente de software que haga una
cosa, para que la haga bien. Una parábola - Un pato se acerca a un delfín y le dice Observa
mi superioridad, soy capaz de volar andar y
nadar, a lo que el delfín responde Bien, pero
tu nadas lentamente, vuelas de manera pesada y
andas con torpeza, mientras que yo nado muy
bien. - La moraleja es que el software es más correcto,
robusto y reutilizable si se parece al delfín de
la parábola, no al pato. - En el siguiente ejemplo el método hace tres
cosas pide por teclado el radio del circulo,
calcula el área y la muestra - void funcion_incoherente() throws IOException
- float radio, area
- String cadena_teclado
- BufferedReader entrada new
BufferedReader(new InputStreamReader(System.in)) - System.out.println( "Teclee el radio del
círculo") - cadena_teclado entrada.readLine()
- radio Float.parseFloat( cadena_teclado )
- area radio radio 3.1416F
- System.out.println( "El área es " area)
-
- Cómo se haría de manera coherente o cohesiva?
13Generalización generalizar datos y métodos
- Generalizar tipos de datos y métodos la clase
debe cumplir su rol en una enorme variedad de
contextos. Se trata de generalizar respecto a los
métodos y respecto a los tipos de datos - Respecto a los métodos, los parámetros pueden ser
valores nulos, extremos o situados fuera de los
limites. Aún así, el comportamiento (método) de
la clase debe ser correcto y robusto. - Respecto a los tipos de datos. Por ejemplo, una
clase que ordena un vector de figuras en función
de su extensión o de su perímetro puede ser - class organizador_figuras ....
- Un ejemplo de escasa generalización sería el
siguiente - class ordenador_perímetro_círculos ...
- class ordenador_extensión_rectángulo ...
- Para generalizar nos apoyamos en la gestión de
excepciones, la herencia y el polimorfismo. - Cuál de estas dos clases representa de forma
genérica (abstracta) su posición?
class FIGURA int pos_x int pos_y .....
class FIGURA Point Posicion .....
14Generalización amplia cobertura del servicio
- Amplia cobertura del servicio. Cuando decimos que
una clase tiene un rol estamos diciendo que
proporciona un servicio. Trataremos de hacer que
el servicio sea de amplio espectro, no
limitándose al contexto presente. Esta es una
situación muy común, por ejemplo nuestros equipos
de música tienen numerosas funciones, aunque la
mayoría de los usuarios sólo usan una parte de
ellas. Sería absurdo que los creadores de estos
equipos los hubieran diseñado para usuarios que
fueran como ellos. - Lo mismo ocurre con las clases, darán un
servicio por medio de numerosas funciones, aunque
lo normal es que la mayoría de los usuarios no
las usen todas. - Una de las formas de implementar una cobertura
amplia es usar la sobrecarga de métodos - void imprimir( String cadena ) ....
- void imprimir( Figura fig ) ....
- void imprimir( Imagen img ) ....
15Generalización minimizar información global
- Minimizar la información global. Tratemos de
minimizar las referencias externas. El uso de
objetos globales impone restricciones a la
reutilización del software. Resulta más adecuado
manejar argumentos. En este pequeño ejemplo el
método usa float base, que se le pasa como
argumento - public float calcular_cuadrado( float base )
- return (base base)
-
- Una ventaja de esta versión es que resulta
evidente que el interfaz del método, public float
calcular_cuadrado( float base ), usa un tipo
float para el cálculo. La dependencia es
evidente. En este otro ejemplo el método usa
datos globales (concretamente son atributos
static de la clase calculador). Pero este uso no
aparece en el interfaz del método - public void calcular_cuadrado( )
- calculador.resultado calculador.base
calculador. base -
- Esta forma de programar hace que la dependencia
del método respecto a los datos no sea explicita.
16Generalización gestión de excepciones
- Una excepción es una situación anómala que
normalmente interrumpe el flujo lógico del
programa. Programar con generalidad también
implica hacer aplicaciones que superen estas
situaciones. En el siguiente ejemplo protegemos a
la aplicación de - Un error en la entrada por teclado.
- Un error de conversión de texto a tipo numérico.
- Gracias a este tratamiento de excepciones la
aplicación no se paraliza, sino que reacciona
ante el problema - try
- / Creo el objeto 'entrada', es un lector
de entradas por teclado / - BufferedReader entrada new
BufferedReader(new InputStreamReader(System.in)) - System.out.print("Escriba el radio ")
- c entrada.readLine()
// Leo un String de la
entrada de teclado - radio Double.parseDouble(c)
// Convierto el String en double - System.out.print("El área es " 3.1416
radio radio) - catch ( NumberFormatException e )
- System.out.print( "Error en el formato del
número" ) - catch ( IOException e )
- System.out.print( "Error de entrada" )
-
17Generalización optimizar con precaución
- Como norma elemental conviene optimizar una vez
que funciona el programa. - Con frecuencia los programadores invierten
demasiado esfuerzo intentando optimizar partes
del código que se usan con poca frecuencia. Se
trata de comparar los costes con los posibles (y
normalmente escasos) beneficios. - La optimización generalmente amenaza la
comprensibilidad, extensibilidad y reusabilidad
del software. - Como norma general es más importante hacer
software legible y sensato que software
optimizado e ilegible. - Ejemplo de código JDBC optimizado y poco legible
- ResultSet rs DriverManager.getConnection(
"jdbcmysql//localhost/prueba","root",
"palabra). createStatement().executeQuery(
sentencia )
18Encapsulamiento
19Encapsulamiento introducción (I)
- El principio de encapsulamiento es una forma
moderna de denominar al tradicional principio de
ocultamiento de la información. El principio nos
indica que debemos hacer que los detalles de la
clase estén ocultos para el exterior (también se
denomina implementación encapsulada). - Es un principio de la ingeniería en general. Si
estamos diseñando un equipo de música no parece
adecuado que permitamos al usuario operar sobre
las placas para cambiar el volumen o el tono. Los
botones del equipo son el interfaz del sistema,
la implementación queda encapsulada (oculta).
20Encapsulamiento introducción (II)
- Visión externa (interfaz) definición del mensaje
- Visión interna (implementación) operaciones
concretas
class CUBO .... Rotar( GRADO g)
CUBORotar( GRADO g) .... (C)
21Encapsulamiento introducción (III)
- Algunas definiciones
- Consiste en separar los aspectos externos del
objeto, a los cuales puede acceder otro objeto,
de los detalles internos de implementación, que
quedan ocultos para los demás (RUMBAUGH, 1991) - El encapsulamiento es el proceso de almacenar
en un mismo compartimento los elementos de una
abstracción que constituyen su estructura y
comportamiento sirve para separar el interfaz
contractual de una abstracción y su
implementación (BOOCH, 1994)
22Encapsulamiento de clases
- Siguiendo la metáfora del equipo de música
debemos diferenciar en nuestras clases lo que es
público de lo que es privado. - Una aplicación general de este principio implica
que los atributos serán privados y sólo se puede
acceder a ellos desde los métodos públicos de la
clase. - Ventaja desde el código de la clase controlamos
el acceso a los atributos. En caso de fallo o
modificación del código, el programador comprueba
los métodos de la clase que modifican ese dato y
no tiene que revisar todo el código de los otros
archivos. Además evitamos accesos indeseados que
puedan modificarlos de forma no coherente con
otros datos. Los métodos públicos son el
intermediario (interfaz) entre los datos y los
otros objetos
Objeto
Los métodos públicos de la clase son el interfaz
de la clase
Método 1
Datos
Mensajes
Método 2
23Encapsulamiento ocultar estructuras y algoritmos
internos
- Las estructuras de datos que utiliza una clase
internamente (por ejemplo un vector o un árbol)
no deben ser accesibles para otras clases. - Por la misma razón los algoritmos internos deben
quedar ocultos. Por ejemplo, la mayor parte de
las modernas librerías de software tienen métodos
para ordenar listas. Desde fuera el programador
solo debe conocer el interfaz del método y lo que
hace. No accedemos al interior del algoritmo - / Llamo al método static sort() de la clase
Collections, le - paso como primer arg la lista y como
segundo arg un objeto comparador / - Collections.sort( lista, new comparador() )
24Modularidad
25Modularidad introducción (I)
- Un diseño modular se basa en la conocida
estrategia de divide y vencerás. Descomponer de
forma lógica y robusta el dominio de la
aplicación. - Para conseguir la modularidad también debemos
aplicar las reglas de coherencia de métodos y
clases que vimos con el principio de generalidad,
es decir, hacer que nuestros componentes sean
especialistas.
Fondo Inversión
Analizador Fondos
obtener datos análisis
estudiar alternativas
Recomendación Fondos de Inversión
datos para presentación
Interfaz Usuario
26Modularidad introducción (II)
- La modularidad facilita la reusabilidad y reduce
costes, pero usada con prudencia
27Modularidad introducción (III)
- Hay diversas condiciones que permiten llegar a la
modularidad - Descomposición funcional. Ver cada módulo como un
especialista (aplicación de la regla de la
coherencia). - Bajo acoplamiento. Además de ser especialistas
tienen la mayor autonomía posible. - Comprensibles para un observador externo. Esto es
obvio, pero no es tan común como parece. El
objetivo es que cada módulo sea comprensible de
forma independiente (cómo mucho obligar a un
somero repaso de otros módulos), para ello los
módulos deben obedecer a la lógica del dominio,
ser legibles y estar bien documentados. - De 1 y 3 se deduce la condición de la
trazabilidad.
28Modularidad bajo acoplamiento (I)
- Cuando hablamos de un diseño modular hablamos de
bajo acoplamiento o poca dependencia entre
módulos. La regla del bajo acoplamiento implica - Interfaces pequeños que los métodos públicos que
intercambian información con otros módulos sean - El menor número posible.
- Pequeños. Pocos argumentos. Si un método tiene
muchos parámetros, probablemente hay revisar el
diseño o encapsular los parámetros en una clase. - En el siguiente ejemplo tenemos dos versiones de
un método. El segundo método no sólo tiene menos
argumentos, además resulta más comprensible
fabrica.solicitar_pedido( Fec, Hora, CodComer,
Cantidad, PVP, ModoEntrega )
fabrica.solicitar_pedido( pedido nuevo_pedido )
29Modularidad bajo acoplamiento (II)
- Regla de la continuidad modular debemos diseñar
y programas de tal forma que pequeños cambios en
un módulo producen a lo sumo pequeños cambios en
otro. Evidentemente, esto facilita la
extensibilidad y minimiza los costes de
mantenimiento. - Regla de la protección modular los errores en un
módulo afectan como mucho a módulos adyacentes. - Regla de la comunicación explicita la
comunicación entre módulos es clara. Normalmente
por medio de interfaces con pocos parámetros y
sin usar información global (que hace que la
interacción quede oculta). - Encapsular la implementación. También en los
módulos hay que diferenciar lo público de lo
privado. Un cambio en la parte privada no debería
afectar al interfaz del módulo.
30Modularidad comprensibilidad
- Antes dijimos que si si los módulos no obedecen a
la lógica del dominio, no son legibles o no están
bien documentados, entonces la descomposición es
inútil y no permite la reusabilidad. - Cuando se dice que la descomposición de los
módulos obedece a la lógica del dominio, se
quiere decir que la mayoría de cada uno de
módulos debe ser una representación natural de
entidades o relaciones del dominio (por ejemplo
cuenta, beneficiario, oficina, control de riesgo,
etc.). Decimos la mayoría ya que habrá módulos
que no modelizan entes del dominio (pertenecen al
dominio de la aplicación exclusivamente interfaz
gráfico, sentencia SQL, etc.).
31Modularidad trazabilidad
- Se debe representar la continuidad entre los
conceptos del proceso de desarrollo. - La regla de la trazabilidad indica que cada
conjunto lógico de entidades y relaciones del
dominio tiene su correlato modular. Esto facilita
la extensibilidad y la reusabilidad.
- Los métodos de Diseño orientado a facetas,
orientados a aspectos o temas hacen énfasis en
mejorar la trazabilidad de requisitos.
32Modularidad arquitectura en capas
- De todo lo anterior (coherencia, bajo
acoplamiento, etc.) se deduce que gran parte de
nuestras aplicaciones se descomponen en módulos
que reflejan su especialización funcional - Interfaz con el usuario.
- Implementación. Se aplican cálculos y algoritmos
específicos al dominio. - Control. También implica conocimiento específico
del dominio. Componentes que especifican el orden
de las tareas y las condiciones de disparo
(Si-entonces). Comprueban estados y errores. No
tienen cálculos o algoritmos complejos. Por
ejemplo, reglas de negocio del tipo Si el
solicitante es cliente, entonces producir pedido
si no, solicitar registro de nuevo cliente. - Almacenamiento y conectividad. Módulos
responsables de la interacción con la base de
datos y otras aplicaciones. -
33Modularidad arquitectura en tres capas
- En la práctica, sobre todo en aplicaciones que no
son muy grandes, se suelen reunir en un módulo
las clases de implementación y de control. - Un ejemplo es la arquitectura en tres capas, tan
usual en aplicaciones Web - Presentación
- Reglas de negocio
- Acceso a datos (almacenamiento y conectividad)
34Jerarquía
35Jerarquía introducción
- Las dos formas más usuales de jerarquía de clases
son - Jerarquía de tipos o herencia
- Jerarquía de partes o agregación
- Composición
- Contenedor
- La jerarquía por herencia supone un orden de
abstracción/concreción, donde una excesiva
cantidad de niveles (aprox. más de cuatro) hace
difícil el mantenimiento. - La jerarquía de agregación. También el exceso de
niveles produce confusión.
1
Persona
Coche
Motor
Alumno
Profesor
36Jerarquía herencia y redefinición
- La herencia es una
- Forma de abstracción. Primero nos centramos en el
vehículo y después en sus subtipos (coche,
autobus, etc.) - Forma de modularizar.
- Permite la redefinición de métodos. En la
redefinición se mantiene el interfaz del método y
cambia la implementación esto es un ejemplo
simple de polimorfismo (un interfaz y múltiples
implementaciones). Tipos - Redefinición completa no uso el servicio base
- Redefinición parcial uso el servicio de la clase
base
CLASE EMPLEADO (redefinición completa) public
void mostrar() System.out.print( nombre ", "
) System.out.println( salario_bruto)
CLASE PROFESOR (redefinición parcial) public void
mostrar() super.mostrar() System.out.println(
Horas lectivas " horas_lectivas)
37Jerarquía herencia y polimorfismo
- Un nombre puede denotar instancias de muchas
clases diferentes, siempre que estas clases
hereden de una clase común. - Emplear el mismo interfaz con implementaciones
diferentes
empleado personal new empleadox personal0
new administrativo(...) personal1 new
profesor(...) personal0.mostrar() personal1.
mostrar()
38Jerarquía herencia y ligadura dinámica
- Un ejemplo de polimorfismo en el que la llamada
(ligadura) al método se resuelve en tiempo de
ejecución.
- Imaginemos un vector de figuras
- figura vector new figurax
- Damos la opción al usuario de crear libremente el
tipo de figura que quiera y el programa la
almacena en el vector - vectory new círculo()
- ...
- vectory new rectángulo()
- A qué método llama? vectorz.dibujar()
- Gracias a la ligadura dinámica el programa llama
al objeto adecuado.
39Jerarquía herencia y clases abstractas
- En nuestro ejemplo de las figuras el programador
no ha incluido la implementación del método
obt_area() para la clase figura. Es lógico,
podemos calcular el área de los rectángulos o de
los círculos, pero no podemos calcular el área de
un concepto tan abstracto como el de figura. - Esto no es raro en una clase madre, en muchas
ocasiones las clases más elevadas en una
jerarquía de herencia especifican un interfaz
(declaración de función), sin definir una
implementación. En nuestro ejemplo no se puede
calcular el área de una figura. - Denominamos clases abstractas a aquellas que
tienen o heredan un método abstracto, es decir,
métodos declarados pero no implementados. No
puede haber instancias de las clases abstractas. - En nuestro ejemplo la clase madre puede ser
- abstract class figura
- protected punto origen
- figura( punto origen)
- this.origen origen
-
- figura(int x, int y)
- origen new punto(x,y)
-
- abstract double obt_area()
40Clases abstractas en diferentes lenguajes
41Jerarquía agregación
- Encontrar clases agregadoras es
- Forma de abstracción. Primero nos centramos en el
Coche y después en sus componentes (motor,
etc.). - Forma de modularizar.
- Tipos
- Composición. La parte (Plan estratégico)
desaparece cuando desaparece el todo (Empresa).
Otro ejemplo casa/cocina. - Contenedor. El componente (Ratón) no desaparece
con el contenedor (Computadora). Otro ejemplo
cesta/manzanas.
42Ejemplos de agregación
- Un ejemplo de composición con la librería Swing
para hacer applets (clase JApplet). La parte
(botones y etiquetas) desaparecen cuando
desaparece el todo (applet) - public class mi_japplet extends JApplet
- / Creo los componentes /
- JLabel etiqueta_titulo new JLabel()
- JButton boton1 new JButton()
- JButton boton2 new JButton()
- Un ejemplo de contenedor. El panel de contenidos
que tiene el JApplet se llama contenedor. Debemos
añadir (add) los botones y etiquetas a este
panel para que aparezcan por pantalla - private void jbInit() throws Exception
- Container contenedor getContentPane()
- contenedor.setLayout( new FlowLayout() )
- / Añadir componentes al contenedor /
- contenedor.add(etiqueta_titulo)
- contenedor.add(boton1)
- contenedor.add(boton2)