ABONAMENTE VIDEO REDACȚIA
RO
EN
NOU
Numărul 142
Numărul 141 Numărul 140 Numărul 139 Numărul 138 Numărul 137 Numărul 136 Numărul 135 Numărul 134 Numărul 133 Numărul 132 Numărul 131 Numărul 130 Numărul 129 Numărul 128 Numărul 127 Numărul 126 Numărul 125 Numărul 124 Numărul 123 Numărul 122 Numărul 121 Numărul 120 Numărul 119 Numărul 118 Numărul 117 Numărul 116 Numărul 115 Numărul 114 Numărul 113 Numărul 112 Numărul 111 Numărul 110 Numărul 109 Numărul 108 Numărul 107 Numărul 106 Numărul 105 Numărul 104 Numărul 103 Numărul 102 Numărul 101 Numărul 100 Numărul 99 Numărul 98 Numărul 97 Numărul 96 Numărul 95 Numărul 94 Numărul 93 Numărul 92 Numărul 91 Numărul 90 Numărul 89 Numărul 88 Numărul 87 Numărul 86 Numărul 85 Numărul 84 Numărul 83 Numărul 82 Numărul 81 Numărul 80 Numărul 79 Numărul 78 Numărul 77 Numărul 76 Numărul 75 Numărul 74 Numărul 73 Numărul 72 Numărul 71 Numărul 70 Numărul 69 Numărul 68 Numărul 67 Numărul 66 Numărul 65 Numărul 64 Numărul 63 Numărul 62 Numărul 61 Numărul 60 Numărul 59 Numărul 58 Numărul 57 Numărul 56 Numărul 55 Numărul 54 Numărul 53 Numărul 52 Numărul 51 Numărul 50 Numărul 49 Numărul 48 Numărul 47 Numărul 46 Numărul 45 Numărul 44 Numărul 43 Numărul 42 Numărul 41 Numărul 40 Numărul 39 Numărul 38 Numărul 37 Numărul 36 Numărul 35 Numărul 34 Numărul 33 Numărul 32 Numărul 31 Numărul 30 Numărul 29 Numărul 28 Numărul 27 Numărul 26 Numărul 25 Numărul 24 Numărul 23 Numărul 22 Numărul 21 Numărul 20 Numărul 19 Numărul 18 Numărul 17 Numărul 16 Numărul 15 Numărul 14 Numărul 13 Numărul 12 Numărul 11 Numărul 10 Numărul 9 Numărul 8 Numărul 7 Numărul 6 Numărul 5 Numărul 4 Numărul 3 Numărul 2 Numărul 1
×
▼ LISTĂ EDIȚII ▼
Numărul 47
Abonament PDF

Cum plătim datoria tehnică: o abordare top-down

Georgiana Gligor
Owner @Tekkie Consulting



PROGRAMARE

Ce este datoria tehnică

Ward Cunningham a introdus această metaforă, explicând că "livrarea codului pentru prima dată este ca și cum ai lua un credit", apoi imediat scoțând în evidență că neplătirea acestei datorii curând "se contabilizează ca o dobândă la acel credit". Metafora folosită este extrem de sugestivă, deoarece puteți vizualiza imediat dobânda care se adaugă în timp la datoria inițială. Același autor remarcă, mai bine de 20 ani mai târziu, că "ironia în industria noastră este că se dovedește mai 'greu' codul decât partea hardware atunci când produsul este terminat și programatorii eliberați."

Un alt autor tehnic celebru, Uncle Bob, face o distincție clară între datoria tehnică și codul scris delăsător, atunci când notează că "dezordinea nu este datorie tehnică". În continuarea acestui articol, ne vom referi la acele proiecte care sunt create și dezvoltate corect.

Există o multitudine de moduri în care datoria tehnică se adaugă unui proiect. Iar Martin Fowler duce explicația mai departe atunci când face diferența între datoria prudentă și cea nechibzuită.

