La descarga está en progreso. Por favor, espere

La descarga está en progreso. Por favor, espere

Acrónimo mnemónico introducido por Robert C. Martin a comienzos de la década del 2000 que representa cinco principios básicos de la programación orientada.

Presentaciones similares


Presentación del tema: "Acrónimo mnemónico introducido por Robert C. Martin a comienzos de la década del 2000 que representa cinco principios básicos de la programación orientada."— Transcripción de la presentación:

1

2 Acrónimo mnemónico introducido por Robert C. Martin a comienzos de la década del 2000 que representa cinco principios básicos de la programación orientada a objetos y el diseño. Single responsibility Open-closed Liskov substitution Interface segregation Dependency inversion

3  Es muy fácil entender las definiciones de herencia, composición, abstracción, encapsulamiento o polimorfismo.  Pero así como conocer las reglas del ajedrez no te hace un buen jugador, lo mismo pasa con la programación orientada a objetos: se puede conocer los conceptos pero no saber utilizarlos.

4  Entender para qué sirve la orientación a objetos fue un proceso que demoró varios años.  Si un programador viene del paradigma de la programación estructurada, lo primero que hará será escribir clases como si fueran TDAs, archivos en donde poder agrupar atributos y métodos y nada más.

5  SOLID resume buenas practicas en el uso de las distintas técnicas que provee el paradigma, prácticas fundamentales para el buen diseño que propician la mantenibilidad, extensibilidad, adaptabilidad y escalabilidad del código, y sobre todo la salud de los programadores que tendrán que leer y/o modificar nuestro código (que podemos ser nosotros mismos dentro de unos años).  Estos principios son fundamentales para escribir un buen Modelo de Dominio orientado a objetos.

6  Quién lleva años programando sabe que en el 99.99% de los casos los requisitos iniciales se ven alterados una vez ha comenzado el desarrollo o incluso cuando se ha terminado.  Esto es una realidad que tenemos que asumir los programadores y tenemos que tenerlo muy en cuenta en nuestros desarrollos.

7  Para desarrollar programas eficientes con POO, es necesario conocer algunas reglas importantes al respecto, puesto que no es sólo importante conocer la construcción correcta de los objetos sino también la relación que tienen entre ellos.  Un buen diseño de POO significa que a la hora de darle mantenimiento al programa, va a ser mucho más entendible y sencillo además de tener alta facilidad para hacer cambios.

8  SOLID describe cinco principios fundamentales, uno por cada letra, sobre el diseño orientado a objetos.  Cuando estos principios se aplican en conjunto es más probable que un desarrollador cree un sistema que sea fácil de mantener y ampliar con el tiempo.  Los principios SOLID son guías que pueden ser aplicadas en el desarrollo de software para eliminar código sucio provocando que el programador tenga que refactorizar el código fuente hasta que sea legible y extensible.

9  SRP - Principio de responsabilidad única Este principio indica que una clase debe tener una única responsabilidad y esta responsabilidad debe estar encapsulada en su totalidad por la clase. "Nunca debería haber más de un motivo por el que cambiar una clase" — Robert Martin, paper sobre SRP enlazado desde Los Principios del Diseño Orientado a Objetos.

10  Muchas veces para no construir más clases o por no tener claro el propósito de un objeto, se tiende a programar funciones en una clase que no tienen nada que ver con el concepto que ese objeto representa, pero que tiene alguna similitud a las acciones que ya realiza.  Por ejemplo, cuando tenemos un algoritmo de formateo de números en una clase destinada a leer de la base de datos porque fue el primer sitio donde se empezó a utilizar. Esto conlleva a tener métodos difíciles de detectar y encontrar de manera que el código hay que tenerlo memorizado en la cabeza.

11  Ejemplo:

12  Separando responsabilidades…

13  En la práctica la mayoría las clases tienen uno o dos métodos nada más.  Este principio es quizás el más importante de todos, el más sencillo y a la vez el más complicado de llevar a cabo.

14  Una clase que siga el SRP será más sencilla de modificar que otra que tenga muchas responsabilidades.  Si tenemos la lógica del cálculo, la lógica de la base de datos y la lógica de la presentación mezcladas en una clase puede ser difícil modificar una parte sin estropear las otras.  Mezclar responsabilidades hace, además, que la clase sea más difícil de entender, más difícil de probar, e incrementa el riesgo de duplicar lógica en otras partes del diseño.

15  Las violaciones del SRP son fáciles de detectar: Las clases parecen hacer demasiadas cosas, ser demasiado grandes y excesivamente complicadas.  La forma más sencilla de arreglarlo es partir la clase.  El mejor truco para cumplir con SRP es decidir cómo definir la responsabilidad única.  Hay varias formas de descomponer una funcionalidad en resposabilidades, pero la forma ideal es utilizar responsabilidades que puedan cambiar independientemente, de ahí la descripción oficial: "Nunca debería haber más de un motivo por el que cambiar una clase".

