ErrorProne.NET – partea II
ErrorProne.NET – partea II
In articolul trecut am discutat despre probleme legate de formatare. In acest articol ne vom uita peste exceptii. ErrorProne.Net a mostenit destul de multe caracteristici de la un alt proiect pe care l-am dezvoltat – ExceptionAnalyzer dar intr-o forma usor diferita. Include reguli precum:
13 May 2016
2243
Other articles
Object-relational Mapping folosind JPA, Hibernate si Spring Data JPA. Persistence cu JPA
Cum sa interogam Kafka Streaming Data?
Procrastinarea. Care sunt avantajele ei?
Object-relational Mapping folosind JPA, Hibernate si Spring Data JPA
Procrastinarea
Cerinte. De ce avem nevoie de ele?
Dezvolta-ti abilitatile cu training-urile noastre
Programarea reactiva Java. Implementari
Testarea software. Intrebari tipice si raspunsuri. Continuare
Testarea software. Intrebari tipice si raspunsuri
In articolul trecut am discutat despre probleme legate de formatare. In acest articol ne vom uita peste exceptii.
ErrorProne.Net a mostenit destul de multe caracteristici de la un alt proiect pe care l-am dezvoltat – ExceptionAnalyzer dar intr-o forma usor diferita. Include reguli precum:
Propagarea unei exceptii incorecte
Nu voi petrece foarte mult timp pe acesta problema. Daca ati fost la un interviu sau ati lucrat intr-o echipa mai mare, sunt sigur ca stiti diferenta intre throw.ex; si throw;.

Nu sunt surprize aici. throw.ex va “sparge” callstack-ul exceptiei initiale, aspect care ingreuneaza analiza log-ului si identificarea problemei. Din moment ce este o problema foarte cunoscuta, nu veti gasi foarte multe situatii de acest gen. In ciuda acestui lucru, am descoperit un exemplu de redirectionare discutabila a unei exceptii in codul Roslyn: CompilationWithAnalyzer.cs:602.
Exceptie neobservata in generic exception handler
Din moment ce acest instrument este utilizat pentru cele mai provocatoare zone, majoritatea regulilor legate de procesarea exceptiilor sunt simple, precise si foarte putin dificile. Astfel, oricat de mult ar incerca anumite persoane sa interzica toate catch(Exception) blocks in codul lor, este dificil de facut acest lucru in practica datorita prevalentei acestora. Dar pot si ar trebui sa fie prevenite daca aceste blocks declara handlerul fara a verifica exceptiile pe care le-au identificat.
Din acest motiv urmatorul cod ofera un avertisment:

Orice referinta la variabila e din catch block (precum e.Message, ProcessExcpetion(e) etc.) “deactiveaza” aceasta regula. Dintr-un anume motiv, nu am crezut ca aceasta regula va aparea foarte des si am fost foarte surprins ca in codul Roslyn a fost declansata de mai mult de 60 de ori. Iata cateva exemple:
Tratarea suspicioasa a unei exceptii
Ce poate fi mai rau decat o exceptie care nu a fost identificata? Inregistrarea incompleta a detaliilor exceptiei! De fiecare data cand scrii ex.Message in fisierul log, codul tau va esua in productie indicand TypeLoadException si s-ar putea sa stai peste program pentru a descoperi de ce in productie nu mai functioneaza cand mergea perfect pe PC-ul local. Si te vei uita peste log si inregistrarile din log precum "Exception has been thrown by the target of an invocation.", "The type initializer for 'MyAwesomeType' are o exceptie." sau "One or more errors occurred." si te vei gandi "Ce Dumnezeu s-a intamplat".
Desigur ca putem spune ca noi revizuim codul cat mai atent, ca static constructors nu ignora exceptiile, ca nu recunoastem TPL-ul sau ca, in general, scriem cod fara erori din start. Ca raspuns la aceste afirmatii eu ofer exemplul de mai jos pentru a arata ca exceptiile apar si in locuri unde majoritatea oamenilor nu se asteapta sa fie.

