Dove e come gestire i vincoli di colonna Unici

2

Voglio che una colonna chiave non primaria sia univoca. Questo è applicato con un vincolo univoco. In un endpoint del servizio, desidero restituire un messaggio di errore strutturato in un oggetto {field, messsage} quando vengono violati i vincoli univoci. Attualmente controllo se la colonna è univoca nel livello di servizio e getta una UniqueFieldExcepton per essere gestita globalmente.

Altre opzioni che ho considerato sono:

  1. Gestire il controllo nel livello del database (repository, DAL, ecc.) e lanciare UniqueFieldExcepton per essere gestito globalmente.

  2. Cattura l'errore del database nel livello del database, analizzando il nome della colonna dal messaggio e lanciando un UniqueFieldExcepton per essere gestito globalmente.

  3. Rilevando l'errore del database nel livello di servizio, cercando di analizzare il nome della colonna dal messaggio e lanciando un UniqueFieldExcepton per essere gestito globalmente.

La mia squadra ha opinioni diverse su come risolvere questo problema.

Esistono linee guida / best practice che potrebbero aiutarci a raggiungere un accordo?

    
posta Jakob 04.04.2017 - 02:22
fonte

2 risposte

1

Questo è abbastanza soggettivo, ma mi piace che la gestione degli errori sia il più generica e riusabile possibile. A tal fine, avrei una gestione degli errori del livello dati (particolarmente utile se tutto l'accesso al database passa attraverso una facciata comune) che gestisce l'errore e analizza le eccezioni del database nelle eccezioni dell'applicazione.

Quindi, se hai bisogno di un livello globale / servizio, potresti avere un traduttore per passare dalle eccezioni delle applicazioni alle eccezioni del servizio, se necessario.

    
risposta data 04.04.2017 - 03:13
fonte
0

Il problema con tutti e tre i tuoi approcci è la severa duplicazione del codice che porterebbe a. Il primo mi sembra particolarmente spaventoso:

  • Quando si inserisce un prodotto, il DAL verifica se il nome prodotto esiste già. Se sì, lanciare un'eccezione. Quindi controlla se SKU esiste. Sì? Lanciare un'eccezione Che ne dici di EAN-13? Lancia un'eccezione!

  • Ora stai inserendo un cliente. Stessa storia: più controlli, che alla fine si traducono in un'eccezione.

  • Che ne pensi di una recensione di un prodotto? La stessa cosa qui.

Il secondo e il terzo approccio sono leggermente migliori, poiché non è necessario controllare manualmente per ogni campo UNIQUE. Basta fare la query, prendere l'eccezione della libreria di terze parti sottostante e invece lanciare la tua eccezione. Tuttavia, duplichi questa logica in un metodo che inserisce un prodotto e quello che crea un cliente e quello che aggiunge una recensione del prodotto. Non va bene.

Un altro problema è che catturando e lanciando la tua eccezione invece di prendere-e-rilanciare (o semplicemente lasciare che l'eccezione salga nello stack) è che stai rompendo lo stack. Crea debug di nightmares.¹

In generale, rilevi eccezioni quando puoi gestirle. Ad esempio, viene rilevata un'eccezione che indica che il file non esiste in un metodo che è in grado di decidere se sostituire i contenuti del file con i contenuti predefiniti o cercare i contenuti da qualche altra parte, ad esempio una posizione di backup -Per chiedere aiuto all'utente. Quindi in quale livello dovremmo rilevare le eccezioni relative alla violazione del vincolo UNIQUE? Probabilmente nel livello dell'interfaccia utente: per qualche motivo (ad esempio, le prestazioni) l'interfaccia utente non è stata in grado di impedire all'utente di digitare un'informazione duplicata in primo luogo, ha inviato l'input a valle e ha causato la violazione del vincolo. È anche l'interfaccia utente che può effettivamente gestire l'eccezione, ad esempio dicendo all'utente che il valore inserito è già in uso.

The problem with this approach is that different database drivers could theoretically throw different exceptions. You would have to implement it for each implementation of the database interface. [...] I support 5 different types of databases through java odbc.

Questo non è un problema.

L'interfaccia utente intercetta l'eccezione che proviene direttamente dalla libreria di terze parti e pertanto assomiglia più a java.sql.SQLIntegrityConstraintViolationException piuttosto che a myapp.UniqueFieldExcepton . Ma l'interfaccia utente non sa come analizzare il messaggio all'interno dell'eccezione per estrarre il nome del campo interessato. Il DAL lo sa.

Quindi l'interfaccia utente effettua una chiamata a BL, passando il messaggio di eccezione e chiedendo quale campo è interessato. BL diffonde la richiesta lungo il DAL. Il DAL analizza il messaggio e restituisce l'ID del campo. Ora, l'interfaccia utente può evidenziare il campo corrispondente e mostrare un errore significativo.

¹ Non sto nemmeno parlando figurativamente qui. Ricordo ancora quanto fosse doloroso lavorare con il codice legacy che dovevo supportare sei anni fa.  Uno dei WTF era che gli sviluppatori adoravano catturare eccezioni in luoghi in cui non potevano gestirli comunque. Così a volte, stavano ripensando a se stessi. A volte, stavano lanciando la stessa eccezione,  ma farlo erroneamente e perdere la traccia dello stack. E a volte, ingeriscono queste eccezioni e fanno finta che non sia successo nulla di sbagliato, reinventando In caso di errore, riprendi . Una query SELECT non è riuscita? Va bene, faremo ancora un ciclo sulla sequenza che ci aspettavamo di tornare da noi. Cosa intendi con "NullPointerException"?

    
risposta data 06.05.2017 - 22:05
fonte

Leggi altre domande sui tag