¿Cuál es la diferencia entre el principio de responsabilidad única y la separación de preocupaciones?


19

a) ¿Cuál es la diferencia entre SRP y SoC ? Quizás ese SRP se aplica a nivel de clase, mientras que SoC se puede aplicar a nivel de sistema , subsistema , módulo , clase o función .

b) Si la respuesta a a) es sí, ¿se aplica SoC a nivel de clase como sinónimo de SRP ?

gracias

Respuestas:


13

El Principio de responsabilidad única se trata de que su código solo haga 1 cosa y puede dividir toda la funcionalidad en varias clases, todas ellas destinadas a hacer 1 cosa específica. Un ejemplo es una clase específica para validación, hacer algo de lógica de negocios, enriquecer un modelo, recuperar datos, actualizar datos, navegación, etc.

La separación de inquietudes se trata de que su código no esté estrechamente vinculado a otras clases / sistemas. El uso de interfaces en su código ayuda mucho, de esta manera puede acoplar libremente clases / sistemas a su código. Una ventaja de esto es que también es más fácil hacer una prueba unitaria de su código. Hay muchos marcos de trabajo (IoC) que pueden ayudarlo a lograr esto, pero puede implementarlo usted mismo, por supuesto.

Un ejemplo de algo SoC, pero no tener SRP

public class Foo
{
    private readonly IValidator _validator;
    private readonly IDataRetriever _dataRetriever;

    public Foo(IValidator validator, IDataRetriever dataRetriever)
    {
        _validator = validator;
        _dataRetriever = dataRetriever;
    }

    public NavigationObject GetDataAndNavigateSomewhereIfValid()
    {
        var data = _dataRetriever.GetAllData();

        if(_validator.IsAllDataValid(data))
        {
            object b = null;
            foreach (var item in data.Items)
            {
                b = DoSomeFancyCalculations(item);
            }

            if(_validator.IsBusinessDataValid(b))
            {
                return ValidBusinessLogic();
            }
        }
        return InvalidItems();
    }

    private object DoSomeFancyCalculations(object item)
    {
        return new object();
    }
    private NavigationObject ValidBusinessLogic()
    {
        return new NavigationObject();
    }

    private NavigationObject InvalidItems()
    {
        return new NavigationObject();
    }
}

Como puede ver, este código no está estrechamente acoplado a clases u otros sistemas, porque solo usa algunas interfaces para hacer cosas. Esto es bueno desde el punto de vista del SoC.

Como puede ver, esta clase también contiene 3 métodos privados que hacen algunas cosas elegantes. Desde el punto de vista de SRP, esos métodos probablemente deberían ubicarse dentro de algunas clases propias. 2 de ellos hacen algo con la navegación, que encajaría en alguna clase de INavigation. El otro hace algunos cálculos sofisticados sobre un elemento, esto probablemente podría ubicarse dentro de una clase IBusinessLogic.

Al tener algo como esto, ambos tienen SoC y SRP en su lugar:

public class Foo
{
    private readonly IValidator _validator;
    private readonly IDataRetriever _dataRetriever;
    private readonly IBusinessLogic _businessLogic;
    private readonly INavigation _navigation;

    public Foo(IValidator validator, IDataRetriever dataRetriever, IBusinessLogic businessLogic, INavigation navigation)
    {
        _validator = validator;
        _dataRetriever = dataRetriever;
        _businessLogic = businessLogic;
        _navigation = navigation;
    }

    public NavigationObject GetDataAndNavigateSomewhereIfValid()
    {
        var data = _dataRetriever.GetAllData();

        if(_validator.IsAllDataValid(data))
        {
            object b = null;
            foreach (var item in data.Items)
            {
                b = _businessLogic.DoSomeFancyCalculations(item);
            }

            if(_validator.IsBusinessDataValid(b))
            {
                return _navigation.ValidBusinessLogic();
            }
        }
        return _navigation.InvalidItems();
    }
}

Por supuesto, podría debatir si toda esta lógica debería colocarse en el GetDataAndNavigateSomewhereIfValidmétodo. Esto es algo que debes decidir por ti mismo. Para mí, parece que este método está haciendo demasiadas cosas.


