Domanda

Ho sentito gente affermare che i Generatori di Codice e modelli T4 non deve essere utilizzato.La logica dietro questo è che se si sta generando il codice di un generatore, quindi non c'è un modo più efficiente per generare il codice attraverso generics e modelli.

Mentre ho un po ' d'accordo con questa affermazione di cui sopra, non ho davvero trovato modi efficaci per costruire i modelli che possono dire, per esempio, creare un'istanza di se stessi.In altre non riesco mai a fare :

return new T();

Inoltre, se voglio generare il codice in base a valori di database ho trovato che l'uso di Microsoft.SqlServer.Management.SMO in combinazione con i modelli T4 sono stati meravigliosi a generare massa quantità di codice, senza dover copiare / incollare o utilizzare resharper.

Molti dei problemi che ho trovato con i Generici, troppo, è che per il mio shock, ci sono un sacco di sviluppatori che non li capiscono.Quando faccio esaminare farmaci generici per una soluzione, ci sono momenti in cui diventa complicato, perché C# afferma che non è possibile fare qualcosa che potrebbe sembrare logico nella mia mente.

Quali sono i tuoi pensieri?Si preferisce costruire un generatore, o preferite usare i generici?Inoltre, come ben si può generics andare?Conosco una quantità decente di circa generici, ma ci sono trappole e le insidie che ho sempre eseguito in che mi causa il ricorso a un modello T4.

Che cosa è più il modo corretto per gestire situazioni in cui è necessario una grande quantità di flessibilità?Oh, e come un bonus a questa domanda, quali sono le risorse su C# e Generici?

È stato utile?

Soluzione

Si può fare una nuova T();se si fa questo

public class Meh<T>
  where T : new()
{
  public static T CreateOne()
  {
    return new T();
  }
}

Come per-generatori di codice.Io uso uno ogni giorno senza problemi.Sto utilizzando un proprio ora, in fatto :-)

Generics risolvere un problema,-generatori di codice risolvere un altro.Per esempio, la creazione di un modello di business utilizzando un editor UML e quindi la generazione di classi con codice di persistenza come faccio tutto il tempo di utilizzo questo strumento non potrebbe essere raggiunto con i farmaci generici, perché ogni persistente classe è completamente diverso.

Come per una buona fonte di farmaci generici.Il migliore si è avuto modo di essere Jon Skeet libro ovviamente!!!:-)

Altri suggerimenti

Come il creatore del T4, ho dovuto difendere questa domanda abbastanza un paio di volte come si può immaginare :-)

La mia convinzione è che al meglio la generazione del codice è un passo sulla strada per la produzione di valore equivalente utilizzando librerie riutilizzabili.

Come molti altri hanno detto, il concetto chiave per mantenere ASCIUTTO non è mai, mai cambiare il codice generato manualmente, ma piuttosto di preservare la vostra capacità di rigenerare quando la fonte modifiche dei metadati o si trova un bug nel codice del generatore.A quel punto il codice generato ha molte delle caratteristiche di codice oggetto e non incorrere in copia/incolla tipo di problemi.

In generale, è molto meno sforzo per produrre una con parametri generatore di codice (in particolare con il modello basato su sistemi) che per progettare correttamente un alta qualità di base di libreria che ottiene i costi di utilizzo allo stesso livello, quindi è un modo rapido per ottenere valore dalla coerenza e rimuovere gli errori di ripetizione.

Tuttavia, credo ancora che il sistema finito più spesso essere migliorata avendo meno totale codice.Se non altro, la sua impronta di memoria sarebbero quasi sempre significativamente più piccoli (anche se la gente tende a pensare di farmaci generici, in quanto il costo di connessione a questo proposito, che la maggior parte non sono certo).

Se hai realizzato un certo valore utilizzando un generatore di codice, quindi questo spesso acquista un po ' di tempo o di denaro, o la buona volontà di investire nella raccolta di una libreria dal generati codebase.È quindi possibile in modo incrementale ripensare il generatore di codice a destinazione la nuova biblioteca e, si spera, a generare molto meno codice.Sciacquare e ripetere.

