Principios de S.O.L.I.D explicados en Python con ejemplos.

SOLID es una abreviatura mnemotécnica de un conjunto de principios de diseño creados para el desarrollo de software en lenguajes orientados a objetos. Los principios de SOLID están destinados a fomentar un código más simple, robusto y actualizable por parte de los desarrolladores de software. Cada letra en SOLID corresponde a un principio de desarrollo:

Cuando se implementa correctamente, hace que su código sea más extensible, lógico y más fácil de leer.

Para comprender los principios de SOLID , debe conocer claramente el uso de la interfaz.

Voy a intentar explicar los principios de SOLID en Python de la manera más simple para que sea fácil de entender para los principiantes. Sería muy fácil simplemente tomar los ejemplos proporcionados y aplicarlos a Python.

Repasemos cada principio uno por uno:

1. Principio de responsabilidad única

El principio de responsabilidad única requiere que una clase solo tenga un trabajo. Entonces, si una clase tiene más de una responsabilidad, se empareja. Un cambio en una responsabilidad da como resultado la modificación de la otra responsabilidad.

Tenemos una clase de usuario que es responsable tanto de las propiedades del usuario como de la gestión de la base de datos de usuarios. Si la aplicación cambia de manera que afecte las funciones de administración de la base de datos. Las clases que hacen uso de las propiedades de usuario deberán tocarse y recompilarse para compensar los nuevos cambios. Es como un efecto dominó, toca una carta y afecta a todas las demás cartas de la línea.

Entonces simplemente dividimos la clase, creamos otra clase que manejará la única responsabilidad de almacenar un usuario en una base de datos:

Una solución común a este dilema es aplicar el patrón Façade. Para una introducción al patrón de fachada, puede leer más. La clase de usuario será la Fachada para la gestión de la base de datos de usuarios y la gestión de propiedades de los usuarios.

2. Principio abierto-cerrado

Las entidades de software (clases, módulos, funciones) deben estar abiertas para extensión, no modificación.

Imaginemos que tiene una tienda y ofrece un descuento del 20% a sus clientes favoritos que usan esta clase: cuando decide ofrecer el doble del 20% de descuento a los clientes VIP. Puede modificar la clase de esta manera:

No, esto no cumple con el principio de OCP. OCP lo prohíbe. Si queremos dar un nuevo porcentaje de descuento tal vez, a un tipo diferente de clientes, verá que se agregará una nueva lógica. Para que siga el principio OCP, agregaremos una nueva clase que extenderá el descuento. En esta nueva clase, implementaríamos su nuevo comportamiento:

Si decide un 80% de descuento para clientes super VIP, debería ser así:

Extensión sin modificaciones.

3. Principio de sustitución de Liskov

La idea principal detrás del principio de subtitulación de Liskov es que, para cualquier clase, un cliente debería poder utilizar cualquiera de sus subtipos de forma indistinguible, sin siquiera darse cuenta y, por tanto, sin comprometer el comportamiento esperado en tiempo de ejecución. Esto significa que los clientes están completamente aislados y desconocen los cambios en la jerarquía de clases.

Más formalmente:
Sea q (x) una propiedad demostrable sobre objetos de x de tipo T. Entonces q (y) debería ser demostrable para objetos y de tipo S donde S es un subtipo de T .

En términos más simples, significa que una subclase, hijo o especialización de un objeto o clase debe ser adecuada para su padre o superclase.

Comentarios sobre el LSP El LSP es fundamental para un buen diseño de software orientado a objetos porque enfatiza uno de sus rasgos centrales: el polimorfismo. Se trata de crear jerarquías correctas para que las clases derivadas de una base sean polimórficas a lo largo de la principal, con respecto a los métodos en su interfaz. También es interesante notar cómo este principio se relaciona con el anterior: si intentamos extender una clase con una nueva que es incompatible, fallará, el contrato con el cliente se romperá y, como resultado, dicha extensión. no será posible (o, para hacerlo posible, tendríamos que romper el otro extremo del principio y modificar el código en el cliente que debería estar cerrado para su modificación, lo cual es completamente indeseable e inaceptable).

Pensar detenidamente en las nuevas clases de la forma que sugiere LSP nos ayuda a extender la jerarquía correctamente. Entonces podríamos decir que LSP contribuye al OCP.

4. Principio de segregación de la interfaz

Cree interfaces de grano fino que sean específicas del cliente. Los clientes no deberían verse obligados a depender de interfaces que no utilicen. Este principio trata las desventajas de implementar grandes interfaces.

Para ilustrar esto completamente, usaremos un ejemplo clásico porque es muy significativo y fácilmente comprensible. El ejemplo clásico

Otro buen truco es que en nuestra lógica empresarial, una sola clase puede implementar varias interfaces si es necesario. Por lo tanto, podemos proporcionar una implementación única para todos los métodos comunes entre las interfaces. Las interfaces segregadas también nos obligarán a pensar en nuestro código más desde el punto de vista del cliente, lo que a su vez conducirá a un acoplamiento flojo y pruebas fáciles. Por lo tanto, no solo hemos mejorado nuestro código para nuestros clientes, también lo hemos hecho más fácil de entender, probar e implementar.

5. Principio de inversión de dependencia

La dependencia debe estar en abstracciones, no en concreciones. Los módulos de alto nivel no deberían depender de módulos de bajo nivel. Tanto las clases de nivel bajo como las de alto nivel deberían depender de las mismas abstracciones. Las abstracciones no deberían depender de los detalles. Los detalles deben depender de abstracciones.

Llega un punto en el desarrollo de software en el que nuestra aplicación estará compuesta en gran parte por módulos. Cuando esto sucede, tenemos que aclarar las cosas usando la inyección de dependencia. Componentes de alto nivel dependiendo de los componentes de bajo nivel para funcionar. Para crear un comportamiento específico, puede utilizar técnicas como herencia o interfaces.

Puede obtener más información:

Python sólido

Código limpio en Python