Este timpul să fim cinstiți față de noi înșine și să recunoaștem că nu tratăm codul frontend în același mod în care îl tratăm pe cel backend. Și aceasta se vede prea bine! Când ne referim la propriul cod, discutăm despre aplicarea regulilor de scriere a codului curat, despre codul simplu, despre scrierea testelor unitare. Cu toate acestea, atunci când vine vorba despre scrierea codului frontend, ignorăm cu bună știință toate regulile pe care ni le impunem de obicei. Și facem aceasta pentru că, într-un fel, ne-am convins de inferioritatea codului frontend față de cel backend: "Acolo se află motorul: în backend! Backendul duce tot greul. Frontendul este egal cu zero. Este bun numai la a prezenta datele la care backendul a trudit cu sârg. Deci este firesc să nu petrecem atât de mult timp în scrierea codului frontend. Să trecem prin el repede și superficial! Îl vom revizui mai târziu, când se va mai domoli agitația.
Însă nu ajungem să facem asta niciodată, nu-i așa? E timpul să ne confruntăm cu realitatea dură că frontendul nostru este în paragină. Este timpul să aplicăm regula cercetașilor și în acest caz: Lăsați locul mai curat decât l-ați găsit. Ori de câte ori mai adăugăm ceva la frontend, ar trebui să ne luăm un răgaz pentru a evalua dezordinea de acolo. Apoi, ar trebui să ne suflecăm mânecile şi să facem puţină curăţenie.
Dar ce e în neregulă cu codul nostru frontend, te-ai putea întreba? Deloc surprinzător, este vorba despre aceleași lucruri pe care le recunoaștem, de obicei, ca Lucruri Rele™ în backend: duplicare, cuplare, dezordine, lipsa testelor unitare, denumiri neclare etc. . Să aruncăm o privire mai atentă asupra unor astfel de anti-șabloane care apar în codul frontend.
Cu siguranță ești familiarizat cu conceptul de Clasă-Dumnezeu: o clasă cu mii de linii de cod care se comportă ca un zeu omniscient, omnipotent, omniprezent. De regulă, în backend împărțim clasa respectivă în mai multe clase cu joasă cuplare, cu responsabilităţi unice. Însă nu este cazul și în frontend, unde lăsăm fișierele HTML sau JSP să crească de parcă ar căuta să intre în Cartea Recordurilor. În schimb, am putea folosi taguri de include pentru a descompune şi recompune fişierul de view Cel Mare în unul mai mic. De exemplu:
<jsp:include page="header" />
<jsp:include page="navigationMenu" />
<jsp:include page="landingPageDescription" />
<jsp:include page="latestNews" />
<jsp:include page="contactForm" />
<jsp:include page="footer" />
Mai departe, identifică instanțele de duplicare pe care le poți refactoriza. Ia, de pildă, codul HTML pe care l-ai copiat și lipit pentru a crea încă un formular, încă o listă de meniuri sau încă un grup de taburi. Frameworkuri pentru JavaScript cum ar fi React, Angular și Polymer oferă componente web de-a gata, care pot fi incluse în propriul proiect. Mai mult decât atât, Componentele Web sunt proiectate de Consorțiul World Wide Web (W3C) ca un set de caracteristici care vor fi suportate direct de browsere pentru a permite crearea widgeturilor reutilizabile.
Există un alt fel de duplicare mai subtilă pe care o poți identifica în codul tău frontend. De exemplu, în următorul cod:
<div class="form-group">
<label for="firstName"/>
<input type="text"
name="firstName"
value="${user.firstName}"/>
</div>
<div class="form-group">
<label for="lastName"/>
<input type="text"
name="lastName"
value="${user.lastName}"/>
</div>
<div class="form-group">
<label for="email"/>
<input type="text"
name="email"
value="${user.email}"/>
</div>
La prima vedere, nu este nimic în neregulă cu ce vezi mai sus. Cu toate acestea, vei avea nevoie de câteva secunde de procesare mentală pentru a înțelege că respectivul cod se referă la trei câmpuri de formular. Putem să-l îmbunătățim, rescriindu-l după cum urmează:
<tmpl:formInput field="firstName"/>
<tmpl:formInput field="lastName"/>
<tmpl:formInput field="email"/>
unde formInput este un template având următorul conținut:
<div class="form-group">
<label for="${field}"/>
<input type="text" name="${field}" value="${user[field]}"/>
</div>
În această a doua versiune, poți observa aproape instantaneu că avem de-a face cu trei câmpuri de formular. Și am aplicat principiile de încapsulare și responsabilitate unică în frontend!
Există alte câteva tipuri de cod cu deficiențe pe care le poți identifica în frontend: denumiri inconsecvente, abrevieri, denumiri care nu exprimă în mod clar intenția, duplicare la nivel de CSS, cod comentat, comentarii care nu mai au legătură cu codul, etc. . Nu lăsa situația să îți scape de sub control! Alege și repară câte ceva aparent nesemnificativ în fiecare zi. Până la sfârșitul anului, codul proiectul va reveni la o formă mult mai bună. Tu cel din viitor îți vei mulțumi pentru aceasta.
De obicei, codul JavaScript aferent unui proiect nu este testat din punct de vedere unitar. Uneori, aceasta nu ridică nicio problemă, deoarece pot fi numai câteva linii care execută niscaiva scamatorii de animație sau ceva validare a intrărilor. Dar câteva linii se pot transforma rapid în câteva zeci, sute și apoi câteva mii. Înainte să îți poți da seama, te alegi cu o grămadă de cod JavaScript netestat care controlează starea și logica aplicației. Scrierea testelor unitare pentru acest tip de cod nu este imposibilă. Trebuie doar să îl analizezi și să îți dai seama ce te împiedică să scrii cu ușurință testele unitare. Îndepărtează obstacolele unul câte unul și vei învinge. Iată câteva probleme și soluții comune:
Cuplare la nivel înalt - Este mult prea ușor în JavaScript să amesteci diferite funcționalități la un loc. O singură funcție poate conține cod referitor la comunicarea cu backendul, validarea datelor, gestionarea erorilor, logica aplicației, gestionarea stării și redarea vizuală. Pentru a fi ușor de testat, funcția în cauză trebuie împărțită astfel încât fiecare element enumerat mai sus să fie separat de toate celelalte.
$(document).ready(function() {
$.get('/siteSections', function(subsectionNames) {
for (i = 0; i < subsectionNames.length; i++) {
var idName = "#" + subsectionNames[i];
var width = $(idName).width();
if (idName =="#blog" || idName =="#calendar"
|| idName =="#contact")
width += 15;
$(idName + "-bg").css("width", width);
}
});
});
Scopul codului de mai sus este acela de a adăuga 15 pixeli la lățimea anumitor secțiuni de site (și anume, "Blog", "Calendar" și "Contact") prin ajustarea unei proprietăți CSS. Următoarea bucată de cod refactorizat este echivalentă:
var siteSection = function(idName) {
return {
getWidth: function() { $(idName).width() },
setWidth: function(width) {
$(idName).css("width", width) }
}
};
var setWidthOnSiteSections = function(subsectionNames, siteSection) {
for (i = 0; i < subsectionNames.length; i++) {
var idName = "#" + subsectionNames[i];
var width = siteSection(idName).getWidth();
if (idName =="#blog" || idName =="#calendar"
|| idName =="#contact")
width += 15;
siteSection(idName + "-bg").setWidth(width);
}
};
$(document).ready(function() {
$.get('/siteSections', function(subsectionNames) {
setWidthOnSiteSections(subsectionNames,
siteSection)
});
});
Putem observa cum funcția setWidthOnSiteSections nu mai depinde de JQuery. Am extras dependența într-o funcție specială siteSection, care ne permite să stabilim și să obținem lățimea unei secțiuni de site prin API-ul JQuery. Am scos JQuery din funcția setWidthOnSiteSections. Acum putem testa cu ușurință funcția setWidthOnSiteSections, deoarece se poate pasa orice în parametrul siteSection. Putem folosi librăria preferată de mockuri și stuburi sau putem pasa un stub construit chiar de noi prin natura dinamică a limbajului JavaScript.
Poluarea namespace-ului global - JavaScript dispune de un domeniu global în care ajung toate variabilele și funcțiile dacă nu sunt izolate în mod corespunzător. Acest lucru poate conduce la un conflict de nume și la buguri subtile. Există mai multe modalități prin care poți evita scenariul descris: expresii de funcție invocată imediat, utilizarea let în locul var pentru a limita domeniul de aplicare al variabilei, sau gruparea funcţionalităţilor în module ES6.
Am aruncat o privire atentă asupra codului nostru de frontend și recunoaștem că nu ne-a plăcut ce am găsit acolo. Dar nu trebuie să fim deznădăjduiți, pentru că mai există încă speranță. Ne-am mai confruntat cu aceasta și, din fericire, există soluții de-a gata pentru rezolvarea problemelor respective care apar și în acest mediu. Este nevoie numai de o atitudine pozitivă, care va deschide calea spre un viitor mai luminos, în care nici nu ne va fi frică și nici nu vom fi dezgustați de ideea gestionării codului de frontend.