Un interessante contrappunto che è stato fatto per me e che arriva in questo thread è che ricco, complesso, librerie parametriche non sono la cosa più semplice in termini di curva di apprendimento, soprattutto per chi non è profondamente immerso nella piattaforma.Attaccare con la generazione di codice su semplici strutture di base in grado di produrre dettagliato codice, ma spesso può essere molto semplice e di facile lettura.

Naturalmente, in cui si hanno un sacco di varianza ed estremamente ricco di parametrizzazione nel generatore, si potrebbe essere proprio trading off complessità di un prodotto per la complessità dei modelli.Questo è un percorso facile scivolare dentro e può fare la manutenzione come un gran mal di testa - guardare fuori per questo.

La generazione di codice non è il male, e non ha odore!La chiave è quello di generare il codice giusto al momento giusto.Penso T4 è grande-io uso solo di tanto in tanto, ma quando lo faccio è molto utile.Per dire, incondizionatamente, che la generazione del codice è male è incondizionatamente pazzo!!!

Mi sembra di generatori di codice sono bene purché la generazione del codice è parte del normale processo di costruzione, piuttosto che qualcosa che si esegue una sola volta e quindi mantenere la sua uscita.Aggiungo questa premessa perché se basta usare il generatore di codice una volta e ignorare i dati che lo ha creato, sei solo la creazione automatica di una massiccia LAVAGGIO violazione di manutenzione e mal di testa;mentre la generazione di codice ogni volta che, in effetti, significa che qualunque cosa si sta utilizzando per fare il generare è il vero codice sorgente e i file generati sono solo intermedio compilare fasi che si dovrebbe ignorare.

Lex e yacc sono classici esempi di strumenti consentono di specificare la funzionalità in modo efficiente e generare codice efficiente da esso.Cercando di fare il loro lavoro da mano di allungare i tempi di sviluppo e, probabilmente, produrre meno efficiente e meno leggibile il codice.E mentre si può certamente incorporare qualcosa di simile a lex e yacc direttamente nel codice, e fare il loro lavoro in fase di esecuzione, invece di in fase di compilazione, che sarebbe certamente aggiungere una notevole complessità di codice e rallentare.Se hai veramente bisogno di cambiare la vostra specifica in fase di esecuzione potrebbe essere valsa la pena, ma nella maggior parte dei casi normali utilizzando lex/yacc per generare il codice in fase di compilazione, è una grande vittoria.

Una buona percentuale di quello che è in Visual Studio 2010 non sarebbe possibile senza la generazione di codice.Entity Framework non sarebbe possibile.Il semplice atto di trascinare un controllo in un form non sarebbe possibile, né sarebbe Linq.Dire che la generazione di codice non deve essere utilizzato è strano come molti lo usano senza nemmeno pensarci.

Forse è un po ' dura, ma per me la generazione di codice di odori.

Che la generazione del codice è utilizzato significa che ci sono numerosi sottostanti principi comuni, che può essere espresso in un "Don't repeat yourself" di moda.Si può prendere un po ' di più, ma è una soddisfazione quando si finisce con le classi che contengono solo i bit che cambiano, basata su un'infrastruttura che contiene la meccanica.

Come per i farmaci Generici...no non ho troppi problemi con esso.L'unica cosa che attualmente non funziona, è come dire che

List<Animal> a = new List<Animal>();
List<object> o = a;

Ma anche che sarà possibile, nella prossima versione di C#.

Più il codice della complessità.Complessità significa più posti per i bug da nascondere, il che significa più fix cycles, il che vuol dire maggiori costi tutto il progetto.

Quando possibile, preferisco ridurre al minimo la quantità di codice per fornire una funzionalità equivalente;idealmente mediante dinamici (programmatico) approcci piuttosto che la generazione del codice.La riflessione, gli attributi, gli aspetti e i generics di fornire un sacco di opzioni per un LAVAGGIO strategia, lasciando generazione come ultima risorsa.

