Qual è la differenza tra il principio di responsabilità singola e la separazione delle preoccupazioni


19

a) Qual è la differenza tra SRP e SoC ? Forse l' SRP viene applicato a livello di classe, mentre il SoC può essere applicato a livello di sistema , sottosistema , modulo , classe o funzione .

b) Se la risposta a ) è sì, il SoC applicato a livello di classe è sinonimo di SRP ?

grazie

Risposte:


13

Il principio di responsabilità singola riguarda il fatto che il tuo codice faccia solo 1 cosa e puoi dividere tutte le funzionalità in diverse classi che sono tutte pensate per fare 1 cosa specifica. Un esempio è una classe specifica per la convalida, la logica aziendale, l'arricchimento di un modello, il recupero dei dati, l'aggiornamento dei dati, la navigazione, ecc.

La separazione delle preoccupazioni riguarda il fatto che il codice non sia strettamente associato ad altre classi / sistemi. L'uso delle interfacce nel tuo codice aiuta molto, in questo modo puoi associare liberamente le classi / i sistemi al tuo codice. Un aspetto negativo di questo è che è più facile testare anche il tuo codice. Ci sono molti framework (IoC) che possono aiutarti a raggiungere questo obiettivo, ma puoi anche implementare una cosa del genere, ovviamente.

Un esempio di qualcosa di SoC, ma senza 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();
    }
}

Come puoi vedere, questo codice non è strettamente associato a classi o altri sistemi, perché usa solo alcune interfacce per fare cose. Questo è buono dal punto di vista del SoC.

Come puoi vedere questa classe contiene anche 3 metodi privati ​​che fanno cose fantasiose. Da un punto di vista SRP, questi metodi dovrebbero probabilmente essere inseriti in alcune classi a parte. 2 di loro fanno qualcosa con la navigazione, che rientrerebbe in una classe di INavigation. L'altro esegue alcuni calcoli elaborati su un oggetto, questo potrebbe probabilmente essere inserito in una classe IBusinessLogic.

Avendo qualcosa del genere, entrambi avete il SoC e SRP a posto:

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();
    }
}

Ovviamente potresti discutere se tutta questa logica debba essere inserita nel GetDataAndNavigateSomewhereIfValidmetodo. Questo è qualcosa che dovresti decidere da solo. A me sembra che questo metodo stia facendo troppe cose.


"Dopo aver letto l'intero post nella risposta di JB King, penso che sia anche un buon post." Ma la risposta di JB King sta sostenendo il contrario della tua risposta - vale a dire che il SoC riguarda anche la singola responsabilità, solo che può essere applicato a livelli più alti rispetto a SRP
user1483278

2

Per quanto riguarda l'SRP applicato solo a livello di classe, nei suoi libri Robert C. Martin (per quanto ne so ha reso popolare se non è venuto fuori con il concetto) afferma:

Codice pulito, pagina. 138 : "Il Single Responsibility Principle (SRP) afferma che una classe o un modulo dovrebbe avere una, e una sola, ragione per cambiare".

In Agile Principles, Patterns and Practices in C #, page 116 : "[...] e correlare la coesione alle forze che causano il cambiamento di un modulo o di una classe."

Enfasi mia.

In APPP parla più a lungo di SRP e si concentra quasi interamente a livello di classe. Mentre sembra concentrarsi sul livello di classe, penso che il principio sia anche diretto ai moduli e ad altri costrutti di livello superiore.

Per tale motivo non classificherei SRP come SoC a livello di classe, come suggerisci nella tua domanda.


Quindi se assumiamo che SRP possa essere applicato anche a livelli più alti, allora la differenza tra SRP e SoC è che SRP ha una sola responsabilità, mentre SoC può avere una serie di responsabilità strettamente correlate?
user1483278

@ user1483278: Beh, ho molta familiarità con SRP ma ho sentito parlare per la prima volta del SoC mentre leggevo questa domanda, quindi non posso rispondere alla domanda nel tuo commento. Dalla semantica sembra che SRP riguardi 1 responsabilità e preoccupazioni che separano il SoC, so che è una risposta pedante, ma in termini di applicazione i principi di fastidio producono risultati simili.
Gilles,

0

Qui puoi trovare un breve video che spiega chiaramente la differenza tra queste terminologie. https://www.youtube.com/watch?v=C7hkrV1oaSY

Separazione delle preoccupazioni (SoC). Dividi la tua applicazione in funzionalità distinte con la minima sovrapposizione di funzionalità possibile. (Microsoft).

“Preoccupazione” = “distinto caratteristica” = “distinta sezione”

"Preoccupazione" funziona sia a livelli alti che bassi

Il principio di responsabilità unica stabilisce che ogni modulo o classe dovrebbe avere la responsabilità su una singola parte della funzionalità fornita dal software e che la responsabilità dovrebbe essere interamente incapsulata dalla classe. Tutti i suoi servizi dovrebbero essere strettamente allineati a tale responsabilità. (Definizione di Wikipedia)

“Responsibility” = “motivo per cambiare”

cambiare cosa? "Una singola parte della funzionalità fornita dal software" = Unità base

Conclusione

Il principio di responsabilità singola funziona su unità di base -> funziona a basso livello

La separazione delle preoccupazioni funziona sia a livelli alti che bassi

SRP e SoC lavorano insieme per la separazione delle preoccupazioni. Sono esattamente gli stessi a basso livello


0

Ecco la mia comprensione di questi principi.

Separation of Concerns (SoC) : si tratta di dividere un sistema software in moduli più piccoli, ognuno su questi moduli è responsabile di una singola preoccupazione. Una preoccupazione, in questo caso, è una caratteristica o un caso d'uso di un sistema software. Un modulo ha un'API (interfaccia) ben definita di conseguenza che rende l'intero sistema altamente coeso. Esistono due tipi principali: orizzontale e verticale.

Single Responsibility Principle (SRP) - è un principio di progettazione che afferma che ogni blocco predefinito (può essere una classe, un modulo, un oggetto o persino una funzione) di un sistema dovrebbe avere una sola responsabilità. Robert C. Martin. Martin descrive una responsabilità come una ragione per cambiare. In generale, è molto meglio avere una singola classe / oggetto che ha la responsabilità su una singola parte della funzionalità invece di essere in grado di eseguire molte funzioni, a volte anche non correlate, rendendo questa classe grande e strettamente accoppiata, quindi- chiamato "oggetto di Dio".

Inoltre ho descritto questi principi in maggiore dettaglio nel mio post sul blog, per favore dai un'occhiata.

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

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.