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"?