16  OCP - Principio de abierto/cerrado "Todas las entidades software (clases, módulos, funciones, etc.) deberían estar abiertas a extensión, pero cerradas a modificación" — Robert Martin, paper sobre OCP enlazado desde Los Principios del Diseño Orientado a Objetos. Es decir, se debe poder extender el comportamiento de tal entidad pero sin modificar su código fuente.

17  La idea radica en usar técnicas de Orientación a Objetos como herencia y composición para cambiar (o extender) el comportamiento de una clase sin tener que modificar la propia clase.

18  Por ejemplo, si tenemos una clase llamada ValidacionPedido con un método largo llamado validar(Pedido pedido) que contiene todas las reglas necesarias para validar un pedido.  Si las reglas cambian necesitamos cambiar la clase ValidacionPedido, con lo que estamos violando el OCP.  Si la clase ValidacionPedido incluyera una colección de objetos IReglaValidacion que contuvieran las reglas podríamos hacer que validar(Pedido pedido) ejecutase todas esas reglas para validar el pedido.  De este modo, si las reglas cambian sólo necesitamos crear una nueva IReglaValidacion e incluirla en la instancia de ValidacionPedido en tiempo de ejecución en lugar de hacerlo en la propia definición de la clase.

19  Cumplir con el OCP debería conseguir que el comportamiento fuese más fácil de cambiar, y además nos ayuda a evitar romper el comportamiento actual mientras se realizan cambios.  El OCP además nos hace pensar sobre qué zonas de la clase pueden cambiar, lo cual nos ayuda a elegir abstracciones correctas necesarias para nuestro diseño.

20  Si se necesita modificar una zona concreta del código constantemente (por ejemplo, las reglas de validación) probablemente sea el momento de utilizar OCP y abstraerse de la parte cambiante del código.  Otra señal de una posible violación del OCP es la aparición de estructuras switch que utilizan tipos — si se crea otro tipo nuevo es necesario modificar el switch. En ese caso una saludable dosis de polimorfismo es el mejor tratamiento.  Por lo general el OCP es una señal de advertencia de que algunos patrones de diseño deberían ser utilizados.

21  LSP - Principio de substitución de Liskov "Las funciones que utilicen punteros o referencias a clases base deben ser capaces de usar objetos de clases derivadas sin saberlo" — Robert Martin, paper sobre LSP enlazado desde Los Principios del Diseño Orientado a Objetos. En otras palabras, las subclases deberían comportarse correctamente cuando se utilizan en lugar de las clases padre.

22  Si parece un pato, suena como un pato, pero necesita pilas, probablemente no estés haciendo la abstracción correcta..

23  LSP es engañosamente sencillo: › Deberíamos ser capaces de sustituir una instancia de una subclase por su clase padre y todo debería seguir funcionando.  ¿Parece fácil? › Bueno, realmente, no lo es, lo que probablemente se deba a que por lo general se nos ha aconsejado usar composición en lugar de herencia. › Asegurarse de que una subclase funciona en cualquier situación en la que la clase padre también lo hace es realmente complicado, entonces es una buena idea tener el LSP en mente cuando se vaya a utilizar herencia.

24  El ejemplo típico de violación de LSP es la relación Cuadrado ES-UN Rectángulo. Matemáticamente un cuadrado es un caso particular de rectángulo ya que tiene todos sus lados iguales, pero esto no encaja bien cuando se modela en el código. ¿Qué debería hacer la función setAncho(int ancho) cuando ésta se invoca en un Cuadrado? ¿Debería cambiar el largo también? ¿Cómo debería funcionar si se trata como su clase padre, la clase Rectángulo? Si el código espera un comportamiento pero recibe otro en función al subtipo de la clase en sí puede que nos enfrentemos a errores muy difíciles de encontrar.

25  ISP - Principio de segregación de la interfaz "Los clientes no deberían estar obligados a depender de interfaces que no utilicen". — Robert Martin, paper sobre ISP enlazado desde Los Principios del Diseño Orientado a Objetos..

26  ISP trata de mantener las interfaces (tanto las interfaces en sí como las clases abstractas) pequeñas y limitadas únicamente a una necesidad muy concreta (a una única responsabilidad).  El crear interfaces grandes obliga a desarrollar implementaciones muy extensas a todo aquel que quiera seguir el contrato definido en la interfaz.  Peor todavía es hacer clases que sólo dan una implementación real de una parte pequeña de la interfaz grande, lo cual elimina totalmente las ventajas de usar interfaces

27

28 En caso que solo necesitemos usar la utilidad que permite asegurar páginas en base al perfil del usuario usando el archivo web.config, significaría que únicamente se necesita implementar GetRolesForUser(...) e Initialize(...). ¿Cuál sería entonces la implementación del resto de métodos?. Exacto, throw new NotImplementedException();. El hecho de tener una clase que implemente RoleProvider y no tengamos ni idea de qué métodos realmente implementa es malo. Aparte de esto también ocurre que dejamos un montón de ruido inútil dentro de nuestra clase.