De ce să ne chinuim să o plătim?

Pe 31 iulie 2012, Knight Capital Group, cel mai mare trader de capital din SUA a falimentat în doar 45 minute, din cauza unei serii de evenimente care a dus la executarea unui cod nefolosit de 8 ani care nu a fost eliminat din codebase, cunoscut și ca funcționalitatea Power Peg.

Algoritmul lor de bază se numea SMART, fiind un router automat care trimitea comenzi în piață. Atunci când a scris un update pentru acesta, echipa a refolosit un flag vechi, care până în acel moment activa Power Peg. Codul trebuia să fie instalat pe 8 mașini, un proces manual derulat în câteva zile, însă doar 7 din acestea l-au recepționat. Când piața a început tranzacționarea și codul a început să fie executat cele 7 mașini care aveau codul corect au funcționat așa cum trebuia, însă cea de-a 8-a mașină a început să execute codul Power Peg (considerat 'mort'), iar acesta a început să inunde piața cu comenzi neobișnuite; în total au fost peste 4 milioane de tranzacții care au condus la pierderi de \$460 milioane de dolari.

Cauza nu este lipsa testării, nici deployment-ul incorect luate individual, ci mai degrabă lanțul de evenimente care a condus la executarea codului Power Peg într-un mediu de producție fără posibilitatea de a-l dezactiva, așa cum arată raportul SEC. Datoria tehnică și dobânda acesteia au fost plătite simultan. Așa cum un medic a explicat "atribuirea unui accident unei singure 'cauze originare' este în mod fundamental greșită [...] nu reflectă o înțelegere tehnică a naturii eșecului, ci mai degrabă o nevoie socială, culturală, de a da vina pe forțe specifice, localizate, sau pe evenimente pentru anumite rezultate."

Rolurile din cadrul echipei

Este important să înțelegem mentalitatea intrinsecă a fiecărui membru al echipei, deoarece aduce într-o lumină specială felul în care ei abordează procesul de construcție software. Ne preocupă acest aspect datorită legii lui Conway care spune că "orice organizație care proiectează un sistem va produce inevitabil unul a cărui structură este o copie a structurii de comunicare din interiorul acelei organizații".

Chiar dacă nu aveți persoane specializate pentru fiecare din aceste roluri, fiind posibil ca o persoană să îndeplinească mai multe simultan, este important să fiți conștienți de importanța fiecăruia dintre aceste roluri și să le folosiți în avantajul vostru.

De unde începem?

Trebuie să integrăm testarea în modul de lucru al dezvoltatorilor, fără să o lăsăm până când codul e deja scris. Veți întâmpina rezistență, deoarece modificarea status quo-ului nu e niciodată un lucru ușor. Chiar dacă echipa dorește să facă testare, nivelele lor de competență sunt diferite, iar armonizarea acestora într-o strategie comună va prezenta câteva probleme.

'Programatorii adevărați nu testează'

Care sunt cel mai des întâlnite scuze pe care le folosesc inginerii software atunci când nu vor să includă testarea în fluxul de lucru?

  1. "Avem o echipă de testare bine pregătită. Este treaba lor să semnaleze problemele posibile."

  2. "Clientul nostru a cerut această funcționalitate în producție până lunea viitoare. Nu este timp pentru altceva decât implementare. Nu avem timp pentru altfel de teste decât cele pe cale oricum le face testerul nostru manual."

  3. "Codul meu funcționează, am un istoric foarte bun. De ce m-aș apuca acum de testare?"

  4. "Clientul nu plătește decât pentru software funcțional. Programatorii sunt scumpi, nu putem vinde acest timp suplimentar clientului, deoarece va alege altă firmă cu care să colaboreze."

  5. "Fac doar o modificare cosmetică minoră, n-are ce să se întâmple."

  6. "Folosim modelul în V pentru livrarea proiectelor noastre software, o echipă separată de testeri are în grijă procesul de validare. Nu îi voi călca pe bătături."

