Principios de Diseño Orientado a Objetos€¦ · los servicios de los objetos deben cumplir con...

27
Principios de Diseño Orientado a Objetos

Transcript of Principios de Diseño Orientado a Objetos€¦ · los servicios de los objetos deben cumplir con...

Principios de Diseño Orientado

a Objetos

PRINCIPIOS DE DISEÑO DE CLASES• PRINCIPIO ABIERTO-CERRADO (OCP): Un

módulo debe ser abierto para extensión pero cerrado para modificación.

• Wikipidia: La noción de que las “entidades de software … deben estar abiertas para su extensión, pero cerradas para su modificación”.

• Principio Abierto-Cerrado: Abierto a extensiones Cerrado a modificaciones de código existente debido a extensiones

PRINCIPIOS DE DISEÑO DE CLASES• El Principio Open/Closed (Open/Closed Principle, OCP) fue acuñado por

el Dr. Bertrand Meyer en su libro "Object Oriented Software Construction" y básicamente lo que nos dice este principio es que "las entidades de software (clases, módulos, funciones…) deben estar abiertas para extenderse, pero cerradas para modificación".

• Las clases que cumplen con OCP tienen dos características:– Son abiertas para la extensión; es decir, que la lógica o el comportamiento

de esas clases puede ser extendida en nuevas clases, usando herencia.– Son cerradas para la modificación, y por tanto el código fuente de dichas

clases debería permanecer inalterado.

• ¿Qué significa esto?: Que una entidad tiene que ser extendida sin necesidad de ser modificada internamente. Por ejemplo, deberíamos poder ampliar la funcionalidad de una clase vía herencia sin necesidad de tener que modificar su comportamiento interno.

Principio abierto/cerrado

Las entidades software deben estar abiertas para su

extensión, pero cerradas para su modificaciónBertran Meyer

Diseño cerrado/cerrado

• Finalidad– Sistema funcionando (cerrado), pero

ampliable (abierto)

– Conseguir cambios añadiendo nuevo código sin afectar al resto de elementos del diseño

Clase A Clase B

• Ambigüedad– La dependencia “uno a uno” se

transforma en una dependencia de “uno a muchos”

• Ventajas• Evita que cambios en un módulo

afecten a otros módulos

Diseño abierto/cerrado

Principio abierto/cerrado

Análisis

Diseño cerrado/cerrado

Clase A Clase B

Clase A Clase Abstracta B

Clase B1 Clase B2

Principio de responsabilidad única

Principio de Única Responsabilidad (Single responsibility principle)

La noción de que un objeto solo debería tener una única responsabilidad

• El Principio de responsabilidad única (Single Responsability Principle - SRP) fue acuñado por Robert C. Martin en un artículo del mismo título y popularizado a través de su conocido libro [patrones Gof]

• "Cada objeto en el sistema deben tener una simple responsabilidad, y todos los servicios de los objetos deben cumplir con esa simple responsabilidad"

• En términos prácticos, este principio establece que:

• "Una clase debe tener una y solo una única causa por la cual puede ser modificada.“

• "Cada clase debe ser responsable de realizar una actividad del sistema

Principio de responsabilidad única

Principio de Única Responsabilidad (Single responsibility principle)

La noción de que un objeto solo debería tener una única responsabilidad

Diseño con una sola clase (incorrecto)

Cliente P

Cliente Q

Clase X

Elementos asociados a la responsabilidad A

Elementos asociados a la responsabilidad B

• Finalidad– Evitar que el cambio de una

responsabilidad en una clase pueda provocar fallos en las demás responsabilidades de la clase

– Evitar que los clientes de una clase carguen con elementos que no utilizan

Diseño con una sola clase

(no adecuado)

Diseño con dos clases

Cliente P

Cliente Q

Clase X

Elementos asociados a la responsabilidad A

Elementos asociados a la responsabilidad B

Cliente P

Cliente Q

Clase XA

Elementos asociados a la responsabilidad A

Clase XB

Elementos asociados a la responsabilidad B

Principio de responsabilidad única

Principio de responsabilidad única

Justificación del principio según R. Martin

Principio de cohesión (DeMarco y Pages-Jones)Cohesión: Relación funcional de los elementos de un módulo

