Analfabetia de miercuri dimineata

Posted in 112 on March 28th, 2012 by Mihnea

Ca oricarui militian, lui Ovidiu Cucu ii place sa intocmeasca liste: liste cu norme, liste cu abateri de la norme, liste cu sanctiuni de aplicat pentru abateri de la norme, liste cu sanctionati si sanctionabili etc. De asemenea, e ferm convins ca odata intocmita, o lista trebuie lasata asa cum e; orice manipulare de lista il scoate din ale lui. Astazi el s-a decis sa redacteze o lista cu fruntasi in ale programarii si s-o posteze la avizierul ograzii, ca material de studiu pentru membrii Uniunii Tineretului Codexpert.

Ce e insa cu adevarat interesant e modul in care a luat nastere aceasta pornire. Ovidiu marturiseste ca ideea rabojului i-a venit citind o lista asemanatoare pe site-ul lec-academy.ro, un colt de internet unde niste tutorialisti intreprinzatori isi propun sa ne lumineze zilnic cu vorbe sau imagini din programare sau Microsoft Office. Sa spicuim, dara, din lista celor mai importanti 20 de programatori ai tuturor timpurilor in viziunea extrem de relevanta a acestor antrenori de secretare:

Pe primul loc este Tim Berners-Lee, care “a fost clasat pe locul ntai […] in lista Telegraph a celor 100 de marii genii.”

Ne bucura nespus sa-l vedem pe 2 pe marele programator Matt Mullenweg. Cum, nu stiti cine e Matt? E ala care a facut WordPress.

Urmeaza Larry Page care e “top 27 cei mai bogat miliardari”, precum si colegul sau Sergey, care este “top 28 cei mai bogat miliardari”.

Despre Linus Torvalds aflam ca “exista mii de variante / distributiile de servere de web Linux si multe ruleaza pe el“. Deci Linux ruleaza pe el Linux, sau pe el Linus?

Dennis Ritchie este “creatocul limbajului C si un mare dezvoltator a sistemului de operare UNIX”.

Brian Kernighan este “autorul a mai multe programe UNIX”. Sigur, orice student de la orice facultate de calculatoare este autorul “a mai multe” programe UNIX, ca doar e cursul ala de SO unde te chinuie cu asa ceva, deci locul asta ar trebui impartit de Brian cu toti studentii din toate timpurile. Cel putin eu asta inteleg din epifatul tutorialistilor.

Ken Thompson este “un pionier american in informatica, si a ajutat la crearea limbaj de programare B”. Redactorul a fost si el un mare pionier, motiv pentru care a petrecut mai mult timp la muncile patriotice decit in clasa. Asa se explica de ce nu stie cum se declina “limbaj”.

Rasmus Lerdorf “a autorizat primele 2 versiuni de PHP, si apoi a contribuit la dezvoltarea celor mai recente ale PHP. Astazi, PHP ruleaza peste 34% dintre site-urile online“. Sint curios ce cuvint era in original in engleza, de a tradus Google “autorizat”. De asemenea, daca s-ar fi pus si site-urile offline pe care ruleaza “cele mai recente PHP”, cred ca procentul ala ar fi depasit 100%.

Ca sa nu se simta singur Matt Mullenweg in lista (ala care a scris WordPress, in caz ca ati uitat deja cine e), il avem ceva mai jos si pe celebrul programator Jason Fried, a carui contributie la propasirea omenirii este un site ce “contine unele aplicatii web uimitoare“.

Alan Cooper “este numit parintele Visual Basic, deai mare parte din munca pentru Visual Basic a fost realizata de grupul intern de la Microsoft”. Chiar daca n-a muncit, aparent a fost facut parinte pentru ca “a contribuit la interfata grafica pentru sistemul API“. In caz ca nu stiti, interfata grafica pentru sistemul API este folosita pentru a realiza interfete GUI de urmarit IP-uri.

Larry Wall este S.A. Societate pe actiuni? Silviu Ardelean?

John Resig completeaza constelatia frecatorilor de text din care mai fac parte Matt Mullenweg (ala cu WordPress) si Jason Fried (ala cu site-ul de site-uri). Asta a facut jQuery, dar nu s-a multumit cu atit: el este si blogger.

