Per un ORM che supporta la convalida dei dati, i vincoli dovrebbero essere applicati anche nel database?

13

Ho sempre applicato vincoli a livello di database oltre ai miei modelli (ActiveRecord). Ma mi stavo chiedendo se è davvero necessario?

Un po 'di background

Recentemente ho dovuto testare unitamente un metodo di generazione timestamp automatico di base per un modello. Normalmente, il test crea un'istanza del modello e lo salva senza convalida. Ma ci sono altri campi obbligatori che non sono annullabili nella definizione della tabella, il che significa che non posso salvare l'istanza anche se salta la convalida di ActiveRecord. Quindi sto pensando se dovrei rimuovere tali vincoli dal db stesso, e lasciare che l'ORM li gestisca?

Possibili vantaggi se salta i vincoli in db, imo -

  • Può modificare una regola di convalida nel modello, senza dover eseguire la migrazione il database.
  • Può saltare la convalida nei test.

Possibile svantaggio?

Se è possibile che la validazione ORM fallisca o sia saltata, comunque, il database non controlla i vincoli.

Che ne pensi?

EDIT In questo caso, sto utilizzando il Framework Yii , che genera il modello dal database, quindi vengono generate anche le regole del database (anche se potrei sempre scriverle anch'io post-generazione).

    
posta Bojack 21.06.2012 - 07:30
fonte

5 risposte

16

Il tuo principio guida dovrebbe essere Non ripetere te stesso :

In software engineering, Don't Repeat Yourself (DRY) is a principle of software development aimed at reducing repetition of information of all kinds, especially useful in multi-tier architectures. The DRY principle is stated as "Every piece of knowledge must have a single, unambiguous, authoritative representation within a system."

L'ORM è essenzialmente un livello extra (o di livello se si preferisce), comodamente seduto tra l'applicazione e lo / gli spazio / i dati / i. I tuoi vincoli dovrebbero essere in un posto, e solo in un posto, che si tratti dell'ORM o dell'archiviazione dei dati, altrimenti presto finirai per mantenerne versioni diverse. davvero non vuoi farlo.

Tuttavia, in pratica, la maggior parte degli ORM decenti genera automaticamente una grande quantità di modelli dallo schema dei dati. Sebbene ci sia ancora una duplicazione, le possibilità di interruzione della manutenzione sono minime poiché il codice ORM duplicato viene generato ogni volta seguendo lo stesso schema. Sarebbe ideale non avere codice duplicato, ma i vincoli generati automaticamente sono la cosa migliore.

Inoltre, avere i tuoi vincoli in un posto non significa necessariamente che dovresti avere tutti i tuoi vincoli nello stesso posto. Alcuni, come i vincoli di integrità referenziale, possono essere più adatti all'archiviazione dei dati (ma potrebbero andare persi se ci si sposta in un'altra memoria di dati) e alcuni, soprattutto quelli che riguardano la logica aziendale complessa, sono più adatti per l'ORM. Sarebbe preferibile avere tutte le tue mele nello stesso cestino, ma ...

Guasti

Hai menzionato il mancato funzionamento di ORM. Questo è assolutamente irrilevante per la tua domanda, la tua applicazione dovrebbe pensare all'ORM e all'archiviazione dei dati come un'unica entità. Se fallisce, fallisce, scavalcare l'ORM per parlare direttamente con l'archiviazione dei dati è non una buona idea.

Bypassare l'ORM per qualsiasi altra cosa

Inoltre non è una buona idea. Tuttavia, può accadere per una serie di motivi:

  1. Parti legacy dell'applicazione che sono state create prima che l'ORM sia stato introdotto.

    È difficile, e esattamente la situazione che sto trattando con adesso , quindi la mia ripetizione costante di "manutenzione infernale". O si continua a mantenere le parti non ORM o le si riscrive per utilizzare l'ORM. La seconda opzione potrebbe avere più senso inizialmente, ma è una decisione basata esclusivamente su quali sono esattamente le parti della tua applicazione e sulla preziosa riscrittura completa a lungo termine.

    Prova a cambiare una chiave in una tabella MySQL 2 * 10 ^ 8 righe mal progettata (senza tempi di inattività) e capirai da dove vengo.

  2. Parti non legacy dell'applicazione che devono assolutamente parlare direttamente alla memoria dati:

    Ancora più complicato. Gli ORM sono strumenti elaborati e si occupano di quasi tutto, ma a volte si mettono semplicemente in mezzo o addirittura sono assolutamente inutili. La buzzword (veramente la buzzphrase) è disadattamento dell'impedenza relazionale all'oggetto , semplicemente non è tecnicamente possibile che il tuo ORM faccia tutto il tuo database relazionale fa, e per alcune delle cose che fanno, c'è una penalità significativa nelle prestazioni.

Commenti

