February 2007 - Posts
Ogni tanto mi viene voglia di qualcosa di "vintage" e vado a finire nei meandri di wikipedia a leggermi un po' di storia dell'informatica.
Con particolare predilezione, devo dire, per le cose cadute in disuso :-)
Non necessariamente poco importanti, semplicemente non più usate in quanto tali: magari sopravvissute e riemerse come "idea" dietro la nuova, fiammante feature dell'ultimo linguaggio di programmazione.
Una menzione particolare, però, mi tocca farla per CLU.
Due ragioni dietro questo link.
Uno (scusate il copia e incolla secco dalla fonte):
- Python and Ruby borrowed several concepts from CLU (for example, the yield statement and multiple assignment)
- CLU, along with Ada were major inspirations for C++ templates;
- CLU's exception handling mechanisms also influenced newer languages like Java and C++.
- All objects in a CLU program live in the heap, and memory management is automatic. Directly influenced Java.
- Python and C# include generators (iterators in C#), which first appeared in CLU as iterators
Due, che in effetti è ciò che mi porta a parlarne: clu è il mio soprannome :-)
Uno dei tanti, in realtà ... gli altri ve li risparmio per amor proprio.
Insomma, sono parte della storia dei linguaggi di programmazione, oltre che della computer graphic !
Mi sembra strano riuscire a fare una cosa in anticipo di *ben 5 giorni* sulla scadenza dell'early bird. Eppure :-)
Ci si vede là ?
"Studio" forse non è il termine corretto, dal momento che presuppone un minimo di metodo e, magari, di programma.
"Lettura" neanche, perchè onestamente mettere sotto la stessa categoria un romanzo con un articolo MSDN ... mmmhhh ...
Diciamo "quella cosa che si fa quando si ritaglia un po' di tempo da dedicare all'aggiornamento delle proprie conoscenze".
Io di solito ho due strade.
Uno: apro un libro e leggo. Tendenzialmente questo mi dà un minimo di linea didattica.
Due: apro il browser (aggregator, newsreader, ...) e leggo. Tendenzialmente questo mi porta alla più totale perdita di orientamento. Mi sento un po' "spaghetti reader": circonvoluto anzichè no, si sa dove parto ma per certo non dove arrivo.
Che poi se volete sta tutto nella differenza fra testo e ipertesto (e qui chiudo :-)).
Curioso il giro che ho fatto stasera: stavo facendo qualche prova con Orcas, con il buon Reflector a portata di shortcut. Finisco a riguardarmi l'implementazione degli anonymous methods in C# (quello che fa il compilatore dietro le quinte). Capito su questo post di Yves Dolce, nulla di particolare ma già che ci sono spulcio un po' e capito sul blog di Ben Karas, e qui mi fermo a leggere per un po' codice COM e a farmi venire i brividi al ricordo dei 172 tipi diversi per rappresentare una stringa.
Al di là del giro di link che ho fatto, pensavo ad una cosa.
Molto empiricamente, divido il mio "tempo libero" (quello in cui non si lavora, e qui chiudo di nuovo) fra tecnologie future (Orcas, appunto), tecnologie presenti (C# 2.0 e anon methods, appunto) e tecnologie passate (COM, BSTR, smart pointers, appunto). Devo dire anche piuttosto equamente suddivise.
Le "beta" si guardano perchè sono ciò che avremo domani, perchè in fondo è bello cercare (risucirci è impossibile) di stare al passo coi tempi, perchè si è curiosi ...
Le tecnologie attuali le guardo perchè bene o male ci lavoro su. E ovviamente ci sono un bel po' di cose che non conosco in maniera sufficiente !
Quelle vecchie ... Sento una voce: "masochismo !"
Può darsi, però in certe cose mi appassiono ancora.
Non credo sia "nostalgia". Vi assicuro che di AddRef e Release non sento la minima mancanza. Tutt'altro.
Indubbiamente, in certi casi mi piace spulciare qualche dettaglio delle tecnologie che usavo ieri.
Il fatto è che, osservandole in maniera più distaccata (non devo cercare di capire quali diavolo di porte devo aprire per far comunicare due componenti via DCOM) ne apprezzo maggiormente i pregi. Il C (senza il ++) è tuttora il mio linguaggio di programmazione preferito. In parte credo che questo giudizio sia dovuto al fatto che ... beh ... non lo uso più "in produzione" e quindi sono meno soggetto a tutti i suoi difetti !
Premetto che stamattina mi sono svegliato un po' di storto. Il che, rileggendo questo post, mi ha in effetti portato a buttar giù una marea di critiche a quello che considero un *grave* problema del mercato ICT attuale. Se la pensate diversamente da me ... beh, non posso che essere contento perchè sarebbe la riprova che invece, ogni tanto, le cose funzionano come si deve. Fine del disclaimer, dicendo che ovviamente "non si può fare di tutta l'erba un fascio".
Veniamo al dunque.
Una serie di avvenimenti (personali/professionali) e un'interessante discussione con un cliente, la settimana scorsa, mi hanno fatto pensare alla figura del "Consulente SAP Junior".
Siamo d'accordo che è un ossimoro ?
Provate a seguire questa logica. Secondo me non fa una piega, ma evidentemente è smentita dai fatti, ed è questo che mi fa in*°#ò§re.
Prodotti come SAP (R3), WebSphere, Axapta, ... insomma, metteteci qualsiasi piattaforma applicativa/applicazione che costi un occhio della testa. Nell'ordine di grandezza delle centinaia di migliaia di euro (discutevo sul licensing di WebSphere, ho qualche informazione su installazioni SAP di un certo livello, si arriva tranquillamente sui *milioni* di euro).
Tendenzialmente una azienda in grado di investire cifre simili per rispondere ad un'esigenza interna ha fatto una scelta molto semplice (togliete qualsiasi questione "politica" o surrogati della stessa).
Devo risolvere questo problema: .......
Sul mercato ci sono queste soluzioni: ....... + soluzioni custom / home-made ecc..
Adottando SAP ho un ROI che è, in fin dei conti, il migliore (questo "conto" è complicato ! ma non è il punto di questo post :-).
Compro SAP.
Ora, SAP non è Office, doppio click sul setup e pronti all'uso, magari dopo la lettura di un buon manuale o (meglio) dopo un breve corso di formazione del personale che lo andrà ad utilizzare.
Quindi "compro SAP" vuol dire: prendo contatti con i rivenditori, discuto ed acquisto le licenze ed, infine, cerco le competenze per poter "implementare" SAP.
Se fossi l'AD di un'azienda che ha speso 1M$ per acquistare il prodotto, e se non avessi le competenze in casa, non avrei problemi ad investire su consulenti senior, che costano molto di più ma garantiscono, anche, un risultato migliore (a volte semplicemente garantiscono il risultato !). Fa parte del cosiddetto "TCO" della soluzione, sicuramente ne ho tenuto conto in fase di scelta, no ?
Sono disposto a pagare perchè voglio la cosa funzionante. Dove cerco un consulente SAP esperto ?
Esistono, ovviamente, società che su questo hanno basato il proprio business. Magari assumendo personale junior, prendendosi carico della formazione (imparare SAP non è esattamente imparare Javascript, per lo meno sono due piani completamente differenti), affiancando le persone meno esperte a quelle più esperte ...
Società che però danno una garanzia ai clienti.
Il cliente si fida perchè la società ha un nome, un passato, un'esperienza, delle referenze. Ha portato a termine progetti complessi per realtà grandi rispettando gli accordi e con la soddisfazione del cliente. E queste cose si sanno !
Esistono anche società di consulenza (e qui, scusate, ma sta la mia polemica) che sono completamente "ignoranti e cieche" dal punto di vista tecnico (rimanendo dal lato "passivo" della cosa ... quello attivo si traduce in "scorrette e truffaldine").
Società che magari vedono quanto è bello il prodotto (ed *è* bello, magari, e di nuovo non è questo il punto).
Società che scoprono che un consulente SAP lo possono vendere a 100 e pagare 5 (i numeri non hanno unità di misura ma l'ordine di grandezza è *reale*).
Ecco trovato il business.
Peccato che 5 puoi pagarli a uno stagista, ad un apprendista appena entrato nel mondo del lavoro, a un junior, insomma.
Ed ecco nascere la figura del consulente SAP junior.
Che viene "venduto" come senior, e a prezzi aggressivi rispetto ai consulenti senior "veri", prezzi che sono possibili solo perchè cambiano enormemente i costi.
E i costi cambiano perchè cambiano le competenze. Legge di mercato.
Quindi io, AD di un'azienda che ha comprato SAP, ma che questa volta non sono abbastanza accorto nella scelta dei collaboratori, trovo questa società che fornisce consulenti a 100 invece che a 400 e ... beh ... la chiamo.
Se il mio ragionamento finora fila, quello che si ottiene è:
- Ho scelto consulenti senior da una società nota, che se li fa pagare. Spendo quello che devo spendere, ma il mio sistema funziona.
- Ho scelto consulenti junior, vestiti da senior, e li ho pagati poco (in proporzione). Il mio sistema non funziona.
E, di consenguenza:
- Le mie referenze nei confronti della società di consulenza saranno ottime. E visto che "io" sono una società grossa, sono referenze che pesano.
- Mi pento e mi maledico per la scelta, d'altra parte sono alle strette: mi rivolgo ad una società seria, e nel mentre cerco di distruggere la società non seria, con bombe atomiche o semplicemente facendo pesare la mia voce negativa.
Quindi, infine:
- La società seria guadagna, fattura ed acquista man mano credibilità sul mercato
- La società poco seria fallisce dopo 2 giorni.
Correggetemi se ho sbagliato l'analisi.
Cosa che deve essere successa, perchè conosco (per via più o meno diretta) un paio di società "poco serie" che continuano a lavorare male proprio nei termini che ho descritto, che hanno un rapporto pessimo con i dipendenti (e come potrebbe essere altrimenti) e, tuttavia, sono perfettamente vive e vegete.
Il perchè, scusate, ma proprio non riesco a capirlo :-(
Mi aggancio ad una discussione avuta durante l'ultimo corso sulle potenzialità di prorammazione asincrona in Javascript.
A partire dalla "A" di Ajax, ovviamente :-)
Segnalo a questo proposito questo post su LambdaTheUltimate, che rimanda a sua volta ad un paio di post/discussioni piuttosto interessanti, ad una prima visione.
Il tema è abbastanza complesso e ho letto il post solo ora ... E' nella mia lista di "review", ci darò un'occhiata più approfondita però !
La *musica*, per come la vivo io, è paragonabile ad una droga. Amplifica le sensazioni. Frantuma i vincoli che la professione o la società impongono. E' così che succede: argomenti oscuri diventano d'improvviso estremamente chiari, almeno fino al termine della traccia ...
p.s. Chi riconosce la citazione del titolo del post ?
p.p.s. Come ? Ah ... ok ... torno a scrivere codice :-)

Su TheServerSide.NET, un ... "indice" con alcune risorse utili a chi vuole scoprire o approfondire l'argomento LINQ.
Source: LINQ/C# Learning Guide
Discussione interessante, di cui riporto la chiusura:
I'm increasingly beginning to think that the established best practice is waning, and that a new best practice will emerge. What exactly that new best practice will be, I don't know yet, but it's going to be interesting to find out!
Source: How Will LINQ Impact Database Development Best Practices?
Sono sempre più curioso di ascoltare la sessione di Marco e Paolo a DevCon :)
Violo un po' la regola di APPTXT prendendo spunto, questa volta, non dal solito file di appunti o da qualche mail di richiesta info, ma piuttosto dai commenti ricevuti al termine dell'ultimo corso (finito ieri, applicazioni distribuite in .NET 2.0).
Il suggerimento ("Maggior uso di UML") è di sicuro validissimo.
Ma *purtroppo* non sempre è applicabile.
Il motivo è semplice: non tutti conoscono UML.
Non so se, per una persona completamente digiuna di UML, l'utilizzo dello stesso come strumento di illustrazione (durante un corso comunque non architetturale) possa comportare un reale beneficio in termini di immediatezza di apprendimento.
In questo contesto si tratta, fondamentalmente, di trovare un mezzo di espressione (quindi di comunicazione) semplice, intuitivo e condiviso da tutti i partecipanti ad un corso. Non si parla della scelta di adozione di UML all'interno di un team di sviluppo ... non è la stessa cosa, per lo meno.
Tante volte, almeno per la mia esperienza, è stato più efficace scrivere "pseudocodice" alla lavagna che fare schemi (indipendentemente, peraltro, dal rispetto della notazione UML).
Spero di poter smentire la mia considerazione precedente ... e in ogni caso nelle prossime occasioni, tra le domande iniziali con cui cerco di inquadrare la classe, sì sì ...
buona idea ;-)
Ieri sera ho (finalmente) iniziato a leggere uno dei tanti libri che ho nella mia personalissima coda di attesa.
Il libro è Essential Windows Workflow Foundation di Dharma Shukla e Bob Schmidt.
Lo segnalo volentieri, anche se chiaramente il giudizio non può essere completo nè esaustivo, per una ragione ben precisa. Che va al di là del contenuto (anzi, se vogliamo col contenuto proprio *non c'entra*, per lo meno non è il cuore del discorso). Mi ha realmente colpito l'approccio.
Da che seguo il mondo dell'informatica ho letto una marea di libri. Non per questo mi considero un valido reviewer, però diciamo che almeno la quantità mi consente di stilare qualche classifica. Personale e opinabile, se vogliamo, ma sempre classifica è :-)
Chi sta nella mia top ten può essere argomento per un altro post. Quello che mi ha fatto riflettere, nel pensarci su, è piuttosto il metro che sto utilizzando per una valutazione così difficile.
Volete la mia regoletta in due parole?
Stanno in cima i libri che mi hanno cambiato.
Per cambiamento intendo, soprattutto, l'apertura a nuovi modi di pensare alle cose (vogliamo chiamarli "prospettive" ?)
Vi porto due esempi, relativi allo stesso argomento. Due libri che nel loro genere credo siano definibili come *must read* e che, in ogni caso, sono universalmente considerati (e lo sono, secondo me) degli Ottimi testi, con la O maiuscola.
Jeffrey Richter (Applied Ms .NET Fx Programming, CLR via C# nella nuova edizione) e Don Box (Essential .NET Volume I, CLR).
Il Richter mi ha letteralmente insegnato .NET. L'ho letto molto presto, l'ho riletto un paio di anni dopo, ho letto (a pezzetti) la versione aggiornata al fx 2.0. Le mie 5 stellette su Amazon non gliele leva nessuno, e solo perchè non c'è spazio per la sesta.
Il libro di Don Box ... mi ha cambiato ! Il primo capitolo, il modo in cui viene introdotta la nascita della piattaforma .NET a partire dai limiti di COM, la discussione su MBR, Context Bound Objects, Proxy e AOP, insomma ...
Sono due testi molto diversi. Si sovrappongono per buona parte come contenuto, ma sono differenti nell'approccio.
Se volete applicarla, la mia regoletta da 4 soldi dice senza esitare: "Don Box, Don Box !".
Lo consiglierei a chi vuole imparare ? Sì, certo, ma non come prima scelta e non subito. Il Richter, dal mio punto di vista, è didatticamente più completo e meglio strutturato.
Devo però sceglierne uno da portare su un'isola deserta (ehmmm ... *non è* mutuamente esclusivo con una bella donna) ? Non avrei un secondo di dubbio.
Comunque ... visto che così avevo iniziato questo post, torno da capo per dire che EWWF, o per meglio dire il primo capitolo, nonchè l'unico che ho letto, beh ...
... complice una notte con poco sonno, complice l'entusiasmo per una tecnologia che mi appassiona (workflow), complice tutto ... ma quel primo capitolo sta cambiando il mio modo di vedere certe cose.
Ah, per inciso. Mica ve lo dico di cosa parla il primo capitolo. Vale la pensa scoprirlo :-)
Cambiamo radicalmente genere rispetto ai due ultimi "numeri".
Nessuna spiegazione sulla tecnologia, forse qualche consiglio sull'architettura.
Queste alcune domande che mi sono state poste in una mail:
- [Vorrei creare degli user control che]... dovranno anche accedere ai dati contenuti nei database. Problem: come si scambiano i dati il controllo con il database?
- Nella tua mail precedente mi suggerisci di non usare la tecnica DataSet per i dati ... (usando DataSet o se possibile altre tecniche) ... che altra tecnica dovrei usare ?
- Come interagiscono le Class Library basate sulle tabelle (e quindi sui campi delle stesse) con gli user control e quindi sui DataSet e come si relazionano con i databases?
Altrettanto, spulciando i miei appunti.txt, spesso ho inserito note riguardo le tematiche di accesso ai dati.
Bad News: qui non c'è risposta ...
Bad Bad News: non è detto che ci sia *la risposta* !
Il motivo è presto detto. Queste domande presuppongono la discussione di tematiche non prettamente tecniche stile Q&A. Come dicevo nel numero zero, non è "come si fa a creare una stringa di connessione" che viene toccato in questo caso. Piuttosto la scelta di una strategia di accesso ai dati.
"Mi suggerisci di non usare il DataSet, e allora cosa uso ?"
"Come si relazionano {controllo|classlibrary|...} con il database ?"
So già che una certa persona riderà (o forse mi tirerà un accidente da far cascare le montagne) ma, mi spiace, la risposta è "dipende". E non è la solita risposta per svicolare. Dipende veramente da una pletora di fattori.
Qualcosa, sì, si può anche ritenere valido in linea generale.
Non inserirei il codice di accesso al database (query, connessioni, ...) all'interno di un controllo utente. Perchè assegneremmo ad una parte della nostra applicazione (quella che si occupa della presentazizone della stessa all'utente, l'interfaccia grafica per dirla in due parole) una responsabilità che, almeno direttamente, non è sua.
Non userei i DataSet ... ma non è mica detto che in ogni applicazione siano richiesti quei requisiti (scalabiità. modularità, ...) che giustificano la rinuncia a tutte quelle funzionalità "così comode" che il DataSet utilizza ed eroga (supporto dal designer di VS su tutti).
Anche perchè, sarà banale, ma di tipologie di applicazioni ce n'è un pochetto !
La classica demo da mezz'oretta ("bisogna far vedere al cliente qualcosa, arriva stopomeriggio") e eBay (a proposito, fate un giro qui) hanno qualcosa in comune: accedono a dati.
In effetti hanno anche qualcosina di diverso: per esempio qualche centinaio di migliaia di utenti contemporaneamente connessi :)
Nella mia demo lo metto anche un controllo che fa login sul db prendendo userid e password dalla finestrella che viene visualizzata all'avvio ... basta ricordarsi che quel codice tendenizalmente *non deve* andare in produzione pena taglio del.....le mani.
Con queste considerazioni alla mano, forse quel "dipende" ha un po' più senso.
Ma allora il povero sviluppatore (col cappellino da architetto) come fa ??
Secondo me, dal momento che suo malgrado si ritrova costretto ad effettuare una scelta progettuale che può avere una portata e delle ripercussioni piuttosto importanti, conviene discutere, leggere, imparare ... semplicemente per poter affrontare un decisione con maggiore consapevolezza.
Ecco quindi qualche riferimento.
Dove, ripeto a forza di diventare rompiballe, non si trova *la soluzione*, ma di sicuro si trovano contenuti validi e giudizi competenti per capire quali sono i fattori da considerare nel *cercare la soluzione*.
Ecco qualche link:
Ok, discorso anche questo vecchio come il mondo.
Il tutto, usando come riferimento le domande che mi sono state fatte, parte spesso dalla descrizione del type system utilizzato dal CLR e dalla distinzione, fondamentale, fra reference e value type.
E' un argomento tanto fondamentale quanto, a volte, difficile da illustrare in maniera semplice. Soprattutto a chi ha poca dimestichezza con le "strutture di memoria" che vengono utilizzate durante l'esecuzione di un'applicazione (e non parlo solo di applicazioni .NET).
In questo post vorrei, appunto, cercare di descrivere "che cosa succede in memoria" nel momento in cui andiamo ad allocare oggetti di tipo reference.
Approccio "a bomba sul codice" ed ecco qua:
internal class ReferenceType
{
public Int32 Number;
public void WriteTheNumber() { System.Console.WriteLine(Number.ToString()); }
}
class Program
{
static void Main()
{
ReferenceType anObject;
anObject = new ReferenceType();
anObject.Number = 42;
anObject.WriteTheNumber();
}
}
Credo che il codice sia auto-esplicativo: abbiamo definito un tipo reference (ReferenceType) che contiene un campo pubblico intero Number; il codice chiamante (in questo caso il metodo statico Main) istanzia un oggetto di tipo ReferenceType e ne memorizza il riferimento nella variabile locale anObject. Infine accede ad un campo e ad un metodo di istanza.
Due righine di codice, ma alla fine abbiamo causato modifiche ad almeno 3 aree di memoria ben definite e distinte del processo in esecuzione.
Lo stack
Scrivendo
ReferenceType anObject;
abbiamo come minimo occupato sizeof(IntPtr) bytes in cima allo stack del thread chiamante.
Brevissimamente: ogni thread Win32 ha in dote dal sistema operativo un'area di memoria "tutta sua", lo stack del thread, grande (per default, si può cambiare) 1 Mb.
Quando definiamo una variabile locale (come nell'esempio) questa risiede, fisicamente, nello stack del thread chiamante.
Inoltre, una chiamata a funzione comporta la creazione, in cima allo stack, di un frame che consente di identificare la funzione in esecuzione e di ritornare al punto di chiamata al termine della stessa.
Quando la funzione ritorna, il frame viene "virtualmente" rimosso dalla cima dello stack. Virtualmente perchè in realtà non viene azzerata la memoria che questo ha occupato, ma più semplicemente viene "spostato indietro" il valore che indica la locazione di memoria della cima dello stack, il primo posto libero da utilizzare.
Corollario: ogni variabile locale, quindi ogni variabile dichiarata all'interno di un metodo, "muore" al termine di questo, ovverosia non è più raggiungibile una volta che il frame del metodo viene rimosso dallo stack.
Ritornando al nostro esempio e a quanto detto all'inizio, la prima istruzione del metodo Main implica la allocazione di sizeof(IntPtr) bytes nello stack.
Una precisazione, prima di concludere.
Con sizeof(IntPtr) intendo la dimensione, in bytes, di un puntatore, cioè di un indirizzo di memoria. Questo valore dipende dall'architettura per la quale l'applicazione viene compilata (in .NET, lo ricordo, stiamo parlando della compilazione Just In Time, che genera codice macchina per l'architettura di esecuzione).
Le piattaforme x86 (32 bit) hanno indirizzi di memoria da 4 bytes, le piattaforme a 64 bit hanno indirizzi di memoria da 8 bytes, e via dicendo.
Managed Heap
L'istruzione successiva
anObject = new ReferenceType();
è un filino più complessa, dietro le quinte.
Detta in breve, succedono tre cose.
Primo. Da "qualche parte" viene allocata un'area di memoria sufficiente a contenere l'oggetto anObject, di tipo ReferenceType.
Secondo. Viene richiamato il costruttore di ReferenceType, che "inizializza" l'oggetto.
Terzo. L'indirizzo di memoria dell'oggetto appena istanziato viene memorizzato nella variabile locale anObject, residente sullo stack.
Tre affermazioni, nessuna completa :(
Con ordine ...
Il "qualche parte" è un'area di memoria, ben distinta dallo stack dei thread (e pre inciso comune a tutti), chiamata, solitamente, managed heap o heap gestito.
Gestito = gestito dal Common Language Runtime, sia in fase di allocazione che in fase di rilascio della memoria (il famigerato Garbage Collector agisce qui).
Il CLR, quindi, si occupa personalmente (sorry ... forse non è il caso di dare del tu al CLR ?!) di realizzare il layout dell'oggetto in memoria, riservando lo spazio per tutte le sue ... cose.
Quali cose ?
Beh, in prima battuta, tutti i campi che prendono parte alla definizione del relativo tipo. In questo caso, semplicemente 4 byte per rappresentare il campo Number (Int32). Questi 4 byte risiedono, fisicamente, all'interno del managed heap.
E questi 4 bytes sono valorizzati nel momento in cui il costruttore del tipo ReferenceType viene invocato.
In IL, questo corrisponde all'istruzione newobj, che riceve come parametro un "identificatore" del metodo .ctor (nickname del costruttore di istanza), riserva spazio all'oggetto e infine invoca il .ctor, responsabile dell'inizializzazione dello stato dell'oggetto.
Nel nostro esempio il costruttore ... non c'è ! In realtà il compilatore C# (idem fa VB.NET) ne inserisce uno di default, senza parametri. Per default, inoltre, i campi vengono inizializzati a valori ... beh, i numerici a zero, i riferimenti a null, i boolean a false, ecc...
Detto questo, alla fine del punto secondo ci ritroviamo con un po' di memoria, all'interno del managed heap, riservata e inizializzata per l'oggetto anObject. Questa area di memoria, beh, *è* l'oggetto. Almeno in parte, come vedremo a breve.
Il codice chiamante (e veniamo al punto 3) ottiene quindi un riferimento a quell'area di memoria (un puntatore, se volete).
E tramite quel riferimento è in grado di utilizzare l'oggetto.
Accedendo ai suoi campi (fatti salvi i vari modificatori di accessibilità) e, magari, invocando i suoi metodi.
Metodi .... mmmhhh ... non manca qualcosa, quindi ?
Dove stanno i metodi ? Le proprietà ? Insomma, da che OOP è OOP ci hanno insegnato che un oggetto contiene "both attributes and behaviour". Attributes, qui, ci sono. Behaviour, mica tanto. Insomma ... una classe (un tipo) non è solo una sequenza di campi !
Visto dove risiedono i campi in memoria, tempo di passare al terzo, conclusivo paragrafo. E di chiudere il cerchio.
CLR Heaps
Il concetto di tipo è assolutamente basilare nell'architettura del CLR.
Un tipo è completamente descritto dai suoi metadati.
A bocce ferme, possiamo prendere un assembly .NET e ispezionarlo (vedi anche APPTXT#1). Tanto noi, quanto i vari tool (XSD.exe, SOAPSUDS.exe, REGSVCS.exe, TLBEXP.exe ... e la lista potrebbe continuare a lungo).
A bocce in movimento (leggi: a runtime) le stesse informazioni sono ovviamente disponibili. Ma è chiaro che non è pensabile che il CLR effettui un I/O su disco ogni volta che deve avere informazioni su un tipo.
E infatti ...
Il CLR "possiede" diverse aree di memoria all'interno del processo host. Aventi scopi differenti, magari, ma comunque tutte deputate a garantire il funzionamento di una (o più)delle sue funzionalità.
Una di queste aree di memoria è nota con il nome di Loader Heap (da *non confondere* con managed heap).
Il loader heap è, per così dire, zona privata al common language runtime: il codice utente non vi alloca mai direttamente, il garbage collector non spazzola il loader heap.
Il CLR, tuttavia, utilizza questa area di memoria per caricare e mantenere strutture dati (piuttosto complesse, articolate e non del tutto documentate) che rappresentano un tipo. Se vogliamo, una copia dei metadati *estremamente* ottimizzata per le prestazioni in fase di esecuzione.
A questa area di memoria ci si riferisce generalmente con il nome di MethodTable.
Nome che non è del tutto corretto, ma ne indica comunque parzialmente i contenuti. Un tipo in memoria è rappresentato *anche* da un array i cui elementi rimandano, per via più o meno diretta, al codice dei metodi esposti dal tipo stesso.
A fare le pulci a quanto ho scritto ci sono alcune affermazioni un po' frettolose, ma quello che mi interessa chiarire è più o meno detto: così come i singoli oggetti, anche i tipi (classi, strutture, interfacce ...) hanno una propria identità all'interno del processo che esegue un'applicazione .NET.
Come si lega il tutto
Ricapitoliamo un attimo.
- Sullo stack abbiamo allocato 4 byte per la variabile locale anObject.
- Nel managed heap abbiamo allocato almeno 4 byte per lo stato dell'oggetto (il campo Number).
- Nel loader heap qualcuno ha allocato n bytes che rappresentano il tipo ReferenceType.
Come si ... legano queste aree di memoria ? Altrimenti detto, e considerato che a partire dalla variabile locale possiamo invocare un metodo il cui riferimento è mantenuto altrove, come è possibile risalire da anObject all'indirizzo del metodo WriteTheNumber, cosa che ovviamente sarà richiesta in esecuzione ?
Abbiamo già raccontato, in realtà, la metà della storia: la variabile locale contiene l'indirizzo di memoria dereferenziando il quale è possibile "arrivare" all'oggetto contenuto nel managed heap.
Rimane, tuttavia, da spiegare, il legame fra la memoria che descrive il tipo (nel loader heap) e quella che contiene i dati dell'oggetto (nel managed heap).
Presto fatto (e così correggiamo anche un imprecisione !).
Immediatamente al di sopra dell'area dati che contiene lo stato di anObject (nel managed heap) è presente un riferimento (grande, pure lui, sizeof(IntPtr)) che contiene l'indirizzo di memoria della MethodTable (nel loader heap).
E, qui sta la correzione, il riferimento anObject memorizzato sullo stack punta, in realtà, al puntatore alla MethodTable memorizzato nel managed heap.
Spero che il disegnetto qui sotto illustri meglio la situazione.

Nota
Ripeto quanto detto all'inizio: questo post si focalizza sulle aree di memoria coinvolte nell'allocazione di un oggetto di tipo reference.
Di roba ne è rimasta fuori parecchia. Solito problema, argomenti ce ne sono per scrivere un libro, probabilmente. Una cosa su tutte: come funziona il tutto con i value types ?
Beh ... diciamo che ne parliamo in un prossimo, spero, post della serie.
Per ora spero solo che, magari, alcune questioni risultino un po più chiare.
E, inutile dirlo, ogni imprecisione e/o errore in questo post è dovuto al sonno e non è imputabile in alcun modo al Common Language Runtime, a heap e stack o ai puntatori in generale :)
Risorse e link
Come sempre, qualche link per descrizioni più dettagliate.
Libri: consiglio (e non solo su questo argomento, ma in modo assolutamente generale e in ordine assolutamente sparso):
Sul web ... mioddio, c'è pieno di documentazione, faccio quasi prima a linkare una querystring di ricerca su google !
Anzi ... questo lo lascio come esercizio ;)
Guardo tra i feed stamattina ... sono state annunciate le date e le track di DevCon 2007 !
Tutte le info qui.
Accorrete numerosi gente, Early Bird fino al 28-02 ... :)