-
Intro
În 2011 am fost la primul meu hackathon. Am fost foarte entuziasmat, compania asta mare și faimoasă venea în România pentru a organiza un hackathon! Compania respectivă era Yahoo!, și da, știu că acum nu pare ceva spectaculos, dar pe atunci era impresionant.
În timpul evenimentului am dezvoltat (împreună cu câțiva prieteni) un mic joc amuzant de snake multiplayer, care, ca orice proiect de hackathon, a fost abandonat în ziua următoare.
Jocul a fost scris în Node.js și a fost primul meu proiect de backend în JS, chiar dacă eram deja un adevărat entuziast al limbajului.
Câțiva ani mai târziu am vrut să revizuiesc proiectul și să văd cam cât de groaznic era scris de fapt. Din păcate m-am lovit de o problema: nu am versionat pachetele așa că nu mai știam versiunea lor și nimic nu mai funcționa. Pe atunci lucrurile erau destul de la început cu Node.js, așa că schimbările de la o versiune la altă aveau tendința să fie substanțiale. Prin urmare, am decis că era timpul să-l refac, doar pentru amuzamentul propriu.
Refactorizarea
Era finele anului 2015, acordul de la Paris urma să puna stop poluării, Volkswagen a fost găsit vinovat de manipularea rezultatelor testelor pentru emisiile de poluare, iar eu refăceam "Tequila worms".
Node.js nu mai era o noutate, devenise o tehnologie consacrată și începuse deja să suporte alternative la JS, sau mai bine spus la EcmaScript. Unele dintre cele mai importante opțiuni erau: TypeScript și CoffeeScript.
Dacă TypeScript oferea tipuri de date statice, lucru care ajută la găsirea unor probleme la compilare înainte de runtime, CoffeeScript avea o abordare mult mai orientată către "cod". CoffeeScript permitea o sintaxa mult mai agreabilă. Recunosc, avea tendința să fie un pic mai dificilă la început, dar arăta super!
Decizia a fost luată, backend-ul urma să fie scris în CoffeeScript, era în mod evident o alternativă mai bună decât TypeScript.
Pentru frontend erau câteva opțiuni, dar era cert că nu voi folosi jQuery, pentru că erau deja disponibile multe frameworkuri interesante. Întrebarea era de fapt: să folosesc React sau Angular?
Credeam cu îndârjire că o librărie de frontend nu ar trebui să folosească backend pentru compilare. Angular era deja la versiunea 1, lucru care denotă stabilitate, un favorit! Avea o versiune stabilă (deci nu avea să se schimbe prea curând), o comunitate importantă în spate și, în plus, era dezvoltată de Google!
React, pe de altă parte, nu era la fel de popular. Avea nevoie de backend pentru compilare, lucru care e un pic ciudat dacă te gândești, era făcută de Facebook, și mai avea și o abordare diferită față de mai popularul MVC.
Angular (versiunea 1) și CoffeeScript au fost câștigătorii! Pot spune că a fost o plăcere să reconstruiesc acest joculeț și, pe lângă asta, am avut ocazia să lucrez cu tehnologii de ultima oră, lucru care a făcut proiectul să fie pregătit să reziste probei timpului!
Rezultatul este aici: https://github.com/claudiu-persoiu/tequila-worms/
8 ani mai târziu...
Acordul de la Paris nu a schimbat lumea așa de radical cum aveam nevoie, Volkswagen a început să facă mașini electrice și hibride, iar aplicația mea nu este tocmai pregătită pentru viitor, nici măcar pentru prezent.
O dată ce Node.js s-a maturizat, dependințele lui au devenit și ele mai complexe și au nevoie din ce în ce mai multă atenție pentru tot felul de actualizări.
Pe de altă parte, Angular a fost complet regândit în versiunea 2, iar visul meu de a face frontend independent de backend a rămas doar un vis.
CoffeeScript a fost înlocuit ușor, ușor de TypeScript și mai există acum ca o bucățică de istorie pentru entuziaști decât ca un limbaj folosit uzual.
Pe pagina de Wikipedia a CoffeeScript, la secțiunea "Adoption", este o frază care descrie foarte bine la ce s-a ajuns:
In data de 13 septembrie 2012, Dropbox a anunțat că au rescris din JavaScript in CoffeeScript tot codul lor care rulează în browser, dar au migrat apoi către TypeScript în 2017.
Concluzii
Chiar dacă Node.js se pare că a fost o decizie bună pentru stack, restul alegerilor făcute demonstrează că nu ar trebui să urmezi sfaturi de la oameni de pe Internet, mai ales nu pe ale mele, pentru că nu am fost deloc pe aproape...
Pe de altă parte, niciuna dintre tehnologii nu a fost o alegere greșită la momentul respectiv, iar să vrei să construiesti frontend fără librării de backend nu era o dorință atât de excentrică pe cât pare astăzi.
CoffeeScript a fost doar ghinionist, deoarece, chiar dacă sintaxa arată mai bine, făcea codul să arate un pic mai greu de citit pentru programatorii proveniți din limbaje cu sintaxa din familia C.
Chiar dacă sintaxa TypeScript nu este mai plăcută, ajută totuși cu verificarea tipurilor de date și rezolvă o problemă reală.
Concluzia poveștii cred că este că nu ai cum să faci o aplicație rezistentă la trecerea timpului dacă te bazezi pe un framework și, mai ales, să nu ai încredere în predicțiile celorlalți, în special nu în ale mele.
--
-
Introducere
Recent am fost pus într-o situatie dificilă. Am primit un laptop cu Windows. Partea și mai ciudată a fost că eu eram singurul din toata echipa tehnică care a primit un laptop cu Windows, toți ceilalți colegi aveau Mac. In mod evident, proiectul nu a fost făcut niciodată sa funcționeze pe Windows.
Singurii care au mai primit Windows în trecut l-au folosit în jur de o săptamană, până când le-a venit MacBook-ul, dar pe măsură ce treceau zilele (și săptămânile), a devenit evident că acesta nu o să fie și cazul meu.
Având in vedere că suntem în anul 2021 și criza cipurilor este în plină desfășurare, a trebuit să mă descurc în condițiile date.
Inițial am încercat opțiunea evidentă, Docker for Windows și Git for Windows, dar nu s-a dovedit a fi o idee prea bună. Problema este că aplicațiile Windows au nevoie de terminator de linie in stil Windows (\r\n), pe cand aplicațiile de Linux și macOS folosesc terminator de tip Unix (\n), și s-a dovedit foarte dificil să-mi dau seama unde e nevoie de unul și unde de altul. Chiar și atunci cand mi-am dat seama care se folosește unde, tot aveam problema că nu puteam face commit cu fișierele cu terminații diferite și trebuia sa le fac stash înainte de fiecare pull.
Cum funcționează
-
Descarcă și instalează WSL2 folosind instrucțiunile de aici: https://docs.microsoft.com/en-us/windows/wsl/install-win10
-
Restartează Windows (pentru că asta e ceva ce faci atunci când lucrezi cu Windows)
-
Din "Microsoft Store" instalează o distribuție de Linux (în acest tutorial voi folosi Ubuntu)
-
După ce s-a instalat distribuția, setup-ul va cere crearea de cont cu parolă, folosește ceva adecvat, acest cont se va folosi doar în interiorul distribuției Linux;
-
Deschide un PowerShell cu drepturi de admin și rulează următoarele comenzi:
wsl --set-version Ubuntu 2 wsl --set-default Ubuntu
-
Pentru a verifica dacă pasul anterior a rulat cu succes, în aceeași instanță de shell rulează
wsl -l -v
, unde rezultatul ar trebuie să fie o linie cu Ubuntu și versiunea 2 -
Acum putem instala Docker, folosind pașii de aici: https://docs.docker.com/engine/install/ubuntu/#install-using-the-repository
-
Suntem aproape gata, trebuie doar să facem să pornească serviciul de Docker automat;
-
Apasă "Start" și apoi "Task Scheduler";
-
Apoi "Actions" > "Create Basic Task...";
-
Dă-i un nume și apasă Next;
-
în secțiunea de Trigger selectează "When I log on" și apasă Next;
-
în secțiunea de Action selectează "Start a program" și apasă Next;
-
în ecranul "Start a program" valoarea pentru "Program/script:" va fi "C:\Windows\System32\wsl.exe" și în "Add arguments (optional)" adaugă "-u root service docker start" și apoi apasă Next și Finish;
Asta este tot, după un restart de Windows, daemon-ul de Docker ar trebui sa porneasca automat.
Am observat ca uneori Windows nu rulează task-urile de startup dacă laptopul nu este la încărcat, dacă ai această problemă, sau Docker pur și simplu nu pornește, rulează în interiorul distribuției:
service docker start
O sugestie
Dacă folosești calculatorul doar pentru dezvoltare de software, ar trebui să iei în considerare distribuțiile de Linux mai prietenoase, cum este Ubuntu. Aplicații ca Docker și Git rulează mult mai bine pe Linux și suportul pentru aplicații ca IntelliJ și VS Code este foarte bun. Dacă nu ai încercat niciodată, sunt mult mai prietenoase cu utilizatorul decât ai crede.
Să folosești Docker pe orice altceva decât Linux este un compromis, chiar și pe Mac, ca să nu mai vorbim de Apple Silicon care este un compromis chiar mai mare decât Windows.
Folosesc Ubuntu pe calculatoarele mele personale de mai mult de un deceniu și, cu foarte puține excepții (cum ar fi interacțiunea cu unele aplicații web ale statului român), nu am avut nevoie de altceva.
-
-
Am acest blog de 12 ani.
În 2008, când am început blog-ul, Wordpress era cea mai populară platformă open source pentru blogging.
O dată cu trecerea timpului, au fost descoperite multe probleme de securitate.
Plugin-urile, motorul principal pentru extinderea platformei și motivul principal pentru care era atât de populară, creau îngrijorare din punct de vedere arhitectural.
Astăzi, după toți acești ani și cu toate aceste probleme de arhitectură și de securitate, Wordpress a ajuns sa fie… cea mai populară platformă PHP de pe Internet! Codul vechi este în continuare folosit de ultimele versiuni, iar majoritatea pluginurilor din 2008 sunt încă functionale!
Pe măsură ce a trecut timpul (iar eu am scris din ce în ce mai puțin), a devenit evident că petreceam mai mult timp menținând platforma Wordpress actualizată decât scriind.
Așa că am decis într-un final să migrez la Hugo!
Hugo este un generator de site-uri statice, realizat in Golang. Site-ul construit cu Hugo este static, și (în mod și mai bizar) nu are baze de date, sunt doar fișiere de configurare și de tip Markdown. Așa că rezultă o platformă care aproape că nu mai are nevoie de mentenanță.
Împreună cu noua platformă a venit și o nouă temă, care are un design mai modern și o funcționalitate deosebit de căutată în vremurile noastre: modul de noapte!
Jekyll este probabil cea mai populară platformă pentru generat site-uri statice, dar este făcută cu Ruby așa că am preferat Hugo pentru că template-urile folosesc sintaxa de Go Templates. Este vorba mai mult de gusturi decât de altceva.
Iar cu acest update, vă invit să vă bucurați de acest blog, acum chiar și mai static!
-
Am avut recent o problemă interesantă: accesul meu la un depozit care necesită autentificare a fost invalidat în mod abrupt. Problema în cazul meu a originat de la depozit, dar ar fi putut fi la fel de ușor din cauză că mi-am pierdut credențialele sau altceva similar. Accesul meu urma să fie restabilit în curând. Cum știm cu toții, “în curând” în IT poate dura între cateva minute și dispariția tuturor formelor de viață cunoscute, iar eu trebuia să fac un build până atunci.
Și încă un detaliu, localul meu funcționa în continuare.
Pentru o vreme m-am întrebat de ce funcționează localul meu, dar tu ai citit titlul, deci ai văzut deja motivul, cache-ul meu local era încă valabil.
Am căutat o vreme o metoda usoara de a pune pachetele de pe local la eliminarea care făcea construirea, și există modalități, dar nu intenționam să pierd zile lucrand la o problemă care s-ar putea rezolva oricum înainte sa-mi finalizez eu abordarea.
Soluția a fost foarte simpla:
- trebuie doar făcută o copie a cache-ului local, pentru linux este în mod normal în “~/.composer”;
- trebuie copiata pe serverul de interes intr-o locație preferată (sa zicem /tmp/composer_cache);
- exportam variabila COMPOSER_CACHE_DIR (“export COMPOSER_CACHE_DIR=/tmp/composer_cache”);
- se ruleaza composer in mod normal.
Asta e tot, acum poți folosi cache-ul local pe un server la distanță. Nu este cel mai elegant lucru, dar este un hack rapid foarte util.
-
Folosind Magento de ceva timp, pot spune ca platforma s-a schimbat mult de-a lungul timpului și vreau sa impartasesc câteva păreri personale legate de ea.
Cum a invatat Magento 2 din trecut cum sa facă greșeli noi noute
M-am intalnit prima oară cu platforma Magento în 2011, iar, in acel moment, știam despre ea doar că era bazată pe Zend Framework 1 și (în mod evident) ca se ocupă cu e-commerce.
Eu veneam din universul framework-ului Symfony, unde exista documentație din belșug, o comunitate foarte mare, și care avea o implementare solidă. Acestea se intamplau de-abia pe vremea Symfony 1, Symfony 2 de abia aparuse.
Prin comparatie, Magento nu avea aproape deloc documentație, comunitatea era într-un stadiu incipient, și implementarea nu ducea lipsa de bug-uri. Încă din primele zile la noul job am văzut mulți colegi care făceau debugging adanc in Core, eram perplex, eu aproape că nu avusesem niciodată nevoie sa fac debugging în Core-ul de Symfony, darămite să mai găsesc și bug-uri.
Unii pot argumenta ca Symfony este un framework, pe cand Magento este o platforma, iar eu sunt de acord ca acesta este un argument cel puțin la fel de solid ca un porcusor de guinea.
Motivul pentru care s-a ajuns la aceasta situatie e simplu: nu se așteptau ca platforma sa aiba atat de mult success; dar a avut, și motivul a fost simplu – a fost cam singura platforma din universul PHP care fusese construită sa fie modulară, punct! Mai erau și alte platforme, dar în mod sigur nu la fel de versatile, pline de functionalitati și modulare precum Magento.
În perioada următoare au investit mult timp și efort pentru a construi o documentație ampla pentru Magento1, s-au concentrat pe calitate, pe stabilitate imbatabilă, și toate acestea au fost completate cu un suport de excepție oferit partenerilor de tip enterprise!
Te-am prins! Nu, nu au făcut asta! Documentatia pentru M1 a fost mereu sărăcăcioasă și de foarte slabă calitate. Cea mai buna resursa a fost cursul “Fundamentals of Magento Development” de Ben Marks, o carte (despre care nu-mi pot exprima o opinie pentru ca nu am citit-o), niște postări pe bloguri personale și ale companiilor care lucrau cu platforma și, nu în ultimul rand, multe întrebări și răspunsuri pe StackOverflow. Toate acestea au fost combinate cu un suport deosebit de prost pentru clienții enterprise, răspunsuri lente și de o calitate îndoielnică și, peste toate astea, o varietate de bug-uri în Core. Nu era ceva ieșit din comun sa gasesti implementări atipice sau făcute doar pe jumate alături de bug-uri în Core. Dar Core-ul era suficient de simplu, așa ca, folosind doar Xdebug și multă răbdare, totul era mai mult sau mai puțin rezolvabil.
Fix-urile de la suport erau intamplari aproape mitice. Dacă nu aveai chef sa repari un bug, sau pur și simplu nu aveai chef de munca, puteai deschide un ticket și de cele mai multe ori dura cateva zile sau chiar saptamani pana cand primeai un răspuns corespunzător. Până în acel moment, de multe ori problema era deja rezolva și (în unele cazuri) soluția chiar trimisă celor de la suport ca sa poată repara problema si în Core..
Și așa apare Magento 2
Cu povara popularității care a incurajat dezvoltarea Magento 1, Magento 2 a venit sa salveze situatia.
A durat mult timp pana cand Magento 2 a fost gata, și cred ca asta ar putea sa fie în sine o poveste, dar de data aceasta au fost luate unele măsuri pentru a evita problemele pe care le-a avut prima versiune.
Sa vedem unele din probleme platformei:
- functionalitatea claselor nu puteau fi extinsă decât prin suprascriere;
- partea de frontend era bazată exclusiv pe framework-ul Prototype.
Existau multe alte probleme, dar cred ca acestea erau printre cele mai relevante.
Și sa vedem cum Magento 2 a reușit sa rezolve toate aceste probleme
Este de bun augur sa începi cu ceva pozitiv, așa ca voi începe cu documentatia, Magento2 avea documentație încă de la început și era atat utilă, cat și bine făcută!
Legat de suprascrierea claselor, au fost implementate două abordări:
- implementarea a dependency injection (din Symfony);
- implementarea pluginurilor folosind Interceptor pattern.
Dependency injection ajuta foarte mult la înlocuirea de clase și functionalitati, iar plug-in-urile ajuta la extinderea sau modificarea functionalitatilor printr-o metoda neinvaziva. Înainte de plug-in-uri, doar observerele ofereau posibilitatea de a modifica date într-o maniera neinvaziva, marea problema fiind ca (în multe cazuri) pur și simplu nu erau observere peste tot unde aveai nevoie de ele.
Din pacate, aceasta abordare a crescut cu mult complexitatea. Dacă în M1 puteai pune un breakpoint și apoi urmareai stacktrace-ul ca sa vezi ce metode modifică ce anume, acum… era pur și simplu mult mai complex, pentru ca fiecare metoda clasa interceptor declanșează mecanismul de plug-in. Fiecare plug-in poate sa declanșeze o acțiune înainte, după, sau în jurul metodei și poate chiar sa prevină metoda din a fi apelată. Atunci cand functioneaza, abordarea este mult mai elegantă, dar atunci cand nu funcționează este mult mai dificil de făcut debugging.
Într-o intorsatura dramatica de situație, nu toate clasele au fost implementate corespunzător în Core. Vezi tu, atunci cand Magento 2 a fost lansat, au fost necesare multe compromisuri, iar multe module din Core a trebuit sa fie “făcute sa mearga” în noul framework. Mai tarziu, cand toata lumea aștepta sa se facă curățenie… momentul nu a mai venit, iar motivul a fost simplu: de ce sa repari Core-ul cand riști să strici compatibilitatea cu modulele deja existente?
Acest lucru i-a făcut pe dezvoltatorii de Core sa sugereze sa folosesti direcția sugerată de ei in ghid, sa nu iei implementarea din Core drept exemplu: fa cum spunem noi, nu cum facem noi.
Frontend-ul a fost reparat și mai bine! Poate unii se întreabă ce este “prototype” și de ce cineva întreg la cap ar alege așa ceva? În vremurile in care Magento 1 a fost creat avea mai mult sens, pentru ca exista o serie intreaga de librării populare, în principal: jQuery, Prototype și MooTools. Erau mult mai multe pe langa acestea trei, dar acestea erau printre cele mai populare. Era un război între jQuery și Prototype, așa cum este in prezent cel dintre React, Angular și Vue. jQuery avea o abordare nouă care părea să semene chiar cu un limbaj nou, în timp ce Prototype a mers pe extinderea capabilitatilor browserului într-o maniera mai discreta. Acum știm cine a castigat, dar pe atunci nu era la fel de evident. Ca o mica nota, și eu eram fan Prototype la vremea respectivă.
Echipa Magento 2 a realizat în timp ca a făcut o gresala si, ca sa o repare, au promis ca vor avea o abordare mai flexibilă. Noua abordare mai flexibilă nu a mai folosit libraria Prototype, iar în locul ei au fost incluse: jQuery, Knockout.js și Require.js, asta doar la nivelul superior, fără sa luăm toate celelalte dependinte in considerare.
Ideea era o mai buna separare între frontend și backend, pentru a putea face o aplicație de frontend complet nouă. Dar, la fel ca mai înainte, acest plan nu a fost finalizat, iar acum este doar un sistem foarte complicat, parțial separat, parțial aplicație “single page” și parțial… “multi page”, implementat folosind o varietate de stiluri. Iar aceasta este doar pe store front, pe store backend este puțin diferit, un sistem mai complex format din fișiere xml, phtml, html și js. Ca backend developer, pot spune sincer ca este mult mai dificil decât înainte sa faci debug (sau doar sa înțeleg cum funcționează părți din frontend).
Poate cea mai dificila parte este cea de generare de griduri folosind XML, debugging-ul poate fi facut doar cu mari dificultati, iar daca gresesti ceva nu primești niciun warning, trebuie sa gasesti clasa care construiește efectiv gridul și sa vezi daca apare acolo vreo excepție, ceea ce nu este deloc o soluție evidenta…
Și, evident, totul este mult mai lent, din pricina noilor “abordări inginerești”. Cand tot codul intermediar este generat, legăturile facute către resursele statice și totul este setat în modul producție, nu este foarte rapid, dar nu este nici groaznic de încet. Dar atunci cand nu ai cache, nu ai făcut deploy la resurse statice, și mai ești și în modul developer, este groaznic de încet, poate dura minute bune pentru a incarca o simpla pagina de produs! Este pur și simplu ridicol! Dacă mă întrebați pe mine, nu este un sistem de operare, sau un joc video, este un magazin virtual, nu exista niciun motiv pentru care sa dureze 5 minute pentru a afișa o pagina, lucru care se intampla chiar si in cazul in care nu ai multe module adiționale instalate.
Trebuie avut în vedere ca Magento 2 nu a venit cu o multitudine de noi functionalitati, majoritatea funcționalitatilor principale erau și în M1, doar ca au fost mai “inginerizate”, asa ca acele 5 minute de generare de cod, generare de legături și alte magii pe care le mai face, nu vin de la adaugarea de functionalitati noi, doar refactorizari ale sistemului vechi.
Magento Cloud
Magento a oferit și o soluție de Cloud, nu știu dacă-l mai oferă, nu-mi pasa prea tare, nimănui nu pare să-i mai pese, în speță pentru ca nu era ce își dorea lumea.
Oamenii vor lucruri simple: ai o aplicație, o urci în nori și începe sa ploua cu bani. Cam asta este tot ce ar trebuie sa fie – mai puține griji.
Demandware, care nu are un core open source, face ceva de acest tip. Nu ai la fel de mult control, dar nu tu te ocupi de website-ul tău, zeii din nori se ocupă (suna mai bine în engleza)! Dezvoltatorul doar dezvolta, lui nu ar trebui să-i pese ce magii fac cei de la operations, pentru ca el nu e ops, el e dev!
Magento Cloud încerca sa facă asta, speranta era ca tu doar trimiti caracatita în norișor și niște ops foarte inteligenți o sa scaleze pentru tine! Dar nu era deloc așa, nu era deloc ușor, si nici rapid. Si, peste toate acestea, au inceput sa apara hosting providers cu soluții specializate pe Magento care făceau o treaba mai buna la scalare decât hostingul oficial, lucru care mi se pare de necrezut.
Dar sa incheiem intr-o nota pozitiva
Sub toate aceste neajunsuri, exista totuși un Core interesant. Sunt o mulțime de functionalitati foarte inteligente care au făcut platforma atat de populara. Acum exista și teste, deci poți face chiar și TDD.
Chiar și cu atatea provocări (supra)inginerești, exista totuși destui programatori pasionați care sunt gata sa le depaseasca.
Sunt și multe unelte dezvoltate de comunitate pentru a acoperi din lipsuri, cum ar fi problema cu numarul foarte mare de fișiere care trebuie generate pentru un model, sau MSP_DevTools care ajuta la debugging pe frontend, sau n98-magerun2 care te ajuta sa lucrezi cu cronuri și multe, multe altele.
Și, nu în ultimul rand, încă sunt mulți programatori straluciti și pasionați care sunt gata să găsească un mod de a dezvolta și scala aplicatii e-Commerce bazate pe Magento pentru a face vanzari încă o zi!