No me parece útil en estos días debatir sobre qué constituye y qué no constituye una responsabilidad única o una única razón para cambiar. Propondría un principio de pena mínima en su lugar:
Principio de pena mínima: el código debe buscar minimizar su probabilidad de requerir cambios o maximizar la facilidad de cambio.
¿Cómo es eso? No debería recurrir a un científico espacial para descubrir por qué esto puede ayudar a reducir los costos de mantenimiento y, con suerte, no debería ser un punto de debate interminable, pero como con SOLID en general, no es algo que se aplique a ciegas en todas partes. Es algo a tener en cuenta al equilibrar las compensaciones.
En cuanto a la probabilidad de requerir cambios, eso se reduce con:
- Buenas pruebas (confiabilidad mejorada).
- Involucrando solo el código mínimo necesario para hacer algo específico (esto puede incluir reducir los acoplamientos aferentes).
- Solo haciendo que el código sea duro en lo que hace (vea Hacer el principio de Badass).
En cuanto a la dificultad de realizar cambios, aumenta con los acoplamientos eferentes. Las pruebas introducen acoplamientos eferentes pero mejoran la confiabilidad. Hecho bien, generalmente hace más bien que daño y es totalmente aceptable y promovido por el Principio de Dolor Mínimo.
Haga el principio de Badass: las clases que se usan en muchos lugares deben ser increíbles. Deben ser confiables y eficientes si eso está relacionado con su calidad, etc.
Y el principio de Make Badass está ligado al principio de pena mínima, ya que las cosas badass encontrarán una menor probabilidad de requerir cambios que las cosas que apestan a lo que hacen.
Habría comenzado señalando la paradoja mencionada anteriormente, y
luego indique que el SRP es altamente dependiente del nivel de
granularidad que desea considerar y que si lo toma lo suficientemente lejos,
cualquier clase que contenga más de una propiedad o un método lo viola.
Desde un punto de vista de SRP, una clase que apenas hace algo sin duda tendría solo una (a veces cero) razones para cambiar:
class Float
{
public:
explicit Float(float val);
float get() const;
void set(float new_val);
};
¡Eso prácticamente no tiene razones para cambiar! Es mejor que SRP. ¡Es ZRP!
Excepto que sugeriría que se trata de una violación flagrante del principio de Make Badass. También es absolutamente inútil. Algo que hace tan poco no puede esperar ser rudo. Tiene muy poca información (TLI). Y, naturalmente, cuando tienes algo que es TLI, no puede hacer nada realmente significativo, ni siquiera con la información que encapsula, por lo que tiene que filtrarlo al mundo exterior con la esperanza de que alguien más realmente haga algo significativo y rudo. Y esa filtración está bien para algo que solo está destinado a agregar datos y nada más, pero ese umbral es la diferencia que veo entre "datos" y "objetos".
Por supuesto, algo que es TMI también es malo. Podríamos poner todo nuestro software en una clase. Incluso puede tener solo un método run
. Y alguien podría incluso argumentar que ahora tiene una razón muy amplia para cambiar: "Esta clase solo tendrá que cambiarse si el software necesita mejoras". Estoy siendo tonto, pero por supuesto podemos imaginar todos los problemas de mantenimiento con eso.
Así que hay un acto de equilibrio en cuanto a la granularidad o la tosquedad de los objetos que diseñas. A menudo lo juzgo por la cantidad de información que tiene que filtrar al mundo exterior y la funcionalidad significativa que puede realizar. A menudo encuentro que el Principio de Make Badass es útil para encontrar el equilibrio mientras lo combino con el Principio de Duelo Mínimo.