Post on 19-Sep-2018
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