Sto lavorando a un servizio basato su ReST che chiama altri servizi basati su ReST e si occupa anche di Persistenza in un database. Quindi una tipica chiamata potrebbe apparire come
- Ottieni alcuni dati dal database.
- Effettua una chiamata a un servizio esterno utilizzando un ReSTClient per creare un record.
- Persiste la risposta al database.
- Effettua un'altra chiamata a un altro servizio.
- Restituisci una risposta.
Il problema è che sia il ReSTClient che il livello di persistenza del DB generano solo le proprie RuntimeException personalizzate. Non voglio inquinare il mio codice con try catch blocks attorno ad ogni passo e volevo avere un mappatore di eccezioni di alto livello che fondamentalmente restituiva un codice di errore 500 al chiamante con un messaggio di base che la chiamata falliva. Alcuni sviluppatori dicono che dobbiamo mettere un blocco catch try su ogni passaggio e prendere le RuntimeException e restituire un codice di errore 500 ma anche il motivo esatto per l'errore. La mia esperienza ha dimostrato che i messaggi di errore esatti mostrati all'utente non aggiungono molto valore poiché l'utente non capisce il nostro sistema e non sa veramente cosa significhi avere la chiamata di servizio fallita o un errore nel database strato, sa solo che l'operazione è fallita. Inoltre, non vi è alcuna garanzia che il client che chiama il nostro servizio sia un utente umano, potrebbe essere un altro servizio.
Anche durante lo sviluppo alcune situazioni possono accadere come per es. il passaggio 2 ha esito positivo ma il passaggio 3 non riesce a causa di un errore del database. In questo caso il sistema si trova in uno stato incoerente in cui la chiamata riuscita non viene registrata nel DB e se l'utente umano non lo sa, esegue di nuovo l'operazione per creare due record nel sistema esterno. Ci sarebbero molti casi simili riguardo a DB e guasti del disco ecc. Che non possiamo prevedere. Così prendi queste eccezioni ad ogni passaggio e scrivi messaggi di codice e di errore per gestire queste situazioni.