Cohesión = responsabilidad única (Martin)

Principio de responsabilidad única (Martin)Responsabilidad: razón de cambio

Cohesión: Fuerzas que provocan cambios en una clase o módulo

Principio de responsabilidad única

¿ cohesión = razón de cambio ?

• Creencia

– Alta cohesión y bajo acoplamiento conlleva facilidad de modificación

• Problema (incluye lo que estaba escrito antes)

– Infinitud de definiciones de cohesión y acoplamiento

• Consecuencia

– No hay justificación para asociar cohesión con fuerzas de cambio

Diseño con una clase

• Realidad del principio:– División salomónica puntual

• Ambigüedad:– Aumenta entre los elementos de

responsabilidades separadas

– Aumenta entre la clase cliente hacia las clases separadas que no utilizan

– Disminuye entre la clase cliente hacia las clases separadas que utilizan

Cliente P

Cliente Q

Clase XResponsabilidad A

Responsabilidad B

Diseño con dos clases

Cliente P

Cliente Q

Clase XAResponsabilidad A

Clase XBResponsabilidad B

Principio de responsabilidad única

Análisis

Principio de inversión de dependencias

Los módulos de alto nivel no deben depender de los

módulos de bajo nivel. Ambos deben depender de las

abstracciones

Las abstracciones no deben depender de los detalles.

Los detalles deben depender de las abstracciones.Robert C. Martin

Principio de inversión de dependencias

• Básicamente lo que nos dice este principio es que– Las clases de alto nivel no deberían depender de las clases de bajo nivel.

Ambas deberían depender de las abstracciones.

– Las abstracciones no deberían depender de los detalles. Los detalles

deberían depender de las abstracciones.

• El Principio de Inversión de dependencia ayuda a

mantener nuestro código totalmente desacoplado,

asegurándonos que dependemos de abstracciones en vez

de implementaciones concretas. La Inyección de

dependencias es una implementación de este principio,

aunque ambos términos se usan de forma intercambiable.

Principio de inversión de dependencias

• Finalidad:– Conseguir que los cambios

en los módulos de bajo nivel no afecten a los módulos de alto nivel

– Facilitar la reutilización de los módulos de alto nivel

Diseño tradicional

Nivel Política

Nivel Mecanismo

Nivel Utilidad

Diseño tradicional

Nivel Política

Nivel Mecanismo

Nivel Utilidad

Principio de inversión de dependencias

Diseño con inversión de dependencias

Nivel Política

Nivel Mecanismo

Nivel Utilidad

InterfazPolítica

InterfazMecanismo

Política

Mecanismo

Utilidad

Principio de separación de la interfaz

Los clientes no deben ser forzados a depender de

interfaces que no utilizan Robert C. Martin

• Básicamente lo que nos quiere decir este principio es que las clases que implementen una interfaz o una clase abstracta no deberían estar obligadas a tener partes que no van a utilizar.

• Una interfaz es un contrato que debe cumplir una clase, y tales contratos deben ser específicos, no genéricos; esto nos proporcionará una forma más ágil de definir una única responsabilidad por interfaz - de otra forma, violaríamos además el Principio de Responsabilidad Única

Principio de separación de la interfaz

Los clientes no deben ser forzados a depender de

interfaces que no utilizan Robert C. Martin

• Otras definiciones de este principio son:

• La implementación de las abstracciones debe estar en la medida de lo posible en interfaces y no en clases.

• Los clientes no deben estar obligados a implementar y/o a depender de una interface que luego no usarán.

• Es mejor tener interfaces específicos para cada cliente que uno de propósito general, o lo que es lo mismo, no deberíamos obligar a los clientes a depender de métodos que no utilizan.

Diseño con una interfaz

(incorrecto)

Diseño con dos interfaces

Cliente C

Cliente D

Interfaz Z

Métodos que utiliza el cliente C

Métodos que utiliza el cliente D

Cliente C

Cliente D

interfaz ZC

Métodos que utiliza el cliente C

Interfaz ZD

Métodos que utiliza el cliente D

Principio de separación de la interfaz

Diseño con una interfaz

• Extensión del principio de responsabilidad única

• Ambigüedad– Aumenta entre los métodos de

interfaces separadas

