Pulire la convalida dell'architettura nel livello di persistenza dei dati rispetto ai domini?

8

Sto studiando su clean e di conseguenza sto ripensando in modo molto significativo a come disegno e software scrivo.

Ho una cosa con cui sto ancora combattendo, è per le regole del business come "salva gli aggiornamenti su qualche oggetto, prima carica tutto l'elenco di elementi che ho il permesso di vedere / modificare ecc., conferma che questo elemento è in la lista, e che la categoria dell'articolo non è attualmente bloccata dall'uso, (e altre regole etc etc) ".. perché questa è una regola aziendale (complessa ma non atipica), e quindi dovrebbe essere gestita nel dominio dell'applicazione piuttosto che premere logica aziendale nel livello db / persistence.

Tuttavia, mi sembra che per controllare in modo efficiente queste condizioni spesso viene gestito meglio con una query db ben realizzata, piuttosto che caricare tutti i dati nel dominio dell'applicazione ...

Senza l'ottimizzazione prematura, qual è l'approccio consigliato o alcuni articoli dello zio Bob che trattano questa domanda? O direbbe "convalidare nel dominio fino a quando non diventa un problema" ??

Sto davvero cercando di trovare buoni esempi / campioni per qualcosa di diverso dal più semplice dei casi d'uso.

Aggiornamento:

Ciao a tutti, grazie per le risposte. Avrei dovuto essere più chiaro, ho scritto (per lo più app web) per molto tempo, e ho sicuramente già sperimentato e concordato con tutti gli argomenti che descrivi collettivamente (convalidato dal backend, non mi fido dei dati dei clienti, in generale inseguire l'efficienza grezza solo quando richiesto, ma riconoscere i punti di forza degli strumenti db quando disponibili, ecc. ecc.) e passare attraverso il ciclo di vita dell'apprendimento degli sviluppatori di "buttare tutto insieme" per "costruire un controller grasso gigante con le tendenze del codice" e ora mi piace e indago sullo stile clean / single responsibility, in pratica come risultato di alcuni progetti che si sono evoluti in regole aziendali piuttosto grezze e ampiamente distribuite mentre i progetti si sono evoluti e sono venute alla luce ulteriori esigenze del cliente.

In particolare, sto osservando l'architettura degli stili Clean nel contesto della creazione di apis REST per le funzionalità client-facing e di utilizzo interno, dove molte delle regole di business potrebbero essere molto altro complesso di praticamente ogni esempio che vedi in rete (anche dagli stessi ragazzi dell'architettura Clean / Hex).

Quindi suppongo che stavo davvero chiedendo (e non avessi detto chiaramente) su come Clean e una API REST si starebbero insieme, dove la maggior parte delle cose MVC che vedi in questi giorni ha validatori di richieste in entrata (es. libreria FluentValidation in .NET), ma dove molte delle mie regole di "validazione" non sono tanto "è una stringa di meno di 50 caratteri" ma più "può questo utente che chiama questo tipo di esecuzione / interazione eseguire questa operazione su questa raccolta di dati dato che alcuni oggetti correlati sono attualmente bloccati dal Team X fino a più tardi nel mese ecc. ecc. "... questo tipo di convalide profondamente coinvolte in cui sono applicabili TANTO di oggetti del dominio aziendale e regole del dominio.

Dovrei far ruotare tali regole in un tipo specifico di tipo di oggetto Validator per accompagnare ciascun interlocutore di casi (ispirato al progetto FluentValidator ma con più logica aziendale e accesso ai dati coinvolti), dovrei trattare la convalida in qualche modo come un gateway , devo mettere quelle convalide in un gateway (che penso sia sbagliato), ecc. ecc.

Per riferimento, sto andando fuori diversi articoli come questo , ma Mattia non discutiamo molto sulla validazione.

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

    
posta Dale Holborow 22.06.2017 - 17:13
fonte

4 risposte

19

