Si prega di spiegare perché abbiamo bisogno di SRP in "Plain English" nonostante i suoi inconvenienti?

4

Puoi in "semplice inglese" spiegare perché abbiamo bisogno del principio di singola responsabilità ?

Soprattutto che sposta quello che io chiamo "gonfio" in altri posti. Vedi sotto per maggiori informazioni. Con bloat intendo nel mio caso specifico, ho più responsabilità in un controller che si presentano come funzioni / metodi. Applicando SRP nel modo che ho capito, suddivide il controller in diversi controller, ciascuno con un metodo. Il "bloat" viene quindi spostato da "numero di metodi" a "numero di file".

L'articolo nel link wiki sopra spiega cos'è l'SRP, ma non sembra dirmi "perché" lo usiamo. Mi piacerebbe una ragione / spiegazione / senso non tecnico (o forse anche tecnico) per quanto riguarda perché abbiamo bisogno di questo principio.

Perché nella mia attuale esperienza, l'implementazione di SRP porta a un codice più piccolo e allineato in modo più ristretto, ma crea più file.

Esempio

Ho un file controller che può avere molte varie azioni / metodi al suo interno. Per mantenere tutte quelle azioni nel controller, devo gonfiare il numero di dipendenze che devo passare al controller, perché le dipendenze devono coprire tutte le azioni possibili, anche se qualsiasi azione particolare non ha bisogno di tutte delle dipendenze.

quindi posso suddividere il controller in 2 o più pezzi dove ho un'azione per controller. Questo soddisfa l'SRP, ma aumenta di massa il numero di file che devo creare.

Esempio

/*
 * Repository initialized with $quoteId
 */
class Repository
{
    private $quoteId;

    function __construct($quoteId)
    {
        $this->quoteId = $quoteId;
    }        
}

/*
 * Controller initialized with $repository
 */   
class Controller
{

    private $repository;

    function __construct($repository)
    {
        $this->repository = $repository;
    }        

    function addForm()
    {
         //repository is initialized elsewhere with $quoteId
         $this->repository->getFormDataFromQuote();
    };

    function viewForm()
    {
         $id = int_val($_GET['id']);

         //does *not* use $quoteID
         $this->repository->getViewDataFromId($id);
    };
}

SRP

Per rispettare SRP possiamo suddividere il controller in due, uno per addForm, uno per viewForm. Quindi possiamo suddividere il repository in due, uno per ciascun metodo in Controller. Quindi, abbiamo iniziato con 2 file, per finire con 4 file.

Inconvenienti

Interpreto SRP qui come "Spezza il controller" (e, presumo anche altri file di supporto, come Repository qui) in due in questo caso. Quindi nell'esempio sopra ci saranno ControllerAddForm e ControllerViewForm , e se sto usando un repository per quei metodi, che sono, devo creare RepositoryViewForm e RepositoryAddForm per soddisfare anche SRP, perché sono richiesti metodi di repository diversi per le diverse azioni del Controller. Quindi, ottengo 2x file gonfiati. Perché ancora una volta è raccomandato SRP, nonostante lo spostamento del numero di file anziché del numero di metodi per file.

    
posta Dennis 07.11.2017 - 22:43
fonte

4 risposte

12

Hai bisogno dell'SRP per gli stessi motivi per cui non permetti al tuo Sous Chef di riparare la tua auto. Hanno responsabilità diverse.

Ogni persona è specializzata in una diversa area di competenza. Se aiuta, pensa alle tue lezioni come dipendenti. Dare a ciascuno un titolo di lavoro; di solito è il nome di ogni classe. Elabora la "area di competenza" di quella classe e poi scrivi il codice che soddisfa quell'area di competenza.

    
risposta data 07.11.2017 - 23:13
fonte
12

SRP è uno dei principi di ingegneria del software più fraintesi. Non c'è nemmeno una definizione precisa di cosa sia una "responsabilità", rendendo questo più difficile da comprendere.

In parole povere, una "responsabilità" non è una singola azione atomica, ma piuttosto una serie di azioni strettamente correlate. L'aggiunta di un modulo, la visualizzazione di un modulo, l'invio di un modulo, ecc. Sono tutti la stessa responsabilità di "gestione del modulo X".

To abide SRP we can break up Controller into two, one for addForm, one for viewForm.

No. Per rispettare SRP, hai controller separati per la gestione delle quotazioni e la gestione dei clienti. Possono delegare a modelli che gestiscono la persistenza per ogni tipo di dati (preventivi e clienti).

