Il presente articolo è stato tradotto automaticamente.
Il programmatore al lavoro
Piattaforma .NET multiparadigmatica, Parte 5: Metaprogrammazione automatica
Ted Neward
Ultimo mese del pezzo , oggetti fornita sotto il microscope e in particolare esaminato “ asse ” dell'analisi di variabilità/analogia offre l'ereditarietà. Mentre l'ereditarietà non è la sola forma di analogia/variabilità disponibile all'interno di un moderno orientato (OO) linguaggio come C# o Visual Basic, è certamente al centro del paradigma OO. E, come anche illustrato, non sempre fornisce la soluzione migliore per tutti i problemi.
Per riassumere, cosa abbiamo abbiamo scoperto finora è che C# e Visual Basic sono procedurali e linguaggi OO, ma chiaramente il brano non interrompe non esiste. Entrambi sono anche metaprogrammatic lingue, lo sviluppatore di Microsoft .NET Framework ognuno offre l'opportunità di creare programmi di programmi, in diversi modi: automatico riflettente e generative.
Metaprogrammazione automatica
L'idea di base sottostante metaprogramming è semplice: i costrutti di tipo procedurale o programmazione OO tradizionali non risolti abbastanza tutti i problemi di progettazione software, almeno non in modo da trovare soddisfacente. Ad esempio, per citare un difetto di base, gli sviluppatori trovato spesso necessitano di una struttura di dati che viene mantenuto un elenco ordinato di un tipo specifico, che è possibile inserire elementi nell'elenco in uno slot specifico e visualizzare gli elementi nell'ordine esatto. Per motivi di prestazioni, talvolta l'elenco desiderato in un elenco collegato di nodi. In altre parole, si desiderava un elenco collegato ma fortemente tipizzato per il tipo archiviato all'interno di essa.
Gli sviluppatori che provengono il mondo di c ++ per .NET Framework conoscono una soluzione a questo problema, ovvero che i tipi con parametri, noti anche più informale generics. Ma, come gli sviluppatori che provengono da .NET a Java di giorni precedenti SA, un'altra soluzione emersa molto prima modelli (che, infine, la piattaforma Java). Tale soluzione è stata semplicemente scrivere ciascuna implementazione necessaria elenco secondo le esigenze, come illustrato in di Figura 1.
Figura 1 un esempio di creazione di implementazioni di elenco come necessario
Class ListOfInt32
Class Node
Public Sub New(ByVal dt As Int32)
data = dt
End Sub
Public data As Int32
Public nextNode As Node = Nothing
End Class
Private head As Node = Nothing
Public Sub Insert(ByVal newParam As Int32)
If IsNothing(head) Then
head = New Node(newParam)
Else
Dim current As Node = head
While (Not IsNothing(current.
nextNode))
current = current.
nextNode
End While
current.
nextNode = New Node(newParam)
End If
End Sub
Public Function Retrieve(ByVal index As Int32)
Dim current As Node = head
Dim counter = 0
While (Not IsNothing(current.
nextNode) And counter < index)
current = current.
nextNode
counter = counter + 1
End While
If (IsNothing(current)) Then
Throw New Exception("Bad index")
Else
Retrieve = current.data
End If
End Function
End Class
A questo punto, ovviamente, si verifica un errore del test Don't Repeat Yourself (asciutto), ogni volta che la progettazione richiede un nuovo elenco di questo tipo, sarà necessario scrivere “ manualmente, ” che sarà chiaramente un problema nel corso del tempo. Anche se non è complicata, è ancora prevede sia difficile e richiede molto tempo scrivere ciascuna di esse, in particolare se più funzionalità diventa necessario o consigliabile.
Naturalmente, nessuno ha mai gli sviluppatori dovevano essere quelle scrivendo codice. Che ci porta perfettamente alla soluzione di generazione di codice o come si è detto, automatico metaprogramming . Un altro programma può facilmente eseguire, ad esempio un programma progettato per avviare le classi personalizzate per ogni tipo necessaria, come illustrato in di Figura 2.
Figura 2 di esempio Metaprogramming automatico
Sub Main(ByVal args As String())
Dim CRLF As String = Chr(13).ToString + Chr(10).ToString()
Dim template As String =
"Class ListOf{0}" + CRLF +
" Class Node" + CRLF +
" Public Sub New(ByVal dt As {0})" + CRLF +
" data = dt" + CRLF +
" End Sub" + CRLF +
" Public data As {0}" + CRLF +
" Public nextNode As Node = Nothing" + CRLF +
" End Class" + CRLF +
" Private head As Node = Nothing" + CRLF +
" Public Sub Insert(ByVal newParam As {0})" + CRLF +
" If IsNothing(head) Then" + CRLF +
" head = New Node(newParam)" + CRLF +
" Else" + CRLF +
" Dim current As Node = head" + CRLF +
" While (Not IsNothing(current.
nextNode))" + CRLF +
" current = current.
nextNode" + CRLF +
" End While" + CRLF +
" current.
nextNode = New Node(newParam)" + CRLF +
" End If" + CRLF +
" End Sub" + CRLF +
" Public Function Retrieve(ByVal index As Int32)" + CRLF +
" Dim current As Node = head" + CRLF +
" Dim counter = 0" + CRLF +
" While (Not IsNothing(current.
nextNode) And counter < index)"+ CRLF +
" current = current.
nextNode" + CRLF +
" counter = counter + 1" + CRLF +
" End While" + CRLF +
" If (IsNothing(current)) Then" + CRLF +
" Throw New Exception()" + CRLF +
" Else" + CRLF +
" Retrieve = current.data" + CRLF +
" End If" + CRLF +
" End Sub" + CRLF +
"End Class"
If args.Length = 0 Then
Console.WriteLine("Usage: VBAuto <listType>")
Console.WriteLine(" where <listType> is a fully-qualified CLR typename")
Else
Console.WriteLine("Producing ListOf" + args(0))
Dim outType As System.Type =
System.Reflection.Assembly.Load("mscorlib").GetType(args(0))
Using out As New StreamWriter(New FileStream("ListOf" + outType.Name + ".vb",
FileMode.Create))
out.WriteLine(template, outType.Name)
End Using
End If
Quindi, dopo aver creata la classe in questione, deve solo essere compilato e sia aggiunto al progetto oppure compilati nel proprio assembly per il riutilizzo come un file binario.
Naturalmente, non dispone di linguaggio generato per il linguaggio in cui è scritto il Generatore di codice, infatti, spesso semplificherà enormemente se non, poiché, quindi sarà più semplice mantenere i due più chiaramente distinti in head dello sviluppatore durante il debug.
Analogia, variabilità e responsabili e negativi
Nell'analisi analogia/variabilità automatico metaprogramming occupa un punto interessante. Nell'esempio Figura 2 colloca struttura e comportamento (la struttura della classe precedente) in analogia, consentendo di variabilità lungo le righe di tipo di dati del tipo archiviato nella classe generata. Ovviamente, è possibile scambiare in qualsiasi tipo desiderato nel tipo ListOf.
Ma automatico metaprogramming possibile invertire, troppo, se necessario. Utilizzando un linguaggio ricco modello, quali il Toolkit trasformazione del modello testo (T4) fornito con Visual Studio, la generazione di codice modelli possono eseguire origine fase decisionale, che consente il modello fornire analogia lungo le righe di dati/strutturale e variano da linee strutturale e funzionali. Infatti, se il modello di codice è sufficientemente complesso e non necessariamente un buon angolo di perseguire, è anche possibile eliminare del tutto analogia e variare tutto (dati, struttura, comportamento e così via). Ciò generalmente diventa ingestibile abbastanza rapidamente, tuttavia e generalmente devono essere evitati. Che conduce a una realizations chiave su metaprogramming automatico: Perché manca alcun tipo di restrizioni intrinseche strutturale, scegliere l'analogia e variabilità in modo esplicito, almeno il modello di codice sorgente crescere di controllo tenta di essere troppo flessibile. Ad esempio, dato nell'esempio ListOf di Figura 2, l'analogia è nella struttura e comportamento e la variabilità è nel tipo di dati archiviato, qualsiasi tentativo di introdurre variabilità nel comportamento o struttura deve essere considerato un contrassegno rosso e una pendenza slippery potenziale di caos.
Ovviamente, generazione del codice comporta alcuni rischi significativi, in particolare intorno alle manutenzione: Scoperto un bug (ad esempio la concorrenza uno nell'esempio ListOf… di Figura 2), tale correzione non è sufficiente. Il modello può ovviamente essere risolto, ma che non eseguire alcuna operazione per il codice già generato, ognuno di questi elementi di origine deve essere rigenerato, a sua volta, e questo è qualcosa che è difficile tenere traccia e verificare automaticamente. E, cosa ’s più fatto a mano modifiche ai file generati saranno intrinsecamente perse, a meno che il codice generato da modelli ha consentito di personalizzazioni. Il rischio di sovrascrittura può essere ridotto mediante l'utilizzo delle classi parziali, che consentono agli sviluppatori di compilare il “ altra metà ” (o non) della classe generata e dai metodi di estensione, fornendo agli sviluppatori l'opportunità di “ aggiunta ” metodi a una famiglia di tipi esistente senza dover modificare i tipi. Ma le classi parziali devono essere presenti dall'inizio all'interno dei modelli e metodi di estensione eseguire alcune restrizioni che impediscono loro di sostituire il comportamento esistente, lasciando nuovamente né approccio come un meccanismo efficace per eseguire variabilità negativo.
Generazione di codice
Generazione di codice, o automatico metaprogramming, è una tecnica che è stata una parte della programmazione per molti anni, compreso completamente la macro del preprocessore C attraverso il motore di C# T4 e probabilmente continuerà a eseguire, a causa di semplicità concettuale dell'idea. I difetti principali sono tuttavia la mancanza della struttura del compilatore e verifica durante il processo di espansione (a meno che, naturalmente, che il controllo viene eseguita dal generatore di codice, un'attività è più difficile rispetto alla suoni) e l'impossibilità di acquisire variabilità negativo in modo significativo. .NET Framework offre alcuni meccanismi per facilitare la generazione di codice, in molti casi, tali meccanismi sono state introdotte per salvare alcuni grief altri sviluppatori Microsoft, ma non eliminare tutti i potenziali problemi nella generazione di codice, non da un colpo lungo.
E ancora, automatico metaprogramming rimane uno dei formati più diffusi di metaprogramming. C# è una macro del preprocessore, come c ++ e c. (Utilizzo di macro per creare “ piccoli modelli ” era comune prima di c ++ ottenuto modelli.) Utilizzando sopra di questo, metaprogramming come parte di una libreria o framework è comune, in particolare per gli scenari di comunicazione tra processi (ad esempio stub di client e server generati da Windows Communication Foundation). Altri strumenti utilizzano metaprogramming automatico per fornire “ basi ” per facilitare le prime fasi di un'applicazione (ad esempio, ciò che è visualizzato in ASP.NET MVC). In realtà, probabilmente ogni progetto di Visual Studio inizia con metaprogramming automatica, nel modulo dei modelli di progetto “ ” e “ modelli di elemento ” che la maggior parte di noi utilizza per creare nuovi progetti o aggiungere file ai progetti. E così via. Come molte altre cose in informatica, automatico metaprogramming rimane uno strumento utile e pratico che nella casella degli strumenti Progettazione, nonostante le evidenti difetti e inconvenienti. Fortunatamente, è lontana da strumento metadati solo nella casella degli strumenti del programmatore.
Ted Neward è un'entità con Neward & Associates, un'impresa indipendenti ed è specializzato in sistemi piattaforma .NET Framework e Java enterprise. Ha scritto più di 100 articoli, è un MVP per C# e INETA relatore e ha creato e coautore di libri di una dozzina, tra cui “ Professional F # 2.0 ” (Wrox 2010). Ha inoltre consulta e mentors regolarmente. Contattarlo all' ted@tedneward.com e leggere il suo blog all'indirizzo blogs.tedneward.com .