L'SRP è un principio ambiguo? [chiuso]

4

Sono stato a conoscenza di SOLID da molti anni e ho sempre pensato che "OLID" fosse un buon insieme di principi di progettazione da seguire ... il problema è che ho sempre riscontrato difficoltà con la "S", L'ho sempre pensato come un principio molto ambiguo e credimi, ho letto di questo principio da molti posti / libri diversi ...

Oggi ho trovato questo articolo e riassume molto bene tutti i miei pensieri / dubbi su SRP.

Quindi vorrei chiederti, è davvero un principio SRP come nella coppia di definizioni qui sotto?

  1. a fundamental truth or proposition that serves as the foundation for a system of belief or behaviour or for a chain of reasoning. "the basic principles of justice" synonyms: truth, proposition, concept, idea, theory, postulate; More
  2. a general scientific theorem or law that has numerous special applications across a wide field.

Perché sto chiedendo questo? Bene, sarebbe bello se si potesse applicare SRP in modo chiaro e non ambiguo, così si finisce con lezioni o funzioni libere e si può con orgoglio dire "questo segue SRP" e lo si può dimostrare formalmente.

Quando dico "bene" intendo qualcosa "logicamente parlando" corretto. Mi piace quando l'articolo dice:

I really tried to understand the SRP, and to like it. I really tried. But I can't agree with it, and that's why I decided to publish this.

Fondamentalmente è sempre stata la mia preoccupazione, in questo caso cambierò da quella frase "è per questo che ho deciso di pubblicare questo" per "ecco perché ho deciso di chiedere qui" quindi forse qualche esperto codificatore esperto può portare alcune perle di saggezza.

    
posta BPL 13.11.2017 - 01:22
fonte

4 risposte

19

Non userei il termine ambiguo, ma senza dubbio c'è un elemento significativo del giudizio situazionale .

Per rispondere alla tua domanda in anticipo, no, non esiste un mezzo di verifica formale e matematicamente verificabile per verificarne la conformità.

Il motivo è perché non tutti i programmi software e domini sono uguali. Joel ha toccato questo argomento nel suo saggio Five Worlds . Un enorme software di gestione dei processi aziendali richiede approcci progettuali diversi rispetto al software che controlla un distributore automatico.

Riconoscerò che l'SRP è uno dei concetti più pesanti per il giudizio del gruppo SOLID e ci sono tonnellate di cattive descrizioni là fuori. Spesso volte, scritto dagli autori solidamente nell'e.g. mondo di consultingware aziendale, scrivendo affermazioni assolute completamente inconsapevoli o ignorando aspetti di altri mondi. La "ragione per cui cambiare" le persone che scrivono spesso le trovo particolarmente insensate e vaghe. Penso che i principi SOLID siano più adatti ai tipi di software di consulenza aziendale e agli autori professionisti, ad es. Lo zio Bob si guadagna da vivere vendendo i loro servizi a quei tipi di società. Quindi, a meno che tu non sia anche tu in quel mondo, devi riconoscere ciò che è appropriato per la tua situazione.

Una singola responsabilità può significare cose diverse per persone diverse in situazioni diverse. Ad esempio, di recente ho avuto bisogno di un corso per gestire le impostazioni di un programma. Quella classe legge il file di configurazione, lo analizza, ha i mezzi per accedere ai valori di configurazione e può riportare la configurazione sul disco. Tutto ciò, in una singola classe, ConfigurationSettings . Nella mia particolare circostanza, nonostante abbia fatto molte cose diverse e disparate, direi che la mia classe si attiene a una singola responsabilità: occuparsi della configurazione.

Ora, alcune persone direbbero che il mio design è difettoso, fa troppo. Dovrei iniettare in un oggetto parser di file config, avere un factory IConfig astratto che istanzia la classe ConfigSettings invece di new() , o un mucchio di altre cose per rompere ulteriormente le responsabilità di quella classe.

