Convalida dell'architettura pulita nel livello di persistenza dominio vs dati?


13

Sto studiando in modo pulito e, di conseguenza, sto ripensando in modo abbastanza drammatico il modo in cui progetto e scrivo software.

La cosa con cui sto ancora lottando, tuttavia, è per le regole di business come "sul salvataggio degli aggiornamenti di un elemento, prima carica tutto l'elenco degli elementi che ho il permesso di visualizzare / modificare ecc., Conferma che questo elemento è nell'elenco, e che la categoria di articoli non è attualmente bloccata dall'uso, (e altre regole, ecc. ecc.) "perché si tratta di una regola aziendale (complessa ma non atipica) e quindi dovrebbe essere gestita nel dominio dell'applicazione piuttosto che inserire la logica aziendale in il livello db / persistenza.

Tuttavia, mi sembra che per controllare efficacemente queste condizioni, sarà spesso meglio gestirlo con una query db ben realizzata, piuttosto che caricare tutti i dati nel dominio dell'applicazione ...

Senza ottimizzazione prematura, qual è l'approccio raccomandato o alcuni articoli di zio Bob che si occupano di questa domanda? O direbbe "convalida nel dominio fino a quando non diventa un problema" ??

Faccio davvero fatica a trovare qualche buon esempio / campione per qualcosa di diverso dal più semplice dei casi d'uso.

Aggiornare:

Ciao a tutti, grazie per le risposte. Avrei dovuto essere più chiaro, sto scrivendo software (principalmente app web) da molto tempo e sicuramente ho già sperimentato e concordato con tutti gli argomenti che descrivi collettivamente (convalida per backend, non fidarti dei dati dei clienti, in generale parlando inseguire l'efficienza grezza solo quando richiesto, tuttavia riconoscere i punti di forza degli strumenti db quando disponibili, ecc. ecc. e aver attraversato il ciclo di vita dell'apprendimento degli sviluppatori di "unire tutto insieme" per "costruire un controller di grasso gigante con applicazioni di livello N" tendenze del codice , e ora piace molto e studia lo stile pulito / di responsabilità individuale ecc., fondamentalmente come il risultato di alcuni progetti recentemente che si sono evoluti in regole di business piuttosto ingombranti e ampiamente distribuite man mano che i progetti si sono evoluti e sono venute alla luce ulteriori esigenze dei clienti.

In particolare, sto esaminando l'architettura in stile pulito nel contesto della creazione di apis REST per funzionalità client-side e per uso interno, in cui molte delle regole aziendali potrebbero essere molto più complesse di praticamente ogni esempio che vedi in rete (anche dagli stessi ragazzi dell'architettura Clean / Hex).

Quindi suppongo che stavo davvero chiedendo (e non sono riuscito a dichiarare chiaramente) come si collocherebbero l'API Clean e un REST, dove la maggior parte delle cose MVC che vedi in questi giorni ha validatori di richieste in arrivo (ad esempio la libreria FluentValidation in .NET), ma dove molti di le mie regole di "convalida" non sono così tante "è questa una stringa di meno di 50 caratteri" ma più "può questo utente che chiama questo utente / interattore eseguire questa operazione su questa raccolta di dati dato che alcuni oggetti correlati sono attualmente bloccati dal Team X fino a fine mese, ecc. ecc. "... quel tipo di convalide profondamente coinvolte in cui sono applicabili MOLTI oggetti di dominio aziendale e regole di dominio.

Devo estrapolare queste regole in un tipo specifico di tipo di oggetto Validator per accompagnare ogni interattore di base utente (ispirato al progetto FluentValidator ma con più logica aziendale e accesso ai dati coinvolti), se dovessi trattare la convalida in qualche modo come un gateway, dovrei mettere quelle convalide IN un gateway (che penso sia sbagliato), ecc. ecc.

Per riferimento, sto uscendo da diversi articoli come questo , ma Mattia non discute molto della validazione.

Ma immagino che la risposta breve alla mia domanda sia molto simile alla risposta che ho accettato: "Non è mai facile e dipende".


2
C'è spesso una differenza tra essere "corretti" ed essere "pratici". Vista la scelta, quale preferisci?
Robert Harvey,

"carica tutto l'elenco degli articoli" non sembra una regola aziendale, sembra che si stia immergendo troppo nei dettagli dell'implementazione. Se riesci a soddisfare la regola utilizzando una query db, senza caricare nulla, perché la regola dice "carica"?
Smetti di fare del male a Monica il

Risposte:


31

