What would you be if you were attached to another object by an inclined plane, wrapped helically around an axis?

Posted in Codare cu premeditare, Slagare internationale on January 23rd, 2013 by Mihnea

Tovarasi, am infrint. Minerul ex-multinational emblematic Silviu Virgula Ardelean pare sa se fi vindecat de tutorialita, militianul Ovidiu a demisionat de la Radio Erevan, iar singurul semn de viata din directia ograzii cu experti este sunetul mocirlos pe care il face pulanul flasc al cite unui fondator cind mai usuie un elev de liceu care are nevoie urgent sa-i faca cineva tema. Cred ca este timpul sa gasim noi mineri, dar jugul capitalist ne-a cam impiedicat sa dedicam timpul cuvenit activitatii de largire a orizonturilor si abatajelor.

Pina una-alta, o sa va delectez cu doua slagare internationale. In deschidere ne cinta formatia NewTek, care in SDK-ul de Lightwave ne ofera o viziune lirica alternativa asupra puterilor lui 2:

#define IQ_CTRL         1
#define IQ_SHIFT        2
#define IQ_ALT          4
#define IQ_CONSTRAIN    8
#define IQ_ADJUST       16
#define MOUSE_LEFT      32
#define MOUSE_MID       64
#define MOUSE_RIGHT     96
#define MOUSE_DOWN      128

Aceste constante sint combinate intr-un bit field care-ti zice starea butoanelor cind iti vine un eveniment de mouse. Cind bitii 5 si 6 sint setati, nu inseamna ca userul tine apasat pe left si middle, ci ca tine apasat pe right. Era absolut vital sa se faca economie de un bit, chiar daca asta inseamna ca “sistemul” nu poate sa-ti spuna cind userul tine apasat pe mai multe butoane in acelasi timp. In caz ca va intrebati, variabila care tine bit field-ul e int, deci masura de austeritate n-a izvorit din utilizarea unui char, ci pur si simplu din spirit civic si responsabilitate sociala.

Lasind aritmetica in sant cu botul umflat, este timpul sa ne ocupam un pic si de algebra. Pentru neinitiati, un quaternion este un hack matematic care-ti permite sa encodezi o rotatie in 3D folosind 4 numere. In practica, cel mai des construiesti un quaternion dintr-un vector care reprezinta axa de rotatie si unghiul de rotatie in jurul axei respective. Primele 3 numere din quaternion sint componentele vectorului inmultite cu sinusul jumatatii unghiului, iar al 4-lea numar este cosinusul jumatatii unghiului. Orice implementare de quaternion dintr-o biblioteca de algebra contine un constructor sau o functie care ia un vector si un unghi si face manevra asta cu sin si cos. 3D Studio Max are si el asa ceva:

/*! \remarks Constructor. The quaternion is initialized from the
 vector <b>V</b> and angle <b>W</b> passed. The quaternion is
 then normalized.\n\n
*/
GEOMEXPORT Quat(const Point3& V, float W);

In caz ca aveam dubii, autorul remarca clar (ma rog, cit de clar se poate intr-un comentariu minjit cu puroi de doxygen) ca acest constructor face un quaternion dintr-un vector si un unghi. Asa ca te pui linistit pe scris cod si rotit obiecte si cind rulezi observi ca ele nu prea se rotesc cum ai dori tu. Si te uiti peste cod, si pare bun, si totusi nu merge. Si intr-un final te paleste inspiratia sa privesti in interiorul quaternionilor si vezi ca nu contin deloc ce ar trebui. Codul constructorului, fiind foarte complicat, nu putea fi pus in header, ci sta intr-un cpp (care ajunge sa fie un DLL, ca sa treci printr-un import table de fiecare data cind vrei sa initializezi 4 floati). Din fericire insa, Autodesk ofera apropiatilor bucati din sursele de Max, astfel incit putem lectura quat.cpp si vedea urmatoarea grozavie (cu tot cu indentarea de oligofreni):

Quat::Quat(const Point3& V, float W) {
    x = V.x; y = V.y; z = V.z; w = W;
    Normalize();
    }

Cum ba pula? Cum este W un unghi, daca tu il asignezi direct in a 4-a componenta, fara sa faci muismul cu sin si cos de juma din el? Cum cacat ti s-a parut mai util sa faci asta intr-un constructor care ia vector si scalar, decit sa faci ce face tot restul lumii?

Citeva linii mai jos intilnim si urmatoarea gema:

Quat Quat::operator+(const Quat &q) const {
   //return(Quat(x + q.x,y + q.y,z + q.z,w + q.w));
   return *this * q;
   }