Chi ha ragione? Dipende da come la singola responsabilità si inserisce nel quadro più ampio. Ho visto alcuni autori fare affidamento su "ad un dato livello di astrazione" sulla descrizione della singola responsabilità, che a mio avviso ha molto senso. E così nella mia situazione, al mio livello di astrazione scelto, la mia classe ConfigurationSettings fa una sola cosa, persiste le impostazioni del mio programma. I dettagli di quel formato di file di configurazione, dove sono salvati, ecc. Sono cose che non hanno importanza nel quadro generale, e a nessuno importa dove vanno.

Che tipo di situazione ci sarebbe dove gli amanti astratti della fabbrica avrebbero ragione sulla mia classe? Spesso, sarebbero persone in quel mondo mega-impresa. Il mio software ha esattamente 1 cliente e non avrà mai più di quel singolo cliente. Posso avere un processo di aggiornamento che consiste esclusivamente di "eliminare la vecchia versione, installare quella nuova". Se introduco una modifica alle impostazioni di configurazione che non è retrocompatibile con i vecchi formati, posso semplicemente farli eliminare la vecchia configurazione e ricominciare da capo.

Non tutti possono essere così disinvolti riguardo alle loro impostazioni di configurazione. Alcune persone potrebbero scrivere software per centinaia o migliaia di clienti. Potrebbe dover gestire e preservare diversi formati tra diverse versioni del loro software. Potrebbero dover supportare una singola configurazione condivisa da più computer, tutti leggendo dallo stesso posto. Non devo fare nulla di tutto ciò. Ma per queste altre persone, il formato del file, la posizione, ecc. importa. In quelle situazioni, l'iniezione di un parser nella mia classe di configurazione potrebbe avere senso una volta capito il formato in cui si trovano le impostazioni. Potrebbe avere senso avere una fabbrica che lo capisca. Potrebbe avere senso avere un sistema di notifica per quando le impostazioni vengono modificate, invece di un insieme di variabili statiche (globali) come sto usando.

E se stavo scrivendo software per migliaia di cliniche dentistiche per pianificare appuntamenti e fare fatturazione, la mia classe di configurazione sarebbe senza dubbio non appropriata. Ma non è quello che sto facendo, così è.

A corto di intelligenza artificiale di livello skynet, nessuno strumento di analisi statica sarà in grado di esaminare una classe e capire quale sia il suo livello di astrazione previsto, e quindi non può effettuare alcuna determinazione significativa della conformità SRP o meno.

    
risposta data 13.11.2017 - 03:59
fonte
5

L'articolo in questione sembra sostenere "Big Ball of Mud" -architettura:

when one writes code, there are only real, present requirements. The future is pretty irrelevant

Questa è una visione estremamente miope dello sviluppo. Dopo tutto, se non ci interessa il futuro, perché anche cercare di scrivere codice mantenibile? Perché non usare sempre l'hack più veloce e più sporco per soddisfare i requisiti attuali?

In realtà, qualsiasi sviluppatore degno di questo nome progetterà il codice con qualche anticipazione dei cambiamenti futuri.

L'SRP lo afferma esplicitamente. Dobbiamo analizzare quali fattori possono far cambiare i requisiti in futuro e tentare di strutturare il codice seguendo queste linee. Devi capire quali forze e interessi diversi influenzano i requisiti.

In breve, devi capire il business e l'organizzazione.

Non è possibile "formalmente" e "logicamente" dimostrare che un codice segue l'SRP - il mondo è troppo complicato per questo. Tale prova dovrebbe coinvolgere non solo il codice ma anche l'intera azienda e tutte le forze esterne che lo influenzano.

    
risposta data 13.11.2017 - 19:17
fonte
3

Bob Martin ha chiarito l'SRP in alcuni discorsi e nel suo nuovo libro. Una citazione:

Of all the SOLID principles, the Single Responsibility Principle (SRP) might be the least well understood. That's likely because it has a particularly inappropriate name. It is too easy for programmers to hear the name and then assume that it means that every module should do just one thing.