– Aumenta entre la clase cliente hacia los métodos de las interfaces no utiliza

Cliente C

Cliente D

Interfaz ZMétodos cliente C

Métodos cliente D

Diseño con dos interfaces

Cliente C

Cliente D

Interfaz ZCMétodos cliente C

Interfaz ZDMétodos cliente D

Principio de separación de la interfaz

Análisis

Principio de sustitución de Liskov

Los subtipos deben ser sustituibles por sus supertiposRobert C. Martin

• Básicamente lo que nos dice este principio es que “Cada clase que hereda de otra puede usarse como su padre sin necesidad de conocer las diferencias entre ellas”

• El Principio de Sustitución de Liskov fue acuñado por Bárbara Liskov (de ahí el nombre del principio) en el año 1987 durante una conferencia sobre Jerarquía y Abstracción de datos.

Principio de sustitución de Liskov

Los subtipos deben ser sustituibles por sus supertiposRobert C. Martin

• Su principal cometido es la de asegurar en la herencia entre clases de la Programación Orientada a Objetos que una clase derivada debe comportarse como la clase base. La definición es:

• “Debe ser posible utilizar cualquier objeto instancia de una subclase en lugar de cualquier objeto instancia de su superclase sin que la semántica del programa escrito en los términos de la superclase se vea afectado”

Principio de sustitución de Liskov

Otras definiciones de este principio son:

• Cada clase que hereda de otra puede usarse como su padre sin necesidad de conocer las diferencias entre ellas

• Toda subclase debe soportar ser sustituida por su clase base lo que en términos de contratos significa que las precondiciones de los métodos de la subclase no serán más fuertes que las de la clase base, y sus pos condiciones no serán más débiles, es decir, los métodos derivados no deben esperar más ni proveer menos que los originales.

• Las funciones que usan punteros o referencias a clases base deben ser capaces de utilizar objetos de las clases derivadas sin tener conocimiento de ello (Martin96b), también: “Las clases derivadas deben ser utilizables a través de la interfaz de la clase base, sin necesidad de que el usuario conozca la diferencia”

• Si por cada objeto O1 del tipo S existe un objeto O2 del tipo T tal que para todos los programas P definidos en términos de T y el comportamiento de P permanece invariable cuando O1 es sustituido por O2, entonces S es un subtipo de T.

Rectángulo Cuadrado

Propiedades alto

ancho

lado

Operaciones SetAlto(x)

SetAncho(y)

GetAlto()

GetAncho()

SetLado(z)

GetLado()

Rectángulo

Cuadrado

ES – UN ?

Principio de sustitución de Liskov

¿ Rectángulo ES-UN Cuadrado ?

Propiedades y métodos

• Ambigüedad:– Los programas no saben si

trabajan con objetos de supertiposo de subtipos

• Ventajas

• El enunciado de Martin es confuso:

– “Los subtipos deben ser sustituibles por los supertipos”, pero la definición de subtipo se basa en la sustitución

S es subtipo de T

Obj-1 es un objeto de S

Obj-2 es un objeto de T

Para todo programa P ( T )

comportamiento P(Obj-1) = comportamiento P(Obj-2)

Cuando Obj-1 es sustituido por Obj-2

T

S

Principio de sustitución de Liskov

Análisis

Ley de Deméter

La Ley de Deméter (LoD por sus siglas en ingles Law of Demeter) o Principio de Menos Conocimiento

• En su forma general, la LoD es un caso específico de loosecoupling. Esta directiva fue inventada en la Universidad Northeastern (Boston, Massachusetts) a finales del año 1987, y puede ser sustancialmente resumida de las siguientes maneras:

• Cada unidad debe tener un limitado conocimiento sobre otras unidades y solo conocer aquellas unidades estrechamente relacionadas a la unidad actual.

• Cada unidad debe hablar solo a sus amigos y no hablar con extraños.

• Solo hablar con sus amigos inmediatos.

Ley de Deméter

“Habla sólo con tus amigos”

Detallando un poco más, quiere decir que para un método M de una clase O sólo deberían invocarse métodos de los siguientes tipos de objetos:

• del propio objeto O• de los parámetros que recibe el propio método M• de cualquier objeto que instancie el propio método M• de cualquier atributo de O

Gracias….