Nu fi de acord să dezvolți ceva ce nu înțelegi

Nu fi de acord să dezvolți ceva ce nu înțelegi

De la începutul anului 2018 ocup poziția de lead/boss/lead developer în echipă - spuneți cum doriți, dar ideea este că sunt în întregime responsabilă pentru unul dintre module și pentru toți dezvoltatorii care lucrează pe el. Această poziție îmi oferă o nouă perspectivă asupra procesului de dezvoltare, deoarece sunt implicat în mai multe proiecte și implicat mai activ în luarea deciziilor. Recent, datorită acestor două circumstanțe, mi-am dat seama brusc cât de mult afectează măsura înțelegerii codul și aplicația.

Ideea pe care vreau să subliniez este că calitatea codului (și a produsului final) este strâns legată de cât de conștienți sunt oamenii care proiectează și scriu codul de ceea ce fac.

S-ar putea să vă gândiți chiar acum: „Mulțumesc, Cap. Desigur, ar fi bine să înțelegeți ce scrieți în general. În caz contrar, ați putea la fel de bine să angajați un grup de maimuțe care să lovească tastele arbitrare și să lăsați totul așa.” Și ai perfectă dreptate. Prin urmare, iau de la sine înțeles că îți dai seama că este necesar să ai o idee generală despre ceea ce faci. Acesta poate fi numit nivelul zero de înțelegere și nu îl vom analiza în detaliu. Vom analiza în detaliu ce anume trebuie să înțelegeți și modul în care acesta afectează deciziile pe care le luați în fiecare zi. Dacă aș fi știut aceste lucruri dinainte, m-ar fi scutit de mult timp pierdut și de cod îndoielnic.

Deși nu veți vedea o singură linie de cod mai jos, tot cred că tot ceea ce este spus aici este de mare importanță pentru scrierea unui cod expresiv de înaltă calitate.

Primul nivel de înțelegere: De ce nu funcționează?

De obicei, dezvoltatorii ating acest nivel foarte devreme în cariera lor, uneori chiar fără nici un ajutor din partea altora - cel puțin din experiența mea. Imaginați-vă că ați primit un raport de eroare: o anumită funcție din aplicație nu funcționează, trebuie remediată. Cum vei proceda?

Schema standard arată astfel:

  1. Găsiți fragmentul de cod care cauzează problema (cum se face acest lucru este un subiect separat, îl acopăr în cartea mea despre codul moștenit)
  2. Efectuați modificări la acest fragment
  3. Asigurați-vă că eroarea este remediată și că nu au apărut erori de regresie

Acum să ne concentrăm asupra celui de-al doilea punct - a face modificări la cod. Există două abordări ale acestui proces. Primul este să aprofundați ce se întâmplă exact în codul actual, să identificați eroarea și să o remediați. În al doilea rând: mutați prin simțire - adăugați, să spunem, +1 la o declarație sau o buclă condiționată, vedeți dacă funcția funcționează în scenariul dorit, apoi încercați altceva și așa mai departe la infinit.

Prima abordare este corectă. După cum explică Steve McConnell în cartea sa Code Complete (pe care o recomand cu căldură, apropo), de fiecare dată când schimbăm ceva în cod, ar trebui să putem prezice cu încredere cum va afecta aplicația. Citez din memorie, dar dacă o remediere a erorilor nu funcționează așa cum vă așteptați, ar trebui să fiți foarte alarmați și ar trebui să vă puneți la îndoială întregul plan de acțiune.

Pentru a rezuma ceea ce s-a spus, pentru a realiza o remediere bună a erorilor care nu degradează calitatea codului, trebuie să înțelegeți atât întreaga structură a codului, cât și sursa problemei specifice.

Al doilea nivel de înțelegere: De ce funcționează?

Acest nivel este înțeles mult mai puțin intuitiv decât cel anterior. Eu, în timp ce eram încă un dezvoltator începător, l-am învățat datorită șefului meu și, ulterior, am explicat în mod repetat esența problemei noilor veniți.

De data aceasta, să ne imaginăm că ați primit două rapoarte de eroare simultan: primul este despre scenariul A, al doilea este despre scenariul B. În ambele scenarii se întâmplă ceva greșit. În consecință, abordați primul bug mai întâi. Folosind principiile pe care le-am dezvoltat pentru înțelegerea nivelului XNUMX, cercetați în profunzime codul relevant pentru problemă, vă dați seama de ce determină aplicația să se comporte așa cum o face în scenariul A și faceți ajustări rezonabile care produc rezultatul dorit. . Totul merge grozav.

Apoi treci la scenariul B. Repeți scenariul în încercarea de a provoca o eroare, dar — surpriză! — acum totul funcționează așa cum ar trebui. Pentru a vă confirma presupunerea, anulați modificările făcute în timp ce lucrați la bug-ul A, iar bug-ul B revine. Remedierea dvs. a rezolvat ambele probleme. Norocos!