La generazione del codice è per me una soluzione per molti problemi di lingua, quadri, etc.Non sono male da soli, direi che è molto, molto male (cioèmale) per il rilascio di un linguaggio (C# e framework che ti costringe a fare copia&incolla (swap su proprietà, gli eventi, la mancanza di macro) o utilizzare numeri magici (associazione di wpf).

Così, io grido, ma io li uso, perché devo.

Ho usato T4 per la generazione del codice e anche i farmaci Generici.Entrambi sono buoni, hanno i loro pro e contro, e sono adatti per scopi diversi.

Nel mio caso, io uso T4 generare Entità, DAL e BLL basato su uno schema di database.Tuttavia, DAL e BLL di riferimento di un mini-ORM ho costruito, a base di farmaci Generici e di Riflessione.Quindi penso che si può utilizzare fianco a fianco, come mantenere il controllo e tenerlo piccolo e semplice.

T4 genera codice statico, mentre i Generici è dinamico.Se si utilizzano farmaci Generici, è possibile utilizzare la Riflessione che ha detto di essere meno performante di "hard-coded" soluzione.Naturalmente è possibile memorizzare nella cache riflessione risultati.

Per quanto riguarda "return new T();", io uso Metodi Dinamici come questo:

public class ObjectCreateMethod
    {
    delegate object MethodInvoker();
    MethodInvoker methodHandler = null;

    public ObjectCreateMethod(Type type)
    {
        CreateMethod(type.GetConstructor(Type.EmptyTypes));
    }

    public ObjectCreateMethod(ConstructorInfo target)
    {
        CreateMethod(target);
    }

    void CreateMethod(ConstructorInfo target)
    {
        DynamicMethod dynamic = new DynamicMethod(string.Empty,
                    typeof(object),
                    new Type[0],
                    target.DeclaringType);
        ILGenerator il = dynamic.GetILGenerator();
        il.DeclareLocal(target.DeclaringType);
        il.Emit(OpCodes.Newobj, target);
        il.Emit(OpCodes.Stloc_0);
        il.Emit(OpCodes.Ldloc_0);
        il.Emit(OpCodes.Ret);

        methodHandler = (MethodInvoker)dynamic.CreateDelegate(typeof(MethodInvoker));
    }

    public object CreateInstance()
    {
        return methodHandler();
    }
}

Quindi, io la chiamo così:

ObjectCreateMethod _MetodoDinamico = new ObjectCreateMethod(info.PropertyType);
object _nuevaEntidad = _MetodoDinamico.CreateInstance();

I farmaci generici e la generazione di codice sono due cose diverse.In alcuni casi si potrebbe utilizzare farmaci generici invece per la generazione di codice e per quelli credo che si dovrebbe.Per gli altri casi, la generazione del codice è uno strumento potente.

Per tutti i casi in cui è sufficiente per generare il codice è basato su alcuni dati di input, la generazione del codice è la strada da percorrere.La più evidente, ma non è l'unico esempio è il form editor di Visual Studio.Qui l'ingresso è il designer di dati e l'output è il codice.In questo caso generics è davvero alcun aiuto, ma è molto bello che la VS semplicemente genera il codice basato su GUI layout.

Generatori di codice potrebbe essere considerato un codice odore che indicano un difetto o una mancanza di funzionalità nella lingua di destinazione.

Per esempio, mentre è stato qui detto che "gli Oggetti che persistono non può essere generalizzata", sarebbe meglio pensare ad esso come "Oggetti in C# che automaticamente mantenere i loro dati non possono essere generalizzati in C#", perché ho sicuramente in Python attraverso l'uso di vari metodi.

Il Python approccio potrebbe, tuttavia, essere emulato in statico lingue attraverso l'uso di operatore[ ](method_name as string), che restituisce un funtore o una stringa, a seconda delle esigenze.Purtroppo la soluzione non è sempre applicabile, e la restituzione di un funtore può essere scomodo.

Il punto che sto facendo è che i generatori di codice di indicare un difetto in una lingua che gli vengono rivolte, fornendo un più conveniente specializzati la sintassi per il problema specifico a portata di mano.

Il copia/incolla tipo di codice generato (come Orm fare) può essere anche molto utile...

È possibile creare il tuo database, e quindi l'ORM generare una copia del database definizione espressa nella vostra lingua preferita.

Il vantaggio arriva quando si modifica la definizione originale (il database), premere la compilazione e l'ORM (se si dispone di una buona) in grado di ri-genera la copia di definizione.Ora tutti i riferimenti al database può essere controllato dai compilatori di tipo ortografico e il tuo codice non verrà compilare quando si utilizza tabelle o colonne che non esiste più.

Pensate a questo:Se io chiamo un metodo un paio di volte nel mio codice, non sto facendo riferimento al nome che ho dato a questo metodo originale?Io continuo a ripetere che il nome più e più...Lingua designer ha riconosciuto questo problema e si avvicinò con "Tipo di sicurezza" come soluzione.Non rimuovere le copie (come LAVAGGIO suggerisce di fare), ma il controllo della correttezza, invece.

L'ORM codice generato porta la stessa soluzione quando si fa riferimento a nomi di tabelle e colonne.Non rimuovere le copie di riferimenti, ma portando il database definizione nel tuo (type-safe) lingua in cui si può fare riferimento alle classi e proprietà.Insieme con i compilatori tipo di controllo, questo risolve un problema simile in un modo simile:Garanzia di errori in fase di compilazione, invece di runtime quando si fa riferimento a obsolete o errate tabelle (classi) o colonne (proprietà).

citazione:Non ho davvero trovato modi efficaci per costruire i modelli che possono dire, per esempio, creare un'istanza di se stessi.In altre non riesco mai a fare :

return new T();

public abstract class MehBase<TSelf, TParam1, TParam2>
    where TSelf : MehBase<TSelf, TParam1, TParam2>, new()
{
    public static TSelf CreateOne()
    {
        return new TSelf();
    }
}

public class Meh<TParam1, TParam2> : MehBase<Meh<TParam1, TParam2>, TParam1, TParam2>
{
    public void Proof()
    {
        Meh<TParam1, TParam2> instanceOfSelf1 = Meh<TParam1, TParam2>.CreateOne();
        Meh<int, string> instanceOfSelf2 = Meh<int, string>.CreateOne();
    }
} 

La generazione di codice, come i generics, modelli, e altri tali collegamenti, è un potente strumento.E come con strumenti più potenti, amplifica la capaility del suo utente, per il bene e il male non possono essere separati.

Quindi, se si capisce il generatore di codice a fondo, prevedere ciò che produrrà, e perché, e l'intenzione di farlo per motivi validi, quindi avere in esso.Ma non lo uso (o di qualsiasi altra tecnica) per ottenere passato un luogo dove non si è sicuri di dove sei diretto, o come arrivarci.

Alcune persone pensano che, se si ottiene il tuo attuale problema risolto e qualche comportamento attuato, sei d'oro.Non è sempre evidente quanto il cruft e opacità si lascia in tutto il percorso per il prossimo sviluppatore (che potrebbe essere se stessi.)

Perché non essere in grado di copiare/incollare davvero, davvero veloce, la rende più accettabile?

Che è l'unica giustificazione per la generazione del codice che posso vedere.

Anche se il generatore offre tutta la flessibilità di cui avete bisogno, dovete ancora imparare come utilizzare la flessibilità - che è ancora un altro strato di apprendimento e test necessari.

E anche se si esegue in tempo zero, è ancora ingolfa il codice.

Ho arrotolato i miei dati di accesso di classe.Si sa tutto di connessioni, transazioni, stored procedure, parametri, ecc, ecc, e ho solo dovuto scrivere tutti i ADO.NET roba di una volta.

Ora è stato così tanto tempo da quando ho dovuto scrivere (o anche guardare) qualsiasi cosa con un oggetto di connessione, che mi sarebbe difficile ricordare la sintassi sbrigativo.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top