Claudio Brotto

marzo 2005 - Posts

Ode alle Annotated References

Prendo spunto da questo post, in cui Brad Abrams annuncia il completamento del vol.2 della Standard Library Annotated Reference (no, non mi paga la Amazon per tutte queste segnalazioni editoriali !), per esporre il mio punto di vista su questo "genere letterario" rappresentato dalle annotated references.

Mi piace !! Anche se un paio di asterischi ce li metto (e non sia mai che riesca a concludere un giudizio in due parole ...).

Studiare, o semplicemente leggere, le specifiche non è esattamente l'attività più semplice e diretta, almeno dal punto di vista dell'apprendimento. Proprio perchè esse sono, appunto, specifiche, e i requisiti sono necessariamente differenti da quelli di un volume divulgativo, per quanto di riferimento questo possa essere. 

Molto dipende dall'attitudine personale, questo è chiaro: conosco persone che si trovano meglio a leggere un'enciclopedia che un romanzo, a testimonianza del fatto che l'efficacia di una forma di divulgazione è difficilmente valutabile in termini assoluti, data la disomogeneità del pubblico al quale essa si rivolge.

Le annotated references, in questo contesto, credo siano un valido punto di unione delle due metodologie di esposizione. 

Reference sono, reference restano - tanto è vero che generalmente le annotazioni vengono evidenziate come tali in maniera piuttosto chiara, almeno dal punto di vista tipografico.

D'altro canto, se gli annotatori compiono un buon lavoro, spesso si riesce a creare l'amalgama che in un testo di specifiche a volte manca. Le note a margine possono aggiungere struttura, oltre che contenuto , al testo al quale si riferiscono, e in questo senso rappresentano un modo di avvicinare un volume di riferimento ad un volume di esposizione più ... narrata.

Spero che il v2 delle SLAR confermi questa mia opinione, che il v1 e il CLI a.r. di Jim Miller hanno contribuito a creare.

powered by IMHO 1.2

C# standard in Giappone

In questo post di Scott Wiltamuth si legge che C# è stato accettato come standard dal consorzio JIS (Japanese Industrial Standard).