29  DIP - Principio de inversión de dependencias El objetivo de este principio es el uso de abstracciones para conseguir que una clase interactúe con otras clases sin que las conozca directamente. Es decir, las clases de nivel superior no deben conocer las clases de nivel inferior. Dicho de otro modo, no debe conocer los detalles. "A. Los módulos de alto nivel no deberían depender de módulos de bajo nivel. Ambos deben depender de abstracciones. B. Las abstracciones no deben depender de detalles. Los detalles deben depender de abstracciones." — Robert Martin, paper sobre DIP enlazado desde Los Principios del Diseño Orientado a Objetos.

30 DIP explica que un módulo concreto A, no debe depender directamente de otro módulo concreto B, sino de una abstracción de B. Tal abstracción es una interfaz o una clase (que podría ser abstracta) que sirve de base para un conjunto de clases hijas.

31  DIP dice que si una clase depende de otras clases, ésta relación debería ser de dependencia de interfaces en lugar de dependencia de implementaciones concretas.  La idea es aislar nuestra clase detrás de un muro de abstracciones de las que depender.  Si los detalles tras las abstracciones cambian nuestra clase se encuentra a salvo.  Esto ayuda a mantener un acoplamiento bajo y hace que nuestro diseño sea más fácil de cambiar.

32  Ejemplo: La clase Logica necesita de un colaborador para guardar el dato Dato en algún lugar persistente. Disponemos de una clase MyBD que es capaz de almacenar Dato en una base de datos MySQL y de una clase FS que es capaz de almacenar Dato en un archivo binario sobre un sistema de archivos. Si en el código de Logica escribimos literalmente el nombre de la clase MyBD como colaborador para persistir datos, ¿Cómo haremos cuando necesitamos cambiar la base de datos por archivos binarios en disco?. No quedará otro remedio que modificar el código de Logica.

33 Ejemplo: Si las clases MyDB y FS implementasen una misma interfaz IPersistor para guardar Dato, podríamos limitarnos a usar IPersistor (que es una abstracción) en el código de Logica. Cuando los requerimientos exigiesen un cambio de base de datos por archivos en disco o viceversa, sólo tendríamos que preocuparnos de que el atributo myPersistor de la clase Logica, que es de tipo IPersistor contuviese una instancia de MyDB o bien de FS.

34  Donde DIP comienza a ser más útil y un poco más profundo es en un concepto relacionado llamado Inyección de Dependencias.  La Inyección de Dependencias consiste en incluir unas clases dentro de otras que las necesitan, de tal forma que no haya que hacer new( ) de instancias concretas. Esta técnica aísla nuestras clases y consigue que los cambios y la reutilización sean mucho más fáciles de conseguir.

35  La otra faceta de DIP se encuentra en las dependencias que hay entre módulos de alto y bajo nivel en aplicaciones que utilizan un diseño basado en capas.  Por ejemplo, una clase que acceda a la base de datos no debería depender de un formulario mostrado en la interfaz gráfica con el que mostrar esos datos. En su lugar, la interfaz gráfica debería apoyarse en una abstracción (o abstracciones) sobre la clase que acceda a la base de datos.  Las capas tradicionales utilizadas en las aplicaciones (datos, lógia, interfaz gráfico) han sido reemplazadas por el patrón MVC, así que se tiende a pensar en DIP únicamente desde la perspectiva de abstracción de dependencias.

36  El uso de los principios puede servir de guía cuando se está realizando el diseño.  No hay diseños perfectos, únicamente compromisos y los principios SOLID pueden ayudar a evaluarlos y a alcanzar un balance equilibrado.  Sin embargo, ninguno de los principios debe ser seguido al pie de la letra ni dogmáticamente, se debe analizar por ejemplo: ¿Realmente se necesita hacer una gran descomposición en las interfaces para cumplir OCP y DIP?  Quizá sí, quizá no, pero considerar los principios SOLID puede ayudar a decidir.

37  Los principios SOLID encajan naturalmente con la práctica de TDD (Test Driven Design).  Por ejemplo, escribir un test o prueba unitaria realmente efectiva para una clase es mucho más fácil si cumples con DIP y se aisla a la clase de sus dependencias.  Si se está escribiendo el test primero para así dirigir su diseño, entonces las clases tenderán a usar DIP naturalmente.  Si se están haciendo tests de clases que ya están escritas, probablemente se encontrará que es más difícil hacer y puede que se acabe haciendo tests que requieran interacción del usuario, que se reescriban clases para seguir DIP o, peor todavía, que se tiren a la basura de las clases-demasiado-dificil- de-probar.


Descargar ppt "Acrónimo mnemónico introducido por Robert C. Martin a comienzos de la década del 2000 que representa cinco principios básicos de la programación orientada."

Presentaciones similares


Anuncios Google