Non c'è una risposta chiara a questo. Sebbene la domanda sia ristretta, le spiegazioni no.
Per me, è qualcosa come Occam's Razor se vuoi. È un ideale in cui provo a misurare il mio codice attuale. È difficile inchiodarlo con parole semplici e chiare. Un'altra metafora sarebbe »un argomento« che è tanto astratto, cioè difficile da comprendere, quanto »una sola responsabilità«. Un terzo descripton verrebbe a "occuparsi di un livello di astrazione".
Cosa significa praticamente?
Ultimamente uso uno stile di codifica che consiste principalmente in due fasi:
La fase I è meglio descritta come caos creativo. In questa fase scrivo il codice mentre scorrono i pensieri, cioè crudo e brutto.
La fase II è l'esatto contrario. È come pulire dopo un uragano. Questo richiede più lavoro e disciplina. E poi guardo il codice dal punto di vista di un designer.
Sto lavorando principalmente in Python ora, il che mi permette di pensare a oggetti e classi in seguito. Prima fase I : scrivo solo funzioni e le diffondo quasi casualmente in diversi moduli. Nella fase II , dopo che le cose sono andate avanti, ho uno sguardo più da vicino a quale modulo si occupa di quale parte della soluzione. E mentre sfoglio i moduli, gli argomenti mi emergono. Alcune funzioni sono tematicamente correlate. Questi sono buoni candidati per le lezioni . E dopo che ho trasformato le funzioni in classi - il che è quasi finito con il rientro e l'aggiunta self
all'elenco dei parametri in Python;) - Uso SRP
come Occam's Razor per eliminare funzionalità ad altri moduli e classi.
Un esempio attuale potrebbe essere la scrittura di piccole funzionalità di esportazione l'altro giorno.
C'era la necessità di fogli CSV , Excel e Excel combinati in una zip.
La normale funzionalità è stata eseguita in tre viste (= funzioni). Ogni funzione utilizzava un metodo comune per determinare i filtri e un secondo metodo per recuperare i dati. Quindi in ciascuna funzione ha avuto luogo la preparazione dell'esportazione ed è stata consegnata come risposta dal server.
C'erano troppi livelli di astrazione confusi:
I) gestire la richiesta / risposta in entrata / in uscita
II) determinazione dei filtri
III) recupero dei dati
IV) trasformazione dei dati
Il semplice passo era usare un'astrazione ( exporter
) per trattare gli strati II-IV in un primo passo.
L'unica cosa rimasta era l'argomento relativo alle richieste / risposte . Allo stesso livello di astrazione sta estraendo i parametri di richiesta, il che va bene. Quindi ho avuto per questo punto di vista una "responsabilità".
In secondo luogo, ho dovuto interrompere l'esportatore, che come abbiamo visto consisteva in almeno altri tre strati di astrazione.
La determinazione dei criteri di filtro e l'effettivo recupero sono quasi allo stesso livello di astrazione (i filtri sono necessari per ottenere il sottoinsieme corretto dei dati). Questi livelli sono stati inseriti in qualcosa di simile a un livello di accesso ai dati .
Nel passaggio successivo ho suddiviso gli attuali meccanismi di esportazione: laddove era necessaria la scrittura su un file temporale, l'ho suddivisa in due "responsabilità": una per la scrittura effettiva dei dati su disco e un'altra parte che si occupava del formato effettivo.
Lungo la formazione delle classi e dei moduli, le cose sono diventate più chiare, ciò che apparteneva a dove. E sempre la domanda latente, se la classe fa troppo .
Come si determinano le responsabilità che ogni classe dovrebbe avere e come si definisce una responsabilità nel contesto di SRP?
È difficile dare una ricetta da seguire. Ovviamente potrei ripetere il criptico "un livello di astrazione" - regola se questo aiuta.
Principalmente per me è una sorta di "intuizione artistica" che porta al design attuale; Modello il codice come un artista può scolpire l'argilla o dipinge.
Immaginami come un programmatore Bob Ross ;)