Le mie domande/curiosità sono:

  • Il fatto che non esista UN SOLO ente di standardizzazione è solo una questione politica (che so, il governo tale accetta software sviluppato sulla piattaforma talaltra e si affida solo all'ente talaltroancora) ?
  • Ci sono differenze nelle metodologie di uno piuttosto che dell'altro ?
  • Ci sono relazioni tra di essi (per esempio una "cosa" può venire standardizzata da un ente solo se è già stata standardizzata da un altro) ?

powered by IMHO 1.2

Posted: mar 28 2005, 10.40 by devlizard
Filed under:
System.Variant

In un'annotazione a proposito di System.Convert, riportata in questo post di Brad Abrams dal volume .NET Standard Library Annotated Reference Vol. 1, Anders Hejlsberg ricorda che ai primordi dello sviluppo della piattaforma .NET esisteva il tipo System.Variant:

... System.Variant was basically a managed wrapper for OLE Automation variants ...

Non avendo avuto modo (o tempo, o voglia ?) di utilizzare le versioni preliminari del .NET Framework, non sospettavo dell'esistenza di questo tipo.

All'epoca ero praticamente ogni giorno alle prese con ADO/COM e con le amenità dei tipi OleAutomation e dei loro innumerevoli wrapper.

Erano le mie prime esperienze nel campo della programmazione, e una cosa che proprio non capivo era perchè una buona percentuale del mio codice fosse dedicata a convertire un LPCTSTR in CString in BSTR in _bstr_t in CComBstr in VARIANT in _variant_t, nelle varie combinazioni possibili e con l'ausilio di ogni tipo di macro o metodo di un wrapper.

Non ho la minima idea di come si comportasse il tipo System.Variant e di come fossero implementate le conversioni, ma vi assicuro che il solo aver sentito parlare ancora una volta di VARIANT mi ha fatto correre un brivido lungo la schiena, così come l'aver letto che questo tipo è stato ucciso nella culla mi ha fatto sentire subito meglio :-)

powered by IMHO 1.2

Posted: mar 28 2005, 10.40 by devlizard
Filed under:
70-300. Considerazioni

Come anticipato ieri, eccomi a scrivere un po' di commenti sull'esame 70-300 (Analyzing Requirements and Defining Microsoft .NET Solution Architectures), che ho sostenuto venerdì.

Ho passato la scorsa settimana a tempo pieno (e le due precedenti a spizzichi) dedicandomi alla preparazione. Seguendo, anche, i consigli che mi sono stati dati, ho finito di leggere il volume di preparazione (questo) e ho ordinato e letto quest'altro da Amazon.

Alla fine della fiera, il commento breve è: "Potevo leggermi Topolino, e il risultato non sarebbe cambiato di molto".

Il commento lungo, invece, recita: "Sono state letture molto utili per la mia preparazione."

La disparità è presto spiegata.

Al solo scopo di superare l'esame, sono state ben poche le informazioni che ho ricavato dalla studio.

In un paio di domande ho risposto con maggior sicurezza (non chiedetemi quali ... ho sottoscritto un NDA !), e nulla più. Non posso che confermare quello che mi era stato detto: esperienza e buon senso sono la chiave per passarlo.  

Intendendo la preparazione in senso un po' più generale, invece, cioè come attività non esclusivamente finalizzata al superamento di un test, devo dire che le cose cambiano, e non di poco.

Esco da tre settimane di studio con un'opinione molto diversa su alcuni aspetti.

Punto Uno: ho rivalutato UML.

Purtroppo ne avevo (e ne ho tuttora, anche se adesso va un po' meglio) una conoscenza raffazzonata e decisamente poco organica. Impossibile, quindi, capirne le potenzialità, al di là di qualche effetto grafico. Lo giudicavo, evidentemente, in modo non proprio corretto. Non vengo a dire ora che UML è la soluzione di tutti i mali, ci mancherebbe ! Semplicemente credo che, adeguatamente studiato e capito, si possa rivelare un ottimo compagno nella fase di analisi e di progettazione.

Personalmente, sono un po' meno convinto riguardo alle funzionalità di forward-engineering da un diagramma UML. Una volta preparato lo schema di un'applicazione (o di un componente ...) non credo sia molto il risparmio di tempo (almeno per progetti relativamente piccoli), anche perchè inevitabilmente qualche modifica al codice auto-generato andrà fatta. Non dò un giudizio definitivo perchè non ho avuto modo di provare questa funzionalità in prima persona (devo decidermi a passare a MSDN Universal !), quindi aspetto di essere smentito.

Punto due: ho fatto il mio primo incontro serio con MSF, e non mi è dispiaciuto per niente.

Il primo approccio è stato un po' difficile, perchè mi aspettavo qualcosa di molto più concreto. In realtà questa valutazione dipendeva da un mio modo, errato, di affrontare l'argomento.

Fondamentalmente cercavo qualcosa del tipo: "Usa COM+ se (a), (b) e (c), usa i WS se (d) o (f), ecc...". O, più in generale, mi aspettavo qualcosa di molto più vicino alla tecnologia di implementazione.

Invece ho letto con interesse di problematiche che avevo sempre considerato estranee al processo di sviluppo. Il che può ancora essere vero, se cambio lo scope che dò al termine sviluppo ! Detto in altri termini, ho avuto modo di vedere in un'altra ottica le attività di analisi e progettazione di un sistema software che, anche a causa dell'esperienza raccolta finora, avevo relegato dentro un calderone informe.

Punto tre: ho fatto amicizia con Visio, finalmente !

Punto quattro, nonchè somma e riassunto dei punti precedenti: sono ritornato sulle mie opionioni riguardo la "bellezza" dell'essere architetto.

Lasciamo da parte il fatto che il termine è piuttosto generico ed infinitamente abusato. 

Quello che intendo è che ho intravisto, per quel che si può fare da alcune (centinaia di) pagine di libro, diversi aspetti legati all'attività di analisi e progettazione software che mi hanno stimolato parecchio.

Se, poi, questa opinione trovi conferma in qualche caso reale, beh ... non può che essere una speranza. Speranza che, per ora, mi tengo ben stretta.

Detto questo, mi godo i miei 4/5 di MCSD ... e vi rifaccio ancora una volta gli auguri di buone feste !

powered by IMHO 1.2

300 Auguri di Buona Pasqua

Post numero 100, breve e conciso (ma con follow-up più dettagliato a venire), per dire che:

Ho passato l'esame (70-300) !

Ora scappo (week-end lungo, nonostante il meteo non invogli alle scampagnate) ... 

... giusto il tempo per fare a tutti gli auguri di Buona Pasqua !

powered by IMHO 1.2

PM@MS

Vi siete mai chiesti cosa fa un PM in Microsoft ?

Kit George descrive quali sono le attività di un BCL Program Manager.

powered by IMHO 1.2

.NET Framework 2.0 Beta 2 Obsolete APIs

Per chi ha iniziato a giocare con le varie release preliminari del .NET Framework 2.0, questo link è di sicuro interesse.

Contiene, infatti, una lista delle API che (cito testualmente):

... were added during the beta cycles of the V2.0 product lifetime, but as a result of design changes and/or product feedback, have subsequently been replaced, or will simply be removed. ...

Fonte: questo post di Brad Abrams.

powered by IMHO 1.2

Posted: mar 21 2005, 07.39 by devlizard
Filed under:
SharpTools VS Plugin

Un RSS Aggregator che si integra con l'IDE di VS.NET.

Accidenti, neanche più i blog si possono leggere in pausa dal lavoro ?

Qui la fonte.

powered by IMHO 1.2

Leggibilità del Codice

Riporto qui il link che Adrian Florea ha segnalato come commento al mio post di ieri, che riguardava la notazione "not not".

Lungo tutto il thread si sviluppa una discussione interessante che coinvolge anche il concetto di leggibilità del codice.

Mi ha colpito la frase di Addy Santo che trascrivo qui sotto:

When training new developers I always try to pound several basic rules into their brains, one of them being: "Always assume that the person who will be tasked with maintaining your code is a psychopathic killer who knows where you live." 

Un'altra nota da appendere al muro !

powered by IMHO 1.2

Posted: mar 20 2005, 04.59 by devlizard
Filed under:
Notazione curiosa nella C-Runtime Library

Sono capitato più o meno casualmente di fronte alla funzione check_managed_app  della libreria run-time C, deputata a verificare se l'immagine eseguibile caricata sia o meno un'applicazione managed valida.

La funzione è definita come:

static int __cdecl check_managed_app(void) {...}

e il suo valore di ritorno viene memorizzato in una variabile locale a mainCRTStartup. Tale variabile (managedapp) è utilizzata nel prosequio della funzione in un paio di occasioni, tramite codice come quello che segue:

if (!managedapp) {...}

Il codice "incriminato" è il seguente (file crt0.c, riga 399):

return !! pNTHeader32->
          DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].
          VirtualAddress;

Questo snippet di codice verifica che il campo VirtualAddress della struttura _IMAGE_DATA_DIRECTORY a cui si riferisce pNTHeader32 ->DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR] sia diverso da zero. Se il valore è diverso da zero, l'applicazione è managed.