From the point of data integrity, constraints MUST be on the database, and SHOULD be on the application. What if your application is accessed from a web and a desktop applications, or a mobile app, or a webservice? – Luiz Damim

Questo è il punto in cui l'aggiunta di un ulteriore livello sarebbe estremamente utile, e se stiamo parlando di un'applicazione web andrei con un'API REST. Un design eccessivamente semplicistico per questo sarebbe:

enter image description here

L'ORM si posizionerebbe tra l'API e gli archivi di dati e tutto ciò che si trova dietro l'API (incluso esso) sarebbe considerato una singola entità dalle varie applicazioni.

    
risposta data 21.06.2012 - 07:37
fonte
20

Questa è in realtà una domanda molto difficile a cui rispondere e ho trovato che sia un argomento molto controverso.

Come sottolineato da Yannis Rizos nella sua risposta, avere la logica dei vincoli in sia il database che lo strato ORM sembrerebbe violare il DRY, che "può portare a incubi di manutenzione, scarso factoring e logico" contraddizioni".

Tuttavia, rimuovere la logica del vincolo dal database e mantenerlo solo sul livello ORM non funzionerebbe se si verifica una delle seguenti condizioni:

  1. Aggiornamenti del DB manuale (sembrano accadere in ogni azienda)

  2. Aggiornamenti DB da un altro sistema che non può sempre condividere l'ORM logica di vincoli facilmente (ex / uno script Perl che esegue attività di routine quando il livello ORM è implementato in Hibernate e utilizzato da un Java domanda per attività giornaliere)

Questo suggerirebbe solo aggiungere la logica del vincolo al DB e rimuoverlo dal livello ORM per impedire una violazione DRY. Tuttavia, questo può portare a casi in cui il codice dell'applicazione non è in grado di catturare correttamente il problema e inoltrarlo all'utente (sebbene sia probabile che lo sviluppatore esegua il debug del problema). Questo potrebbe non essere accettabile per alcuni progetti.

L'ultima opzione è quella di automatizzare la creazione dei vincoli nell'ORM (e qualsiasi altro sistema) dai vincoli DB (o, in realtà, ... viceversa). Anche se alla fine finirai con due o più implementazioni dei vincoli, non sarà una violazione del principio DRY come descritto in "The Pragmatic Programmer" poiché raccomandano l'utilizzo della generazione di codice per evitare violazioni DRY. Ovviamente, non è così semplice perché, ad esempio, ogni modifica a un vincolo DB può forzare una ricostruzione e una nuova distribuzione di tutte le applicazioni che la utilizzano (non banale da automatizzare).

In realtà, dovrebbe essere valutato caso per caso . Posso dirti che, a questo punto, mi sono imbattuto in sguardi vuoti quando suggerisco di non ripetere la logica dei vincoli.

    
risposta data 21.06.2012 - 15:24
fonte
3

Definirò sicuramente i vincoli al database come opzione predefinita. Questo perché per un'azienda i dati sono re e la qualità dei dati è fondamentale. @Annis Rizos ha portato il principio DRY alla discussione. Bene, un altro principio è Difesa in profondità. Per i dati vorrei usare questo principio.

Ho lavorato in aziende reali in cui il database ha creato dati 30 anni fa. Era ed è ancora accessibile dall'applicazione COBOL e ora da un'applicazione .Net. Tra 10 anni potrebbe essere un'app vendor, chissà. C'è stata una fusione e milioni di righe di dati sono state convertite e migrate dall'altra azienda a questo database usando SQL. Nessun ORM può farlo. La linea di fondo è che i dati rimangono, le applicazioni cambiano, il modo in cui i dati vengono generati cambiano. Quindi, perché non ridurre la possibilità di corruzione dei dati?

    
risposta data 22.06.2012 - 11:37
fonte
2

Penso che lo farai entrambi in una certa misura.

  • I vincoli primari dovrebbero vivere nell'ORM - i linguaggi di programmazione sono molto più flessibili, è più facile da testare e più facile da modificare quando cambiano i requisiti; non c'è bisogno di preoccuparsi delle correzioni DDL almeno. E in genere eviti di testare i problemi di regressione dei dati.

  • Alcuni vincoli molto difficili e veloci dovrebbero anche vivere nel database. Ad esempio, non sto parlando di nomi non annullabili. Sto parlando di cose come l'integrità referenziale o la necessità di alcuni identificatori assolutamente cruciali. Requisiti strutturali in modo che il tuo codice non debba occuparsi di "cosa succede se l'ordine ha un prodotto inesistente".

risposta data 21.06.2012 - 19:42
fonte
1

Il database è IMO l'unico posto in cui DRY può essere violato, perché se qualcosa aggira l'ORM e ha dati errati, il gioco è fatto. Gioco finito. Avere dati corrotti è il colpo mortale.

    
risposta data 22.06.2012 - 04:50
fonte

Leggi altre domande sui tag