Nu te-ai contat deloc pe asta. Ați venit cu o modalitate de a remedia eroarea din scenariul A și nu aveți idee de ce a funcționat pentru scenariul B. În această etapă, este foarte tentant să credeți că ambele sarcini au fost finalizate cu succes. Acest lucru este destul de logic: scopul era să eliminăm erorile, nu-i așa? Dar munca nu este încă terminată: mai trebuie să vă dați seama de ce acțiunile dvs. au corectat eroarea din scenariul B. De ce? Pentru că poate funcționa pe principii greșite și atunci va trebui să cauți o altă cale de ieșire. Iată câteva exemple de astfel de cazuri:

  • Deoarece soluția nu a fost adaptată pentru eroarea B, luând în considerare toți factorii, este posibil să fi defectat fără să știți funcția C.
  • Este posibil să existe și un al treilea bug pe undeva, legat de aceeași funcție, iar remedierea dvs. depinde de aceasta pentru funcționarea corectă a sistemului în scenariul B. Totul arată bine acum, dar într-o zi acest al treilea bug va fi observat și remediat. Apoi, în scenariul B, eroarea va apărea din nou și este bine, dacă numai acolo.

Toate acestea adaugă haos la cod și îți vor cădea într-o zi în cap - cel mai probabil în cel mai inoportun moment. Va trebui să vă adunați voința pentru a vă forța să petreceți timp înțelegând de ce totul pare să funcționeze, dar merită.

Al treilea nivel de înțelegere: De ce funcționează?

Perspectiva mea recentă se referă tocmai la acest nivel și, probabil, este cel care mi-ar fi oferit cel mai mult beneficiu dacă aș fi ajuns la această idee mai devreme.

Pentru a fi mai clar, să ne uităm la un exemplu: modulul dumneavoastră trebuie să fie compatibil cu funcția X. Nu sunteți foarte familiarizat cu funcția X, dar vi s-a spus că pentru a fi compatibil cu ea trebuie să utilizați cadrul F. Altele modulele care se integrează cu X funcționează exact cu el.

Codul tău nu a fost deloc în contact cu framework-ul F din prima zi de viață, așa că implementarea lui nu va fi atât de ușoară. Acest lucru va avea consecințe grave pentru unele părți ale modulului. Cu toate acestea, te arunci în dezvoltare: petreci săptămâni întregi scriind cod, testând, lansând versiuni pilot, obținând feedback, remediând erori de regresie, descoperind complicații neprevăzute, nerespectând termenele convenite inițial, scriind mai mult cod, testând, obținând comunicare cu feedback, corectarea erorilor de regresie - toate acestea pentru a implementa cadrul F.

Și la un moment dat vă dați seama brusc - sau poate auziți de la cineva - că poate cadrul F nu vă va oferi deloc compatibilitate cu caracteristica X. Poate că tot timpul și efortul au fost depuse complet greșit pentru asta.

Ceva similar s-a întâmplat o dată în timp ce lucram la un proiect de care eram responsabil. De ce s-a întâmplat asta? Pentru că înțelegeam puțin ce este funcția X și cum se leagă de cadrul F. Ce ar fi trebuit să fac? Cereți persoanei care atribuie sarcina de dezvoltare să explice în mod clar modul în care cursul de acțiune intenționat duce la rezultatul dorit, mai degrabă decât să repete pur și simplu ceea ce s-a făcut pentru alte module sau să-și creeze cuvântul că aceasta este ceea ce trebuie să facă caracteristica X.

Experiența acestui proiect m-a învățat să refuz să încep procesul de dezvoltare până când vom înțelege clar de ce ni se cere să facem anumite lucruri. Refuza categoric. Când primești o sarcină, primul impuls este să o asumi imediat pentru a nu pierde timpul. Dar politica „înghețați proiectul până când intrăm în toate detaliile” poate reduce timpul pierdut cu ordine de mărime.

Chiar dacă încearcă să pună presiune pe tine, să te oblige să începi munca, deși nu înțelegi rațiunea acestui lucru, rezistă. Mai întâi, află de ce ți se oferă o astfel de sarcină și decide dacă aceasta este calea corectă către obiectiv. A trebuit să învăț toate acestea pe calea grea - sper că exemplul meu va face viața mai ușoară celor care citesc asta.

Al patrulea nivel de înțelegere: ???

Există întotdeauna mai multe de învățat în programare și cred că am zgâriat doar suprafața subiectului înțelegerii. Ce alte niveluri de înțelegere ați descoperit de-a lungul anilor de lucru cu codul? Ce decizii ați luat care au avut un impact pozitiv asupra calității codului și aplicației? Ce decizii s-au dovedit a fi greșite și ți-au învățat o lecție valoroasă? Împărtășește-ți experiența în comentarii.

Sursa: www.habr.com

Adauga un comentariu