Software Design se numără printre ultimele trenduri care impresionează domeniul IT. Se pare că în fiecare an apar alte câteva idei de design. Mai întâi au fost design patterns. MVC este modul în care construim aplicații web, în timp ce idei cum ar fi: domain driven design, porturi și adaptoare, microservices se bucură de adopție și interes crescut.
Am învățat software design făcând, cu un mentor care a ținut să-mi dea un feedback foarte util, deși uneori enervant. Acest lucru a fost înainte să știu despre design patterns, SOLID principles sau TDD. Prin urmare, înțelegerea mea pornește de la legile de bază ale software design-ului. De aceea, atunci când lucrez cu dezvoltatori, eu sau colegii mei, îi învățăm nu numai design patterns și SOLID principles, dar și cum să gândească designul aplicațiilor. Iată patru idei pe care ar trebui să le iei în considerare atunci când iei o decizie de design pentru a obține software design mai bun:
Când facilitez exerciții de arhitectură sau design, cum ar fi Architectural Kata,Code Retreats sau unul dintre workshop-urile de software design, le cer participanților să creeze un design, fie scriind cod fie sub formă de diagramă. Apoi discutăm și oferim feedback soluției lor. De multe ori, un participant îmi cere să dau „cea mai bună soluție” pentru problema respectivă. Răspunsul neașteptat este că nu există „cea mai bună soluție”.
Realitatea este că orice decizie de software _design_are avantaje și dezavantaje. Dar la urma urmei, iată o listă succintă a caracteristicilor unui design bun:
Este imposibil să scrii cod care obține un 10/10 pentru toate aceste criterii simultan. De aceea avem sloganul „quick and dirty” în loc de „corect și rapid și scalabil și fără bug-uri și ușor de schimbat și ...”. Întrebarea importantă devine atunci: pentru care criteriu este acceptabil să obții un 8/10, 6/10 sau 4/10, în contextul în care te afli.
Acest lucru se traduce în „cea mai potrivită” soluție pentru un anumit context; probabil că nu va arăta precum „cea mai bună soluție” la care te gândeai. Iată o poveste personală pentru a sprijini acest fapt. Când dezvoltam în C#, am descoperit că am putea folosi delegates ca expresii lambda, reducând astfel numărul de linii de cod pe care trebuia să le scriu. Am rezistat tentației deoarece colegii mei ar fi găsit acest cod confuz și ar fi crescut șansa de a face greșeli. Aș fi putut încerca să-i învăț acest mod de a scrie cod, dar nu eram atât de bun la instruirea oamenilor pe atunci. A fost o decizie conștientă pentru binele proiectului.
Am două moduri de a identifica avantajele și dezavantajele, astfel încât să obțineți software design mai bun. Ori de câte ori evaluăm soluții potențiale pentru o problemă:
Listăm alternativele, avantajele și dezavantajele fiecăreia dintre ele și apoi facem o alegere conștientă pentru una dintre soluții.
Experimentăm: începem punerea în aplicare a uneia dintre soluții, fiind gata să aruncăm sau să schimbăm soluția dacă nu este destul de bună.
Acest proces nu trebuie să ia mult timp. De obicei, o jumătate de oră sunt mai mult decât suficiente pentru prima opțiune și maxim două ore pentru a doua. După puțină practică, vei începe să faci aceasta în mod automat pentru cele mai multe decizii.
Dacă există un lucru pe care îl poți învăța din această lege, acesta ar trebui să fie: Pentru a face software _design_mai bun, identifică avantajele și dezavantajele soluției pe care o alegi.
Întrebarea de reflecție: Care sunt dezavantajele clasei la care lucrezi? Ce ar putea merge prost?
Ori de câte ori vorbim despre design în alte domenii decât software-ul, discutăm din punct de vedere orientat către utilizator. Produsele Apple sunt renumite pentru că se concentrează pe experiența unui utilizator cu dispozitivul lui: cum se simte, cum arată, cât de repede răspunde, sunetele pe care le face, etc. .
Software design-ul este singurul tip de design care pare a nu avea utilizator. La urma urmei, utilizatorul final nu are nicio idee despre cum funcționează software-ul și nici nu-i pasă. Tot ce le pasă utilizatorilor finali este ca software-ul să funcționeze cum trebuie.
Atunci de ce ar trebui să ne pese de structura internă a software-ului? Există motive economice foarte bune pentru a face acest lucru. În cazul în care software-ul nu este ușor de schimbat, dezvoltatorii nu vor putea adăuga caracteristici rapid, ducând la o potențială pierdere a clienților. Atunci când structura software-ului nu este organizată în mod corespunzător, ar putea să apară mai multe bug-uri care necesitând mai multe ore de săpat prin cod pentru a le repara, ar crește costurile de întreținere.
Acestea nu sunt probleme noi. Designurile inițiale pentru multe obiecte pe care le folosim acum zilnic au început prin a fi slabe, dar au fost îmbunătățite în timp. Cum? Cheia stă în a asculta feedback-ul utilizatorilor.
În echipa noastră, Claudia lucrează full-time în timp ce eu lucrez part-time la un produs eHealth. În afară de sarcinile mele de dezvoltare, ajut ca mentor, coach și o ajut cu decizii mai dificile. Una dintre întrebările mele recurente este: „Ce a fost greu de schimbat în ultimele două săptămâni?”. Pe baza acestei întrebări, am îmbunătățit viteza de modificare a codului în zonele unde se schimbă cel mai mult.
Software design-ul are utilizator. Utilizatorul este dezvoltatorul care va trebui să schimbe codul pe care îl scrii. Dacă folosiți collective code ownership (ca majoritatea echipelor Scrum), ar fi bine să luați în considerare user-centric software design (software design orientat către utilizator).
Și iată o idee pentru tine: ce zici despre rularea de teste de usability pe software design pentru a reduce costurile de dezvoltare?
Pentru a face software design mai bun, analizează-l din punctul de vedere al altor dezvoltatori.
Întrebarea de reflecție: Care sunt unele dintre plângerile comune ale colegilor tăi de echipă legate de cod? Ce este dificil să schimbați? Cum ai putea să-l faci mai ușor?
Software-ul este cunoaștere executabilă. De exemplu, când scrii o aplicație de contabilitate, se codifică tot ce știi despre regulile și procedurile de contabilitate. Cum au ajuns aceste cunoștințe în aplicație? Prin preluarea acestora de la specialiști și trecerea prin creierul dezvoltatorilor pentru a le transforma în cod.
O observație aparte este că cele două caracteristici care diferențiază dezvoltatorii de restul lumii este că ei înțeleg calculatoarele și pot gândi cu un nivel foarte ridicat de precizie. De aceea nu cred în programarea vizuală făcută de specialiști.
Cum învață și își structurează cunoștințele oamenii? Prin atribuirea de nume lucrurilor. Dacă te gândești la anii de școală, îți amintești de învățarea despre numere, operații aritmetice, tabla înmulțirii etc..Acestea sunt doar nume date unor concepte, nume care ne ajută să comunicăm unul cu celălalt despre idei complexe.
Vă invit să realizați următorul test. Scrieți unele dintre numele claselor, metodelor și variabilelor din codul pe care lucrați. Apoi notați-vă ceea ce face aplicația. Apoi numărați câte dintre aceste nume corespund domeniului de aplicare. Sau întrebați pe cineva care nu știe la ce lucrați să ghicească ce face aplicația doar pe baza listei de nume. În cazul în care au ghicit, atunci vă rog să mă contactați pentru că vreau să învăț de la voi cum faceți.
Acest test arată o deconexiune tipică între ceea ce aplicația face și cum își structurează dezvoltatorii cunoștințele în cod. De ce este acest lucru rău? Deoarece creierul trebuie să-și petreacă timp valoros încercând să traducă ceea ce citește către ce face aplicația. Acest lucru duce la reducerea productivității și te obosește.
Nu există în acest moment nici un mod definitiv pentru a elimina distanța dintre cunoștințe și cod. Aceasta poate fi însă redusă mult de iterarea prin continuumul numelor definit de JB Rainsberger. Un sfat: veți găsi că este foarte dificil la început, dar devine mai ușor cu exercițiu.
Pentru a face software design mai bun, numește clasele, metodele și variabilele cât mai aproape de domeniul de business posibil.
Întrebarea de reflecție: Ce face aplicația ta? Care sunt câteva nume specifice businessului? Sunt acestea prezente în cod?
Acum 40 de ani, Fred Brooks a scris o carte pentru dezvoltarea de software numit „The Mythical Man Month”. Cartea conține multe constatări esențiale despre dezvoltarea de software și inginerie pe care cei mai mulți oameni care lucrează în industrie nu le știu și nu le aplică pentru că nu au citit cartea.
Cea mai importantă idee de design din carte este următoarea:
Voi susține că integritatea conceptuală este cel mai important aspect în proiectarea sistemului. Este mai bine să avem un sistem care omite anumite caracteristici anormale și îmbunătățiri, dar care reflectă un set de idei de design, decât de a avea unul care conține multe idei bune, dar independente și necoordonate.
Pagina wiki a lui Ward Cunningham pe această temă oferă următoarele exemple de integritate conceptuală:
Putem identifica exemple specifice, binecunoscute de Conceptual Integrity? Vă prezint o listă de asemenea exemple specifice, care nu este definitivă:
De ce este utilă integritatea conceptuală? Probabil din cauza modului în care creierul nostru funcționează. Memoria omenească de lucru se limitează la păstrarea a patru articole în paralel, dar există o metodă de a o păcăli: fiecare element poate fi de fapt un set de concepte înrudite (un așa numit chunk). Când ai de luat decizii de design dificile, cu siguranță ai nevoie să iei în considerare mai mult de patru lucruri în același timp. Ajută dacă sunt similare, deoarece creierul poate să le prelucreze, permițându-ți să iei decizii mai informate de design.
Integritatea conceptuală poate fi aplicată la diferite niveluri, de la variabile, metode la clase. De exemplu, să facem următorul test. Notați numele câtorva clase și numele tuturor metodelor lor publice. Arată interfața clasei cuiva care nu știe la ce lucrați și întrebați ce face clasa respectivă. Întrebați-i dacă e ceva ce pare că nu e la locul ei în acea clasă. Dacă ghicesc și totul se potrivește, felicitări: ați realizat integritate conceptuală la nivel de clasă. Acum faceți același exercițiu la nivel de namespace și modul (arătând doar interfața publică a modulului).
La nivel de sistem, lucrurile devin tot mai complexe. Ports and adapters și microservices sunt unele dintre modelele care ușurează integritatea conceptuală la nivel de sistem. Dar nici o soluție nu este perfectă, fiecare dintre ele are dezavantaje .
Un avertisment: integritatea conceptuală este foarte greu de obținut, mai greu decât găsirea de nume potrivite. Cu toate acestea, experiența m-a învățat că atunci când reușești, integritatea conceptuală este nu numai foarte utilă, dar și frumoasă. Într-o lume plină de bug-uri și cod urât, frumusețea poate face minuni pentru moralul tău.
Pentru a face software design mai bun, străduiește-te să obții integritate conceptuală la nivel de clasă, namespace, modul și de sistem.
Întrebarea de reflecție: Ce părți din aplicație au integritate conceptuală? Alege o clasă la care lucrezi; cum o poți aduce mai aproape de integritate conceptuală?
Vrei să înveți mai multe despre software _design_și arhitectură? Ești interesat de ultimele practici în industria de IT software precum: DevOps, Microservices, Technical Leadership, Technical Strategy, etc.? Vino pe 28 - 29 Mai, la I T.A.K.E. Unconference să faci parte din comunitatea europeană desoftware craftsmen și practicieni experimentați.
„The not-to-be-missed event” în Europa Centrală și de Est pentru software craftsmanship - http://itakeunconf.com
de Peter Lawrey
de Răzvan Costa