În această ultimă parte a seriei de articole dedicate datoriei tehnice prezentăm rezultatele experimentale ale cercetărilor noastre în domeniu. Asemenea marii părți a literaturii existente, am utilizat mai multe proiecte open-source mature care au jucat rolul sistemelor testate. Majoritatea rezultatelor au fost obținute folosind unealta SonarQube, care rămâne cel mai utilizat instrument atât în mediul de cercetare cât și în cadrul industriei software. Episodul trecut al seriei noastre include o prezentare a instrumentului SonarQube și a altor unelte populare pentru analiza codului, în timp ce primul episod al seriei prezintă modelele pe care au fost construite acestea.
Proiectele de complexitate mare, cu o perioadă de dezvoltare întinsă pe mai mulți ani, care implică echipe numeroase, uneori, dispersate geografic prezintă un risc mai mare de a acumula datorie tehnică. De multe ori, decizia de a aborda aspectele care țin de această datorie sunt amânate, ceea ce duce la o acumulare accelerată a acesteia.
Punctul de pornire este reprezentat de dorința de a identifica și caracteriza datoria tehnică la nivelul codului sursă. Literatura oferă multe exemple de studii empirice focalizate pe studierea calității sistemelor software, a datoriei tehnice și a legăturii dintre ele, însă ceea ce am descoperit că lipsește este o caracterizare detaliată a componenței și evoluției pe termen lung a datoriei tehnice. Mai mult, studiile existente se limitează de regulă la utilizarea unei singure versiuni a unui singur instrument. Lucrări precum [1] reprezintă un punct de pornire excelent pentru cei interesați de o privire comparativă, de nivel înalt al instrumentelor existente. În completare, noi propunem să furnizăm o privire mai aproape "de firul ierbii", în care arătăm utilitatea celui mai cunoscut astfel de instrument în analiza mai multor aplicații open-source populare. Țintele studiului nostru sunt aplicația de diagramare FreeMind, editorul de text jEdit și editorul pentru notație muzicală TuxGuitar.
Figura 1 - Cele trei aplicații utilizate în evaluarea noastră
Aplicațiile țintă sunt caracterizate prin existența unui istoric de dezvoltare care acoperă o durată de cel puțin 15 ani, și care include atât versiuni inițiale, de complexitate redusă, precum și versiuni mature și complexe, care sunt utilizate pe scară largă. Scopul nostru a fost să învățăm mai mult despre modul în care datoria tehnică este introdusă și ulterior gestionată în codul sursă; mai mult, am dorit să studiem compoziția datoriei tehnice, pentru a determina dacă aceasta variază de la o aplicație la alta, astfel putând determina "specificul" unei aplicații din punct de vedere al problemelor de cod.
Utilizăm Tabelul 1 pentru a stabili contextul prezentării tehnice. Acesta include informații legate de prima și ultima versiune din studiul nostru. În mod particular, ne-au interesat primele versiuni, care în cazul FreeMind constau din 2,770 linii de cod și constituie mai degrabă o demonstrație (eng. proof-of-concept) decât o aplicație pregătită pentru utilizare. Ultimele patru coloane ale tabelului arată numărul de probleme de cod detectate de SonarQube 8.2, care atribuie și o evaluare pe scara SQALE de la (A) - cel mai bun și până la (E) - cel mai rău. Așa cum am prezentat și în episodul trecut, o evaluare (A) pentru mentenabilitate presupune că timpul necesar remedierii tuturor problemelor găsite este mai mic de 5% din timpul necesar dezvoltării aplicației. În schimb, o evaluare (E) corespunde unei estimări în care e nevoie de mai mult de 50% din timpul total de dezvoltare pentru remedierea problemelor de mentenabilitate. Efortul total estimat este inclus pe ultima coloană și variază între cinci zile per om pentru prima versiune a FreeMind, și 211 zile per om pentru cea mai recentă versiune a jEdit. În cazul aspectelor legate de fiabilitate și securitate, instrumentul SonarQube folosește o evaluare mai strictă, conform căreia problemele ce au un efect imediat asupra aplicației fac ca aceasta să primească o evaluare (E).
Tabel 1 - Detalii despre prima și ultima versiune studiată (sursa [2])
Următorul pas a fost să studiem modul în care datoria tehnică evoluează pe termen lung în cadrul aplicațiilor. Literatura științifică nu acoperă în mod corespunzător acest aspect nici în cazul aplicațiilor open-source, iar în cazul aplicațiilor proprietare nu am descoperit astfel de analize.
În cazul aplicațiilor studiate, am luat în calcul fiecare versiune publică, ajungând la 112 versiuni care au fost analizate cu instrumentul SonarQube. Am folosit un mod de analiză longitudinal, care permite instrumentului să urmărească modul în care problemele descoperite evoluează în versiunile viitoare. Am reprezentat în Figurile 2, 3 și 4 toate versiunile FreeMind, jEdit și TuxGuitar, respectiv. Barele de culoare mai întunecată reprezintă rația de datorie tehnică nou introdusă în acea versiune. De exemplu, întreaga datorie tehnică a primei versiuni analizate este nou-introdusă. Vom prezenta pe scurt câteva din cele mai interesante descoperiri, celelalte fiind publicate în literatura științifică [2].
În cadrul aplicației FreeMind, observăm că majoritatea versiunilor au o rație a datoriei de categorie (A) (\<5%), cu excepția versiunilor 0.8.0 și 0.8.1. Prima din acestea a introdus o actualizare importantă a interfeței grafice însoțită de multe funcționalități noi. Cu acestea am descoperit și o cantitate mare de cod generat ce prezenta probleme precum secțiuni duplicate de cod, utilizarea de nume non-standard pentru variabile și utilizarea claselor dintr-o implementare specifică a limbajului Java (ex: clase din pachetul *sun.**, care nu se regăsesc în multe din implementările limbajului). Aceste probleme au fost rezolvate în versiunea 0.9.0Beta17, în care codul generat a fost înlocuit printr-o cantitate de cod semnificativ mai mică, însă scrisă în mod direct de programatori. Datoria nou introdusă în această versiune este tocmai în acest cod nou introdus. După variația din aceste versiuni, am observat stabilizarea aplicației din punct de vedere al datoriei tehnice - modificările ulterioare, incluzând dezvoltarea versiunii 1.0.0 nu au dus la alte variații importante.
Figura 2 - Evoluția rației datoriei tehnice în versiunile FreeMind
În cadrul jEdit nu am înregistrat modificări de asemenea anvergură, majoritatea versiunilor având o rație foarte bună a datoriei tehnice. Mai mult, am observat că dezvoltarea aplicației și adăugarea de noi funcționalități au continuat în cadrul versiunilor mature, codul adăugat nu a prezentat probleme, rația datoriei fiind astfel diluată. Cea mai interesantă versiune de analizat a fost 4.0pre4, în care implementarea unei interfeței mai complexe cu utilizatorul, împreună cu adăugarea de noi funcționalități au dus la introducerea a peste 2% de datorie tehnică nouă. După această versiune, aplicația nu a mai trecut prin schimbări de arhitectură sau tehnologice, rația de datorie fiind pe un curs descrescător.
Figura 3 - Evoluția rației datoriei tehnice în versiunile jEdit
O evoluție asemănătoare poate fi observată și în cadrul aplicației TuxGuitar. Versiunea cea mai interesantă este poate 1.0.rc1, în care au fost introduse multe noi funcționalități și plugin-uri pentru importul și exportul datelor. Este interesant însă că această versiune are o rație a datoriei mai bună față de cea imediat precedentă; acest lucru se datorează refactorizărilor care au îmbunătățit estimarea SonarQube a mentenabilității aplicației. Acest exemplu ne arată importanța unei analize amănunțite - de multe ori nu este suficient să privim indicatorii oferiți de mediul de analiză, ci aceștia trebuie analizați în detaliu, la nivel de subsistem și componentă pentru a înțelege mai bine evoluția aplicației.
Figura 4 - Evoluția rației datoriei tehnice în versiunile TuxGuitar
Indicatorii oferiți de mediul de analiză trebuie analizați în detaliu, la nivel de subsistem și componentă pentru a înțelege cu adevărat evoluția
Care e compoziția datoriei tehnice?
Următorul pas a fost să încercăm să caracterizăm datoria tehnică din punct de vedere al compoziției; oare toate aplicațiile prezintă aceleași probleme sau au propriul specific? Datele din Tabelul 2 ne arată că mai mult de jumătate din datoria tehnică acumulată în toate cele trei aplicații s-a datorat încălcărilor a doar 9 din cele peste 600 de reguli Java implementate în SonarQube. Comparând acest rezultat cu cele obținute de alte studii [3, 4], am observat o suprapunere importantă - anumite reguli sunt încălcate în mod frecvent în multe aplicații open-source. Mai mult, din Tabelul 2 observăm că distribuția regulilor încălcate este specifică fiecărei aplicații, chiar și în cadrul acestui număr mic de reguli.
Tabel 2 - Problemele care au generat cel puțin jumătate din datoria tehnică în aplicațiile studiate
Încălcările a doar 9 din cele peste 600 de reguli verificate de SonarQube au generat mai mult de jumătate din datoria tehnică din aplicațiile studiate
Din cauză că nu toate regulile au aceeași putere predictivă legată de apariția de defecte software sau vulnerabilități de securitate, oglindim concluzia secțiunii anterioare - este nevoie de o analiză detaliată la nivelul aplicației pentru a identifica aspectele cu adevărat problematice și a le ierarhiza pentru a fi remediate.
Această secțiune este inspirată din experiența noastră în utilizarea mai multor versiuni de SonarQube (includem aici cel puțin versiunile 7.9, 8.2, 8.6, 9.0.1 și 9.1). Analizând aceleași aplicații, am observat o variație importantă în cadrul rezultatelor obținute - astfel s-a născut și întrebarea care inspiră titlul acestei secțiuni. Am decis astfel să facem o analiză retrospectivă a uneltei SonarQube, pentru a vedea gradul de modificare a rezultatelor pe parcursul diferitelor versiuni - de data aceasta, am păstrat constante versiunile de aplicații studiate, și am variat versiunile instrumentului SonarQube.
Am inclus toate versiunile SonarQube LTS (eng. long term support, adică suport pe termen lung - denumire acordată versiunilor care integrează modificările dezvoltate în cadrul unui ciclu de dezvoltare asociat unei versiuni majore și care primește suport timp de o durată de 18 luni) capabile de a măsura datoria tehnică și de a analiza aplicații Java 8. Cu acestea, am analizat cele mai recente versiuni compilabile folosind Java 8 ale aplicațiilor studiate și am comparat rezultatele. Figurile 5, 6 și 7 ilustrează problemele care au fost identificate de diferitele versiuni SonarQube testate.
În primul rând, versiunea 4.5.7, lansată în septembrie 2014 a fost prima care calculează datoria tehnică în cadrul unei aplicații. Aceasta însă nu face o defalcare a problemelor pe categoriile deja cunoscute (fiabilitate, securitate și mentenabilitate), acestea fiind raportate doar ca probleme (eng. issue).
Figura 5 - Problemele detectate de versiunile SonarQube în aplicația FreeMind 1.1.0Beta2
E ușor de observat că între diferitele versiuni ale uneltei există diferențe importante și replicate în toate aplicațiile studiate. Am trecut în revistă aceste modificări pentru a înțelege mai bine gradul de maturitate al uneltei, precum și pentru a încerca să estimăm modul în care rapoartele generate s-ar putea modifica în viitor. Vedem că începând cu versiunea 5.6.7, numărul de probleme de fiabilitate (eng. bugs) este mult redus. Aceasta se datorează unei analize îmbunătățite a fluxului de date din cadrul aplicației, lucru care reduce numărul detecțiilor fals-pozitive și îmbunătățește precizia analizorului. Versiunea 8.9.3, care este versiunea cu suport pe termen lung curentă la momentul scrierii a introdus analiza modului în care datele introduse de utilizator sunt prelucrate de program, ceea ce face detecția problemelor de securitate mult mai sigură. Aceste modificări au dus și la reducerea estimării timpului necesar pentru repararea tuturor problemelor din cadrul aplicației - un fapt pozitiv, ținând cont de consensul din mediul academic cum că SonarQube supraestimează timpul necesar reparării problemelor detectate.
Figura 6 - Problemele detectate de versiunile SonarQube în aplicația jEdit 5.5.0
În final, datoria tehnică, exprimată ca numărul de zile necesare reparării problemelor ce țin de mentenabilitatea aplicației a avut o evoluție în general descrescătoare, ce credem că aduce estimările SonarQube mai aproape de realitatea din teren. Aceasta se datorează îmbunătățirilor graduale legate de numărul și configurarea regulilor. De exemplu, versiunile \< 8.9.3 considerau problematică existența unei ierarhii de moștenire cu mai mult de cinci nivele; acestea sunt însă obișnuite în aplicațiile Java Swing, precum și în alte cadre de aplicație și nu relevă în mod deosebit o problemă. Versiunile recente au păstrat regula legată de ierarhia de moștenire, dar au adăugat excluderi specifice cadrelor de aplicație.
Figura 7 - Problemele detectate de versiunile SonarQube în aplicația TuxGuitar 1.5.4
Există diferențe importante între estimările oferite de diverse versiuni ale SonarQube - și când acestea sunt utilizate pe aceleași aplicații țintă
În cadrul acestei serii de trei articole am trecut în revistă cel mai des utilizate modele pentru estimarea datoriei tehnice. Am prezentat câteva din instrumentele folosite atât în mediul academic, cât și în industrie pentru estimarea datoriei tehnice și am detaliat câteva din rezultatele noastre recente legate de evoluția și compoziția datoriei tehnice în aplicațiile open-source.
În concluzie, putem afirma că există un număr mare de modele și unelte specializate în fenomenul datoriei tehnice. Primul pas de făcut pentru oricare organizație ce dorește să dețină controlul asupra fenomenului este de a-și defini propriile obiective și arii de importanță. Pe baza acestora și cu ajutorul unor ghiduri orientative precum [1] sau cel prezent se poate alege unealta sau uneltele potrivite. În această ultimă parte a seriei noastre am reliefat și importanța înțelegerii modului în care lucrează aceste instrumente și a avantajului obținut prin efectuarea unei analize bazate pe estimările furnizate de acestea.
Experimentele noastre au fost întreprinse cu diferite versiuni ale SonarQube, o platformă open-source care este și cel mai utilizat instrument pentru controlarea datoriei tehnice, atât în mediul academic cât și în industrie. Dorința noastră este de a ne extinde orizontul și spre alte instrumente, capabile de a furniza estimări bazate pe o analiză la nivel mai înalt a arhitecturii aplicației și a cuplării și coeziunii dintre modulele acesteia. Dintre acestea amintim Sonargraph și DV8, ambele fiind disponibile într-o versiune gratuită pentru evaluare.
[1] P. C. Avgeriou et al., "An Overview and Comparison of Technical Debt Measurement Tools," in IEEE Software, vol. 38, no. 3, pp. 61-71, May-June 2021, doi: 10.1109/MS.2020.3024958.
[2] Arthur-Jozsef Molnar and Simona Motogna, "Long-Term Evaluation of Technical Debt in Open-Source Software". In Proceedings of the 14th ACM / IEEE International Symposium on Empirical Software Engineering and Measurement (ESEM) (ESEM '20). Association for Computing Machinery, New York, NY, USA, Article 13, 1-9. DOI:https://doi.org/10.1145/3382494.3410673
[3] Maria Teresa Baldassarre, Valentina Lenarduzzi, Simone Romano, Nyyti Saarimäki, "On the diffuseness of technical debt items and accuracy of remediation time when using SonarQube", Information and Software Technology, Volume 128, 2020, 106377, ISSN 0950-5849,
[4] Valentina Lenarduzzi, Nyyti Saarimäki, Davide Taibi, "Some SonarQube issues have a significant but small effect on faults and changes. A large-scale empirical study", Journal of Systems and Software, Volume 170, 2020, 110750, ISSN 0164-1212,
de Ovidiu Mățan