avvisando che un oggetto non può essere cancellato (a causa di vincoli)

0

Assumi un'applicazione con un modello di dominio ricco con molte classi (ad esempio School , Classroom , Teacher , Student , Course , Exam , Submission , ...) che rimanda a l'un l'altro. Modello e collegamenti sono mappati al database che utilizza FK e vincoli appropriati (senza eliminazione a cascata). Nel pannello di amministrazione l'utente ha pulsanti di eliminazione accanto a ciascun oggetto.

Il tentativo di eliminare un oggetto ha uno dei seguenti due risultati:

  • l'oggetto non viene referenziato da nessun altro oggetto, quindi viene cancellato
  • l'oggetto viene referenziato da almeno un altro oggetto in modo che non possa essere cancellato. Un avviso viene mostrato all'utente.

Ho due modi per implementarlo:

  1. prima dell'esecuzione dell'eliminazione sql, esegui tutte le query necessarie per scoprire se questo oggetto può essere eliminato. Se non è possibile, avvisa l'utente.
  2. vai avanti ed esegui l'eliminazione sql e se fallisce (a causa dei vincoli rdbms) cattura l'eccezione sql e avvisa l'utente che non può essere cancellato.

Entrambi i modi funzionano bene. Il primo modo mi consente di fornire all'utente un motivo dettagliato per cui l'oggetto non può essere cancellato (ad esempio viene referenziato dal 2% diCourse s e dall'1% diClassroom). Il secondo modo mi consente di risolvere l'intero problema non scrivendo alcun vincolo controllando il codice e facendo affidamento sull'implementazione solida (ed esistente) del db.

C'è una ragione per cui dovrei sicuramente sceglierne una rispetto all'altra?

    
posta cherouvim 12.08.2014 - 10:20
fonte

4 risposte

2

Uso regolarmente l'approccio due. Il rovescio della medaglia è che i test richiedono un database. Alcuni sosterranno che, a seconda del database, non è un "test unitario". Anzi.

Il problema con questa critica è che considera i test unitari come One Size Fits All. Chiaramente i test unitari non sono personalizzati per essere utilizzati con sistemi esterni. Ciò non significa che non si debba fare affidamento su tali sistemi; o peggio ancora, non testare la loro interazione con il tuo codice. In ogni caso, dovrai verificare il caso delle violazioni delle chiavi esterne del database perché sarebbe una brutta cosa non avere vincoli di chiave esterna e una brutta cosa non metterli alla prova.

In una piccola misura, puoi testare i sistemi esterni con mock generando le eccezioni previste ... se sai cosa aspettarti! (Questo potrebbe non essere il caso dal momento che la dichiarazione del problema suona molto scolastica).

Nel tuo caso, il campione del problema sembra così piccolo che il round trip extra della soluzione 1 non ha molta importanza e non devi fare affidamento sul database per le prestazioni. Ma la soluzione 1 richiederebbe una piccola codifica aggiuntiva da parte tua, mentre i vincoli di chiave esterna sono già applicati dal database.

Sii intelligente, sii pigro.

    
risposta data 12.08.2014 - 17:47
fonte
1

Una ragione per cui non userei la seconda opzione: testabilità. Semplicemente non è possibile testare il caso, che dipende dal fatto che il server SQL genera un'eccezione. Ma puoi facilmente testare il caso, in cui richiedi dati specifici e ti comporti in base a quei dati.

La testabilità è uno dei motivi principali per cui molti sviluppatori si allontanano dall'avere logiche all'interno del server DB o dipendono dal comportamento relativo al DB e mettono tutto il comportamento all'interno dell'applicazione stessa (server).

    
risposta data 12.08.2014 - 11:36
fonte
1

Vorrei anche optare per l'opzione 2. A proposito di problematiche relative alla testabilità, ovviamente non è possibile testare realmente l'unità, ma, in realtà, non dovrebbe esserlo. Tali test sono test di integrazione e devono essere eseguiti in un ambiente reale (benché controllato), idealmente come parte dell'integrazione continua (CI), in cui testare ogni modifica dello schema DB e ogni modifica del codice sorgente dell'applicazione l'uno contro l'altro.

Perché preferire l'opzione 2? Bene, perché uno dovrebbe usare gli strumenti giusti per fare il lavoro. Mantenere l'integrità dei dati è uno dei punti chiave di RDBMS, e non usarlo è come non raccogliere i soldi che giacciono a terra.

    
risposta data 12.08.2014 - 18:17
fonte
1

Per prima cosa voglio chiarire questo:

  • Il database deve utilizzare FK, PK e controllare i vincoli, indipendentemente dall'applicazione che esegue convalide preventive o meno.

Dopo averlo chiarito,

Vantaggi delle convalide preventive

  • Sono necessari meno ricaricamenti di pagine
  • Le convalide preventive consentono di disabilitare il pulsante Elimina di conseguenza
  • Più facile da usare

Svantaggi delle convalide preventive

  • Logica di presentazione più complessa
  • Più codice per mantenere
  • Più tempo di sviluppo

Nel mio caso tendo a favorire la semplicità del codice con tutto il resto, quindi sceglierei l'opzione 2, ma non sembra questo il tuo caso quindi ti raccomando vai con l'opzione 1 .

Ciò che non dovresti mai fare è avere il database NON imporre PK, FK o controllare i vincoli e affidarti solo all'applicazione per la coerenza dei dati.

    
risposta data 12.08.2014 - 18:05
fonte