A parte il metodo utilizzato per la verifica, quello che mi ha colpito è la notazione "!!".

Perchè utilizzare un doppio not ? Dal momento che uno degli assiomi dell'algebra booleana recita (più o meno): "not (not (a)) = a"  ?

La spiegazione che mi dò è la seguente.

In C è considerato true qualsiasi valore numerico diverso da zero.

Ecco perchè, per inciso, è perfettamente lecito, e piuttosto frequente, trovare codice come:

if (! pPuntatoreAQualcosa) {
  
// Non provo nemmeno a dereferenziare un puntatore nullo !  
  // ...
else {
  
// ... ammesso, e non concesso, che un puntatore non nullo sia effettivamente valido ! 
}

Ad un primo esame, mi sembrava più naturale scrivere semplicemente:

return pNTHeader32 ->
       DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].
       VirtualAddress;

eliminando la doppia negazione.

Ma andando ad esaminare il codice macchina generato dal compilatore, la differenza risulta evidente.

[Disclaimer.: Ho dovuto rispolverare le mie già scarse conoscenze di assembler, spero di non aver preso qualche abbaglio !]

Senza la doppia negazione, l'output del compilatore sarebbe stato (ho fatto qualche test con una struttura fatta a mano, più semplice ma funzionalmente analoga):

mov eax,dword ptr [pNTHeader32] ; carica nel registro eax l'indirizzo di memoria a cui 
                                
; punta pNTHeader32
mov eax,dword ptr [eax+0D0h]    ; carica 
in eax il valore contenuto nel campo richiesto, 
                                ; calcolato come offset rispetto all
'indirizzo base della struttura

Poichè nella convenzione di chiamata utilizzata (cdecl) il valore di ritorno di una funzione è passato al chiamante nel registro EAX, tutto chiò che serve è copiare in tale registro il valore del campo richiesto (pNTHeader32 ->DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].VirtualAddress ).

E'ovvio che, se il campo contiene il valore 123, tale sarà il valore di ritorno della funzione. Nelle istruzioni decisionali, il valore è considerato  true, e la cosa funziona.

Con la doppia negazione, invece, il compilatore genera il seguente codice macchina:

mov         eax,dword ptr [pNTHeader32]
xor         ecx,ecx 
cmp         dword ptr [eax+0D0h],0 
setne       cl
   
mov         eax,ecx

In pratica, il valore del campo interessato viene confrontato con la costante 0, e il registro EAX (per via indiretta) viene settato a 1 se il confronto fallisce, cioè se pNTHeader32 ->DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].VirtualAddress è diverso da zero .

Il codice:

return (pNTHeader32 ->
       DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].
       VirtualAddress != 0);

genera, infatti, lo stesso codice x86.

Il contro della soluzione scelta credo siala maggiore occupazione di spazio da parte del codice e la leggera pessimizzazione. Ma si parla di pochi byte e di nanosecondi in una funzione che viene eseguita una volta sola, all'avvio dell'applicazione !!!

Il pro, a mio parere, è una maggiore "debuggabilità" della funzione, che deriva dall'aver forzato i valori true ad 1, cosa non espressamente richiesta dal linguaggio C.

Se volete la mia opinione, fatta salva la scelta di forzare i valori true a 1, sarebbe stato più leggibile un codice che avesse effettuato il confronto esplicito con zero (come quello scritto sopra), dato anche che l'assembler generato risulta perfettamente identico.

O forse è semplicemente una convenzione sintattica che non conoscevo per niente, e mi risulta meno naturale da leggere, oltre ad avermi fatto passare mezza mattinata ad indagarne il funzionamento !

powered by IMHO 1.2

Posted: mar 19 2005, 12.55 by devlizard | with 3 comment(s)
Filed under:
Top3 Download

Questo sembra un periodo molto attivo quanto a nuove release software.

Spulciando i feed in giro per la rete, elenco i seguenti:

Essendo sempre senza collegamento ADSL (sob), credo che per ora mi limiterò ad Opera.

Anche perchè sono sempre alla ricerca del browser.

In attesa di IE7, e non volendo rinunciare a funzionalità che trovo indispensabili, almeno per la mia abitudine di utilizzo, come il tabbed browsing, ho usato per un periodo Firefox. Molto ben fatto, molto veloce, molto personalizzabile, anche molto sicuro (dicono), però purtroppo non visualizza correttamente alcuni siti che visito con discreta frequenza.

Ho installato e disinstallato nel giro di poche ore Netscape, che era un po' troppo instabile e avido di risorse in questa versione (beta).

Sto usando da alcuni mesi Avant Browser, che, devo dire, non mi dispiace per nulla.

Ma sono ancora in attesa ...

powered by IMHO 1.2

Nuovo Feed nella mia Lista

Quello di Mark Russinovich. 

Ad oggi ha scritto alcuni post sui motori di desktop search ... a quando la rivelazione di qualche oscuro particolare del kernel di Windows ?

powered by IMHO 1.2

Ascoltare musica e scrivere software

Da quando scrivo software, per hobby o per lavoro, ho un rapporto con la musica piuttosto variabile.

All'inizio ero abituato a preparare una playlist più o meno tranquilla e più o meno lunga, far partire WinAmp e iniziare a programmare con le cuffie in testa (sul luogo di lavoro, per lo meno).

Nell'ultimo periodo questa abitudine è andata progressivamente scemando, salvo le dovute eccezioni.

Dipende molto dal tipo di sviluppo che sto facendo.

Per esempio, se devo disegnare il layout di una finestra, magari anche complessa e piena zeppa di controlli, ecco, quello è un momento candidato all'ascolto di musica.

Perchè è un'attività semplice e ripetitiva: posizionare i controlli in modo corretto, dare ad ogni elemento della UI un nome più significativo che button1, preparare gli handler che mi servono, inserire un po' di commenti e dare al codice una forma che maggiormente si adatti alle mie convenzioni, e via dicendo.

Se l'attività, invece, è più complessa, abitualmente metto in pausa il player. Perchè mi serve una concentrazione maggiore che la musica, per quanto distensiva, tende a distogliere.

Infine c'è l'attività più complicata: progettare la struttura di un'applicazione. Nei casi semplici, ovviamente, dove la fase di progetto si può ridurre ad un paio d'ore di disegnini e mock-up.

Lì, evidentemente, la mia concentrazione supera la distrazione della musica. Non avvio WinAmp appositamente, ma neanche lo spengo, se è in esecuzione.

Semplicemente, non ascolto.

Poco importa se sta riproducendo un pezzo New Age o Heavy Metal, perchè in quell'occasione la musica è assimilabile ad un rumore di fondo. Con infinite scuse per chi la musica l'ha scritta, e bene magari. E' solo il mio modo di percepirla che cambia.

