Con el tiempo pude entender dos partes de SOLID : la "S" y la "O".
"O" - Aprendí el Principio Abierto Cerrado con la ayuda del Patrón de Herencia y Estrategia.
“S”: aprendí el principio de responsabilidad única mientras aprendía ORM (la lógica de persistencia se elimina de los objetos de dominio).
De manera similar, ¿cuáles son las mejores regiones / tareas para aprender otras partes de SOLID (la "L", "I" y "D")?
Referencias
Respuestas:
Estuve en tu lugar hace un par de meses hasta que encontré un artículo muy útil.
Cada principio se explica muy bien con situaciones del mundo real que cada desarrollador de software puede enfrentar en sus proyectos. Estoy cortando aquí y señalando la referencia: Desarrollo de software SOLIDO, un paso a la vez .
Como se señaló en los comentarios, hay otra muy buena lectura en pdf: el desarrollo de software SOLID de Pablo .
Además, hay algunos buenos libros que describen los principios de SOLID con más detalles: Good Book on SOLID Software Development .
Edición y comentarios de un breve resumen de cada principio:
"S" - El Principio de Responsabilidad Única es impulsado por las necesidades del negocio para permitir el cambio. "Una sola razón para cambiar" le ayuda a comprender qué conceptos lógicamente separados deben agruparse considerando el concepto y el contexto del negocio, en lugar del concepto técnico solo.
In another words
, aprendí que cada clase debería tener una única responsabilidad. La responsabilidad es solo cumplir con la tarea asignada“O” - Aprendí el Principio Abierto Cerrado y comencé a "preferir la composición sobre la herencia" y, como tal, preferir las clases que no tienen métodos virtuales y posiblemente están selladas, pero dependen de abstracciones para su extensión.
“L”: aprendí el Principio de sustitución de Liskov con la ayuda del patrón de repositorio para administrar el acceso a datos.
Como se mencionó en los comentarios un recurso útil de CodePlex, se incluye una referencia a SOLID por ejemplo
fuente
(I) La segregación de la superficie y (D) la Inversión de la dependencia se pueden aprender mediante pruebas unitarias y burlas. Si las clases crean sus propias dependencias, no puede crear buenas pruebas unitarias. Si dependen de una interfaz demasiado amplia (o ninguna interfaz), no es muy obvio qué se debe burlar para realizar las pruebas de su unidad.
fuente
El Principio de sustitución de Liskov básicamente no le permite usar en exceso la herencia de implementación: ¡nunca debe usar la herencia solo para la reutilización de código (hay composición para esto)! Al adherirse a LSP, puede estar bastante seguro de que realmente existe una "relación es-es" entre su superclase y su subclase.
Lo que dice es que sus subclases deben implementar todos los métodos de la subclase de manera similar a la implementación de los métodos en la subclase. Nunca debe anular un método con la implementación de NOP o devolver nulo cuando el supertipo arroja una excepción; indicado en los términos de Diseño por Contrato, debe respetar el contrato del método de la superclase al anular un método. Una forma de defenderse contra la ruptura de este principio es nunca anular un método implementado; en su lugar, extraiga una interfaz e implemente esa interfaz en ambas clases.
Principio de segregación de interfaz , Principio de responsabilidad única y Principio de alta cohesión de GRASP están de alguna manera relacionados; se refieren al hecho de que una entidad debe ser responsable de una sola cosa para que haya una sola razón para el cambio y que el cambio se realice con mucha facilidad.
En realidad dice que si una clase implementa una interfaz, entonces debe implementar y usar todos los métodos de esa interfaz. Si hay métodos que no son necesarios en esa clase en particular, entonces la interfaz no es buena y debe dividirse en dos interfaces, una que solo tenga los métodos necesarios para la clase original. Se puede considerar desde un POV, que se relaciona con el principio anterior por el hecho de que no le permite crear interfaces grandes para que su implementación pueda romper el LSP.
Puede ver la Inversión de dependencias en el Patrón de fábrica; aquí, tanto el componente de alto nivel (el cliente) como el componente de bajo nivel (instancia individual que se creará) dependen de la abstracción(La interfaz). Una forma de aplicarlo en una arquitectura en capas: no debe definir una interfaz para una capa en la capa que se implementa sino en el módulo que se llama. Por ejemplo, la API de la capa de origen de datos no debe escribirse en la capa de origen de datos sino en la capa de lógica de negocios, donde es necesario llamarla. De esta manera, la capa de origen de datos hereda / depende del comportamiento definido en la lógica de negocios (por lo tanto, la inversión) y no al revés (como sería de una manera normal). Esto proporciona flexibilidad en el diseño, permitiendo que la lógica de negocios funcione sin ningún cambio de código, con otra fuente de datos completamente diferente.
fuente