Significa che non significa. Ciò che l'onorevole Martin sta cercando di dire è che ogni particolare modulo dovrebbe essere riservato ad un unico agente di cambiamento.

L'identificazione degli agenti di cambiamento dipende probabilmente dalle dimensioni dell'organizzazione / progetto, ma una volta identificata, dovrebbe essere chiaro chi può influenzare quali moduli.

Ad esempio, scrivo app iOS. Ho moduli che sono legati al progettista dell'interfaccia utente, al progettista UX e allo sviluppatore del server. Se una modifica al server può causare la modifica del modulo S, non ci dovrebbe essere nulla in quel modulo che dovrebbe essere modificato poiché il progettista ha deciso di modificare le dimensioni di un pulsante. Né dovrebbe esserci qualcosa in quel modulo che dovrebbe cambiare perché il progettista UX voleva cambiare il flusso logico dell'app.

In una delle altre risposte, viene utilizzato un esempio di una classe "impostazioni". Poiché la classe è descritta, interrompe l'SRP perché dovrebbe cambiare se cambia il metodo di salvataggio delle informazioni o se cambia la logica di ciò che deve essere salvato. Queste sono due preoccupazioni diverse che cambiano per diversi motivi. Cambiare il modo in cui le cose vengono salvate causerebbe l'aggiornamento della classe e la modifica di ciò che deve essere salvato causerebbe anche l'aggiornamento.

In Response To Comments: Fondamentalmente, l'SRP è il principio che si sta seguendo quando si separa il codice di visualizzazione / presentazione dal modello / codice logico. È il principio che stai seguendo quando separi il codice che accede al database dal codice che decide cosa viene salvato nel database.

Ulteriore modifica in risposta ai commenti: nei commenti, l'OP sta rendendo chiaro che sta cercando un "modo non ambiguo" per determinare chi sono gli agenti di cambiamento, se un particolare modulo segue l'SRP. C'è, ma non è universale. Come sviluppatore, probabilmente sai chi può e non può fare richieste di modifica, o forse il tuo codice è basato su diversi documenti di requisiti, nel qual caso questi sono gli agenti di modifica. Nel mio caso, ad esempio, ho documenti di casi d'uso che definiscono la logica, quindi ho documenti di tipo "look-and-feel" che definiscono la presentazione, e ho documenti di endpoint del server che definiscono l'integrazione del server. Infine, ho anche le mie esigenze tecniche che definiscono cose come la strategia di archiviazione e le aree nel codice in cui voglio lasciare aperta la possibilità di aggiungere / rimuovere moduli esterni. Quindi nel mio caso, ho 4 agenti di cambiamento. In altre società, la strategia di archiviazione potrebbe essere un editto a livello aziendale che aggiungerebbe un agente di modifica. In altre situazioni potrebbe non esserci alcuna integrazione del server che rimuoverebbe un agente di modifica.

    
risposta data 14.11.2017 - 04:14
fonte
-1

È un'affermazione assoluta. Se qualcuno suggerisce un modo per dividere una classe in due, in cui la nuova classe non ha bisogno di accedere all'originale. Quindi l'SRP dice che dovresti dividerlo.

C'è anche un limite a quanto puoi dividere qualsiasi classe. Hai solo tante righe di codice. Ma anche a parte questo hai solo tanti parametri con cui giocare con un metodo.

L'ipotesi è che le classi più piccole siano sempre migliori. Sono decisamente più flessibili e riducono il potenziale codice ripetuto. Penso che potresti dire accademicamente che è meglio.

L'unica domanda è se il profitto aziendale è sufficiente per giustificare lo sforzo. Ovviamente hai un po 'di stangato da scrivere con ogni classe che aggiungi. Quindi, a meno che in realtà non riduca la duplicazione del codice in pratica, è solo una maggiore digitazione.

    
risposta data 13.11.2017 - 16:03
fonte