El principio de responsabilidad única se basa en el principio de alta cohesión. La diferencia entre los dos es que una clase altamente cohesionada presenta un conjunto de responsabilidades que están fuertemente relacionadas, mientras que las clases que se adhieren al SRP tienen una sola responsabilidad.
Pero, ¿cómo determinamos si una clase en particular presenta un conjunto de responsabilidades y, por lo tanto, es muy coherente, o si solo tiene una responsabilidad y se adhiere al SRP? En otras palabras, ¿no es más o menos subjetivo, ya que algunos pueden considerar una clase muy granular (y como tal creerán que la clase se adhiere al SRP), mientras que otros pueden considerar que no es lo suficientemente granular?
design-patterns
single-responsibility
cohesion
usuario1483278
fuente
fuente
Respuestas:
Por qué sí, es muy subjetivo, y es el tema de muchos debates acalorados y enrojecidos en los que se encuentran los programadores.
Realmente no hay una sola respuesta, y la respuesta puede cambiar a medida que su software se vuelve más complejo. Lo que una vez fue una tarea bien definida, eventualmente puede convertirse en múltiples tareas mal definidas. Ese es siempre el problema también. ¿Cómo elige la forma correcta de dividir un programa en tareas?
El único consejo que puedo dar es este: use su mejor juicio (y el de sus compañeros de trabajo). Y recuerde que los errores pueden (generalmente) corregirse si los detecta lo suficientemente pronto.
fuente
Bob Martin (tío Bob), quien originó los principios SÓLIDOS de los cuales SRP es el primero, dice acerca de esto (estoy parafraseando, no puedo recordar las palabras reales):
Si tiene más de una razón, no se adhiere a SRP.
fuente
Puedo darte varias reglas generales.
fuente
Los Principios de responsabilidad única dicen que cada módulo de software debe tener una sola razón para cambiar. En un artículo reciente, el tío Bob explicó "razones para cambiar",
Explicó además el concepto con un ejemplo AQUÍ .
fuente
Para responder a esto, dé un paso atrás y considere la intención del principio de responsabilidad única. ¿Por qué es un principio de diseño recomendado en primer lugar?
El propósito del principio es "compartimentar" la base del código, de modo que el código relacionado con una única "responsabilidad" está aislado en una sola unidad. Esto facilita la búsqueda y comprensión del código y, lo que es más importante, significa que los cambios en la "responsabilidad" solo afectarán a una sola unidad de código.
Lo que nunca quiere en un sistema es cuando una pequeña posibilidad hace que otra parte aparentemente no relacionada del código falle o cambie el comportamiento. El SRP ayuda a aislar errores y cambios.
Entonces, ¿qué es una "responsabilidad"? Es algo que podría cambiar independientemente de otros cambios. Supongamos que tiene un programa que puede guardar algunas configuraciones en un archivo de configuración XML y puede volver a leerlas desde el archivo. ¿Es esta una responsabilidad única o "cargar" y "guardar" dos responsabilidades diferentes? Cualquier tipo de cambio en el formato o estructura del archivo requeriría cambiar tanto la lógica de carga como la de guardar. Por lo tanto, es una responsabilidad única que debe estar representada por una sola clase. Ahora considere una aplicación que puede exportar algunos datos en formato CVS, Excel y XML. En este caso, es fácil imaginar que un formato podría cambiar sin afectar al otro. Si decide cambiar el delimitador en el formato CVS, no debería afectar la salida de Excel.
fuente
OO dice que las clases son una agrupación de datos y una funcionalidad. Esta definición deja mucho espacio para la interpretación subjetiva.
Sabemos que las clases deben definirse clara y fácilmente. Pero, para definir una clase de este tipo, debemos tener una idea clara de cómo una clase encaja en el diseño general. Sin requisitos de tipo cascada que, paradójicamente, se consideran un antipatrón ... esto es difícil de lograr.
Podemos implementar un diseño de clase con una arquitectura que funcione en la mayoría de los casos, como MVC. En las aplicaciones MVC solo asumimos que tenemos datos, una interfaz de usuario y un requisito para que los dos se comuniquen.
Con una arquitectura básica, es más fácil identificar casos en los que se rompen las reglas de responsabilidad individual. Por ejemplo, pasar una instancia de un Control de usuario a un modal.
fuente
Solo por el bien de la discusión, mencionaré una clase de JUCE llamada AudioSampleBuffer . Ahora esta clase existe para contener un fragmento (o quizás un fragmento bastante largo) de audio. Sabe que la cantidad de canales, la cantidad de muestras (por canal), parece estar comprometida con el flotante IEEE de 32 bits en lugar de tener una representación numérica variable o un tamaño de palabras (pero eso no es un problema para mí). Hay funciones miembro que le permiten obtener numChannels o numSamples y punteros a cualquier canal en particular. Puede hacer que un AudioSampleBuffer sea más largo o más corto. Supongo que los primeros cero-pads el búfer, mientras que el último se trunca.
Hay algunos miembros privados de esta clase que se utilizan para asignar espacio en el montón especial que utiliza JUCE.
Pero esto es lo que falta AudioSampleBuffer (y he tenido varias discusiones con Jules al respecto): un miembro llamó
SampleRate
. ¿Cómo puede faltar eso?La única responsabilidad que debe cumplir un AudioSampleBuffer es representar adecuadamente el audio físico que se escucha que representan sus muestras. Cuando ingresa un AudioSampleBuffer de algo que lee un archivo de sonido o de una transmisión, hay un parámetro adicional que debe obtener y pasarlo junto con el AudioSampleBuffer a los métodos de procesamiento (digamos que es un filtro) que necesita conocer la frecuencia de muestreo o, finalmente, a un método que reproduce el búfer para ser escuchado (o lo transmite a otro lugar). Lo que sea.
Pero lo que tiene que hacer es continuar pasando este SampleRate, que es inherente al audio específico que vive en AudioSampleBuffer, por todas partes. He visto código donde se pasó una constante 44100.0f a una función, porque el programador no parecía saber qué más hacer.
Este es un ejemplo de incumplimiento de su responsabilidad única.
fuente
Se puede hacer una forma concreta, en base a lo que usted dijo: que la alta cohesión conlleva una responsabilidad única que puede medir la cohesión. Una clase cohesiva máxima tiene todos los campos utilizados en todos los métodos. Si bien no siempre es posible ni deseable tener una clase de cohesión máxima, es mejor llegar a esto. Tener este objetivo de diseño de clase es bastante fácil deducir que su clase no puede tener muchos métodos o campos (algunos dicen que a lo sumo 7).
Otra forma es desde los conceptos básicos puros de OOP: modelo después de objetos reales. Es mucho más fácil ver la responsabilidad de los objetos reales. Sin embargo, si el objeto real es demasiado complejo, divídalo en múltiples objetos de contacto, cada uno de ellos tiene su propia responsabilidad.
fuente