posts - 644, comments - 1982, trackbacks - 137

My Links

News

Raffaele Rialdi website

Su questo sito si trovano i miei articoli, esempi, snippet, tools, etc.

Archives

Post Categories

Image Galleries

Blogs

Links

Come si è arrivati a WinRT, una API object oriented

Prima di analizzare WinRT bisogna tornare indietro nel tempo e ripercorrere l'evoluzione dei linguaggi.

Il linguaggio C ha consolidato un modo standard per interoperare in due diversi modi:

  • A livello sorgente grazie alla standardizzazione ANSI del 1989 (e successive)
  • A livello binario, grazie alle calling convention dell'architettura x86 (stdcall, fastcall, cdecl) che stabilisce il modo in cui sono passati i parametri (ed altro).

Ad oggi questo rimane il modo più diffuso di fare interoperabilità tra linguaggi e, anche eseguiamo chiamate PInvoke con il Framework.NET stiamo di fatto utilizzando queste calling convention.
Quando utilizziamo le Win32, stiamo chiamando le API con la calling convention "stdcall".

Come nota di colore, il mio primo beta testing fu del compilatore MASM (Macro Assembler) di Microsoft come conseguenza di un bug che trovai nella versione 5.1 proprio nelle calling convention del compilatore interoperando con il compilatore C dell'epoca (parliamo degli anni 80).