In generale, refactoring di grandi unità di codice in unità più piccole di codice è una buona idea fino al punto che ci sono troppe piccole unità di codice su cui ragionare. Personalmente, penso che mantenere tutto il mio codice "gestisci quote" in una classe è una grande idea: so esattamente dove cercare il codice del controller per le virgolette. So che tutto il codice è lì per questo scopo, ma nessun codice per la gestione dei clienti.

Si noti inoltre che SRP come si applica a un sistema di gestione delle quote basato sul web sarà diverso rispetto al kernel Linux. Fai un passo indietro e guarda il design generale, e prova a trovare le divisioni naturali in ciò che sta facendo il codice. Quindi chiedi a uno dei tuoi colleghi .

    
risposta data 07.11.2017 - 23:14
fonte
3

SRP è pericoloso (come la maggior parte dei principi di progettazione) se lo segui come dogma. La mia prospettiva è di rispettare SOLID ma attenti al suo strong culto (ure), specialmente quando qualcuno sparge più calore della luce citando questi principi.

Quando ho letto la tua domanda, ho pensato che SRP fosse in opposizione a YAGNI .

Usando l'esempio del tuo controller, ha poco senso separare il tuo controller in classi distinte se i requisiti mai cambiano, non manterrai il progetto dopo la demo di "Shark tank", e / o non avrai mai bisogno di riutilizzare parte della logica del controller in un altro progetto. Sono tutti grandi se possibile.

Robert Martin fornisce un esempio dettagliato utilizzando il codice in un progetto di bowling. Il design porta a una classe Game che ha due responsabilità: tenere traccia dei frame e calcolare il punteggio.

Nell'esperimentodiprogettazionedellaprogrammazioneincoppianelsuolibro,unodeglisviluppatorifiniscepersuggerirediridefinirequesteresponsabilitàseparateinclassidistinte,GameeScorer,citandoSRPcomemotivazione.UncommentosarcasticoèfattocheiprogrammatoridiLinuxamanofaretuttoinunasingolafunzioneilleggibile...

ÈunbuonesempiodiYingeYangdell'SRP.AveremoduliseparatiperleresponsabilitàdiGameandScoringhailvantaggiodiconsentireaiduedievolversiinmodopiùindipendente,forseanchediconsentireaunnuovoprogrammatoreditrovaredovenelcodicepotrebbeesserepresenteunbuginsidiosonelpunteggio(cisonomenorigheinScorerdisetuttoilcodicefossecombinatoinunmodulo),ecc.Questeclassipotrebberoteoricamenteessereriutilizzateinaltreapplicazionichenecessitanodeiloroservizi( Jarts qualcuno?).

Ma c'è un lato negativo: anticipare i cambiamenti che non si verificheranno mai è uno spreco di energie. Quali cambiamenti potrebbero venire alle regole del gioco del bowling !? Teoricamente esistono (ehi, potrebbe esserci un ordine esecutivo da 45?) E se accadessero, avere moduli separati sarebbe sicuramente meglio allora, giusto?

Ahimè, YAGNI dice che non sprecare le tue energie sui cambiamenti finché non arrivano. È un eccesso di tecnologia.

Infine, SRP (e il design orientato alla responsabilità in generale) è un euristico (nel senso sembra che abbia funzionato in passato, ma non è garantito che applicandolo ne trarrai vantaggio). Nessuno ha fatto abbastanza ricerche per dirti quando ripaga. I problemi di progettazione sono difficili e il tentativo di utilizzare un "principio" dogmaticamente porterà ad una delusione.

Ho trovato il Principles Wiki davvero interessante (anche se incompleto) perché tenta di mappare le relazioni tra questi vari principi di progettazione. Per SRP, ci sono molti principi correlati, ad es. Separazione delle preoccupazioni, legge di Curly, ecc. . Leggere quelli ti aiuterà anche a capire i trade-off.

    
risposta data 10.11.2017 - 22:43
fonte
1

Il principio di responsabilità singola (SRP)

Le classi non dovrebbero avere più di un focus di responsabilità. Il contesto lavorativo determinerà anche il livello di segregazione delle responsabilità in una classe.

Nota:

  • Le classi possono essere ragionevolmente coinvolte in diverse interazioni, lo è l'attenzione è il problema.
  • Questo principio è quasi identico al principio di coesione

Analisi SRP: ad esempio, guarda ogni metodo, x, nella classe, diciamo Car , e chiedi, " Car ha la responsabilità primaria di x-ing?" Se la risposta è no, il metodo potrebbe non esserci. Chiedi in merito a object , non a action .

    
risposta data 07.11.2017 - 23:29
fonte

Leggi altre domande sui tag