Generalmente, in queste occasioni non ricordo in modo conscio che cosa ho ascoltato. Salvo, poi, avere un motivo che mi suona nella testa per il resto della giornata.

Ho fatto così ieri con i Litfiba - una band che adoro - e mi sembra di averli ascoltati per ore a ripetizione.

Adesso ci sto riprovando, e l'effetto è radicalmente diverso.

 

"... colorando il nero dell'orizzonte ... "

[Listening to , Litfiba - Ballata - Live at Gimmi's (Rare Acoustic), 04.15]

powered by IMHO 1.2

15 post da leggere

Larry Osterman ha concluso alcuni giorni fa la sua sa serie di post sulla programmazione concorrente.

Una serie davvero molto interessante ed istruttiva: al di là dei suoi "principles of concurrent programming", che vengono riassunti nell'ultimo post, ci sono diversi spunti di riflessione e, almeno per quel che mi riguarda, di studio.

Per esempio mi sono annotato un ripasso del Richter, sezione "Gestione Memoria", capitolo "Heap".

Come illustrato nel post # 11, l'allocazione di memoria da uno heap può essere o meno serializzata, e questo dipende dai flag di creazione dello heap stesso.

A meno di non utilizzare uno heap apposito, questo codice C++:

CSomeClass* pSomeClass = new CSomeClass;

richiede i servizi dello heap primario del processo, che è serializzato. Ogni allocazione (e deallocazione) comporta l'acquisizione e il rilascio di una sezione critica, al fine di garantire la consistenza della struttura dello heap stesso.

Ovviamente se abbiamo la certezza assoluta che un solo thread alla volta possa utilizzare lo heap, nulla ci vieta di crearne uno ad-hoc rinunciando alla funzionalità di serializzazione delle allocazioni, e di sovrascrivere l'operatore new di una classe in modo che gli oggetti relativi non vengano allocati nello heap principale, ma in quello che abbiamo creato allo scopo.

Non c'è dubbio che queste siano ottimizzazioni abbastanza ... spinte, che diventano trascurabili se poi, magari, il nostro software accede al disco in modo pessimizzato.

Ma vale comunque la pena di sapere che cosa succede, non fosse altro per la curiosità di scavare nei meccanismi del sistema.

powered by IMHO 1.2

Posted: mar 16 2005, 03.43 by devlizard
Filed under:
15 post da leggere: digging deeper

Una nota che dovremmo appenderci sul muro, secondo me, è che per fare ottimizzazione (se volete, per rendere un'applicazione veloce, scalabile e poco assetata di risorse) è fondamentale conoscere in profondità il sistema con il quale abbiamo a che fare.

In fin dei conti una buona percentuale del software che scriviamo richiama, in via diretta o indiretta, una API del sistema operativo.

Se apriamo il Task Manager e osserviamo il tempo che il nostro programma trascorre in modalità kernel, ci possiamo rendere conto che avvengono tante (ma tante !) cose sotto il nostro naso. Capire che cosa succede, al di là dell'interesse didattico o della curiosità, è un buon punto di partenza per capire come mai non funziona !

Questo non vuole essere un argomento contro i "framework" che nascondono il vero funzionamento di un sistema.

Innanzitutto perchè lo scopo non è mai quello di nascondere la realtà. Non dovrebbe, per lo meno !

Secondariamente perchè un ambiente di esecuzione porta con sè una serie di servizi, a volte imprescindibili.

Si può discutere se il meccanismo di garbage collection sia rivolto esclusivamente a ridurre il plumbing o comporti anche miglioramenti prestazionali. Ma credo che questioni come type-safety e sicurezza del codice non si possano certo catalogare come "semplificazione per astrazione".

Il punto è che, man mano che il livello di astrazione si alza, le fondamenta su cui costruiamo sono sempre più distanti dal terreno, che in fin dei conti è fatto da tante centinaia di migliaia di transistor (o addirittura, se vogliamo, dalle leggi della fisica dello stato solido).

Quando il nostro giovane programmatore scriveva listati in Assembler, a parte il mal di stomaco che si portava a casa, aveva un controllo molto maggiore sulla macchina.

O meglio, molto più esplicito.

Oggi quel controllo si esprime sotto forma di estrema comprensione dei meccanismi del sistema e dell'interfaccia che abbiamo a disposizione per controllarli.

powered by IMHO 1.2

Posted: mar 16 2005, 03.43 by devlizard
Filed under:
More Posts Next page »