Livello corretto per gestire chiavi duplicate

2

In un'applicazione Web con 4 livelli:

  • Livello dell'interfaccia utente
  • Livello aziendale
  • Livello accesso ai dati
  • Livello di archiviazione dati che è il database

Uno dei requisiti è gestire un elenco di oggetti con chiave univoca. Per il database è ovvio che ho bisogno di usare un vincolo di chiave univoco su una colonna.

La mia comprensione per gestire chiavi duplicate dovrebbe essere gestita dal database. Ad esempio, quando un utente desidera aggiungere una nuova entità con chiave duplicata, tutti e tre i livelli sopra l'archiviazione dei dati non devono eseguire alcuna convalida. Il salvataggio della voce nel database genererà un'eccezione e un messaggio di errore corretto verrà propagato all'interfaccia utente.

Tuttavia, uno dei miei colleghi ha detto che questo non è un progetto corretto: ogni livello non dovrebbe fare affidamento su altri livelli. E suggerito di gestire anche la regola chiave duplicata nel livello di accesso ai dati. Il motivo per cui lo ha: Immagina questo scenario, cambiando il database in modo da avere un file normale, in modo che non possiamo sfruttare il vincolo delle chiavi univoche.

Ma se sono d'accordo con lui, ci sono anche molti svantaggi:

  • Convalida duplicata (4 convalide) in tutti i livelli: devo fare la stessa validazione anche per i livelli aziendali e dell'interfaccia utente.
  • Problemi di prestazioni: individuare la struttura e gli algoritmi corretti per gestire la convalida. Immagina uno scenario di convalida più complesso come chiavi multiple, una grande collezione da gestire nella memoria ...

Qual è il modo corretto per gestire questo tipo di convalida in un'applicazione Web?

    
posta Mhd 13.05.2018 - 19:16
fonte

3 risposte

4

However, one of my colleague said this is not a proper design: Each layer should not rely on other layers. And suggested to handle the duplicate key rule in the data access layer also. The reason He had: Imagine this scenario, changing the database to have a plain file instead so we can not leverage the unique keys constraint.

Il tuo collega è qui vicino. Il problema non è che i livelli in generale non dovrebbero fidarsi l'uno dell'altro. In effetti, dovrebbero fidarsi l'un l'altro con certe preoccupazioni . Il problema è che gli altri livelli sono interessati con questa convalida perché del fatto che il DBMS potrebbe cambiare in un sistema che non può essere considerato attendibile con questa responsabilità.

La domanda che devi porci è, quanto è probabile che sostituirai il tuo DBMS con un sistema che non può imporre questo vincolo?

Se tale sostituzione non è probabile, gli unici vantaggi delle convalide ridondanti sono l'accoppiamento più lento e il non dover attraversare inutilmente i livelli dell'applicazione (pensare di non convalidare in modo ridondante come effettuare una chiamata API con una richiesta che si sa potrebbe non essere valida).

Supponendo che il rischio di sostituzione del DBMS sia sufficiente a compensare il costo di manutenzione delle convalide ridondanti, pensiamo a ogni livello:

Livello UI (non convalidare)

L'unico vantaggio di convalidare qui è il feedback immediato per l'utente, e gli svantaggi sono i problemi di scalabilità / sicurezza di dover esporre tutte le chiavi esistenti all'interfaccia utente per eseguire la convalida. Sebbene ciò possa essere possibile se l'architettura e il set di dati lo consentono, probabilmente non è l'ideale, a meno che non sia un requisito UX rigido che la convalida venga eseguita localmente (e presumibilmente non lo è, poiché attualmente non sta eseguendo la convalida). / p>

Livelli di accesso alle imprese e ai dati (convalidati in uno di questi)