Con l'affermazione di C++ l'interoperabilità è sempre stata solo a livello sorgente. La commissione ISO (oggi presieduta da Herb Sutter) ha stabilito il primo standard nel 1998 (posteriore all'uscita di Visual C++ 6.0 che perciò è fuori standard) e successivi, fino ad arrivare all'attuale C++11 di questo Agosto 2011.

La commissione non ha mai stabilito alcuno standard a livello binario tanto che non è neppure possibile utilizzare librerie che provengono da due versioni differenti della stessa marca di compilatore. È sempre necessario ricompilare tutto con la stessa versione del compilatore C++.

Ecco alcuni dei problemi di uno standard binario per un linguaggio object oriented:

  • definizione di un type system (pensiamo a quanti tipi 'string' sono stati creati in C e C++)
  • gestione del ciclo di vita degli oggetti (costruzione e distruzione)
  • definizione di uno standard per la "decorazione" applicata dal compilatore per differenziare le funzioni in overload
  • definizione di incapsulamento a livello binario (C++ supporta l'ereditarietà private o protected, per cui solo il compilatore conosce l'esatto layout della classe. Da qui la necessità di separare i concetti di interfaccia binaria (virtual table) dalle sue possibili implementazioni in oggetti binari differenti

Parlando di sistemi distribuiti, il problema è ancora più complesso. Pensiamo ad esempio di dover invocare una funzione remota che ha per parametro un blob (Binary Large OBject). In linguaggio C questo buffer è definito da un puntatore che però non ha l'informazione della lunghezza del blob. In C++ il blob può essere incapsulato in una classe ma C++ non fornisce la semantica necessaria per dichiarare, durante l'invocazione della chiamata remota, il blob sia in ingresso, uscita o entrambe le direzioni.
In un sistema distribuito attraversare un "boundary" (confine) ha un costo. Se il blob fosse un parametro di un web service, il costo in termini di banda per spostarlo in una o l'altra direzione non potrebbe essere ignorato.

Per colmare queste lacune nasce IDL (Interface Definition Language a cura dell'Open Software Foundation Distributed Computing Environment Remote Procedure Call) che viene adottato da Microsoft per realizzare COM e dal mondo Unix per realizzare CORBA. La versione binaria dei metadati generata grazie a IDL, le type library, sono le moderne librerie binarie che permettono anche l'interoperabilità binaria tra linguaggi differenti.

Non posso biasimare Don Box quando affermava "COM is Love" indicando (mia interpretazione) finalmente COM come una reale soluzione pratica, vincente e performante per i problemi di compatiblità binaria, interoperabilità e comunicazione distribuita. Tutt'ora è una soluzione che funziona egregiamente in Windows e la più performante (escludendo ovviamente le API "C" in quanto non forniscono una soluzione ai problemi risolti da COM). Nota di colore: Nei corridoi di //build/, al termine della sessione di Herb Sutter ho visto passare Don Box e gli ho detto "So COM is still love" ed è stato un piacere vederlo sorridere.

Fino a qui siamo agli anni 90 al termine dei quali emergono diversi problemi:

  • Il type system è inadeguato e troppo complesso (BSTR, VARIANT, SAFEARRAY, …) e spesso richiede un custom marshaler (un oggetto che sia in grado di descrivere come copiare il layout di memoria di un tipo custom)
  • Le collection non sono native
  • Il sistema di eventi basato sui connection point è complesso
  • Il ciclo di vita degli oggetti basato sul reference counting deve essere gestito manualmente ed è complesso
  • La registrazione di interfacce e classi (registry)

In C++ alcuni di questi problemi vengono colmati dalle librerie ATL (Active Template Library) ma rimane pur sempre una libreria disponibile solo in C++ e complessa da utilizzare.

Potenza hardware

A partire dalla fine anni 90 la potenza dei PC superava abbondantemente i requisiti di una applicazione standard. Questo è stato il trigger che ha visto la nascita di Java e poi del Framework.NET. In quel periodo storico l'overhead dovuto ai runtime e alla garbage collection era minimo rispetto ai benefici di produttività e manutenibilità. Inoltre, in assenza di un moderno standard C++ che ha visto la luce solo questo Agosto 2011, linguaggi come C# hanno avuto giustamente una vasta diffusione.

Il Framework.NET, basato nella sua infrastruttura su COM, riafferma diversi concetti che abbiamo già analizzato:

  • Definisce un type system moderno
  • Provvede alle specifiche CLI che permettono di utilizzare più linguaggi
  • Definisce la compatibilità a livello binario
  • Aumenta la ricchezza dei metadati rispetto a quelli forniti da IDL in COM (pensiamo a reflection)
  • Definisce un Intermediate Language (IL) che permette il disaccoppiamento rispetto all'architettura di sistema (x86 / x64 / …)

In fondo il vero plus del Framework.NET è quello del runtime, da tanti vituperata, che ha comunque diminuito drasticamente il numero di bug nelle applicazioni moderne e un aumento incredibile della produttività che si traduce direttamente nella possibilità di creare applicazioni più sofisticate. Il resto erano già concetti presenti in COM anche se espressi in modo più complesso.

Non più solo PC

Siamo quindi ai giorni nostri e i requisiti sono nuovamente cambiati. Gli utenti infatti chiedono dispositivi sempre più piccoli e potenti (ma che per ovvi motivi non possono essere tanto potenti quanto lo è un PC). Questo requisito si soddisfa principalmente con due fattori: minore consumo di CPU e (come conseguenza) di batteria.
Se prima avevamo cicli da buttare, oggi il discorso è cambiato quel tanto da non poterlo più ignorare.

Un altro fattore non indifferente è che l'introduzione del runtime implica la gestione della sua versione. Garantire che una applicazione che gira su una versione di runtime possa girare anche su una diversa versione di runtime è molto complesso, forse una chimera.

I requisiti cambiano ancora:

  • uso di codice nativo
  • conservare la produttività della programmazione con .NET
  • type system moderno
  • performance
  • eterogenità di linguaggi
  • flessibilità nella gestione della versione

Il Windows RunTime (WinRT) getta le basi su questi concetti e ne aggiunge di nuovi che vedremo in prossimi post quali per esempio il meccanismo di attivazione e le chiamate asincrone.

WinRT non poteva che ripartire da un'infrastruttura ben consolidata nel sistema operativo quale COM, ma apportando una serie di modifiche utili a superare i problemi che abbiamo analizzato in precedenza.
WinRT conserva i meccanismi di layout degli oggetti, IUnknown con le sue AddRef, Release e QueryInterface. Niente più IDispatch che ha dato tanti grattacapi agli sviluppatori per fornire invece la IInspectable. Può sembrare paradossale come queste due interfacce, tra le altre cose, svolgano ruoli simili e cioè la scoperta dei metdati.

Non so se esistano altri precedenti nel mondo dei sistemi operativi, ma l'esposizione dei servizi del sistema operativo in modo object oriented è certamente un grosso salto in avanti. A partire dal prossimo post comincerò ad analizzare le varie parti di WinRT.

Print | posted on Wednesday, September 21, 2011 4:31 PM |

Feedback

Gravatar

# re: Come si è arrivati a WinRT, una API object oriented

Credo anche io che la necessità di far girare Windows anche su device semplici richieda questo "ritorno" al passato. Sui sistemi embedded l'utilizzo di C++ al posto di .NET con XAML in Silverlight for Windows Embedded consente di avere UIs performanti anche su device a 600Mhz (Mega, non Giga :P).
Quanto ai S.O. "object oriented" credo BeOS (mai arrivato al successo) e Symbian (che, come minimo, esponeva un'API in C++ e prevedeva come modello di default per le app delle classi C++).
9/21/2011 4:38 PM | Valter Minute
Gravatar

# re: Come si è arrivati a WinRT, una API object oriented

Ciao Cristian, a quanto mi hanno detto, sarà possibile avere applicazioni ibride (desktop che usano WinRT) e anche qualcosa del contrario ma sono scenari di secondo piano nei loro intenti, quindi non ne hanno parlato nelle sessioni.
Questo però si limita al solo uso delle librerie risolvendo probabilmente il problema delle chiamate PInvoke. Per come è fatta l'architettura di Windows (e non solo Windows) non è possibile applicare certi vantaggi al mondo desktop:
- il broker (di cui non temere che ne parlerò) necessita di un ambiente controllato cosa non fattibile per un processo nativo che sia al di fuori del contesto del runtime di WinRT
- le chiamate asincrone già oggi le puoi fare ma solo WinRT può 'obbligarti' a renderle tali
- il type system di WinRT non è ovviamente compatibile con le attuali chiamate Win32 dove è tutto C-like con buffer, struct di lunghezza variabile, etc.
- Il reference counting è un altro punto non risolvibile senza un sistema come quello di WinRT
- ...
Insomma WinRT è lì per un motivo che ha molto più a che fare con questi argomenti che la UI.

Le app desktop rimarranno a lungo e non ci vedo nulla di male. Il primo driver delle app metro è il marketplace, comodo per gli utenti e anche per chi sviluppa.
9/21/2011 7:44 PM | Raffaele Rialdi
Gravatar

# re: Come si è arrivati a WinRT, una API object oriented

Quindi anche se nessuno lo dice possiamo dire con tutta franchezza che WinRT è l'evoluzoine del .net (pace all'anima sua)
9/22/2011 4:02 PM | fabio
Gravatar

# re: Come si è arrivati a WinRT, una API object oriented

@Fabio. Certo, evoluzione, questo è proprio il concetto che volevo esprimere.
Ma ha senso evolvere nella direzione dei requisiti, non solo perché passa il tempo. E nel corso di questi anni i requisiti sono cambiati.
Sul "pace all'anima sua" invece sono totalmente in disaccordo. Il CLR/.NET è vivo e vegeto e continuerà a svolgere lo stesso ruolo di prima.
9/22/2011 4:32 PM | Raffaele Rialdi
Gravatar

# re: Come si è arrivati a WinRT, una API object oriented

Il mio parere, visto come è fatto WinRT è che non se ne parla.
WinRT ha comportato modifiche in:
- l'infrastruttura COM sottostante
- modifiche a RPCSS e forse anche a DCOM Launcher
- modifiche allo scheduler (i processi adesso possono essere sospesi, punto fondamentale per WinRT)
- modifiche al security subsystem (il security token contiene info specifiche al package, alle capabilities e all'app).
Inoltre non è neppure possibile sviluppare app Metro su Win7 per poi farle girare su Win8, proprio per la mancanza di una serie di API (e dello stesso runtime).

Tu dici che ci vogliono 10 anni. Io dico che sarà l'utente a dirlo.
Su un tablet (e su tutti i device ibridi di piccole dimensioni, comprese le future versioni di WP7 che a mio parere adotteranno questo modello) è impensabile proporre il modello di applicazioni desktop, quindi l'accelerazione sarà maggiore.
Inoltre il marketplace sarà un fattore fondamentale per molte applicazioni.

A questo punto la scommessa è in mano ai dev. Se ci credi inizi subito e sei pronto. Se non ci credi, tutto funziona come prima. Se sbagli, sei fuori mercato. Ognuno ha in mano il proprio destino.
9/23/2011 9:05 AM | Raffaele Rialdi
Gravatar

# re: Come si è arrivati a WinRT, una API object oriented

Fabio per i prossimi post + tecnici, puoi contarci. Ci tenevo a fare una intro storica perché altrimenti sembra che queste cose arrivino per le "voglie" di qualcuno mentre non è così.

La strategia MS cambia in funzione del mercato, mi pare ovvio. E i due fattori sono quelli che scrivevo: utenti e hardware.

La scelta del linguaggio sta a te. Rifacciamo il discorso dopo qualche altro post tecnico ;) Poter scegliere (cosa che prima non potevi fare) è però un gran bel vantaggio. Ti anticipo solo che in tantissimi casi C# resta un ottima scelta.
9/23/2011 12:00 PM | Raffaele Rialdi
Gravatar

# re: Come si è arrivati a WinRT, una API object oriented

Diego, no problem :)
Almeno per ora WinRT limita l'uso di certe librerie (parlo di quelle del framework e alcuni pezzi di Win32). Questo è ragionevole se lo pensiamo in ottica di marketplace. Quando scarico una app dal market non penso certo ad app 'estreme' come Process Monitor che addirittura installa un driver.
In ottica di market, una app deve essere autonoma. Per consumare dati puoi usare servizi (magari RESTful), dati sulla cloud, etc.
In quest'ottica le app metro "forzano" il dev a pensare in modo multi-tier. La tua app non ha più (direi finalmente) nulla che riguardi l'accesso al db (etc. etc.) ma solo la logica di presentazione.

Personalmente faccio già così oggi con WPF, e se è così per renderla Metro-compatibile ci vuole poco.
Se valga la pena di tenere in parallelo la compilazione Metro e quella desktop sarai tu a sceglierlo o meglio saranno i tuoi clienti a chiedertelo.
VS11 già ora prevede sia progetti Metro che quelli a cui sei già abituato.

Quello di cui non si è parlato a //build/ sono le applicazioni ibride (Win32/.NET che parlano con WinRT o viceversa) magari pubblicate su un market privato. Io ho chiesto, lo scenario è previsto ma è presto per avere dettagli.
9/23/2011 4:22 PM | Raffaele Rialdi
Gravatar

# re: Come si è arrivati a WinRT, una API object oriented

Ciao Ste,
ovviamente la mia soddisfazione è riferita al fatto che una Metro app non può essere monolitica.

Quanto alla gestione dei dati disconnessi è un punto su cui non ci sono risposte. Alcuni speaker a build hanno chiaramente detto che bisogna accontentarsi *al momento* di uno storage basato su file, eventualmente sincronizzato sulla cloud.
Cercherò in altre sessioni che non ho visto se sono state date prospettive più allettanti.

Tieni conto però che il team di WCF sta già lavorando a sorgenti dati disconesse per applicazioni basate su js e html5 (anche se non parlano di persistenza locale di storage).
9/25/2011 12:24 PM | Raffaele Rialdi
Gravatar

# Mix di linguaggi con WinRT

Mix di linguaggi con WinRT
9/29/2011 3:26 PM | Web Log di Raffaele Rialdi

Post Comment

Title  
Name  
Email
Url
Comment   
Please add 5 and 8 and type the answer here:

Powered by:
Powered By Subtext Powered By ASP.NET