Să stăpânim conceptele de testare

Să ne uităm puțin la cele mai importante tipuri de teste pe care sistemul nostru trebuie să le primească. Mai jos le vom menționa doar pe cele mai comune, vă recomand să consultați clasificarea extinsă și descrierile asociate

Testarea de acceptanță

Este cel mai cunoscut tip de testare și de obicei se execută fără neapărat ca echipa să fie conștientă de aceasta. Scopul său este să determine dacă cerințele sunt îndeplinite, fără a merge în detaliu pentru fiecare funcționalitate în parte.

Testul simplu de acceptanță funcțională (FAST) ar trebui să fie executat la fiecare release, pentru a verifica dacă funcționalitățile majore sunt accesibile și funcționale pe o configurație cunoscută (de obicei minimală) a sistemului. Permite înlocuirea frazei "la mine merge" cu un mult mai relevant "merge în QA".

Testarea de acceptanță de conformitate verifică dacă software-ul este conform cu anumite regulamente. Pentru proiectele care au nevoie de a fi conforme cu un set de reguli, este deosebit de important și trebuie verificat des.

Testarea de acceptanță a instalării ia un release și îl instalează complet într-un mediu care este foarte apropiat (recomandabil identic) cu producția.

Testare la nivel de funcționalitate

Testele funcționale orientate pe task (TOFTs) se adresează urmăririi happy flow-ului fiecărui feature în parte și verificării validității acestora.

Testele de forțare a erorilor (FOTs) obligă programul să intre pe condiții de eroare și verifică faptul că sunt tratate corespunzător.

Testarea exploratorie indică problemele care altfel nu ar fi găsite, deoarece nu urmează un plan stabilit dinainte.

Celelalte tipuri de verificări sunt la fel de importante, mai jos le vom enumera doar: testarea încărcării, stresului, performanței, securității, scalabilității, regresiei, funcționalității (usability), a documentației, testarea instalării/dezinstalării.

Ne salvează BDD

Introdus în 2006 de către Dan North, modul de dezvoltare bazat pe comportament (BDD) solicită folosirea unui vocabular comun atât de către oamenii de business cât și de dezvoltatori, pentru a descrie comportamentul sistemului prin intermediul criteriilor de acceptanță. Gherkin este limbajul folosit pentru această descriere, acesta permițând o descriere amănunțită a comportamentului dorit. Stilul Given-When-Then a devenit mult mai popular decât ar fi crezut creatorii săi.

Scrierea de teste care conduc sistemul automat prin scenarii verificate de părțile interesate asigură claritatea specificațiilor și previne introducerea regresiilor.

De ce este mai bun BDD decât TDD?

Pe scurt: nu este mai bun. TDD este mai granular, iar disciplina sa adaugă o multitudine de beneficii codului. Dar aceste metode abordează nivele diferite de testare, de aceea nu le putem compara între ele. Ceea ce dorim să sugerăm este să încercați BDD primul.

Modul în care BDD a apărut a fost tocmai nefericirea lui Dan North cu adoptarea TDD în cazul său personal. Așa că a mers un nivel mai sus la procesul de analiză, unde a găsit o metodă de a-l simplifica. De aceea, a câștigat atât de multă popularitate într-o sumedenie de limbaje.

Să trecem la treabă

Înțelegem faptul că modificarea întregului mod în care livrați sofware astăzi este o schimbare drastică ce nu poate avea loc peste noapte. De aceea, am extras câteva practici pe care le puteți încorpora chiar astăzi, pentru a vedea beneficiile imediat.

Învățați progamatorii cum să testeze astăzi

Testarea nu ar trebui să se petreacă după ce codul a fost deja scris. Programatorii care învață conceptele de testare încep să gândească și distructiv, chiar înainte de a scrie cod, astfel că vor produce un cod superior calitativ.

