Teorema stergerii cu rest

Posted in Codare cu premeditare, Slagare internationale on April 13th, 2011 by Mihnea

Am stabilit deja ca lista inlantuita e un subiect delicat. Este timpul sa aratam ca nu doar Ovidiu “MVP” Cucu are probleme cu dinsa, ci si aia carora el le pupa bombeurile au mici dificultati in intelegerea acestei structuri de date fenomenal de complicate. Sa urmarim pentru inceput un scurt material motivational in care se incearca stergerea unei configuratii dintr-un proiect in Visual Studio 2008 (nu stiu de ce se misca in reluare, muie youtube sau muie ffdshow):

Asta e, nu s-a sters. Lucrurile devin insa cu 57% mai interesante daca incercam sa stergem mai multe configuratii deodata:

Acum s-a reusit stergerea, dar ar fi fost un pic mai bine daca ar fi sters ce i-am zis sa stearga, nu ce doream sa pastram (de asemenea gasesc interesant cum in dropdown a ramas selectat “Debug2011”, desi cind il deschizi nu e acolo). Care sa fie explicatia?

Pai e destul de simplu, de fapt. Proiectul are doua configuratii care se cheama Debug5, doua Debug6 si asa mai departe, cite una pentru fiecare platforma (Win32 si x64). Acest lucru se poate observa cu ochiul liber in vcproj, unde nu exista Debug5, ci Debug5|Win32 si Debug5|x64. Mai departe in arhitectura lui VS, o configuratie trebuie sa existe in toate platformele – nu poti, de exemplu, sa ai Debug5 doar in Win32. Orice programator care a folosit vreodata platforme multiple in VC stie asta. Indianul care a implementat stergerea nu stie. Cind apesi pe “Remove”, el cauta prima configuratie care se cheama “Debug5” si o rade. In felul asta se sterge doar aia de Win32, dar cind deschide din nou dropdown-ul, o gaseste p-aia de x64 si o afiseaza acolo, iar acum proiectul e intr-o stare invalida, cu o configuratie care nu exista in toate platformele. Workaround-ul este sa stergi o configuratie, sa inchizi dialogul de edit, sa-l deschizi din nou si s-o stergi inca o data. In felul asta se sterge si Debug5|x64, si proiectul e utilizabil din nou.

Daca te aventurezi sa stergi mai multe configuratii de-odata, ca in al doilea filmulet, se evidentiaza o noua latura a retardarii indiene, aceasta ruda karmica a retardarii ardelene. Boul sterge configuratiile dupa index, nu dupa nume. Daca stersul propriu-zis i-ar fi mers, asta n-ar fi fost o problema. Din pacate insa, deoarece configuratia ramine acolo cind se manifesta prima parte a incompetentei, se fut maparile intre indecsi si nume, asa ca atunci cind dai sa stergi Debug6, se sterge de fapt altceva (jumate de altceva, mai exact). Mai departe retardarea 1 se compune cu retardarea 2 intr-un fel sublim, astfel incit tu dai sa stergi 6 din cele 8 configuratii, dar de fapt se sterg doar 3, printre care si singurele doua pe care vroiai de fapt sa le pastrezi.

VC are acest bug de la 2005, de cind a fost introdus noul configuration manager, cu platforme si cacat. De atunci au iesit 2005 SP1, 2008, 2008 SP1 plus o intreaga pleiada de hotfix-uri, dar nimeni nu s-a ostenit sa invete cum functioneaza de fapt configuratiile si cum se cauta intr-o lista. Bug-ul s-a rezolvat in sfirsit in 2010, pacat ca ala e inutilizabil gratie rescrierii editorului in dotniet (plus alte “goodies”, gen gunoiul ala de MSBuild).

Sa trecem acum in tabara adversa. Aparent exista o corelatie intre retardare si softurile de instalat alte softuri. Cel mai idiot lucru scos vreodata de Microsoft este MSI (chiar luind in considerare Songsmith si reclama pentru el). Cel mai idiot lucru scos de Apple este PackageMaker, echivalentul hipsteristic al lui MSI. Iata ce face PackageMaker cind vrei sa stergi un target din installer:

Pentru asta n-am o explicatie, caci nu inteleg cum functioneaza mintea oamenilor care programeaza pentru Apple. Cert e ca atunci cind stergi ceva, reuseste sa amestece restul target-urilor si chiar sa lase un fisier orfan, atasindu-l de root-ul proiectului. As dori sa mentionez ca in mod normal n-ai cum sa atasezi fisiere direct acolo, folosind UI-ul lui.

Workaround-ul este sa editezi proiectul de mina, caci este tinut in XML. In XML-uri, mai exact. Cite 2 XML-uri pentru fiecare target, plus un XML mare, to rule them all (in speta, 71 de fisiere in proiectul din film). Si aceste XML-uri sint scrise pe o singura linie, cum mentionam in post-ul despre XCode. Si numele lor conteaza, fiind prefixate cu un numar. Si alea in care zici ca vrei sa instaleze tot ce-i intr-un director contin si numele fisierelor din directorul ala, la momentul la care ai facut proiectul. Care nu folosesc la nimic, pentru ca daca adaugi un nou fisier intre timp, se va copia, asa cum iti doresti, dar nu va fi trecut in XML. Si asa mai departe, in pula mea.

Ca sa fiu perfect obiectiv ar trebui sa expun si o muie dintr-un IDE de Linux. Gluma asta se scrie singura, va las pe voi sa va imaginati ce vreti.

Oricum, ce vroiam sa spun e ca le doresc epidermoliza buloasa alora care-s responsabili de chestiile astea. Sau munca silnica pe viata in mina cu Silviu Ardelean ca team leader.

Update: am elucidat si misterul PackageMaker. Si aici retardarea este usor de inteles: gunoiul are un index.xml in care, odata ce-l formatam sa nu mai fie tot pe o singura linie, putem vedea chestii de genul:

<choice title="8.5 plug-in" id="choice210">
	<pkgref id="com.nextlimit.realflowPluginForMaya.realflow.pkg"/>
</choice>
<choice title="2008 plug-in" id="choice211">
	<pkgref id="com.nextlimit.realflowPluginForMaya.realflow-1.pkg"/>
</choice>
<choice title="2009 plug-in" id="choice212">
	<pkgref id="com.nextlimit.realflowPluginForMaya.realflow-2.pkg"/>
</choice>

Mai jos in fisier scrie si:

<item type="file">01realflow.xml</item>
<item type="file">02realflow.xml</item>
<item type="file">03realflow.xml</item>

Observam deja un design fabulos, caci corespondenta dintre “choice-urile” alea si fisierele in care se spune ce contin se face pe baza ordinii. Nu s-a putut pune nodul ala de item sub nodul de choice, sau ceva. Mai departe, daca privim in 01realflow.xml, vedem ca e scris package name ala, ba chiar are si un UUID dupa care ar putea fi identificat:

<pkgref spec="1.12" uuid="A23E47A9-3AB3-4619-847F-2104601981F9">
	<config>
		<identifier>com.nextlimit.realflowPluginForMaya.realflow.pkg</identifier>

Atingerea de geniu este ca muistul tine package name-urile alea acolo doar de decor. De fapt el se asteapta ca in primul fisier sa fie definit intotdeauna pachetul “com.nextlimit.realflowPluginForMaya.realflow.pkg”, in al doilea sa fie ala cu -1 in coada, in al treilea ala cu -2 etc. Nu conteaza ce scrie de fapt in fisier, iar UUID-ul ala nu e folosit la nimic.

Deci ce se intimpla cind dai click dreapta remove? Pai simplu, indianul care a implementat functia de sters nu stie ca numele sint hardcodate. El sterge nodul din XML, sperind ca potriveala se va face dupa nume. Din cauza ca se face dupa ordine, totul aluneca cu o pozitie in jos, deci pachetul de 2009 ajunge in choice-ul de 2008, ala de 2010 in choice-ul de 2009 etc. Primul pachet ramine orfan, iar ultimul choice ramine gol.

Solutia e sa stergi de mina XML-urile corespunzatoare target-urilor de care vrei sa scapi, dupa care sa iei la rind toate XML-urile ramase si sa cirpesti package name-urile alea, ca sa fie consecutive. Apropo, nu eu am dat numele alea care-s toate la fel, sint generate de el pe baza numelor fisierelor din target-uri, iar daca le schimbi se fute.

Uimitor. Fabulos. Nici la scoala ajutatoare nu vezi asemenea “design”. Ala care a facut cacatul asta n-a inteles nimic din programare.

Cum ziceam, epidermoliza buloasa.

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

Scoala ardeleana de aritmetica

Posted in 112, Premiul n00bel on April 12th, 2011 by Mihnea

Viata e grea in Valea Jiului. Intre o descindere in abataj si o incursiune horticola la Bucuresti nu-ti ramine mult timp pentru dezvoltare personala. Daca vrei sa-ti cultivi o pasiune, cum ar fi pescuitul, trebuie sa renunti la unele chestii mai putin importante, cum ar fi scoala primara. Tragedia devine evidenta abia cind destinul te forteaza sa dai pestele din mina pe programarea de pe gard si cei din jurul tau descopera ca ai lipsit cind s-a predat impartirea cu rest sau formarea pluralului.

In post-ul despre atoi-ul ortacului va ziceam, printre altele, despre pasiunea lui Silviu Ardelean pentru modulo. Un cititor vigilent a remarcat insa ca nu era prima data cind fostul viitor pescar rescria regulile aritmeticii. Intr-un thread de pe vremea cind Gardianul Ovidiu nu gasise inca un pretext pentru a denunta unilateral dialogul dintre mine si experti povesteam cum aplica Peter principiile programarii defensive:

int& operator[](unsigned int index)
{
    index = index % count();
    return m_elements[index];
}

Ce a inteles minerul din asta:

Totusi… ma intreb daca el a facut vreodata debug pe acest cod. Sincer, ma cam indoiesc, pentru ca atunci, ar fi constatat ca tot timpul elementul ar fi fost valoarea returnata de count() [datorita faptului ca index era mai mic decat aceasta valoare] si in mod normal, ultimul index al lui m_elements ar fi fost count() – 1. Pracic, se accesa un index inexistent ( valoarea returnata de count() ). Sau?

Deci in 2009, pe cind era expert de 8 ani in C++ ([1]), Silviu credea ca restul impartirii lui 4 la 9 este 9. In lumina acestor fapte, ne intrebam ce a vrut de fapt sa faca cu % 10 ala in implementarea lui de atoi(). Sau la implinirea a 10 ani de experienta a descoperit cum functioneaza de fapt modulo si s-a decis sa-l foloseasca si unde nu face nimic, sau a vrut ca atoi-ul lui sa creada ca toate cifrele sint 10. Sau?

Putin mai incolo in thread, insusi Gardianul Ovidiu incearca sa domoleasca zelul cu care minerul explica principiile de convietuire armonioasa cu sizeof (operatorul care returneaza lungimea array-urilor dinamice, daca tineti minte). Ovidiu intinde urmatoarea nada:

size_t v = 0;
while(v < sizeof(v++))
{
    printf("%u", v);
}

Silviu, cu pedala mintii la podea, raspunde:

Fara a rula, iti zic sigur ca va crapa la printf(), chiar daca pasezi “%d” sau “%d”. printf()-ul are limitele sale, ptr. tipuri simple (int, float, char, etc).
Pune std::cout in loc de printf() si nu mai crapa. Chiar afiseaza ok valorile lui v.

Mare atentie, Silviu, ca si pamintul are limitele sale, ca si printf(), si s-ar putea ca intr-o zi sa se surpe pur si simplu sub tine.

In incheierea paginii aflam ce l-a determinat pe Silviu sa schimbe undita cu calculatorul personal:

Daca as lucra intr-un domeniu embeded unde trebuie sa ma supun unor legi mai stricte, atunci las si de la mine. Din fericire doar mi-a mirosit cu ce se mananca si e putin porbabil sa activez vreo data intr-un astfel de domeniu. Acum 2 ani o firma vroia sa ma atraga pe o pozitie de team leader exact pe ceva “embeded” si le-am multumit frumos. Prefer creeativitatea si complexitatea specifica aplicatiilor ptr. PC.

Eu sper ca de fapt aia vroiau sa-l atraga pe Silviu intr-un beci la marginea orasului unde sa-i arate tot felul de pozitii si obiecte emdeduibile in cur. Altfel vreau sa-i cunosc, in primul rind ca sa nu-mi iau vreodata cuptor cu microunde programat de ei si in al doilea rind ca sa le ofer gratuit un abonament gold la RSS-ul site-ului nostru.

Silviu, mopul e la tine. Speram sa nu te dezminti nici de data asta si sa stergi macar “mica scapare” cu operatorul %. Adevaratul test de creativitate va fi insa la aia cu siguranta craparii, ca pe-acolo nu prea vad cum ai putea spala rusinea fara ajutorul mentorului tau (“few cosmetics”, sau?). Sper ca vei opta pentru o explicatie tehnica, cu cuvintele tale, a modului in care functioneaza functiile variadice si mintea minerului. Asta m-ar bucura cu adevarat.

Fig. 1: Silviu propune, codexpertii dau cu mopu'

 

PS: Avind in vedere ca am ris deja de multiple ori de faptul ca multinationala emblematica nu te-a mai dorit asa de tare cum o doreai tu pe ea, poti sa-ti actualizezi linkedin-ul ala, ca nu mai ai ce secret sa tii. In plus, ne-au zis noii tai colegi ca se intreaba daca ti-e rusine cu alegerea facuta, de nu vrei sa o impartasesti public, tu care in rest esti un om asa de deschis.

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