solid principles
TRANSCRIPT
Principios SOLIDMartín Salías
Decadencia del software• Rigidez
• Fragilidad
• Inmovilidad
• Viscosidad
• Complejidad innecesaria
• Repetición innecesaria
• Opacidad
Newsgroups: comp.objectFrom: [email protected] (Robert Martin)Date: Thu, 16 Mar 1995 15:12:00 GMTSubject: Re: The Ten Commandments of OO Programming---If I had to write commandments, these would be candidates. 1. Software entities (classes, modules, etc) should be open for extension, but closed for modification. (The open/closed principle -- Bertrand Meyer) 2. Derived classes must usable through the base class interface without the need for the user to know the difference. (The Liskov Substitution Principle) 3. Details should depend upon abstractions. Abstractions should not depend upon details. (Principle of Dependency Inversion) 4. The granule of reuse is the same as the granule of release. Only components that are released through a tracking system can be effectively reused. 5. Classes within a released component should share common closure. That is, if one needs to be changed, they all are likely to need to be changed. What affects one, affects all. 6. Classes within a released component should be reused together. That is, it is impossible to separate the components from each other in order to reuse less than the total. 7. The dependency structure for released components must be a DAG. There can be no cycles. 8. Dependencies between released components must run in the direction of stability. The dependee must be more stable than the depender. 9. The more stable a released component is, the more it must consist of abstract classes. A completely stable component should consist of nothing but abstract classes. 10. Where possible, use proven patterns to solve design problems. 11. When crossing between two different paradigms, build an interface layer that separates the two. Don't pollute one side with the paradigm of the other.
Single Responsibility
Open-Closed
Liskov Substitution
Interface Segregation
Dependency Inversion
Responsabilidad única
Abierto-Cerrado
Substitución de Liskov
Segregación de Interfaz
Inversión de Dependencia
Una clase debe tener un único eje de cambio.
Responsabilidad única
Una clase debe tener una única razón para ser cambiada.
Responsabilidad = Eje de cambios
(SI el cambio sucede)
Recibir el primer golpe
Dos responsabilidades
AplicaciónGeométrica + Draw()
+ Area() : double
MyRectangle
AplicaciónGráfica
GUI
Deslindando responsabilidades
AplicaciónGeométrica
+ Draw()
GraphRectangle
AplicaciónGráfica
GUI
+ Area() : double
GeoRectangle
AplicaciónGeométricaAplicación
GeométricaAplicación
GráficaAplicación
Geométrica
Se debe poder extender el comportamiento sin modificarlo.
Abierto-Cerrado
Las entidades de software (clases, módulos, funciones, etc) deben estar abiertas a
extensión, pero cerradas a modificación.
Acercarse a un ideal
Los cambios deben generar código nuevo,no modificar el código viejo.
Cerrando a modificaciones
ServidorClienteEl cliente está abierto a modificaciones.
<<Interfaz>>IClienteCliente
Patrón Strategy: El cliente está abiertoy cerrado.
Servidor
Cerrando a modificaciones
+ ReglaPolitica()- Servicio()
Política
- Servicio()
Implementación
Patrón Template Method:La clase base está cerradaa modificaciones.
La implementación delmétodo lo abre a cuantasextensiones se necesiten.
Las clases derivadas deben poder sustituírse por sus bases.
Substitución de LiskovLos subtipos deben ser substituibles
por sus tipos base.
Si para cada objeto o1 de tipo S hay un objeto o2 de tipo T tal que para todo programa P definido en términos de T, el comportamiento de P no varía cuando o1 es sustitido por o2, entonces S es un subtipo de T.
Es la base de poder del polimorfismo.
Cuidarse de GetType() y otros datos de tipo en runtime.
Implicancias del LSP
• La validez depende del contexto
• No podemos validar un modelo aisladamente
• Diseñar basándose en comportamientos
• Presunciones razonables (¿cómo acotarlas?)
Diseño por contrato• Preservar las invariantes
• Pre y pos-condiciones
• La redeclaración de una rutina (en una derivación) debe solamente reemplazar la precondición original con una igual o más débil, y la poscondición original con una igual o más fuerte.
• Eiffel soporta nativamente DBC
• En .NET ó Java usamos Unit Tests
• Soporte incipiente en .NET 4
Un ejemplo más complejo (1)
Lista
Listailimitada
Listalimitada
Listailimitada
Listalimitada
Librería
Un ejemplo más complejo (2)
Lista
Listapersistente
Listapersistente
Librería
Listapersistente
Un ejemplo más complejo (3)
Contenedor
Listapersistente
Librería
Listapersistente
Quitar(T)Existe(T)
Lista
Agregar(T)
ListaPersistenteAgregar(T)
Produzca interfaces de grano fino específicas para un cliente.
Segregación de Interfaz
Los clientes no deben ser forzados a depender de métodos que no usan.
• Apunta a evitar las interfaces “gordas”.
• No importa la cantidad de métodos, sino que todos sus clientes las utilicen.
• Inadvertidamente podemos acoplar clientes que usan ciertos métodos con otros clientes que no los usan.
Una interfaz engorda
Puerta
+ Trabar()+ Destrabar()+ Abierta()
Timer<<interface>>Cliente Timer
+ TimeOut()
Puerta
Puerta temporizada
Separación por delegación
Timer<<interface>>Cliente Timer
+ TimeOut()
Puerta
Puerta temporizada
Adapter Puerta Temporizada
+ TimeOut()
<<instancia>>
+ TimeOutPuerta()
Separación por herencia múltiple
Timer<<interface>>Cliente Timer
+ TimeOut() Puerta
Puerta Temporizada
+ TimeOut()
Dependa de abstracciones, no de concreciones.
Inversión de dependenciaa) Los módulos de alto nivel no deben
depender de los módulos de bajo nivel. Ambos deben depender de abstracciones.
b) Las abstracciones no deben depender de detalles. Los detalles deben depender de las abstracciones.
Es el principio general detrás del concepto de Layers o Capas.
Capas acopladasCapa
Política
CapaMecanismo
CapaUtilidad
Política
Meca
nism
oU
tilidad
Capas desacopladas
CapaPolítica
CapaMecanismo
CapaUtilidad
<<interface>>Servicio de
políticas
<<interface>>Servicio de
mecanismos
Recursos
Artículo del Tío Bob sobre diseño OOhttp://butunclebob.com/ArticleS.UncleBob.PrinciplesOfOod
Bibliografíaadicional
John Hunt David West
Matt Weisfeld Bertrand Meyer
Rebecca Wirfs-Brock
Scott Ambler