Carlos Fontela cfontela@fi.uba.ar Objetos y clases en POO Objetos – mensajes – responsabilidades Objetos y clases Estado, comportamiento, identidad POO vs. procedural Implementación de clases Diseño contractual TDD o diseño guiado por las pruebas 3 1c2015 lista := OrderedCollection new. lista add: ‘hola’. x := lista size. Transcript show: x. Transcript show: [ lista get:1 ]. Transcript show: [ 4 factorial squared printString ]. Transcript show: [ (8 < 9) ifTrue: [‘verdad’] ifFalse: [‘mentira’] ]. count := 0. total := 1. [count > 10] whileFalse: [count := count + 2. total := total * count]. Transcript show: total printString. 4 1c2015 Los objetos tienen responsabilidades Actuar ante la llegada de un mensaje => “comportamiento” Guardar datos internos => “estado” Objetos = entidades con comportamiento 5 1c2015 Comportamiento => todo programa trabaja con objetos que reciben mensajes y actúan Dándonos información sobre su estado x := lista size. Alterando su estado: lista add: 44. Enviando mensajes a otros objetos: Ejemplo: ordenamiento de la lista implica que cada elemento sea comparado con otro 6 1c2015 Diferencia más importante con programación estructurada No estamos solamente usando variables y tipos simples Tampoco datos estructurados Son “objetos” que saben cómo comportarse Corolarios: Los objetos deben manejar su propio comportamiento No deberíamos manipular su estado desde afuera 7 1c2015 En vez de: cuenta setSaldo: [ cuenta getSaldo + 100 ] . Deberíamos hacer: cuenta depositar: 100. => No tiene sentido un método “setSaldo” 8 1c2015 Los objetos son de determinados tipos Idea de concepto e individuo Los tipos se llaman clases Pueden ser definidos por el programador 9 1c2015 Clase Define estructura y comportamiento de los objetos Los datos internos de un objeto Los mensajes que un objeto entiende Molde de objetos Objeto Una instancia de la clase Tiene existencia en tiempo de ejecución Características Estado (visible e interno) Comportamiento Identidad 10 1c2015 La creación se hace mediante un mensaje a la clase: x := OrderedCollection new. Significado OrderedCollection es la clase del objeto al que se refiere x El objeto se crea recién cuando invoco el mensaje “new” En x queda una referencia a un objeto de tipo OrderedCollection Smalltalk es un lenguaje de tipos dinámicos Luego podría: x := Dictionary new. 11 1c2015 Las variables son referencias a objetos: lista1 := OrderedCollection new. lista1 add: ‘hola’. lista2 := lista1. “lista1” y “lista2” referencian al mismo objeto (hay una sola llamada a “new”) Si hago: lista2 := OrderedCollection new. Ahora “lista2” referencia a otro objeto Una variable que no referencia un objeto tiene el valor “nil” Puedo hacer: lista := nil. 12 1c2015 Si hago: lista1 := OrderedCollection new. lista1 add: ‘hola’. lista1 := OrderedCollection new. El objeto inicial quedó como basura Smalltalk tiene un mecanismo de recolección automática de basura 13 1c2015 No determinística Asegura que No va a faltar memoria mientras haya objetos sin referenciar No se va a liberar ningún objeto que esté siendo referenciado desde un objeto referenciado Extremadamente cómoda Y evita errores muy difíciles de encontrar y reparar 14 1c2015 Cuando un objeto no puede responder a un mensaje, reacciona enviándonos una excepción Una excepción es Un objeto lanzado desde un método Que puede ser capturado Por ejemplo, si hago: vacio := OrderedCollection new. x := vacio at: 4. Voy a obtener un error en tiempo de ejecución 15 1c2015 Pero también puedo capturar la excepción: vacio := OrderedCollection new. [x := vacio at: 4] on: Error do: [:e | Transcript show: e messageText] En este caso no se interrumpe el programa 16 1c2015 Se acceden mediante variables que las referencian Tienen estado, comportamiento e identidad Por ejemplo: Transcript show: e messageText. messageText es un mensaje enviado al objeto referenciado por e Hay muchos tipos de excepciones => luego… 17 1c2015 Estado visible Se accede mediante mensajes de consulta “getters” y “setters” “accesors” en Smalltalk Propios de la clase a la que pertenece Ejemplo: lista get:1. Comportamiento Se obtiene mediante mensajes Propios de la clase a la que pertenece Ejemplo: x factorial squared. 18 1c2015 Estado interno Almacenado en atributos, ocultos Definidos en la clase del objeto En un rato profundizamos… Identidad Única para cada objeto La mantiene el sistema (referencia), no accesible directamente en Smalltalk 19 1c2015 ¿Qué son las responsabilidades de un objeto? ¿Qué es el comportamiento de un objeto? ¿Qué es una excepción? Conjunto de objetos enviando mensajes a otros objetos Los objetos receptores reciben los mensajes y reaccionan Haciendo algo (comportamiento) Devolviendo un valor (que depende de su estado) Los mensajes pueden implicar la creación de nuevos objetos El comportamiento puede delegarse a su vez en otro objeto 22 1c2015 Manejo de la complejidad Abstracción: construir en base a componentes Lo hacen todas las industrias Economía División del trabajo Ya probado y optimizado Se adquiere y se ensambla Hay que definir interfaces: contrato No fue cierto hasta fines de los 90 23 1c2015 Mecanismos para la organización del conocimiento Típicamente humanos Clasificación (individuo-especie) Agrupación (entre individuos) Generalización (entre especies) 24 1c2015 Relación individuo - especie Lassie – perro / Juan Pérez – ser humano 25 1c2015 Relación objeto - clase 26 1c2015 Relación entre individuos Auto - rueda 27 1c2015 Relación entre objetos 28 1c2015 Relación entre especies Lápiz – herramienta de escritura Animal – ser vivo Al revés: especialización 29 1c2015 Relación entre clases 30 1c2015 Todo es un objeto Incluso las clases y las constantes Todo objeto es instancia de una clase Toda clase tiene una clase madre La madre por defecto es Object (en Pharo, ProtoObject) Todo ocurre debido al envío de un mensaje El mensaje a invocar se busca siguiendo la jerarquía de herencia Si no existe hasta Object, hay un “doesNotUnderstand” 31 1c2015 Ambas modularizan, separan en partes Procedural modulariza por funciones (lo que hace el sistema = dominio de la solución) ¿verbos? POO modulariza por entidades (sobre qué trabaja el sistema = dominio del problema) ¿sustantivos? ¿En POO no hay funciones? Son los “métodos” dentro de las clases Pero especifican más bien “comportamiento” de entidades Son secundarias 32 1c2015 Entidades se convierten en clases = tipos con comportamiento ¿Cómo? => Implementando clases Ahí vamos… 33 1c2015 ¿Para qué sirve la OO? ¿Qué diferencia hay entre clasificación/instanciación y especialización/herencia? ¿Qué diferencia hay entre POO y programación procedural? Clase = tipo definido por el programador No “abstractos”: en POO es otra cosa Se definen estructura y operaciones Ocultamiento: cliente necesita conocer interfaz No necesita conocer aspectos internos (implementación) Riesgos de la falta de ocultamiento Impedir evolución Violación de restricciones 36 1c2015 Mensajes => Métodos u operaciones Varios caminos de diseño Modelo contractual Desarrollo guiado por las pruebas Son complementarios y no excluyentes 37 1c2015 Una clase es provista por un proveedor a un cliente en base a un “contrato” [ Bertrand Meyer: “diseño por contrato” ] 38 1c2015 El contrato se evidencia por Firmas de métodos Precondiciones de métodos Postcondiciones de métodos Incluyendo resultados obtenidos Incluyendo casos de excepción Invariantes de la clase Restricciones que siempre cumplen todas las instancias Postcondiciones de todos los métodos 39 1c2015 Métodos (uso): cuenta depositar: monto cuenta extraer: monto cuenta getSaldo cuenta getTitular cuenta getNumero Para crear e inicializar: CuentaBancaria new inicializarConNumero: numero conTitular: titular 40 1c2015 cuenta := CuentaBancaria new inicializarConNumero: 1234 conTitular: ‘Carlos’. cuenta depositar: 1000. cuenta extraer: 250. Transcript show: cuenta getSaldo printString. Transcript show: cuenta getTitular. Transcript show: cuenta getNumero printString. 41 1c2015 Son variables internas de cada instancia, que sirven para mantener el estado de los objetos Para una cuenta bancaria, se nos ocurre: numero titular saldo Podría haber más, que descubramos más adelante 42 1c2015 Son las restricciones en los valores de los atributos, válidas para todas las instancias Son postcondiciones de todos los métodos Invariantes de CuentaBancaria: saldo >= 0 titular <> nil titular <> ‘’ numero > 0 43 1c2015 cuenta depositar: monto Precondición: monto > 0 CuentaBancaria new inicializarConNumero: numero conTitular: titular Precondición 1: titular no debe valer nil ni referenciar una cadena vacía Precondición 2: numero > 0 Tarea: definir precondiciones para los otros métodos 44 1c2015 CuentaBancaria new inicializarConNumero: numero conTitular: titular Postcondición 1: se creó un objeto de la clase CuentaBancaria, con el número y el titular indicados Postcondición 2 (alternativa): si titular es nil o referencia una cadena vacía, se arroja una excepción de tipo Error cuenta depositar: monto Postcondición 1: el saldo de la cuenta aumentó en el valor del monto Postcondición 2 (alternativa): si monto < 0 , se arroja una excepción de tipo Error 45 1c2015 Precondiciones Si no se cumplen, lanzamos una excepción Postcondiciones Mejor, prueba unitaria Enseguida… Invariantes: postcondiciones permanentes 46 1c2015 Las excepciones son objetos Se crean y se lanzan hacia el módulo invocante Sintaxis: ClaseException new signal. ClaseException new signal: ‘un texto’. Ya vimos cómo capturarlas El texto lo obtenemos con el método messageText Veremos formalmente excepciones más adelante 47 1c2015 Test-Driven Development = Test-First + automatización + refactorización Test-First: Escribir código de pruebas antes del código productivo Automatización: Las pruebas deben expresarse como código, que pueda indicar si todo sale bien de manera simple y directa El conjunto de pruebas debe poder ir creciendo Las pruebas deben correrse por cada cambio Refactorización: veremos luego 48 1c2015 Ayudarse por los dos caminos Modelo contractual TDD Pruebas automatizadas sirven para TDD Invariantes y postcondiciones del modelo contractual 49 1c2015 50 1c2015 ¿Para qué me sirve definir las precondiciones? ¿Y las postcondiciones? ¿Por qué escribir las pruebas antes? Object subclass: #CuentaBancaria instanceVariableNames: ‘numero titular saldo’ classVariableNames: ‘’ poolDictionaries: ‘’ category: ‘Cuentas’ 53 1c2015 CuentaBancaria >> getSaldo ^saldo CuentaBancaria >> getTitular ^titular CuentaBancaria >> getNumero ^numero 54 1c2015 CuentaBancaria >> depositar: monto ( monto < 0 ) ifTrue: [ Error new signal. ] . saldo := saldo + monto CuentaBancaria >> extraer: monto ( monto > saldo ) ifTrue: [Error new signal. ] . saldo := saldo - monto 55 1c2015 Objeto “self” depositar: monto ( monto < 0 ) ifTrue: [ Error new signal. ] . self saldo := self saldo + monto El mensaje se envía al “receptor” cuenta depositar: 2000. 56 “self referencia al receptor” 1c2015 CuentaBancaria >> inicializarConNumero: num conTitular: tit ( (num isNil) | (tit isNil) | (tit = '') | (num <= 0) ) ifTrue: [Error new signal ] . numero := num. titular := tit. saldo := 0 57 1c2015 ≠ No todos los atributos tienen “getters” y “setters” Sólo los necesarios Hay propiedades que no corresponden a atributos unString size => ¿tiene que haber un atributo? numeroComplejo getModulo => propiedad calculable Noción: ( propiedad = “atributo conceptual” ) => Los atributos conceptuales deberían estar implementados al menos con “getters” 58 1c2015 Se trabaja con objetos y mensajes Las clases son tipos y los objetos sus instancias Las clases tienen una jerarquía Objetos se crean en tiempo de ejecución Las variables son referencias a objetos A los objetos sin uso los elimina el sistema POO modulariza en base a las entidades del dominio del problema Clases se implementan en base a un modelo cliente-proveedor Las clases son tipos definidos por el programador Implementación con dos modelos: contratos y TDD 59 1c2015 Apunte de Pruebas (campus) “Unit Testing Guidelines”, http://geosoft.no/development/unittesting. html “8 Principles of Better Unit Testing”, http://esj.com/Articles/2012/09/24/BetterUnit-Testing.aspx?p=1 60 1c2015 Object-Oriented Software Construction, Bertrand Meyer Está en la biblioteca Especialmente capítulos 7, 8, 11 y 12 Test Driven Development: By Example, Kent Beck No está en la Web ni en biblioteca Code Complete, Steve McConnell, Capítulo 6: “Working Classes” No está en la Web ni en biblioteca Implementation Patterns, Kent Beck, Capítulos 3 y 4: “A Theory of Programming” y “Motivation” No está en la Web ni en biblioteca Orientación a objetos, diseño y programación, Carlos Fontela 2008, capítulo 3 “Programación basada en objetos” y capítulo 4 “Construcción de clases” 61 1c2015 Delegación, herencia, polimorfismo Calidad de código y buenas prácticas de desarrollo Temas varios de POO 62 1c2015