"Después de leer la publicación completa en la respuesta de JB King, creo que también es una buena publicación". Pero la respuesta de JB King afirma lo contrario de su respuesta, a saber, que el SoC también se trata de responsabilidad única, solo que se puede aplicar a niveles más altos que SRP
user1483278

2

En cuanto a que el SRP solo se aplica a nivel de clase, en sus libros Robert C. Martin (hasta donde sé, él popularizó si no se le ocurrió el concepto) afirma:

Código limpio, página. 138 : "El Principio de Responsabilidad Única (SRP) establece que una clase o módulo debe tener una, y solo una, razón para cambiar".

En Principios, patrones y prácticas ágiles en C #, página 116 : "[...] y relaciona la cohesión con las fuerzas que hacen que un módulo , o una clase, cambie".

El énfasis es mío.

En APPP , habla con mayor extensión sobre SRP y se centró casi por completo en el nivel de clase. Si bien parece centrarse en el nivel de clase, creo que el principio también se dirige a los módulos y otras construcciones de nivel superior.

Por tal razón, no calificaría a SRP como SoC a nivel de clase como sugiere en su pregunta.


Entonces, si suponemos que SRP también se puede aplicar a niveles más altos, ¿entonces la diferencia entre SRP y SoC es que SRP tiene una única responsabilidad, mientras que SoC puede tener un conjunto de responsabilidades estrechamente relacionadas?
user1483278

@ user1483278: Bueno, estoy muy familiarizado con SRP, pero escuché por primera vez de SoC mientras leía esta pregunta, así que no puedo responder la pregunta en su comentario. Desde la semántica parece que SRP se trata de tener 1 responsabilidad y preocupaciones de separación de SoC, sé que es una respuesta pedante, pero en la aplicación los principios molestos producen resultados similares.
Gilles

0

Aquí puede encontrar un video corto que explica claramente la diferencia entre esas terminologías. https://www.youtube.com/watch?v=C7hkrV1oaSY

Separación de preocupaciones (SoC). Divida su aplicación en distintas funciones con la menor superposición de funcionalidad posible. (Microsoft)

“Preocupación” = “característica distinta” = “sección distinta”

La "preocupación" funciona tanto en niveles altos como bajos

El principio de responsabilidad única establece que cada módulo o clase debe tener responsabilidad sobre una sola parte de la funcionalidad proporcionada por el software, y esa responsabilidad debe estar completamente encapsulada por la clase. Todos sus servicios deben estar estrechamente alineados con esa responsabilidad. (Definición de Wikipedia)

"Responsabilidad" = "razón para cambiar"

cambiar que? “Una sola parte de la funcionalidad proporcionada por el software” = Unidad básica

Conclusión

El Principio de Responsabilidad Única funciona en unidades básicas -> trabaja en niveles bajos

La separación de preocupaciones funciona tanto en niveles altos como bajos

SRP y SoC trabajan juntos para separar las preocupaciones. Son exactamente iguales a bajo nivel


0

Aquí está mi comprensión de estos principios.

Separación de preocupaciones (SoC) : se trata de dividir un sistema de software en módulos más pequeños, cada uno de estos módulos es responsable de una sola preocupación. Una preocupación, en este caso, es una característica o un caso de uso de un sistema de software. Como resultado, un módulo tiene una API (interfaz) bien definida, lo que hace que todo un sistema sea altamente cohesivo. Hay dos tipos principales: horizontal y vertical.

Principio de responsabilidad única (SRP) : es un principio de diseño que establece que cada componente básico (puede ser una clase, un módulo, un objeto o incluso una función) de un sistema debe tener una sola responsabilidad. Robert C. Martin. Martin describe una responsabilidad como una razón para cambiar. En general, es mucho mejor tener una sola clase / objeto que tenga responsabilidad sobre una sola parte de la funcionalidad en lugar de poder realizar muchas funciones, a veces incluso no relacionadas, haciendo que esta clase sea grande y estrechamente acoplada, así que llamado "objeto de Dios".

También describí estos principios en mayor detalle en mi blog, por favor, eche un vistazo.

https://crosp.net/blog/software-architecture/srp-soc-android-settings-example/

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.