Rotiți programatorii pentru a fi și testeri

Pentru o anumită funcționalitate, o persoană poate fie să scrie scenariile de test, fie codul, dar nu ambele, deoarece "un programator nu ar trebui să își testeze niciodată propriul cod". Poate sună puțin ca pair-programming, dar perechea lucrează în paralel cu scopuri diferite.

Notă: chiar dacă unul din programatori devine foarte îndemânatic la a scrie scenariile, asigurați-vă că la selecția următoare va scrie cod, pentru a-i păstra îndemânarea.

Adoptați metode sistematice de testare

Partiționarea datelor de intrare. Divizați datele de intrare în mulțimi care au același comportament pentru a putea scrie doar un singur test pentru fiecare și a elimina astfel testele redundante care parcurg același cod. Partiționați în: date goale, date singulare, date multiple.

Testarea limitelor: Identificați elementele de la limite și scrieți câte un test pentru fiecare. Exemple: zero; null; valori minime/maxime; mulțimea vidă; șirul de caractere gol.

Dezvoltarea bazată pe fixture

Tratați modulele de cod drept componente independente. Descrieți comportamentul acestora folosind intrări și ieșiri statice care pot fi alimentate testelor automate. Dacă există o componentă care nu se poate mula pe această abordare, înseamnă că aceasta nu a fost corect specificată în cerințe.

Această metodă face ca testele să fie mai rapide, pentru că nu e nevoie să pregătim întregul sistem, iar acesta poate să revină la starea anterioară după ce testul a fost finalizat.

Un beneficiu suplimentar este acela că testele devin modulare, astfel că ele depind de (și descriu) specificațiile.

Automatizați rularea scenariilor pentru a aborda testarea regresiilor

Introducerea de erori în funcționalitățile existente nu este de dorit. BDD ne ajută să prevenim acest lucru prin faptul că avem testele scrise deja. Dar ele trebuie să poată rula cât mai ușor pentru a fi folosite.

Asigurați-vă că fiecare programator poate rula întreaga suită de teste fără prea mare efort. Cu cât e mai mare efortul necesar executării acesteia, cu atât e mai mică probabilitatea ca acest lucru să se petreacă în realitate.

References

  1. Conway, Melvin E. (1968). How Do Committees Invent?
  2. MyerșGlenford J. (1976). Software Reliability: Principles and Practices. Wiley. ISBN: 978-0471627654.
  3. Cunningham, Ward (1992). The WyCash Portofolio Management System
  4. Cook, Richard I. (1998). How Complex Systems Fail
  5. Nguyen, Hung Q., Bob Johnson, and Michael Hackett (2003). Testing Applications on the Web: Test Planning for Mobile and Internet-Based Systems. Wiley Publishing Inc. ISBN: 0-471-20100-6.
  6. North, Dan (2006). Introducing BDD
  7. Fowler, Martin (2009). Technical Debt Quadrant
  8. Martin, Robert Cecil (2009). A Mess is not a Technical Debt
  9. Group, PA Consulting (2011). Major UK water utility Architecture and design assurance.
  10. Miller, Robert (2011). Lecture notes in Elements of Software Construction.
  11. Fowler, Martin (2013). Given When Then.
  12. Securities and Exchange Commission (2013). Administrative Proceeding File No. 3-15570.
  13. Berstein, David Scott (2015). Beyond Legacy Code: Nine Practices to Extend the Life (and Value) of Your Software. Pragmatic Bookshelf. ISBN: 978-1-68050-079-0.
  14. Cucumber implementations.
  15. Gherkin Reference.

Conferință

NUMĂRUL 141 - Business Anlysis (BA)

Sponsori

  • Accenture
  • BT Code Crafters
  • Accesa
  • Bosch
  • Betfair
  • MHP
  • BoatyardX
  • .msg systems
  • Yardi
  • P3 group
  • Ing Hubs
  • Colors in projects

INTERVIURI VIDEO