Deci dragii mei, in algebra autodesciana, inmultirea si adunarea sint una si aceeasi operatie, caci unui mintos i s-a parut ca “+” este un simbol potrivit pentru compozitia quaternionilor (care, apropo, nu e comutativa ca + ala pe care-l stim cu totii, daca e sa ne legam de detalii). Lucru documentat de altfel si-n header, daca ignori comentariul de la sfirsitul liniei. Cred ca comentariul ala e comentat, deci n-are nici un efect:

/*! \remarks This operator is the same as the <b>*</b> operator. */
GEOMEXPORT Quat operator+(const Quat&) const; // sum of two quaternions

Tirnacop + tirnacop = tirnacop * tirnacop pentru valori foarte mari ale lui 2.

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: , , , , , , , , ,

Conventii

Posted in Codare cu premeditare, Stand-up philosophy on September 21st, 2010 by Mihnea

Uneori cind gindesti un sistem descoperi ca poti face sau reprezenta ceva in mai multe feluri echivalente, si atunci trebuie sa recurgi la o conventie. Bizonul prost ajuns intr-o fundatura d-asta va judeca situatia cu mintea lui si va alege bazindu-se pe ce i se pare lui oportun la momentul ala, ignorind preferintele altora de pina la el.

De obicei cind e nevoie de o conventie, alternativele au merite egale. Nu conteaza ce alegi. Nu e mai bine sa mergi cu masina pe dreapta drumului decit pe stinga lui. E tot aia, deci prima data alegerea se poate face arbitrar. Ceea ce conteaza e sa respecte toata lumea conventia aia si sa nu se trezeasca un bou ca a gasit el nu stiu ce avantaje daca face altfel decit restul lumii, iar alti boi sa se ia dupa el, ducind la schisme, probleme de interoperabilitate si in general haos.

Un teritoriu destul de fertil pentru boi neconventionali este programarea 3D, asa ca ma voi opri asupra a doua cazuri in care s-a gasit un mintos sa faca pe specialu’ si sa nenoroceasca o groaza de oameni care au venit dupa el. Primul e legat de reprezentarea vectorilor.

Cind trebuie sa inmultesti vectori cu matrici ai doua optiuni: ori consideri vectorul ca fiind o linie, si faci v’ = vM, ori consideri vectorul ca fiind o coloana, si faci v’ = Mv. In toate cartile de mate se foloseste a doua varianta, asa ca s-au gasit unii sa remarce ca nu e bine si sa faca invers. Rezultatul e ca DirectX si o groaza de alte chestii sint in momentul de fata in dezacord direct cu matematica, asa ca daca incerci sa treci de la una la alta, te ia rapid cu dureri de cap. Ca sa fie si mai misto, multi oameni confunda “column major” si “row major” cu “column vector” si “row vector”, ducind la un haos complet in terminologie. Cind dai prima data peste un sistem cu propria biblioteca de algebra liniara, esti intr-o mare ceata si sint sanse ca documentatia sa nu te scoata, pentru ca unii au simtit nevoia sa-si puna mintea la contributie cind nu era cazul. In unele manifestari de prostie deosebita, cum e 3D Studio Max, biblioteca de mate chiar are doi operatori de inmultit vectori cu matrici, astfel incit sa poti sa scrii si v*M, si M*v, si sa se intimple acelasi lucru.

Din punct de vedere matematic se poate argumenta ca e mai bine sa folosesti vectori coloane, pentru ca sa nu ajungi la spital cind ai nevoie sa derivezi functii. Chris Hecker da un exemplu aici. Pe rebelii carora le datoram dezastrul asta i-au preocupat insa alte lucruri. Un argument des intilnit este ca daca iti place pe invers, poti implementa mai eficient inmultirile intre vectori si matrici pe procesoare SIMD care n-au operatiuni orizontale (produs scalar, in speta). Cu vectori coloana poti inmulti vectorul cu o linie a matricei intr-o singura instructiune, dar dupa aia trebuie sa despachetezi numerele rezultate si sa le aduni intre ele pe rind. In 3D cu coordonate omogene, asta ar veni vreo 4 inmultiri, 8 adunari, 8 shuffle-uri si 4 store-uri (cel putin in SSE). Cu vectori linie, poti inmulti fiecare linie a matricei cu o componenta a vectorului in 2 instructiuni (un shuffle si un mul), dupa care acumulezi rezultatele si ajungi la vectorul transformat, deci ai 4 inmultiri, 4 shuffle-uri, 3 adunari si 1 store (plus mai putine dependinte deci pipelining mult mai bun). S-ar parea ca miracolul graficii 3D realtime a fost facut posibil prin scuiparea matematicii intre ochi, dar nu-i chiar asa.