Guido van Rossum este “autorul limbajul de programare Python”.

Daca vreti sa invatati programare de la oamenii care au intocmit aceasta lista, ii puteti contacta la office@leconline.ro sau direct la sediul din Strada Frumoasa. Frumoasa, da’ proasta.

PS: in ochii albastri ai lui Ovidiu, lista comite o mare nedreptate istorica omitind s-o includa pe Grace Hopper, un fel de Amelia Earhart a programarii. Chestia asta zdruncina tot fundamentul moral pe care este cladit demersul tutorialistic, deci ar fi bine sa nu-i dati crezare si sa folositi in schimb Lista lui Ovidiu cind simtiti nevoia sa va inchinati si nu stiti cui.

 

Tags: , , , , , , , , , , , ,

Invatati, Invatati, Invatati

Posted in Premiul n00bel, Regula 0, Slagare internationale on January 5th, 2012 by Mihnea

Sper ca sinteti abonati la lista de lecturi obligatorii a Partidului Codexpert Roman, unde muezinii Bancila si Cucu sufla zilnic in trompeta uzinei pentru a culturaliza masele de codexperti. Daca nu ati aderat inca, voi incerca sa va conving acum s-o faceti, prezentind citeva din recomandarile publicate de catre Primi Inter Pares.

In primul rind, ne este dat un link catre un articol in care Raymond Chen povesteste despre un asa-zis “for-if anti-pattern”. Imi pot inchipui cum formatorii de opinie din Codexpertia au schitat un zimbet condescendent dar incredul citind despre tendintele unora de a lua la rind elementele din directoare sau hash map-uri in cautarea unei valori. Cu certitudine nici cel mai prost aspirant nu ar scrie asemenea cod, nu? NU?

Ma rog, in asteptarea momentului in care Silviu va face apel la Regula 0 si Cucu il va bana pe Raymond Chen de pe codexpert, sa ne indreptam atentia spre o noua propunere din categoria Radio Erevan: [WinAPI] Cum aflu frecventa procesorului? Dupa cum ne-a obisnuit, sectoristul iscoditor nu se multumeste sa-si raspunda la intrebari cu un simplu “nu stiu”, ci insista sa ne demonstreze prin cod ca habar n-are. Prima metoda expusa de dinsul, in legatura cu care avea nedumeriri si acum 9 ani, nu reuseste sa ne dea valoarea exacta, dar se apropie. A doua metoda are avantajul de a fi mai “simpla”, dar din pacate are si un dezavantaj: returneaza tot timpul 0. Unii cititori vor spune ca decit gresit, mai bine deloc, insa altii vor sustine ca dimpotriva, mai bine ceva decit nimic. Gardianul Ovidiu lasa aceasta decizie de ordin filosofic la alegerea ta.

Si cum fara norme de buna purtare n-am putea face nimic pe lumea asta, ultimul imbold muncitoresc ne trimite la un articol in care Danny Kalev ne spune cum putem determina cu usurinta daca stim sa programam. Pe Danny l-am cunoscut intr-un episod anterior, in care ne arata ca nu stie ce face header-ul iosfwd, desi in CV se jura ca a fost baiat de comitet C++. De data asta el isi ia si mai in serios rolul de chibit, spunindu-ne ca n-ai voie sa faci clase cu mai mult de 8 metode publice, dind si exemplul std::string, care in opinia sa este de mare cacat si ar fi trebuit spart in mai multe clase care sa deriveze unele din altele. De asemenea, n-ai voie sa folosesti propriile containere in loc de std::map sau std::vector, deoarece Danny a citit pe Internet ca ce ni-i dat in STL este thread-safe si imbatabil ca performanta. Sigur, nu conteaza ca nu le poti folosi in interfata unui LIB/DLL/SO, ca majoritatea fac o alocare per element si se tiriie ingrozitor din cauza asta, ca poate ai nevoie sa fie lock-free, sau alte astfel de lucruri care ii preocupa doar pe inferiorii care scriu cod. In capul lui Danny conteaza ca au rvalue references, pentru a se comporta optim intr-o serie de cazuri in care oricum n-ar fi trebuit sa ajungi. Danny n-are timp sa scrie cod, e prea ocupat sa scrie pilde. A da, si n-aveti voie cu pointeri; daca ar fi dupa Danny, s-ar scoate de tot pointerii din limbaj si s-ar inlocui cu tipuri clasice, de exemplu vectori sau structuri.

 