Se stai seguendo un modello di repository o qualcosa di simile per il tuo livello di accesso ai dati , probabilmente è una buona idea considerare la convalida come logica aziendale e inserirla nel livello aziendale. Se stai seguendo il modello di livello di accesso ai dati più ampio, tuttavia, potrebbe avere più senso per separa la conoscenza del modello di dati dalla logica aziendale. (C'è qualche confusione intorno alle differenze tra questi due tipi di livelli di accesso ai dati e quali dovrebbero essere le responsabilità di un livello di accesso ai dati).

Ricorda che l'unica ragione per cui stiamo validando qui è che stiamo assumendo che il DBMS non possa essere considerato attendibile con tale responsabilità; in quanto tale, per mantenere una separazione valida di questa preoccupazione, dovresti scegliere uno di questi due livelli per essere responsabile della convalida, non entrambi.

Livello di archiviazione dati (valido)

A prima vista, potrebbe sembrare che aggiungere un vincolo univoco come suggerito stia violando troppo la fiducia del business o del livello di accesso ai dati e le preoccupazioni sovrapposte. Tuttavia, ricorda che questo livello, essendo un DBMS, è interessato con integrità dei dati (ad es. Normalizzazione). In quanto tale, è una preoccupazione che si sovrappone e il database ha tutto il diritto di applicare tale integrità sfruttando i vincoli.

Più in pratica, questo è un modo prudente per garantire che non vengano creati dati non validi per errore. Tenere presente che il livello di accesso ai dati potrebbe non essere l'unica entità che crea / modifica i dati in questo database. Il semplice fatto che utenti umani con credenziali di database possano accedere e creare dati direttamente è sufficiente a spaventarmi a violare qualsiasi purismo di SoC che potrebbe esistere qui (sebbene sia mia opinione che nessuno lo fa).

Sommario

  • Separa appropriatamente i dubbi e conferma quando una preoccupazione si sovrappone ai livelli.
  • Utilizza convalide ridondanti quando desideri tenere conto della futura abdicazione di responsabilità o ridurre gli attraversamenti di livelli non necessari.

In questo caso specifico, aggiungerei il vincolo del database e lo convalido nel livello aziendale o nel livello di accesso ai dati (non entrambi), a seconda di come hai definito le responsabilità del tuo livello di accesso ai dati.

    
risposta data 14.05.2018 - 17:39
fonte
2

Il problema con la convalida dell'unicità è che devi conoscere tutti gli altri record.

Questo di solito significa che sì, puoi solo convalidare sul database poiché questo è il punto più efficiente in cui verificare i duplicati.

Ovviamente potresti farlo su qualsiasi livello, purché tu abbia mantenuto un elenco di tutti gli altri tasti, anche se sono stati controllati.

Tuttavia, ti suggerisco di ignorare tutti questi problemi e di utilizzare semplicemente GUID. In questo caso puoi generare le chiavi su uno o tutti i livelli e assicurarti che ognuno sia unico senza doverlo controllare.

    
risposta data 13.05.2018 - 19:47
fonte
0

In parole povere, il tuo collega ha torto. Chiediti, quali sono le parti interessate nel tuo sistema che richiedono questa unicità? Perché la chiave deve essere assolutamente unica? La risposta a queste domande è quasi sempre il tuo livello di persistenza. L'unicità è raramente importante al di fuori del livello di persistenza (che si occupa di cose come la normalizzazione). Oltre a ciò, è semplicemente insostenibile applicare un vincolo univoco per gli insiemi che includono un numero elevato di record.

Indipendentemente dal fatto che l'origine dati sia un RDBMS o un file di testo non è rilevante. Le implementazioni del repository devono essere consapevoli della persistenza, quindi la modifica dell'origine dati richiederà sicuramente modifiche al livello di persistenza. Questo ha senso, no? La modifica del supporto di memorizzazione richiede la modifica del livello di persistenza. Se non è più possibile fare affidamento su un vincolo del database, sarà necessario aggiungere il codice necessario per applicare l'univocità ai file di testo (nel livello di persistenza). Semplice.

Ciò che non cambia, e questa è la parte importante, è l'interfaccia. Il contratto tra i tuoi strati superiori e la persistenza sarà lo stesso. In entrambi i casi sembra:

UniqueDomainModel model = repo.FindByUniqueField('some unique value')

model.ExecuteActionThatChangesUniqueField()

// throws FieldMustBeUniqueException
repo.save(model)

Non c'è nulla da guadagnare con un metodo repo.IsFieldUnique('some possibly unique value') . Dillo, non chiedere.

    
risposta data 15.05.2018 - 16:57
fonte

Leggi altre domande sui tag