Pe masura ce limitarea new() duce la utilizarea Activator .CreateInstance, orice exceptie in object construction dezvoltata cu ajutorul metodelor generalizate precum Create<T> va transforma exceptia initiala intr-o TargetInvocationException. Acest gen de lucruri sunt usor de trecut cu vederea atunci cand revizuim dar este mult mai usor sa impachetam in orice cod care scrie doar un mesaj de exceptie si nu arata stacktrace + exceptii interne.
Din nou, am fost surprins de numarul de dati in care aceasta regula a fost incalcata in codul Roslyn. Sunt mai mult de 12 incalcari de reguli. Multe din ele sunt greseli de ortografie evidente, cum ar fi atunci cand o exceptie noua a fost generata, si au uitat sa defineasca vechea exceptie ca find embedded.
Sergey Teplyakov
Expert in .Net, С++ and Application Architecture
ErrorProne.Net a mostenit destul de multe caracteristici de la un alt proiect pe care l-am dezvoltat – ExceptionAnalyzer dar intr-o forma usor diferita. Include reguli precum:
- ERP021 – propagarea unei exceptii incorecte: redirectionarea exceptiei “incorecte” cu ajutorul throw ex; in loc de throw
- ERP022 – o exceptie neobservata in generic exception handler: atunci cand exceptiile sunt identificate programul declara handler-ul fara a incerca sa “observe” exceptia identificata
- ERP023 - tratarea suspicioasa a unei exceptii: doar proprietatea Message a fost observata: atunci cand catch block generalizat se refera doar la ex.Message exception attribute
Propagarea unei exceptii incorecte
Nu voi petrece foarte mult timp pe acesta problema. Daca ati fost la un interviu sau ati lucrat intr-o echipa mai mare, sunt sigur ca stiti diferenta intre throw.ex; si throw;.

Nu sunt surprize aici. throw.ex va “sparge” callstack-ul exceptiei initiale, aspect care ingreuneaza analiza log-ului si identificarea problemei. Din moment ce este o problema foarte cunoscuta, nu veti gasi foarte multe situatii de acest gen. In ciuda acestui lucru, am descoperit un exemplu de redirectionare discutabila a unei exceptii in codul Roslyn: CompilationWithAnalyzer.cs:602.
Exceptie neobservata in generic exception handler
Din moment ce acest instrument este utilizat pentru cele mai provocatoare zone, majoritatea regulilor legate de procesarea exceptiilor sunt simple, precise si foarte putin dificile. Astfel, oricat de mult ar incerca anumite persoane sa interzica toate catch(Exception) blocks in codul lor, este dificil de facut acest lucru in practica datorita prevalentei acestora. Dar pot si ar trebui sa fie prevenite daca aceste blocks declara handlerul fara a verifica exceptiile pe care le-au identificat.
Din acest motiv urmatorul cod ofera un avertisment:

Orice referinta la variabila e din catch block (precum e.Message, ProcessExcpetion(e) etc.) “deactiveaza” aceasta regula. Dintr-un anume motiv, nu am crezut ca aceasta regula va aparea foarte des si am fost foarte surprins ca in codul Roslyn a fost declansata de mai mult de 60 de ori. Iata cateva exemple:
- AssemblyIdentityUtils.cs:40
- PdbWriter.cs:796
- AssemblyIdentity.DisplayName.cs:842
- AnalyzerFileReference.cs:158
- AbstractAnalyzerAssemblyLoader.cs:102
Tratarea suspicioasa a unei exceptii
Ce poate fi mai rau decat o exceptie care nu a fost identificata? Inregistrarea incompleta a detaliilor exceptiei! De fiecare data cand scrii ex.Message in fisierul log, codul tau va esua in productie indicand TypeLoadException si s-ar putea sa stai peste program pentru a descoperi de ce in productie nu mai functioneaza cand mergea perfect pe PC-ul local. Si te vei uita peste log si inregistrarile din log precum "Exception has been thrown by the target of an invocation.", "The type initializer for 'MyAwesomeType' are o exceptie." sau "One or more errors occurred." si te vei gandi "Ce Dumnezeu s-a intamplat".
Desigur ca putem spune ca noi revizuim codul cat mai atent, ca static constructors nu ignora exceptiile, ca nu recunoastem TPL-ul sau ca, in general, scriem cod fara erori din start. Ca raspuns la aceste afirmatii eu ofer exemplul de mai jos pentru a arata ca exceptiile apar si in locuri unde majoritatea oamenilor nu se asteapta sa fie.

Pe masura ce limitarea new() duce la utilizarea Activator .CreateInstance, orice exceptie in object construction dezvoltata cu ajutorul metodelor generalizate precum Create<T> va transforma exceptia initiala intr-o TargetInvocationException. Acest gen de lucruri sunt usor de trecut cu vederea atunci cand revizuim dar este mult mai usor sa impachetam in orice cod care scrie doar un mesaj de exceptie si nu arata stacktrace + exceptii interne.
Din nou, am fost surprins de numarul de dati in care aceasta regula a fost incalcata in codul Roslyn. Sunt mai mult de 12 incalcari de reguli. Multe din ele sunt greseli de ortografie evidente, cum ar fi atunci cand o exceptie noua a fost generata, si au uitat sa defineasca vechea exceptie ca find embedded.
Sergey Teplyakov
Expert in .Net, С++ and Application Architecture