Tags: , , , , , , , , , , , , , , , , , ,

Autodesk ne invata sa programam

Posted in Codare cu premeditare, Slagare internationale on August 7th, 2011 by Mihnea

Am mai mentionat faptul ca 3D Studio Max este scris de maimute cu sindromul Down. Ei bine, unul din maimutoii in cauza, pe numele sau de botez Cristofor (adica purtatorul lui Cristos), a decis ca el e Alesul ce va scoate lumea programarii din bezna si si-a inceput lucrarea de educare a maselor postind pe blogul pus la dispozitie de uzina-mama un fel de Philosophiæ Naturalis Principia Programatica. Ópusul are toate ingredientele necesare unei nominalizari la premiul Vocea Minerului: proverbe, indemnuri, acronime si link-uri la site-uri de agili. Singura problema este ca lucrarea este in primul rind una teoretica, adresindu-se exegetilor, deci cititorii de rind pot ramine nelamuriti cu privire la modul in care Principiile se aplica in practica. De aceea imi voi face datoria de umil scrib si voi ilustra opera de geniu cu extrase din rodul lumesc al trudei din Gradina Autodeskului.

Primele doua porunci vin la pachet, dupa cum aparent s-a prins si Cristi:

DRY – Don’t repeat yourself. – Probably the single most fundamental tenet in programming is to avoid repetition.

Abstraction Principle – Related to DRY is the abstraction principle “Each significant piece of functionality in a program should be implemented in just one place in the source code.”

Un prim exemplu al modului in care aceste principii pot transforma programatorul ordinar in Ahitect se gaseste in clasa Texmap. Texmap asta e o poza care in teorie are ca scop sa primeasca niste coordonate si sa returneze un pixel. In practica, maimutele au observat ca uneori texturile astea sint folosite pentru bump mapping, caz in care trebuie luate mai multe sample-uri si calculate niste chestii. In programele care nu au auzit de Principiile Lui Cristofor, calculul asta se face separat, independent de poza, caci e la fel indiferent ca poza e un checker procedural sau un bitmap. In Max, primele doua porunci se incarneaza in felul urmator in documentatie:

To understand how this is done, let’s look at some sample code. The method responsible for returning the perturbed normal is Texmap::EvalNormalPerturb(). The code below happens to be from \MAXSDK\SAMPLES\MATERIALS\CHECKER.CPP but all the other 2D textures use a similar approach.

Point3 Checker::EvalNormalPerturb(ShadeContext& sc)
{
	Point3 dPdu, dPdv;
	if (!sc.doMaps) return Point3(0,0,0);
	if (gbufID) sc.SetGBufferID(gbufID);
	uvGen->GetBumpDP(sc,dPdu,dPdv);
	Point2 dM = uvGen->EvalDeriv(sc,&mysamp);
	return dM.x*dPdu+dM.y*dPdv;
}

Sintagma “a similar approach” se refera la faptul ca bucata de cod de mai sus se gaseste in toate sample-urile lor, si ca tu trebuie sa faci acelasi copy/paste daca implementezi un Texmap d-asta, ca ei n-au fost in stare sa scrie o functie. DRY, da?

Urmatorul exemplu se gaseste intr-unul din fisierele mele preferate din Max: blizzard.cpp. Acest fisier care implementeaza un sistem de particule simplist in doar 9000 de linii de cod contine nenumarate exemple de DRY in interiorul sau – dupa cum va las placerea sa descoperiti – dar de asemenea in exterior, deoarece celelalte sisteme de particule (parray.cpp, pcloud.cpp etc.) sint implementate luind mari bucati din el si schimbind chestii in citeva locuri. Tot in dinsul gasim si urmatorul comentariu DRY-compliant:

// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// WARNING - a copy of this class description is in maxscrpt\maxnode.cpp
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

Am putea zabovi mult in zona asta a copypastei, dar haideti sa facem un efort si sa trecem la urmatorul triplet leninist:

KISS (Keep it simple, stupid!) – Simplicity (and avoiding complexity) should always be a key goal.

Avoid Creating a YAGNI (You aren’t going to need it) – You should try not to add functionality until you need it.

Do the simplest thing that could possibly work

In Maya, daca vrei ca un material facut de tine sa se picteze singur in viewport, trebuie sa implementezi o metoda numita glGeometry(). Daca vrei sa faci pe desteptul, mai sint vreo trei metode pe care le poti implementa ca sa suporti batching (adica sa te cheme intii ca sa-ti setezi state-ul, dupa care sa te cheme sa te desenezi pentru fiecare mesh, dupa care sa te cheme sa faci curat) dar sint optionale. Probabil va ginditi ca e bine asa, dar gresiti. Asta nu e KISS. Daca vreti sa vedeti KISS si YAGNI, trebuie sa va uitati cum sta treaba in Max.

Intii si-ntii, in Max trebuie sa derivezi din interfata IDX9VertexShader, care contine 18 functii virtuale pure, dintre care nu te intereseaza nici una. Te intereseaza functia care se cheama la fiecare frame, ca sa pictezi din ea, dar aia e intr-o clasa de baza a lui IDX9VertexShader, numita IVertexShader. Functia aia se cheama Initialize(). Nu glumesc. Aparent ar trebui sa faci doar initializari in ea si sa-l astepti pe Max sa incerce sa deseneze cu tine mai tirziu, dar pina si lor li s-a parut prea complicat, asa ca sample-urile din SDK deseneaza direct de acolo.

Dupa IDX9VertexShader vine IDX9PixelShader cu inca vreo 6 virtuale pure. Asta nu stiu la ce foloseste. Nu vad de ce i-ai povesti lui Max despre shaderele pe care le incarci, tu vrei doar sa te cheme sa te pictezi si sa-ti dea geometria. La fel, nici aia care au facut sample-urile n-au inteles, asa ca nu implementeaza deloc interfata asta. Mai departe vine IDX9DataBridge, cu inca vreo 5 virtuale pure pe care trebuie sa le implementezi ca {}. Preferatele mele sint GetDXVersion(), din care trebuie sa returnezi tot timpul 9.0 (ca float, FFS), deoarece clasa asta oricum merge doar cu DX9 (numindu-se ea IDX9DataBridge) si DisableUI() deasupra careia troneaza urmatorul comentariu:

//! This is no longer used
/*! \remarks Currently this method is not used\n\n
  */
virtual void DisableUI()=0;

Cel mai tare princpiu este insa asta:

Principle of least astonishment

In Max, atributele nodurilor se definesc cu ajutorul clasei ParamBlockDesc2. Constructorul acestei clase este:

ParamBlockDesc2(BlockID ID, MCHAR* int_name, StringResID local_name,
ClassDesc2* cd, USHORT flags, ...);

Alea 3 puncte de acolo deschid calea catre cel mai grotesc simulacru de domain-specific language pe care l-am vazut vreodata. Pentru fiecare atribut trebuie sa pasezi diverse tag-uri urmate de valori:

static ParamBlockDesc2 link_const_paramblk (
	link_const_params, _T("LinkConsParameters"),  0, &linkCD,
	P_AUTO_CONSTRUCT + P_AUTO_UI, LINKCTRL_PBLOCK_REF,
	IDD_LINK_PARAMS, IDS_AG_LINKPARAMS, BEGIN_EDIT_MOTION, 0,
	&linkConstDlgProc,
	link_target_list,  _T(""), TYPE_INODE_TAB, 0, P_VARIABLE_SIZE,
		IDS_LINK_LIST,
		p_accessor,		&link_const_accessor,
		end,

	link_key_mode, _T("key_mode"), TYPE_INT, 0, IDS_AG_LINK_KEY_MODE,
		p_default, 		0,
		p_range, 		0, 2,
		p_ui, 			TYPE_RADIO, 3, IDC_NO_KEY,
		IDC_KEY_NODES, IDC_KHIERARCHY,
		p_accessor,		&link_const_accessor,
		end,

	link_start_time, _T(""), TYPE_TIMEVALUE_TAB, 0, P_VARIABLE_SIZE,
		IDS_START_FRAME_LIST,
		p_accessor,		&link_const_accessor,
		end,
	// etc.

Toate cacaturile alea cu p_ in fata sint valori dintr-un enum al lor si trebuie sa fie urmate de parametrii propriu-zisi. Pentru un nod cu citeva zeci de atribute trebuie sa pasezi citeva sute de parametri catre constructorul asta. Nodul lor de color correction (maxsdk\samples\materials\color_correction.cpp) are vreo 65 de atribute, ceea ce rezulta in cam 800 de parametri pasati catre constructor. Least astonishment, da?

Si mai putin surprinzator este cit de robust e maretul sistem. Daca uiti un parametru undeva pe la mijloc, Max crapa la startup fara sa-ti spuna nimic (nici macar ce definitie l-a speriat). In exemplul de mai sus, daca uiti un parametru dupa p_range la link_key_mode, o sa creada ca maximul atributului este valoarea lui p_ui, dupa care va crede ca urmatorul tag e TYPE_RADIO si in functie de valoarea aluia va face lucruri “least astonishing”. Succes la debug.

Chiar daca reusesti sa ii descrii atributele fara sa crape, urmeaza un amuzament maxim cind vrei sa adaugi atribute intr-o versiune ulterioara a plug-in-ului. In primul rind, nu ai voie sa stergi nimic, pentru ca boul citeste valorile din fisiere si le potriveste cu definitiile pe baza indexului, nu dupa nume, cum fac alte programe scrise de fraieri care nu stiu Principii. Singurul lucru pe care poti sa-l faci este sa adaugi noi atribute la coada, dar si asta cu diverse restrictii. Daca nu-ti convine, au un mecanism extrem de complicat si fragil prin care te cheama la load time sa cirpesti datele din fisier, dar deoarece au aplicat KISS cu sfintenie, e inutilizabil.

Din pacate nu pot sa dau link aici la fisierul mesh.cpp pentru ca doar aia care sint registered developers au privilegiul de a se desfata cu continutul sau. Pot insa sa va spun ca in acel fisier se afla functia Mesh::render() in valoare de 3430 de linii. Acolo se vede cum se imbina armonios toate Principiile Lui Cristofor, mai ales ala cu “Write Code for the Maintainer“: goto-uri, nenumarate catch(…)-uri, if-uri cu cite 11 conditii urmate de else if-uri cu o parte din conditiile din primul if, dar negate si in alta ordine, instantiat obiecte COM prin al saptelea nivel de nesting de if-uri si switch-uri etc. Din cind in cind prin cod se gasesc comentarii confuze, unele semnate si datate, ca scrijeliturile de pe peretii celulelor de puscarie. Cele mai tari sint astea doua, anonime din pacate:

else {
    // (How can this happen?)
    delete pSelConv;
}

12 linii mai jos:

else {
    // How can this happen?  (I'm just copying above...)
    delete pNormalSpec;
}

In fine, nu mai stau sa iau si celelalte Principii la rind, ca m-am enervat si mi s-a facut greata de la atita rascolit prin gunoi. Ce vroiam sa spun e ca-mi bag pula in Cristofor si regulile lui. In loc sa puna mina sa stearga puroiul ala de soft si sa arda toate backup-urile surselor, el se preface ca tocmai a fost in excursie pe multele Sinai si ne blagosloveste pe noi cu zicatorile despre programare pe care le-a prins din zbor dind click-uri random pe wikipedia. Muie ba!

PS: nu pot incheia un post despre Max fara citeva citate din maxsdk\samples\mr-notes.txt:

note that these probably won’t map nicely…for example, mi_img_xxx functions will map somewhat to Bitmap and GBuffer functions, but probably not exactly

Norm — actually shader versioning was kinda a mystery to me. That is…miMTShader has get/setVersion, and this is used when generating the MI, but I can’t tell where the translator gets the version from…or does it?

What follows is a rough mapping of MR shader state variables to MAX class vars, functions, etc.
(Urmeaza o lista cu o coloana de nume de variabile din mental ray si o coloana numita “MAX Class or Function” care e complet goala.)

Tags: , , , , , , , , ,