Daca chiar ai nevoie sa optimizezi inmultirile dintre matrici si vectori, poti sa-ti tii matricile transpuse in memorie, sau “column major”, adica in a[0] – a[3] e prima coloana a matricei, nu prima linie. Layout-ul in memorie nu impune notatia. Poti scrie frumos v’ = Mv peste tot si sa ai un operator care se foloseste asa, dar sa-ti tii matricile column major si sa beneficiezi de viteza superluminica a tehnologiilor SIMD. Totusi, s-ar putea sa n-ai un bottleneck in inmultirea matricilor cu vectorii (mai ales daca traiesti in prezent), sau sa ai un procesor SIMD cu instructiuni orizontale, sau ambele. In particular, GPU-urile au o instructiune de produs scalar, deci daca folosesti vectori coloana, o transformare in GPU se face in 4 instructiuni si atit. D-aia aplicatiile care folosesc matricile din DirectX le tot transpun inainte sa le trimita la shadere. Noroc ca ar putea merge foarte repede inmultirile pe CPU, asta daca s-ar face vreo inmultire acolo.

A doua conventie despre care fiecare pionier al graficii 3D a simtit nevoia sa-si dea cu parerea este aranjarea axelor de coordonate. Daca pui un elev de clasa a 8-a sa-ti deseneze axele de coordonate in spatiu, primesti inapoi ori o privire timpa, ori asta:

Nu e greu. X la dreapta, Y in sus, Z inspre tine. Asa a invatat toata lumea la scoala, nu e nevoie de opinii suplimentare. Nu e mai bine daca il pui pe Z in sus, sau pe X la stinga. Se aude si acolo in spate la 3D Studio Max, in pula mea? Atunci cind treci din 3D in 2D – cum ar veni, atunci cind proiectezi – vrei sa ramii cu X la dreapta si Y in sus. Nu vrei ca axele cu care ramii sa se cheme X si Z. Oamenii normali stau in picioare si privesc inainte. D-aia daca nu esti pe medicamente, Z e adincimea.

La Max n-au lucrat niciodata oameni normali, ci doar labari care nu stiu nimic despre programare. In general, chiar daca un soft e foarte prost, se va gasi cineva care sa incerce sa domoleasca discutiile aprinse cu cuvintele magice “da, dar…”. La Max nu e asa. Orice programator care s-a atins vreodata de SDK-ul lui il uraste cu pasiune. Nimeni nu incearca sa-i gaseasca scuze. In Max, Z este inaltimea. Ca sa ajungi la o asemenea idee ca programator, trebuie sa fii obisnuit sa stai mult pe burta si sa privesti lumea de sus, adica fix pozitia in care-i sta cel mai bine unui muist care crede ca e cool sa descrii atributele nodurilor trimitind sute de parametri la un constructor variadic. Puletul care a facut asta a vrut si el, ca toata lumea, sa ramina cu X si Y cind trece in 2D, dar el se uita de sus, nu din fata, crezindu-se probabil arhitect (d-ala care proiecteaza cladiri, nu d-ala care crede ca design pattern-urile sint chestii interesante si utile). Si din cauza lui si a altora ca el, importatul geometriei dintr-o aplicatie in alta e putin mai greu decit ar trebui sa fie, ca de ce sa avem si noi o viata mai usoara si sa ne concentram pe lucrurile importante, cind putem sa pierdem vremea schimbind axe prin vertecsi si coloane prin matrici. Important e sa fie un jegos fericit ca si-a construit o lume dupa chipul si asemanarea lui, nu dupa cum faceau toti prostii de pina la el.

PS: A da, si e “bitangenta”, nu “binormala”, ca suprafetele n-au doua normale.

Tags: , , , , , , , ,

Dilema

Posted in Slagare internationale on September 4th, 2010 by Mihnea

In articolul asta voi vorbi despre cea mai proasta echipa de programatori din lume, desi mi se pare foarte nedrept sa nominalizez una singura, cind sint atitia imbecili care ne fac viata mai grea in fiecare zi prin faptul ca nu le trece prin cap ideea sa-si puna streangul de git.

Daca ar fi pe categorii, mi-ar fi mai usor. De exemplu cel mai prost soft facut vreodata de Microsoft este MSI, sau Windows Installer, sau cum mortii lui il mai cheama acum. Asta nici n-ar trebui sa fie un soft. Pina si hipsterii aia labagii ai lu’ Steve Jobs s-au prins ca 99.98% din programe (procent determinat stiintific) au nevoie doar sa-si puna niste fisiere intr-un director. Solutia lor pentru cei cu nevoi speciale este o voma cu mai multe bug-uri decit linii de cod si cu o interfata care l-ar face pe Sisif sa se bucure ca sint altii si mai oropsiti ca el, dar nu conteaza pentru ca nu ajungi in fundatura aia decit in 0.02% din cazuri. Microsoft Installer e fix pe dos: pretinde ca face un miliard de cacaturi care nu-s necesare nimanui (si oricum nu merg), insa nu poti pur si simplu sa pui niste fisiere intr-un director si gata. A fost nevoie de un tip special de prost care sa conceapa un sistem in care ai nevoie de installer-ul original pe disc ca sa poti sa stergi un program instalat. In plus este ridicol de incet si inevitabil se fute la un moment dat, astfel incit exista o tona de tool-uri si blog-uri dedicate aducerii lui pe calea cea dreapta. Daca Aron Pumnu’ ala ar lucra la mine in firma si ar sta sa scrie pe blog despre cautat “return value 3” prin log-uri in loc sa puna mina sa repare muia aia de soft, as incepe sa-mi pun intrebari.

