mercoledì 1 aprile 2009

Let it crash! (ovvero non tutto quello che è Exception deve essere gestito da TE!)

Una delle cose che mi piace di più del linguaggio Java è la severità del suo compilatore, resa particolarmente evidente nel caso delle eccezioni. Purtroppo il meccanismo delle eccezioni spesso non viene capito dai programmatori, che si affannano a costruire dei complessi blocchi try..catch per catturare ogni possibile errore che il proprio codice potrebbe sollevare.
Ma questo è sempre corretto?
In un'applicazione multi-threading spesso no. Generalmente le applicazioni multithread hanno uno schema gerarchico, con un thread padre che genera i figli per gestire diverse richieste (si pensi al classico server in attesa di connessioni). In uno schema del genere, il processo padre dovrebbe svolgere anche il ruolo di coordinatore e supervisore fra i figli, che si trovano a fare il lavoro sporco. Cosa succede se un'eccezione viene generate in un figlio? La maggior parte dei programmatori tenta di catturare l'eccezione, di gestirla e di ripristinare lo stato del thread (figlio). Ma l'eccezione viene generata nel thread figlio stesso, quindi il thread tenta di auto-gestire l'eccezione.
La domanda a questo punto è: il thread figlio è in grado di gestirla? Sa quale sia la decisione migliore? Generalmente no!
E' compito del processo coordinatore decidere cosa fare nel caso in cui un figlio termini la sua esecuzione in modo abnorme. Quindi è meglio implementare una logica decisionale nel thread coordinatore piuttosto che nei thread di lavoro. I thread di lavoro dovrebbero essere programmati in stile happy-case, ovvero considerando che tutto vada bene. E se qualcosa andrà male, sarà il coordinatore a decidere cosa fare.
Questa rinuncia di autonomia nei thread da lavoro potrebbe incrementare decisamente le prestazioni dell'intera applicazione. Infatti, un thread figlio difficilmente ha la visione complessiva dell'applicazione (stato della memoria, occupazione processore, stato dei pool,...) e quindi non può decidere cosa è meglio per l'applicazione (continuare o morire). Tanto vale allora lasciar(si) terminare e segnalare al chiamante (il processo coordinatore) che qualche cosa è andata storta; sarà lui a prendere la decisione opportuna (ricreare il thread, riconfigurare il pool, ecc.).

Nessun commento: