Decidi che famiglia di problemi vuoi risolvere e scrivi un programma che genera programmi per ogni problema della famiglia.
Con il termine GenerativeProgramming si intende una tecnica di programmazione focalizzata sulla soluzione di famiglie di problemi software (algoritmi, classi, componenti) invece che sul singolo problema software (Generative Programming, Krzysztof Czarnecki e Ulrich Eisenecker, Addison-Wesley, 2000). Il ParadigmaDiProgrammazioneGenerica è un caso particolare di GenerativeProgramming.
In pratica mediante GenerativeProgramming è possibile generare automaticamente il codice sorgente per implementare un singolo programma a partire da:
il codice sorgente di partenza incompleto (cioè generico similmente al codice C# 2.0 di un generic type e al codice C++ di un Template) che esprime la soluzione ad una intera famiglia di problemi
i componenti di basso livello che forniscono funzioni necessarie alla implementazione specifica del singolo programma (es. le tabelle del Db della applicazione, le classi già realizate, dei componenti di terze parti, i tipi nativi del linguaggio, etc.)
i metadati le cui informazioni (lo Schema del Db, le interfacice delle classi usate, file XML con configurazioni specificate dalprogrammatore, etc.) fanno da collante tra il codice generico del punto 1) e i componenti del punto 2) specifici al singolo problema per la generazione del codice.
Questo diventa realtà con .NET perchè il CLR mette a disposizione
la Reflection di .NET soddisfa le esigenze del punto 3) è lo strumento con cui accedere ai metadati per ottenere programmaticamente la descrizione degli Assebly e dei tipi in esso contenuti similmente a come il Data Dictionary di un Db Relazionale permette di ottenete programmaticamente lo Schema del Db.
il namespace System.CodeDom (che permette la compilazione in memoria ed esecuzione da un grafo CodeDom e la compilazione in memoria ed esecuzione da file sorgente CSharp e VisualBasicDotNet) e il namespace System.Emit (che permette la compilazione in memoria ed esecuzione di codice IL) per le esigenze del punto 1) con la possibilità di generare il codice sia a design-time che a run-time.
Ecco alcuni esempi noti di impiego del GenerativeProgramming: ASP.NET elabora a run-time le pagine ASPX per generare codice C# compilabile e quindi eseguibile; gli oggetti Proxy per accedere ai Web Services vengono generati a design-time a partire dalla descrizione in WSDL (Web Services Description Language) del Web Service; il Remoting genere a run-time un Transparent Proxy quando viene invocato un metodo di un oggetto remoto o in un altro Appliation Domain; CodeSmith è un Tool .NET freeware per fare GenerativeProgramming a design-time.
Scegliere se applicare la programmazione generativa a design-time o a run-time
Il codice generato tramite GenerativeProgramming può essere compilato a design-time o a run-time.
La scelta di applicare il GenerativeProgramming a design-time o a run-time dipende essenzialmente da un fatto: dal momento in cui sono noti quali mattoni del punto 2) sono da applicare per lo specifico problema da risolvere. Se questa conoscienza c'è a design-time è decisamente meglio applicare il GenerativeProgramming a design-time, in caso contrario si è obbligati a posticipare il suo utilizzo a run-time perdendo il contributo del compilatore nella verifica di corretezza della tipizzazione e pagando un costo in prestazioni.