Sau na, daca am vorbi doar de IDE-uri, ar cistiga detasat puroiul de Xcode. Sau daca ne-ar interesa doar soft open source, am putea alege unul la intimplare. Sau daca ne-am uita la site-uri, ar fi twitter sau failbook. Sau daca am cauta prostie concentrata in chestii mici, l-am putea mentiona pe trogloditul care s-a gindit sa sparga calculatorul din Windows 7 in “moduri”, pisa-l-as in ochii lui de muist. Dar nu, aici caut un soft care sa transcenda categoriile, granitele, spatiul si timpul. Ceva de o prostie absoluta, care sa te faca sa-ti doresti sa reaprinzi cuptoarele si sa-i trimiti la dusuri pe toti cei care au lucrat la el.

Stiu ca unii se gindesc deja la 3D Studio Max, dar nu. Ca sa intelegi proportiile ororii intruchipate in Max trebuie sa fii programator, iar eu vreau ceva care nu tine cont de caste, virste si aptitudini.

Cel mai prost soft facut vreodata este Yahoo Messenger. Este incredibil cum un cacat de program de trimis text prin retea poate sa manince atitea resurse si sa aiba atitea bug-uri. Cum pula mea sa ai nevoie de 110 MB de RAM ca sa trimiti text? Altii s-au dus pe Luna cu 4 KB, adica de 28 de mii de ori mai putin. Cum sa te blochezi ma de fiecare data cind pica conexiunea si incerci sa te reconectezi? Cum sa-ti ia atita timp sa pornesti? Cum sa te blochezi cind se stinge calculatoru’ si astfel sa nu lasi calculatoru’ sa se stinga? Cum pula mea sa umbli la setarile globale de window animations cind cineva da minimize la un geam de-al tau? Luati fratilor, sa le trimita cineva link-ul asta, poate la versiunea 11 le iese.

Da, stiu ca pe linga text mai trimite si voice si video prin retea. Mare cacat. Tot n-ai cum sa ajungi la 110 MB de RAM. Photoshop, Starcraft si versiunile mai vechi de Maya incap in mai putin. Muie.

Daca proiectul asta ar fi fost facut pe rentacoder, ar fi costat 50 de dolari, ar fi durat 2 saptamini si probabil ar fi mers mai bine. Orice indian nespalat care maninca de pe jos si bea apa in care se pisa vacile comunitare l-ar fi facut mai bine. Dar nu, Yahoo a reusit cumva sa stringa atitia prosti intr-o singura echipa, incit prostia lor reunita a devenit ceva mai mult decit suma partilor, ca Capitanu’ Planeta.

Problema e ca daca stii sa programezi, nu te intereseaza sa lucrezi la programe de chat, la twitter sau alte mui. Daca loazele care fac astea s-ar fi nascut cu 10 ani mai devreme, ar fi muncit la state de plata in FoxPro si Paradox. Sau la Canal. Din nefericire, e nevoie si de programele astea, ceea ce creeaza o dilema: cum putem face ca si proiectele de cacat sa fie facute totusi de programatori competenti? Asta ar trebui sa-i preocupe pe toti cretinii aia care se duc la conferinte despre project management, nu cum sa pui cite doi prosti la un calculator, ca la cercul de informatica cind erau mai multi boraci decit HC-uri.

Poate ar merge o chestie gen munca in folosul comunitatii. Daca esti programator si o comiti, poti sa alegi intre amenda, puscarie, luat bataie de la mascati sau ce urmeaza sa ti se intimple si contribuit la un proiect de cacat. S-ar putea face un site unde proiectele de cacat isi prezinta nevoile si tu ti-ai alege. Evident, asta n-ar rezolva toate problemele, ca orice om intreg la cap ar prefera sa faca puscarie in aripa de violatori necrofili fani Mac decit sa incerce sa repare ceva in Max, dar rau n-are cum sa fie. Eu de exemplu as face un program de chat daca mi-ar da mai repede carnetu’ inapoi.

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