remarks name method documentacion comentarios c# .net design-patterns solid-principles

c# - name - ¿Los principios SÓLIDOS son realmente sólidos?



remarks c# (10)

El patrón de diseño que representa la primera letra de este acrónimo es el Principio de Responsabilidad Individual. Aquí hay una cita:

el principio de responsabilidad única establece que cada objeto debe tener una responsabilidad única, y esa responsabilidad debe estar completamente encapsulada por la clase.

Eso es simple y claro hasta que comencemos a codificar. Supongamos que tenemos una clase con una responsabilidad única bien definida. Para serializar las instancias de clase, necesitamos agregar atributos especiales a esa clase. Entonces ahora la clase tiene otra responsabilidad. ¿Eso no viola el SRP?

Veamos otro ejemplo: una implementación de interfaz. Cuando implementamos una interfaz, simplemente agregamos otras responsabilidades, por ejemplo, deshacernos de sus recursos o comparar sus instancias o lo que sea.

Entonces mi pregunta. ¿Es posible mantener estrictamente a SRP? ¿Cómo puede hacerse esto?


Al cambiar su definición de "responsabilidad única", los principios SÓLIDOS son bastante líquidos y (al igual que otros acrónimos de acrónimos) no significan lo que parecen significar.

Se pueden utilizar como una lista de verificación o una hoja de trucos, pero no como pautas completas y, ciertamente, como material de aprendizaje.


Aquí hay una preocupación legítima, ya que estas preocupaciones transversales (serialización, registro, notificación de enlace de datos, etc.) terminan agregando implementación a múltiples clases que solo está ahí para soportar algún otro subsistema. Esta implementación tiene que ser probada, por lo que la clase definitivamente ha cargado con responsabilidades adicionales.

La Programación Orientada a Aspectos es un enfoque que intenta resolver este problema. Un buen ejemplo en C # es la serialización, para la cual existe una amplia gama de atributos diferentes para diferentes tipos de serialización. La idea aquí es que la clase no debe implementar código que realice la serialización, sino más bien declarar cómo se serializará. Los metadatos son un lugar muy natural para incluir detalles que son importantes para otros subsistemas, pero que no son relevantes para la implementación verificable de una clase.


Bueno, supongo que lo primero que hay que tener en cuenta es que estos son solo buenos principios de Ingeniería de Software; también hay que aplicar juicio. Entonces, en ese sentido, ¡no, no son sólidos (!)

Creo que la pregunta que hiciste plantea el punto clave: ¿cómo defines la responsabilidad única que debe tener la clase?

Es importante no atascarse demasiado en los detalles al definir una responsabilidad: el hecho de que una clase haga muchas cosas en el código no significa que tenga muchas responsabilidades.

Sin embargo, por favor, quédate con eso. Aunque probablemente sea imposible de aplicar en todos los casos, es mejor que tener un solo "Objeto de Dios" (Antipatrón) en su código.

Si tiene problemas con estos, le recomendaría leer lo siguiente:

  • Refactorización: Martin Fowler: Aunque obviamente se trata de refactorización, este libro también es muy útil para mostrar cómo descomponer los problemas en sus partes lógicas o responsabilidades, lo cual es clave para SRP. Este libro también se refiere a los otros principios, sin embargo, lo hace de una manera mucho menos académica de lo que pueda haber visto antes.

  • Código de limpieza: Robert Martin: ¿Quién mejor para leer que el mejor exponente de los principios SOLIDOS? En serio, me pareció un libro muy útil en todas las áreas de la artesanía del software, no solo en los principios SÓLIDOS. Al igual que el libro de Fowler, este libro se presenta en todos los niveles de experiencia, por lo que se lo recomendaría a cualquiera.


Como descubrirá un día, ninguno de los principios más conocidos en el desarrollo de software puede ser seguido al 100%.

La programación a menudo implica hacer concesiones: pureza abstracta frente a tamaño de código vs. velocidad versus eficiencia.

Solo necesitas aprender a encontrar el equilibrio adecuado: no dejes que tu aplicación caiga en el abismo del caos, pero no te atas las manos con multitud de capas de abstracción.


Creo que hay muchas tareas comunes menores que una clase puede hacer sin que oscurezcan la responsabilidad principal de una clase: serialización, registro, manejo de excepciones, manejo de transacciones, etc.

Depende de su criterio en cuanto a qué tareas de su clase constituyen una responsabilidad real en términos de la lógica de su negocio / aplicación, y lo que es solo un código de plomería.


Entonces, si en lugar de diseñar una clase "Perro" con los métodos "Bark", "Sleep" y "Eat", debo diseñar las clases "AnimalWhoBarks", "AnimalWhoSleeps", "AnimalWhoEats", etc. ¿Por qué? ¿Cómo hace eso que mi código sea mejor? ¿Cómo se supone que simplemente implemente el hecho de que mi perro no se va a dormir y ladrará toda la noche si no ha comido?

"Divide las clases grandes en las más pequeñas", es un buen consejo práctico, pero "cada objeto debe tener una sola responsabilidad" es una tontería dogmática absoluta.

Imagine que .NET Framework se escribió pensando en SRP. En lugar de 40000 clases, tendrías millones.

SRP generalizado ("Generalizado" es la palabra importante aquí) es solo un crimen en mi humilde opinión. No puede reducir el desarrollo de software a 5 principios de librerías.


Lo que hay que recordar sobre los principios de diseño es que siempre hay excepciones, y no siempre encontrarás que tu escenario / implementación coincida con un principio determinado al 100%.

Habiendo dicho eso, agregar atributos a las propiedades realmente no agrega ninguna funcionalidad o comportamiento a la clase, suponiendo que su código de serialización / deserialización esté en alguna otra clase. Simplemente está agregando información sobre la estructura de su clase, por lo que no parece una violación del principio.


No creo que ser serializable o desechable equivale a múltiples responsabilidades.


Para comprender mejor los principios SÓLIDOS, debes comprender el problema que resuelven:

La programación orientada a objetos surgió a partir de la programación estructurada / procedimental: agregó un nuevo sistema organizacional (clases, et al) así como comportamientos (polimorfismo, herencia, composición). Esto significaba que OO no estaba separado de estructura / procedimiento, sino que era una progresión, y que los desarrolladores podían hacer OO muy procedimental si querían.

Entonces ... SOLID apareció como una prueba de fuego para responder la pregunta "¿Realmente estoy haciendo OO, o solo estoy usando objetos de procedimiento?" Los 5 principios, si se siguen, significan que estás bastante lejos del lado OO del espectro. No cumplir con estas reglas no significa que no estés haciendo OO, sino que significa mucho más OO estructural / procedimental.


SOLID significa:

  • Responsabilidad individual Principio
  • Principio abierto-cerrado
  • Principio de sustitución de Liskov
  • Principio de segregación de la interfaz
  • Principio de inversión de dependencia

Estos son los estándares a los que nos referimos cuando hablamos de OOP. Sin embargo, ninguno de esos principios se puede cumplir perfectamente en el desarrollo de software.

Puede ver una presentación muy bien explicativa sobre este tema aquí http://www.slideshare.net/jonkruger/advanced-objectorientedsolid-principles