In questi giorni non mi sembra utile discutere di ciò che fa e non costituisce una singola responsabilità o un singolo motivo per cambiare. Proporrei un principio minimo di dolore al suo posto:
Minimum Grief Principle: code should either seek to minimize its probability of requiring changes or maximize the ease of being changed.
Come va? Non dovresti prendere uno scienziato missilistico per capire perché questo può aiutare a ridurre i costi di manutenzione e, si spera, non dovrebbe essere un punto di discussione senza fine, ma come con SOLID in generale, non è qualcosa da applicare ciecamente ovunque. È qualcosa da considerare mentre si bilanciano i trade-off.
Per quanto riguarda la probabilità di richiedere modifiche, questo va giù con:
- Buona prova (affidabilità migliorata).
- Coinvolgere solo il codice minimo richiesto per fare qualcosa di specifico (questo può includere la riduzione degli accoppiamenti afferenti).
- Semplicemente facendo in modo che il codice funzioni in modo soddisfacente (vedi a fare il principio Badass).
Per quanto riguarda la difficoltà di apportare modifiche, va incontro a accoppiamenti efferenti. I test introducono accoppiamenti efferenti ma migliorano l'affidabilità. Fatto bene, generalmente fa più bene del male ed è totalmente accettabile e promosso dal Principio del lutto minimo.
Make Badass Principle: classes that are used in many places should be awesome. They should be reliable, efficient if that ties to their quality, etc.
E il principio Make Badass è legato al principio del dolore minimo, poiché le cose più difficili troveranno una probabilità inferiore di richiedere modifiche rispetto alle cose che fanno schifo in quello che fanno.
I would have started by pointing to the paradox mentioned above, and
then indicate that the SRP is highly dependent on the level of
granularity you want to consider and that if you take it far enough,
any class containing more than one property or one method violates it.
Da un punto di vista della SRP una classe che a malapena fa qualsiasi cosa avrebbe certamente solo una (a volte zero) ragioni per cambiare:
class Float
{
public:
explicit Float(float val);
float get() const;
void set(float new_val);
};
Questo praticamente non ha motivi per cambiare! È meglio di SRP. È ZRP!
Tranne che suggerirei che è in palese violazione del principio Make Badass. È anche assolutamente inutile. Qualcosa che fa così poco non può sperare di essere tosta. Ha troppe poche informazioni (TLI). E naturalmente quando hai qualcosa che è TLI, non può fare nulla di veramente significativo, nemmeno con le informazioni che incapsula, quindi deve farlo trapelare al mondo esterno nella speranza che qualcun altro possa effettivamente fare qualcosa di significativo e di cazzuto. E quel leakiness è ok per qualcosa che è solo inteso per aggregare dati e nient'altro, ma quella soglia è la differenza che vedo tra "data" e "objects".
Ovviamente qualcosa che è TMI è anche male. Potremmo mettere il nostro intero software in una classe. Può anche avere solo un metodo run
. E qualcuno potrebbe anche obiettare che ora ha una ragione molto ampia per cambiare: "Questo corso dovrà essere modificato solo se il software ha bisogno di miglioramenti". Sono sciocco, ma naturalmente possiamo immaginare tutti i problemi di manutenzione con questo.
Quindi c'è un atto di bilanciamento per quanto riguarda la granularità o la ruvidezza degli oggetti che disegni. Spesso la giudico in base a quanta informazione devi svelare al mondo esterno e a quanta funzionalità significativa possa offrire. Trovo spesso utile il principio Make Badass per trovare l'equilibrio combinandolo con il Principio del lutto minimo.