Diferente pentru propuneri/3-infoarena3 intre reviziile #44 si #45

Nu exista diferente intre titluri.

Diferente intre continut:

h2. Motivatie
Site-ul infoarena1 a fost scris acum vreo 4-5 ani de Cristi pentru a fi prezentat la InfoEducatie, un concurs de soft de la Galaciuc. Site-ul era foarte impresionant si a castigat concursul 2 ani la rand. Mai mult, site-ul era atat de bun incat a intrat in "productie" si a reusit sa adune o comunitate in jurul lui. Comunitatea a produs un numar impresionant de probleme si concursuri iar infoarena un loc de adunare pentru olimpicii romani.
Site-ul infoarena1 a fost scris acum vreo 4-5 ani de Cristi pentru a fi prezentat la InfoEducatie, un concurs de soft de la Galaciuc. Site-ul era foarte impresionant si a castigat concursul 2 ani la rand. Mai mult, site-ul era atat de bun incat a intrat in "productie" si a reusit sa adune o comunitate in jurul lui. Comunitatea a produs un numar impresionant de probleme si concursuri iar infoarena a devenit un loc de adunare pentru olimpicii romani.
Mult timp soft-ul din spatele site-ului a ramas aproape identic cu ce a venit Cristi la Galaciuc; s-au facut doar niste fix-uri absolut necesare. Am incercat sa punem pe picioare un 'site de development':http://hackers.devnet.ro/ si sa bagam codul in subversion dar nimeni nu s-a atins de cod. Au crescut inca niste lucruri *pe langa* infoarena1; un "portal editabil" de informatica, un forum si o integrare urata cu 'MediaWiki':http://www.mediawiki.org/. Eventual am ajuns la concluzia ca nu se poate face nimic in infoarena1 si trebuie rescris totul de la 0.
h2. Ce a mers prost in infoarena2
Pe parcursul dezvoltarii infoarena2 noi (Cristi, Leonard, Mircea, Vali, etc...) am facut un numar de greseli majore la care acum simtim efectele. Daca am incepe din nou programarea la proiectul infoarena3 nu am sa face din nou aceleasi greseli si rezultatul ar fi mult mai bun. Daca stim care au fost gresile si cum sa le evitam nu vom ajunge din nou in aceasi situatie.
Pe parcursul dezvoltarii infoarena2 noi (Cristi, Leonard, Mircea, Vali, etc...) am facut un numar de greseli majore la care acum simtim efectele. Daca am incepe din nou programarea la proiectul infoarena3 nu am face din nou aceleasi greseli si rezultatul ar fi mult mai bun. Daca stim care au fost gresile si cum sa le evitam nu vom ajunge din nou in aceasi situatie.
Poate parea trist ca aruncam la gunoi aproape un an de efort, dar nu este cazul. Vom pastra tot continului site-ului, care valoreaza enorm (si asta tine de fapt infoarena.ro in viata). Vom pastra lectiile infoarena2, care sunt mult mai valoroase decat codul php. Daca am fi alti oameni care am rescrie codul probabil ca am face aceleasi prostii, si atunci ar mai bine sa ne tinem de treaba la infoarena2.
Infoarena2 este un site traditional bazat pe php/mysql si foarte putin javascript. Nu folosim clase si nici exceptii din php. In mod similar nu folosim decat tabele MyISAM in MySQL, fara foreign key-uri, constraint-uri, view-uri sau tranzactii. Pentru layout nu folosim nici un sistem de templating, doar html presarat cu snippet-uri php. Infoarena2 foloseste absolut minimumul de tehnologie posibil pentru un proiect web-based.
Aceasta decizie fost facuta in vara 2006 pentru a face site-ul simplu si usor de programat. Ne-am gandit ca sunt mai multi oameni care stiu si vor sa lucreze cu php/mysql procedural decat cu orice altceva. Este discutabil daca sunt mai multi oameni interesati in php decat in python sau ruby, cel putin dintre utilizatorii nostri. Probabil ca multi ar fi tentati sa ajute la un proiect care foloseste feature-uri avansate de limbaj absente in C/C++/Pascal (si PHP). Dar oricum nu am reusit sa bagam pe nimeni din exterior in echipa de development. Mai mult, am ajuns in situatia in care nici noi nu vrem sa programam in php/mysql, sau cel putin nu in modul in care este folosit in infoarena2. PHP este un limbaj foarte util pentru multe lucruri, dar pentru infoarena2 nu a functionat.
Aceasta decizie fost facuta in vara 2006 pentru a face site-ul simplu si usor de programat. Ne-am gandit ca sunt mai multi oameni care stiu si vor sa lucreze cu php/mysql procedural decat cu orice altceva. Este discutabil daca sunt mai multi oameni interesati in php decat in python sau ruby, cel putin dintre utilizatorii nostri. Probabil ca multi ar fi tentati sa ajute la un proiect care foloseste feature-uri avansate de limbaj absente in C/C++/Pascal (si PHP). Dar oricum nu am reusit sa bagam pe nimeni din exterior in echipa de development. Mai mult, am ajuns in situatia in care nici noi nu mai vrem sa programam in php/mysql, sau cel putin nu in modul in care este folosit in infoarena2. PHP este un limbaj foarte util pentru multe lucruri, dar pentru infoarena2 nu a functionat.
h3. Tabelul ia_parameter_values
* *Nu avem* mai multe tipuri de probleme si concursuri (scopul original).
* Rundele inca nu ruleaza automat.
Ar trebui sa avem pentru fiecare tip de problema sau runda un tabel de genul ia_classic_task, care contine o coloana task_id si apoi cate o coloana pentru fiecare parametru. Eu (Leonard) am incercat aceasta transformare dar *nu am reusit* (din cauza repercursiuni in restul site-ului). Consider ca inlocuirea acestui tabel e mai dificila decat rescrierea de la 0.
Ar trebui sa avem pentru fiecare tip de problema sau runda un tabel de genul ia_classic_task, care contine o coloana task_id si apoi cate o coloana pentru fiecare parametru. Asta este o solutie acceptabila pentru o baza de date. Eu (Leonard) am incercat aceasta transformare dar *nu am reusit* (din cauza repercursiuni in restul site-ului). Consider ca inlocuirea acestui tabel e mai dificila decat rescrierea de la 0.
h3. Tabelul ia_score
Tabelul ia_score are coloanele: score_id, user_id, task_id, round_id si score (aproximativ). Primele 4 coloane sunt sunt nulabile, asa ca tabelul nu poate avea PK. Ideea era sa tinem scoruri per runda cu task_id NULL si eventual statistici per task/round cu user_id NULL. Astfel puteam sa tinem toate scorurile in acelasi tabel. Din pacate *nu a mers* si am ajuns in situatia de a avea mai putine statistici decat in infoarena1. Asta cred ca este singurul punct in care infoarena1 *depaseste* infoarena2.
Tabelul ia_score are coloanele: score_id, user_id, task_id, round_id si score (aproximativ). Primele 4 coloane sunt sunt nulabile, asa ca tabelul nu poate avea PK. Ideea era sa tinem scoruri per runda cu task_id NULL si eventual statistici per task/round cu user_id NULL. Astfel puteam sa tinem toate scorurile in acelasi tabel. Din pacate *nu a mers* si am ajuns in situatia de a avea chiar mai putine statistici decat in infoarena1. Asta cred ca este singurul punct in care infoarena1 *depaseste* infoarena2.
Acest tabel ar trebui spart in mai multe tabele fara coloane nulabile, si fara oroarea de score_id.
Id-urile pentru utilizatori sunt numere, dar restul sunt VARCHAR (64) cu niste validari facuta in cod prin regex-uri. Ar fi mai bine sa avem toate id-urile drept numere, spre exemplu task_id int si task_name string. task_name se poate obtine foarte usor din task_id adaugand un join trivial.
MySQL *nu* face 'index pe hash-uri':http://dev.mysql.com/doc/refman/5.1/en/create-index.html pentru tabele pe disc (doar pentru tabele din memorie). MySQL sorteaza id-urile alfabetic tinand cont de colatii (latin2 pentru noi). Tinand string-uri peste tot crestem dimensiunile tabelelor, iar asta este oribil pentru performanta tabele de genul ia_score sau ia_job. Aici s-ar merita de facut niste teste de performanta. Spre exemplu putem compara un tabel de scor exclusiv numeric cu unul plin de string-uri.
MySQL *nu* face 'index pe hash-uri':http://dev.mysql.com/doc/refman/5.1/en/create-index.html pentru tabele pe disc (doar pentru tabele din memorie). MySQL sorteaza id-urile alfabetic tinand cont de colatii (latin2 pentru noi). Tinand string-uri peste tot crestem dimensiunile tabelelor, iar asta este oribil pentru performanta tabelelor de genul ia_score sau ia_job. Aici s-ar merita de facut niste teste de performanta. Spre exemplu putem compara un tabel de scor exclusiv numeric cu unul plin de string-uri.
h3. Tabele de wiki: ia_textblock, ia_textblock_history, ia_file.
Pe parcursul dezvoltarii infoarena2 ne-am dorit sa evitam pe cat posibil functionalitatea "magica" din wiki, si am mers prea departe. Am pornit de la idea ca orice pagina este o pagina de wiki, si paginile de probleme/useri/runde/news/blog sunt doar un caz oarecare de pagina wiki. Securitatea paginilor de probleme trebuie totusi sa fie subordonata problemelor. Noi am realizat asta adaugand un "descriptor de securitate" ca string pentru fiecare pagina de wiki. Pagina problema/adunare are la securitate un string "task: adunare", si asa vizibilitatea paginii depinde de vizibilitatea task-ului. Este un sistem prea generic, incurcat si greu de folosit sau extins.
Ar fi mai bine ca orice url de forma problema/xxx sa intre prin controller-ul de task-uri, care isi subordoneaza textblock-urile care incep cu problema/xxx. Similar am avea controllere de news, blog, user page care subordoneaza tot ce incepe cu stiri, blog sau utilizator/yyy. Pentru restul paginilor am avea un controler *distinct* de wiki. Codul pentru bucatile de editare si istorie a textblock-urile poate fi refolosit in 1000 de moduri. *Nu* este acceptabil sa nu poti ajunge de la editarea de enuntului la editarea limitei de timp fara sa modifici in address bar.
Ar fi mai bine ca orice url de forma problema/xxx sa intre prin controller-ul de task-uri, care isi subordoneaza textblock-urile care incep cu problema/xxx. Similar am avea controllere de news, blog, user page care subordoneaza tot ce incepe cu stiri, blog sau utilizator/yyy. Pentru restul paginilor am avea un controler *distinct* de wiki. Codul pentru bucatile de editare si istorie a textblock-urile poate fi refolosit in 1000 de moduri. *Nu* este acceptabil sa nu poti ajunge de la editarea de enunt la editarea limitei de timp fara sa modifici in address bar.
Am avea tabele ia_news, ia_blog_post si ia_wiki care sunt "deasupra" lui ia_textblock, iar ia_textblock ar fi folosit doar pentru versionarea unor bucati de text. Securitatea private/protected/public (care este *foarte* utila si absolut ok) poate fi un simplu enum in ia_wiki. Acel enum trebuie editat folosind un simplu dropdown.
Url-urile sunt parsate in index.php si in functie de o logica complicata si nu foarte interesanta fiecare request http este pasat la un "controller". Un controller este o functie php din www/controllers. Acel controller face ceva cu requestul, de obicei niste query-uri in baza da date, si apoi constrieste un hash de "date pentru afisat" care il trimite la un view.
View-urile nu sunt functii, sunt fisiere .php din www/views. Executia unui view este o operatie sinucigasa, care se trimite direct pe teava. Nu se poate executa cod dupa un view. Fisierul de view executa folosind continutul hash-ului de data ca variabile globale. In acel view se poate folosi textile, care poate executa macro-uri care(de obicei) se duc iar pana in baza. Asta inseamna ca poti sa te duci in baza dupa executia controller-ului, dar nu mi se pare nimic rau in asta. Macro-urile sunt efectiv niste mini-controllere.
View-urile nu sunt functii, sunt fisiere .php din www/views. Executia unui view este o operatie sinucigasa, care se trimite direct pe teava. Nu se poate executa cod dupa un view. Fisierul de view se executa folosind continutul hash-ului de data ca variabile globale. In acel view se poate folosi textile, care poate executa macro-uri care(de obicei) se duc iar pana in baza. Asta inseamna ca poti sa te duci in baza dupa executia controller-ului, dar nu mi se pare nimic rau in asta. Macro-urile sunt efectiv niste mini-controllere.
Problema este ca noi din controllere ne ducem direct in baza si logica fragila de genul securitate este imprastiata intre functiile de UI si de DB. Este riscant (error-prone) sa combini logica site-ului cu parsarea requestului sau construirea query-ului. Aceasta problema are o rezolvare destul de clara si larg acceptata in industrie, de care eu personal nu stiam in vara lui 2006.
Problema este ca noi din controllere ne ducem direct in baza si logica fragila de genul securitate este imprastiata intre functiile de UI si de DB. Este riscant (error-prone) sa combini logica site-ului cu parsarea requestului sau construirea query-ului. Aceasta problema are o rezolvare destul de clara si larg acceptata in industrie, de care noi nu stiam in vara lui 2006.
Intre codul de controller (UI) si codul de baza de data (DB) se mai pune niste cod de "business logic" (BL). Tot ce inseamna parsarea request-ului se face in UI si tot ce inseamna contruirea de SQL se face in DB. BL contine de fapt tot codul cu adevarat interesant pentru functionarea corecta a site-ul. Codul de DB nu trebuie sa aiba grija decat sa construiasca query-uri (si sa evite sql injection) iar codul de UI se ocupa de a vedea ce butoane a apasat utilizatorul.
Infoarena2 suporta mai multe forme de caching:
* Cache de textile parsat, inainte de executia macro-urilor. Majoritatea request-urilor nu executa codul de textile.
* Cache de imagini redimensionate. Cand se cere o imagine redimensionata ea este salvata pe disc si se evita operatiile de grafic pentru avatari etc.
* Cache de imagini redimensionate. Cand se cere o imagine redimensionata ea este salvata pe disc si se evita operatiile de grafica pentru avatari etc.
* Cache de obiecte din baza de date, folosind memcached sau eaccelerator. Acest cache tine obiecte de genul useri, task-uri si runde.
Acest ultim mod de caching are inclusiv suport de write-through (cand se salveaza un obiect se sterge varianta din cache) care a fost foarte complex de implementat. Codul de cache este bagat prin multe functii db_ si nu este deloc usor de inteles. Se combina cod de DB, BL si caching in aceleasi functii.

Nu exista diferente intre securitate.

Topicul de forum nu a fost schimbat.