Cum să depășim conflictele dintre business analiști (product management), programatori și QA [P]
Echipele de dezvoltare software sunt formate din oameni care pot avea mentalități diferite, provin din medii diferite, au skill-uri și experiențe diferite, etc. De multe ori apar conflicte și dezbateri aprinse, ajungându-se astfel ca momentele tensionate să facă parte din munca de zi cu zi. Cheia este să identifici zonele în care pot apărea probleme și să găsești soluții clare pentru ele, care să economisească timp, energie, și nervi, și să ajute echipa să lucreze împreună. Ideal ar fi să nu existe astfel neînțelegeri, dar în cazul în care se întâmplă este nevoie să găsim modalități de a le rezolva și clarifica. Iată câteva exemple de conflicte precum și soluțiile pe care le-am întâlnit în Cognyte.
1. Nu este o eroare, dar nici nu este chiar o caracteristică.
Unul din membrii echipei de QA detectează și ridică un bug (o eroare software) în Jira (Instrument de Urmărire a Problemelor și Managementul de Proiect).
Team Lead: Merge bine. Nu înțeleg de ce spui că e bug. Așa a fost specificat că trebuie să funcționeze.
QA: De fapt, este un scenariu pe care nu l-ai luat în considerare când ai scris codul. Clientul ne-a trimis niște scenarii pe care ei le folosesc și, din păcate, nu funcționează cu ce le-am livrat noi.
Programatorul: Ok, pot înțelege că sunt scenarii noi, dar nouă nu ni s-a spus atunci când au fost făcute specificațiile. Pentru noi este ceva nou.
QA: Înțeleg, din păcate, scenariile acestea vin de la client și ei au nevoie de funcționalitățile acestea. Hai să vedem ce zice și echipa de business analiști.
Business analist: Înțeleg ce spuneți, pare că nu am luat în considerare scenariile respective. Care sunt estimările pentru schimbările acestea?
Programatorul: Estimăm 200 de ore de lucru, și va trebui să replanificăm ce facem acum, pentru că este clar că vom avea întârzieri.
Business analist: Ok, înțeleg. Hai să discutăm astfel încât să găsim o soluție.
Răspunsul care îi poate enerva pe cei de la QA și, uneori, pe clienți este: „funcționează conform specificaţiilor”. Practic, acest lucru înseamnă că produsul funcţionează conform specificaţiilor, dar nu satisface pe deplin nevoile clientului. Este posibil să putem schimba, dar trebuie să ținem cont de costuri: orele de lucru care vor întârzia alte evoluții la deteriorarea mai multor sisteme (mai ales atunci când vine vorba de un produs complex, bogat în date, cu componente și integrări, precum și de utilizatorii activi din întreaga lume).
Categoric se pot face schimbările necesare, dar trebuie să ținem cont și de costurile pe care le implică. Sunt ore suplimentare de care trebuie să ținem cont, apoi pot exista efecte adverse, posibil impact în alte zone ale produsului care pot face ca alte funcționalități să nu mai meargă. Asta este foarte posibil atunci când discutăm de un produs complex, cu multe componente și integrări, cu un volum de date semnificativ, clienți din toată lumea, și mai ales o industrie cu toleranță zero pentru perioadele de nefuncționare (zero tolerance for downtime), așa cum avem la Cognyte.
Toate aceste aspecte trebuie luate în considerare.
Ce este important de înțeles, este că nu vorbim de un „blaming game”. Nu arătăm pe nimeni cu degetul. Dacă echipă de QA ridică și confirmă în final un bug, este numai după ce se consultă și cu echipa de programatori. Dacă, în schimb, este o problemă mai complexă, atunci se apelează și la echipa de BA (business analist), cea care conduce din punct de vedere funcțional produsul.
Ce se ȋntâmplă când toată lumea are dreptate?
Este important să înțelegem că orice modificare are un cost, care nu este întotdeauna ușor de evaluat. Doar cei care cunosc cum funcționează întregul sistem, infrastructura sa și posibilul impact, pot estima cât de cât corect costul real al implementării unei schimbări complexe. Și chiar și în aceste cazuri, nu există o siguranță în estimare. O estimare este doar… o estimare. În final, deciziile de a implementa o cerință nouă depinde de priorități, iar echipa de business analiști (product management) și project management este implicată aici. În cazuri speciale, deciziile pot ajunge și la C-level. Totuși, înainte de orice decizie, inițiem o discuție deschisă, unde toate părțile implicate pot veni cu argumente pro și contra, încercând să luăm o decizie care să ne ajute pe viitor, atât din punct de vedere al clientului actual, cât și a altor clienți existenți sau potențiali.
O discuție de acest tip poate duce la două rezultate: fie noua cerință va fi rezolvată ca un bug fix, fie vom decide că este o limitare a versiunii actuale urmând să o implementăm într-o versiune viitoare.
O altă abordare pe care o avem este de a ne defini un plan de testare, convenit cu echipa de QA, înainte de începerea scrierii codului (test driven-development). Acest lucru ajută la definirea clară a așteptărilor și permite programatorilor să știe ce scenarii vor fi testate, astfel încât să poată scrie codul cât mai corect de la început. De asemenea, planul de testare este aprobat de echipa care coordonează cerințele funcționale. Această metodă ajută la reducerea bug-urilor și asigură o bună aliniere între echipe din punct de vedere al înțelegerii noilor cerințe.
2. Modificare majoră sau corecție minoră?
Am menționat că produsele noastre sunt complexe. Unele dintre ele sunt atât de complicate încât o nouă versiune poate apărea doar o dată pe trimestru sau chiar mai rar, uneori la șase luni sau chiar mai mult. Chiar și actualizarea unei versiuni pe platformele interne (On-Premises) este un proces semnificativ. Nu este vorba doar de un „click pe un buton”. Totuși, asta nu împiedică clienții să ne trimită cerințe noi în tot acest timp. Aceste solicitări sunt normale și legitime. Pentru a răspunde rapid tuturor clienților, am creat un nou departament numit „Servicii” (Services). Prin acest departament, există o echipă de programatori dedicată pentru a rezolva bug-uri și a implementa mici corecții și actualizări care nu sunt parte din produsul global standard. Ei sunt primii care interacționează cu clienții atunci când apare o problemă.
Uneori, echipa de produs (Product Management- PM) vine cu o nouă cerinţă pe care ei o consideră simplă şi rapid de implementat și pentru care nu are rost să parcurgem întregul proces de aprobare, analiză, planificare, etc și să „pierdem” timp pentru atât de mulți colegi. Discuția sună cam așa:
PM: Este doar o schimbare mică pentru client și nu vreau să revin către el spunând că trebuie să aștepte încă șase luni pentru ceva atât de ușor.
Programator: Din păcate lucrurile nu merg chiar așa. O mică schimbare cum este aceasta poate avea impact în multe alte componente și avem nevoie de timp să analizăm implicațiile.
PM: Deci, îi spunem clientului să aștepte șase luni?
Programator: Mă tem că va trebui să facem asta, doar dacă nu există alte lucruri pe care le avem în plan și le putem amâna.
PM: Ok. Vorbesc cu clientul, îi explic situația, și vedem cum facem.
În startup-uri sau în companii care nu au mulți clienți sau multe proiecte în desfășurare în același timp, este posibil ca acest gen de situații să nu apară foarte des. Dar într-o organizație mare, o multinațională, cu multe proiecte în paralel, astfel de situații sunt inevitabile.
Ce se ȋntâmplă când toată lumea are dreptate?
Și aici, soluția constă în abordarea „alege-ți bătăliile”, prioritizează și negociază acolo unde este nevoie. Compromisul poate fi o soluție de moment atunci când poate prioritățile sunt în contradicție. Prin dialog se poate ajunge întotdeauna la o soluție de compromis și la un echilibru între nevoile clientului și ale companiei.
3. Uneori nu vedem pădurea din cauza copacilor. Cum putem găsi responsabilul?
În general, fiecare funcționalitate este asignată unei componente, unui modul, unui flow, unui segment, unui grup, etc. De exemplu: fluxul de date (Data Flow Manager) de la utilizator până la baza de date, encodarea sau decodarea datelor, etc. Dar există situații când o funcționalitate poate aparține mai multor segmente, componente, etc. Cine este în acest caz responsabil pentru funcționalitatea respectivă, la cine mergem când avem întrebări, sau probleme, sau bug-uri?
Ce se ȋntâmplă când toată lumea are dreptate?
Sau când este responsabilitatea tuturor? De obicei o echipă/segment trebuie să preia responsabilitatea pentru funcționalitatea respectivă. Dar chiar și în cazul ăsta, pentru echipa respectivă pot exista necunoscute și multe situații să treacă neobservate și neidentificate. Din păcate, nu există mulți colegi care să aibă o privire de ansamblu a întregului sistem, mai ales atunci când zona unde activează ei este deja destul de încărcată cu diverse provocări, probleme sau situații. Și în cazul ăsta ce faci dacă nu există „voluntari” pentru această nouă responsabilitate? Pur și simplu nominalizezi segmentul responsabil, echipa care se va ocupa în continuare. Nominalizarea se face de obicei ținând cont de unele criterii cum ar fi, relevanţă față de segmentul respectiv, cam cât cod implică, poate test case-urile mai relevante, numărul de oameni, cunoștințe tehnice, etc. Și chiar dacă nu este o obișnuință, uneori se practică și ceva politică.
4. Cartoful fierbinte
Titlul pe care l-am ales pentru această ultimă parte a articolului este datorită unei situații des întâlnite în departamentul nostru de R&D (Research & Development – Cercetare și Dezvoltare). De multe ori specificațiile pentru noi funcționalități nu sunt destul de clare. Uneori sunt chiar minimale și atunci se nasc multe întrebări din partea programatorilor, ca de exemplu:
Nici designerul UX (user experience), nici arhitectul nu înțeleg ce a vrut să zică echipă de Product, business analistul. Stăm, citim, discutăm, recitim, rediscutăm și ne întrebăm ce a vrut să zică autorul. Uneori ni se pare că cei din departamentul de Product lasă lucrurile foarte high-level, mai abstracte, tocmai pentru a putea fi interpretabile. Ni se pune în brațe cartoful fierbinte și decidem noi ce facem cu el.
Normal că ceea ce spuneam mai sus este o exagerare, dar există cazuri în care apar întârzieri și neînțelegeri care pot provoca dureri de cap programatorilor, sau echipei de testare și care, în final, pot conduce la nemulțumiri și frustrări din partea clientului. Mai mult, inclusiv echipa de Product poate resimți un anumit nivel de nemulțumire și frustrare, deoarece ei cred că totul este clar, bine documentat, discutat și agreat cu clientul și brusc, dintr-o dată, își dau seama că cerințele de la punctul 5 și 9 nu sunt aplicabile, sau se bat cap în cap cu alte cerințe mai vechi.
Suntem oameni, suntem profesioniști, și frustrări de genul acesta apar mai ales când discutăm despre sisteme complexe, sisteme dezvoltate în mulți ani, sisteme care sunt deja în producție de mulți ani și pentru care ai nevoie să te înconjori de oameni care cunosc fiecare câte o bucățică, astfel încât să poți avea o imagine de ansamblu. Din păcate, există puțini colegi care pot spune că știu și cunosc sistemul în proporție de 100%.
Fiecare funcţionalitate, fiecare componentă, fiecare modul are propria sa importanță. Cei care doar scriu cod, sau doar testează ar trebui să înțeleagă și partea non-tehnică. Ar trebui să înțeleagă scopul, motivația pentru care a apărut cerința respectivă și mai ales ce valoare aduce clientului, cum o va folosi clientul. Asta ajută foarte mult la evitarea discuțiilor în contradictoriu, a pierderii timpului în discuții interminabile, a neînțelegerilor și bineînțeles a erorilor și bug-urilor care apar mai târziu. De aceea este foarte important ca în specificațiile unei noi cerințe să includem și motivația, valoarea pe care o aduce clientului și cum se integrează în produsul deja existent. Asta elimină multe întrebări mai târziu în procesul de dezvoltare.
Și, în final, dacă există modificări, sau dacă există anumite limitări, acestea trebuie specificate în descrierea noii funcționalități (exp. în Epic). Iar dacă acest lucru nu se întâmplă atât echipa de programatori, cât și cea de testing vor descoperi la un moment dat că au lucrat și au prioritizat poate, lucruri care nu mai sunt relevante. Noi am rezolvat probleme de genul acesta într-un mod cât se poate de simplu și, în general, le documentăm în Jira.
Pe scurt: fiți colegi buni, nu lăsați ego-ul să vă controleze! Aveți încredere unii în alții, ascultați cu atenție și lucrați mereu pentru binele produsului, al companiei și succesul echipei.