La convalida dell'inserimento dei dati è una di quelle cose in cui tutti iniziano a cercare di renderlo puro e pulito e (se sono furbi) alla fine si arrendono, perché ci sono così tante preoccupazioni in competizione.

  • Il livello dell'interfaccia utente deve eseguire alcune forme di convalida proprio sulla pagina / modulo del client per fornire un feedback in tempo reale all'utente. In caso contrario, l'utente trascorre molto tempo in attesa di feedback mentre una transazione pubblica attraverso la rete.

  • Poiché il client viene spesso eseguito su una macchina non attendibile (ad esempio in quasi tutte le applicazioni Web), queste routine di convalida devono essere eseguite nuovamente sul lato server in cui il codice è attendibile.

  • Alcune forme di validazione sono implicite a causa di vincoli di input; ad esempio, una casella di testo può consentire solo l'inserimento numerico. Ciò significa che potresti non avere un "è numerico?" validatore sulla pagina, ma ne avrai ancora bisogno sul back-end, da qualche parte, poiché i vincoli dell'interfaccia utente potrebbero essere bypassati (ad esempio disabilitando Javascript).

  • Il livello dell'interfaccia utente deve eseguire alcune forme di convalida sul perimetro del servizio (ad esempio codice lato server in un'applicazione Web) al fine di isolare il sistema da attacchi di iniezione o altre forme dannose di immissione dei dati. A volte questa convalida non è nemmeno nella tua base di codice, ad esempio la convalida della richiesta ASP.NET .

  • Il livello dell'interfaccia utente deve eseguire alcune forme di convalida solo per convertire i dati immessi dall'utente in un formato comprensibile dal livello aziendale; ad esempio, deve trasformare la stringa "26/06/2017" in un oggetto DateTime nel fuso orario appropriato.

  • Il livello aziendale dovrebbe eseguire la maggior parte delle forme di convalida perché, ehi, appartengono al livello aziendale, in teoria.

  • Alcune forme di convalida sono più efficienti a livello di database, specialmente quando sono necessari controlli di integrità referenziale (ad esempio per garantire che un codice di stato sia nell'elenco di 50 stati validi).

  • Alcune forme di convalida devono verificarsi nel contesto di una transazione di database a causa di problemi di concorrenza, ad es. La prenotazione di un nome utente univoco deve essere atomica, in modo che altri utenti non la afferrino durante l'elaborazione.

  • Alcune forme di convalida possono essere eseguite solo da servizi di terze parti, ad esempio quando si convalida che un codice postale e un nome di città vanno insieme.

  • In tutto il sistema, possono verificarsi controlli null e controlli di conversione dei dati su più livelli, per garantire ragionevoli modalità di errore in presenza di difetti del codice.

Ho visto alcuni sviluppatori provare a codificare tutte le regole di convalida nel livello aziendale, quindi gli altri livelli lo chiamano per estrarre le regole aziendali e ricostruire la convalida su un livello diverso. In teoria questo sarebbe fantastico perché si finisce con un'unica fonte di verità. Ma non ho mai visto questo approccio fare altro che complicare inutilmente la soluzione, e spesso finisce male.

Quindi, se ti stai uccidendo mentre cerchi di capire dove va il tuo codice di convalida, tieni presente che, in una soluzione pratica anche a un problema moderatamente complesso, il codice di convalida finirà per andare in diversi punti.


Se ritieni che la tua interfaccia utente gestisca tutti i feedback degli utenti, puoi semplicemente inviare la maggior parte del controllo di convalida nel database e conservare solo ciò che non puoi fare al livello aziendale. Il problema sorge se si progetta un'API back-end completa con una risoluzione dei messaggi molto dettagliata.
Walfrat,

2

La convalida fa parte del livello aziendale.

Il punto è: la logica aziendale nei DAO invaliderà il concetto di DAO. Effettuare la convalida in qualsiasi livello superiore comporterà una convalida ridondante se si chiamano operazioni aziendali da un altro caso d'uso.

Forse valuti un po 'di sicurezza nell'interfaccia utente. Ma questo è facoltativo poiché gli oggetti di dominio protetti faranno il lavoro importante. Nell'interfaccia utente renderà i componenti visibili o invisibili a seconda delle autorizzazioni dell'utente attualmente connesso. Ma questa è solo una parte dell'esperienza dell'utente. Non si desidera che l'utente si imbatta in eccezioni di sicurezza ogni volta che tenta di eseguire un'azione che non gli è consentito.


2

Potresti voler controllare la tua prospettiva su chi sta facendo ciò che riguarda la convalida. È il DB, dove sai che stai lavorando con il DB? O è un servizio (che sembra essere supportato e controllato dalle operazioni DB). Nel mio progetto ogni radice aggregata ha un elenco di gruppi in grado di leggerlo e un elenco di modificatori. Quando il codice cerca una radice specifica o un elenco di radici che l'utente può vedere, tutti i dettagli sono nascosti dietro un servizio che prende l'id utente e le parti extra del contesto di ricerca come dove il riquadro inizia con "blah". Al codice non importa che il DB esegua un controllo esistente per vedere se i gruppi dell'utente esistono nei gruppi dei lettori. Si aspetta semplicemente un elenco con o senza contenuto in base a ciò che fornisce il servizio, che è definito solo dal contratto.

Questo vale per tutti i livelli. L'uniformità della convalida è la chiave. Metti il ​​maggior numero possibile di convalide nel dominio. Restituisci i vincoli con la tua API. Sono la fine, non pensare ai vincoli provenienti dalla libreria X o dalla memoria Z, ma dal servizio.


0

Se una logica di convalida viene espressa nel modo più semplice e più chiaro sotto forma di una query del database, allora vai avanti, hai la tua risposta. Ma l' efficienza dovrebbe essere un problema solo se si riscontra un problema di prestazioni noto, altrimenti si tratta di un'ottimizzazione prematura.

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.