Eficienţă

Programatorii cu experiență pot deosebi cu ușurință o arhitectură bună de una proastă, dar dacă li se cere să o descrie în câteva cuvinte, este puțin probabil să fie capabili să facă acest lucru. Nu există un criteriu unic pentru o arhitectură bună și nici o definiție unică.

Totuși, dacă te gândești bine, poți scrie o serie de criterii pe care ar trebui să le îndeplinească o arhitectură bună. O arhitectură bună este, în primul rând, o arhitectură logică care face procesul de dezvoltare și menținere a unui program mai simplu și mai eficient.

Când un program are o arhitectură bună, este întotdeauna suficient de ușor să înțelegeți cum funcționează și unde să scrieți codul. Un program bine proiectat este mai ușor de modificat, testat, depanat și dezvoltat. Oamenii inteligenți au formulat următoarele criterii pentru o arhitectură bună:

  • Eficienţă;
  • Flexibilitate;
  • Extensibilitate;
  • Scalabilitate;
  • testabilitate;
  • Mentenabilitatea codului.

Eficiența sistemului. Programul, desigur, trebuie să rezolve sarcinile atribuite și să își îndeplinească bine funcțiile și în diferite condiții. Se pare că orice program face ceea ce ar trebui să facă (dacă este scris), dar de multe ori nu este deloc așa.

Vei întâlni în mod constant programe care nu fac ceea ce pretind că fac.

  • Libre Office este un înlocuitor complet pentru Microsoft Office (nu chiar);
  • Browserul Edge acceptă toate standardele web (nu chiar);
  • Băncii îi pasă de securitatea datelor cu caracter personal ale utilizatorilor săi (de fapt nu).

Și încă nu am atins despre performanță, fiabilitate, remedieri de erori în timp util sau publicarea de informații despre vulnerabilități cunoscute.

Este clar că nimeni nu este perfect, dar programul trebuie să-și rezolve sarcinile principale. Prin urmare, fără eficiență, nicăieri.

Flexibilitate

Singurul lucru mai important decât eficiența în opinia mea este flexibilitatea. Orice aplicație trebuie să se schimbe în timp, pe măsură ce cerințele se modifică, se adaugă altele noi. Cu cât este mai rapid și mai convenabil să faci modificări la funcționalitatea existentă, cu atât mai puține probleme și erori provoacă, cu atât mai flexibilă este arhitectura sistemului.

Foarte des, programatorii/arhitecții începători cred că au nevoie de o arhitectură ideală pentru sarcinile curente. Nu. Ai nevoie de o arhitectura ideala pentru sarcinile care ti se vor anunta peste un an. Tu, care nu știi deja sarcinile viitoare, ar trebui să știi care vor fi acestea.

Nu are sens să încerci să le prezici, pentru că întotdeauna va fi ceva neașteptat. Dar trebuie să țineți cont de faptul că astfel de sarcini vor apărea. Prin urmare, în procesul de dezvoltare, încercați să evaluați ceea ce se obține în ceea ce privește modul în care va trebui schimbat.

Întrebați-vă: „Ce se întâmplă dacă decizia arhitecturală actuală se dovedește a fi greșită?”, „Cât va fi schimbat codul?”. Schimbarea unui fragment al sistemului nu ar trebui să afecteze celelalte fragmente ale acestuia.

Ori de câte ori este posibil, deciziile arhitecturale nu ar trebui să fie puse în piatră, iar consecințele erorilor arhitecturale ar trebui limitate în mod rezonabil. „Arhitectura bună vă permite să întârziați deciziile cheie” (Bob Martin) și minimizează „costul” greșelilor.

Una dintre aceste abordări este împărțirea aplicației în microservicii: este ușor să spargeți logica deja existentă în părți separate. Dar cea mai mare problemă este efectuarea de modificări viitoare la o duzină de servicii simultan pentru a implementa o funcție mică.

Scalabilitate

Scalabilitatea este capacitatea de a reduce timpul de dezvoltare prin adăugarea de oameni noi la proiect. Arhitectura ar trebui să permită paralelizarea procesului de dezvoltare, astfel încât mulți oameni să poată lucra la program în același timp.

Se pare că această regulă este îndeplinită de la sine, dar în practică totul este exact invers. Există chiar și o carte super-populară, The Mythical Man-Month , care explică de ce atunci când la un proiect se adaugă oameni noi, timpul de dezvoltare crește.

Extensibilitate

Extensibilitatea este capacitatea de a adăuga noi caracteristici și entități unui sistem fără a rupe structura de bază. În etapa inițială, este logic să puneți în sistem doar funcționalitatea de bază și cea mai necesară.

Acesta este așa-numitul principiu YAGNI - nu veți avea nevoie de el , „nu veți avea nevoie de el”. În același timp, arhitectura ar trebui să vă permită să creșteți cu ușurință funcționalitatea suplimentară, după cum este necesar. Și astfel încât introducerea celor mai probabile schimbări a necesitat cel mai mic efort.