La convalida dell'inserimento dei dati è una di quelle cose in cui tutti iniziano a cercare di renderlo puro e pulito e (se sono intelligenti a questo proposito) alla fine si arrende, perché ci sono così tanti dubbi in competizione.

  • Il livello dell'interfaccia utente deve eseguire alcune forme di convalida direttamente nella pagina / modulo del cliente per fornire all'utente un riscontro in tempo reale. In caso contrario, l'utente passa molto tempo in attesa di feedback mentre una transazione viene inviata attraverso la rete.

  • Poiché il client spesso viene eseguito su una macchina non affidabile (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 convalida sono implicite a causa di vincoli di input; ad esempio, una casella di testo può consentire solo voci numeriche. Questo significa che potresti non avere un "è numerico?" validatore sulla pagina, ma ne occorrerà ancora uno sul back-end, da qualche parte, poiché i vincoli UI potrebbero essere ignorati (ad es. disabilitando Javascript).

  • Il livello dell'interfaccia utente deve eseguire alcune forme di convalida al perimetro del servizio (ad esempio codice lato server in un'applicazione Web) per 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 es. 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 che il livello aziendale può comprendere; ad esempio, deve trasformare la stringa "6/26/2017" in un oggetto DateTime nel fuso orario appropriato.

  • Il livello aziendale dovrebbe fare la maggior parte delle forme di convalida perché, in teoria, 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 presente 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. riservare un nome utente univoco deve essere atomico, quindi altri utenti non lo afferrano mentre stai elaborando.

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

  • In tutto il sistema, verifiche nulle e controlli di conversione dei dati possono verificarsi a più livelli, per garantire ragionevoli modalità di errore in presenza di errori di codice.

Ho visto alcuni sviluppatori tentare di codificare tutte le regole di convalida nel livello aziendale, e poi fare in modo che gli altri livelli lo chiamino per estrarre le regole aziendali e ricostruire la convalida su un livello diverso. In teoria sarebbe fantastico perché finisci con un'unica fonte di verità. Ma non ho mai, mai visto questo approccio fare qualcosa di diverso da complicare inutilmente la soluzione, e spesso finisce molto male.

Quindi, se ti stai uccidendo cercando di capire dove va il tuo codice di convalida, sii avvisato-- in una soluzione pratica anche a un problema moderatamente complesso, il codice di validazione finirà in diversi punti.

    
risposta data 27.06.2017 - 02:48
fonte
2

La convalida fa parte del livello aziendale.

Il punto è: la logica aziendale nei DAO invaliderà il concetto di DAO. Per eseguire la convalida in qualsiasi livello superiore, verrà eseguita la convalida ridondante se si chiamano le operazioni aziendali da un altro caso.

Forse valuti qualche sicurezza nell'interfaccia utente. Ma questo è opzionale in quanto gli oggetti del dominio protetto faranno il lavoro più importante. Nell'interfaccia utente i componenti saranno visibili o invisibili a seconda delle autorizzazioni dell'utente corrente che ha effettuato l'accesso. Ma questa è solo una parte dell'esperienza utente. Non vuoi che l'utente esegua eccezioni di sicurezza ogni volta che tenta di eseguire un'azione che non gli è consentito.

    
risposta data 27.06.2017 - 01:40
fonte
2

Potresti voler controllare la tua prospettiva su chi sta facendo la validazione vis-à-vis. È il DB, dove sai che stai lavorando con il DB? O è un servizio (che è supportato dalle operazioni di DB). Sul mio progetto ogni radice aggregata ha un elenco di gruppi che possono leggerlo e un elenco di modificatori. Quando il codice cerca una radice specifica o un elenco di root 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 se la tessera inizia con "blah". Il codice non si cura che il DB esegua un controllo esistente per vedere se i gruppi dell'utente esistono nei gruppi dei lettori. Si aspetta semplicemente una lista con o senza contenuto basato su ciò che mai il servizio, che è definito solo dal contratto, fornisce.

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

    
risposta data 18.04.2018 - 16:00
fonte
0

Se viene espressa una logica di convalida, la più semplice e più chiaramente sotto forma di query di database, quindi vai avanti, hai la tua risposta. Ma efficienza dovrebbe essere una preoccupazione solo se si ha un problema di prestazioni noto, altrimenti si tratta di ottimizzazione prematura.

    
risposta data 22.06.2017 - 18:18
fonte

Leggi altre domande sui tag