Cerința ca arhitectura sistemului să fie flexibilă și extensibilă (adică să fie capabilă de schimbare și evoluție) este atât de importantă încât este chiar formulată ca un principiu separat - „Principiul Deschis/Închis . Principiul Open-Closed este al doilea dintre cele cinci principii SOLIDE: entitățile software (clase, module, funcții) ar trebui să fie deschise pentru extindere, dar închise pentru modificare .

Cu alte cuvinte: ar trebui să fie posibilă schimbarea și extinderea comportamentului sistemului fără a rescrie părțile existente ale sistemului .

Aceasta înseamnă că aplicația trebuie proiectată în așa fel încât schimbarea comportamentului și adăugarea de noi funcționalități să fie realizate prin scrierea unui cod nou (extensii), fără a fi nevoie să se schimbe codul existent.

În acest caz, apariția unor noi cerințe nu va presupune o modificare a logicii existente, ci poate fi implementată în primul rând prin extinderea acesteia. Acest principiu stă la baza „arhitecturii plug-in” (Plugin Architecture). Tehnicile prin care se poate realiza acest lucru vor fi discutate mai târziu.

Vă amintiți servlet-urile și filtrele? De ce au fost necesare filtre și chiar și cu interfețe separate, dacă, de fapt, toată aceeași logică ar putea fi implementată folosind servlet-uri?

Invenția conceptului de filtre (servlet-uri de serviciu) a făcut posibilă mutarea diferitelor funcții de serviciu într-un strat separat. Și în viitor, la modificarea comportamentului filtrelor, nu a fost necesară schimbarea servlet-urilor.

Înainte de inventarea filtrelor, toată logica serviciului care era responsabilă pentru redirecționarea cererilor era localizată în servleturile în sine. Și adesea, o mică schimbare a logicii ar duce la necesitatea de a parcurge toate servleturile și de a face diferite modificări tuturor.

Testabilitate

Dacă sunteți un dezvoltator Java Backend, atunci aplicațiile dvs. de server expun adesea un set de metode ca API REST. Și pentru a verifica dacă toate metodele tale funcționează conform intenției, acestea trebuie acoperite cu teste.

În general, acoperirea testului API este un stil bun. Vă permite să vă asigurați că API-ul dvs. face cu adevărat ceea ce a fost intenționat să facă. Și, de asemenea, mai important, puteți face modificări în logica serverului și puteți verifica cu ușurință dacă nu ați spart nimic accidental .

De îndată ce începeți să scrieți teste, veți realiza că majoritatea codului nu poate fi testat deloc: metode private, cuplare puternică, clase și variabile statice.

„De ce avem nevoie de teste dacă codul funcționează?”, se va întreba începătorul.

„De ce avem nevoie de cod de lucru dacă nu poate fi testat?”, se va întreba profesionistul.

Codul care este ușor de testat va conține mai puține erori și va fi mai fiabil. Dar testele nu îmbunătățesc doar calitatea codului. Aproape toți dezvoltatorii ajung în cele din urmă la concluzia că cerința de „testabilitate bună” este, de asemenea, o forță de ghidare care duce automat la un design bun.

Iată un citat din cartea Ideal Architecture: „Folosește principiul „testabilității” unei clase ca „test de turnesol” al designului bun al clasei. Chiar dacă nu scrii o singură linie de cod de test, răspunzând la această întrebare în 90. % din cazuri va ajuta la înțelegerea modului în care totul este bun" sau "rău" cu designul său."

Există o întreagă metodologie de dezvoltare a programelor bazate pe teste, care se numește Test-Driven Development (TDD). Aceasta este, desigur, cealaltă extremă: scrieți cod înainte de a scrie cod.

Mentenabilitatea codului

De regulă, mulți oameni lucrează la program - unii pleacă, vin alții noi. Timpul mediu de lucru al unui programator într-o companie IT este de un an și jumătate. Deci, dacă ați venit la un proiect care are 5 ani, atunci doar 20% dintre colegii tăi au lucrat la el încă de la început.

Menținerea și dezvoltarea unui program pe care l-au scris alții este foarte dificilă. Chiar dacă programul este deja scris, de multe ori este necesar să-l mențineți în continuare: remediați erorile și faceți corecții minore. Și adesea acest lucru trebuie făcut de oameni care nu au luat parte la scrierea lui.

Prin urmare, o arhitectură bună ar trebui să facă relativ ușor și rapid ca oamenii noi să înțeleagă sistemul . Proiectul trebuie sa fie:

  • Bine structurat.
  • Nu contine duplicatii.
  • Au cod bine formatat.
  • Este de dorit să includeți documentația.
  • Este necesar să se aplice soluții standard și familiare pentru programatori.

Puteți evalua cu ușurință proiectul la care lucrați pe un sistem în 5 puncte . Numără doar două puncte pentru fiecare dintre aceste cerințe . Și dacă primești 5 sau mai multe, atunci ești norocos.

Programatorii au chiar și un principiu al celei mai mici surprize : cu cât sistemul este mai exotic, cu atât este mai dificil pentru alții să înțeleagă. De obicei, este folosit în legătură cu interfața cu utilizatorul, dar este aplicabil și pentru scrierea codului.