10

コード ジェネレーターと T4 テンプレートを使用すべきではないと人々が言っ​​ているのを聞いたことがあります。その背後にあるロジックは、ジェネレーターでコードを生成している場合、ジェネリックとテンプレートを使用してコードをビルドするより効率的な方法があるということです。

上記の意見には少し同意しますが、たとえば自分自身をインスタンス化できるテンプレートを作成する効果的な方法を実際には見つけられませんでした。言い換えれば、私は決してできません:

return new T();

さらに、データベースの値に基づいてコードを生成したい場合Microsoft.SqlServer.Management.SMO、T4 テンプレートと組み合わせて使用​​すると、コピー/貼り付けや resharper を使用せずに大量のコードを生成できることがわかりました。

私が Generics で見つけた問題の多くは、驚いたことに Generics を理解していない開発者が多いことです。解決策としてジェネリックを検討するとき、複雑になることがあります。C# では、私の頭では論理的に見えるかもしれないことを行うことはできないと述べられているからです。

あなたの考えは何ですか?ジェネレーターを構築することを好みますか、それともジェネリックを使用することを好みますか? また、ジェネリックはどこまで行けるのでしょうか? ジェネリックについてはかなりの知識がありますが、T4 テンプレートに頼る原因となる落とし穴や落とし穴が常にあります。

大きな柔軟性が必要なシナリオを処理するためのより適切な方法は何ですか? ああ、この質問のボーナスとして、C# とジェネリックに関する優れたリソースは何ですか?

4

15 に答える 15

15

new T();を実行できます。あなたがこれをするなら

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

コードジェネレーターについて。毎日問題なく使っています。私は実際に今1つを使用しています:-)

ジェネリックは1つの問題を解決し、コードジェネレーターは別の問題を解決します。たとえば、UMLエディターを使用してビジネスモデルを作成し、このツールを使用していつも行っているように永続コードを使用してクラスを生成することは、各永続クラスが完全に異なるため、ジェネリックでは実現できませんでした。

ジェネリックに関する良い情報源として。もちろん、最高のものはジョン・スキートの本でなければなりません!:-)

于 2009-02-07T18:51:34.067 に答える
15

T4の創始者として、ご想像のとおり、私はこの質問を何度も弁護しなければなりませんでした:-)

私の信念は、最良のコード生成は、再利用可能なライブラリを使用して同等の価値を生み出すための第一歩であるということです。

他の多くの人が言っているように、DRY を維持するための重要な概念は、生成されたコードを決して手動で変更することではなく、ソース メタデータが変更されたときやコード ジェネレーターでバグが見つかったときに再生成する機能を維持することです。その時点で、生成されたコードにはオブジェクト コードの多くの特徴があり、コピー/貼り付けタイプの問題は発生しません。

一般に、パラメーター化されたコード ジェネレーター (特にテンプレート ベースのシステム) を作成する方が、使用コストを同じレベルまで下げる高品質のベース ライブラリを正しく設計するよりもはるかに労力がかかりません。値を一貫性から取り除き、繰り返しエラーを取り除きます。

しかし、完成したシステムは、ほとんどの場合、総コード数を減らすことで改善されると私は信じています。他に何もないとしても、そのメモリ フットプリントはほとんどの場合、大幅に小さくなります (ただし、ジェネリックはこの点でコストがかからないと考える傾向がありますが、実際にはそうではありません)。

コード ジェネレーターを使用して何らかの価値を認識した場合は、多くの場合、生成されたコードベースからライブラリを収集するための時間やお金、または善意を得ることができます。次に、コード ジェネレーターを段階的に再設計して、新しいライブラリをターゲットにし、生成されるコードを大幅に減らすことができます。すすいで繰り返します。

このスレッドに出てくる興味深い反論の 1 つは、豊富で複雑なパラメトリック ライブラリは、特にプラットフォームに深く没頭していない人にとっては、学習曲線の点で最も簡単なものではないということです。単純な基本フレームワークでのコード生成に固執すると、冗長なコードが生成される可能性がありますが、多くの場合、非常に単純で読みやすいものになります。

もちろん、ジェネレーターに多くの分散と非常に豊富なパラメーター化がある場合、テンプレートの複雑さと製品の複雑さをトレードオフするだけかもしれません。これは滑り込みやすいパスであり、メンテナンスが頭痛の種となる可能性があります。気を付けてください。

于 2011-06-04T20:21:00.390 に答える
8

コードを生成することは悪いことではありません。重要なのは、適切なタイミングで適切なコードを生成することです。T4 は素晴らしいと思います。たまにしか使用しませんが、使用すると非常に役立ちます。無条件に、コードを生成することが悪いと言うのは、無条件にクレイジーです!

于 2009-02-07T20:19:13.860 に答える
6

Visual Studio 2010 のかなりの部分は、コード生成なしでは実現できません。Entity Framework は使用できません。コントロールをフォームにドラッグ アンド ドロップするという単純な操作は不可能であり、Linq も同様です。コード生成を使うべきではないというのは奇妙です。

于 2012-04-12T00:40:46.740 に答える
4

少し厳しいかもしれませんが、私にとってはコード生成の匂いがします。

このコード生成が使用されるということは、「繰り返さない」方法で表現される可能性のある多くの基本的な共通の原則があることを意味します。少し時間がかかる場合がありますが、メカニズムを含むインフラストラクチャに基づいて、実際に変更されるビットのみを含むクラスになってしまうと、満足のいくものになります。

ジェネリックスに関しては...いいえ、それほど多くの問題はありません。現在機能していないのは、

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

しかし、それでも次のバージョンのC#で可能になります。

于 2009-02-07T18:59:32.507 に答える
2

コード生成は、私にとって、言語やフレームワークなどに見られる多くの問題の回避策です。それら自体は悪ではありません。言語 (C#) とフレームワークをリリースして、コピー&ペースト(プロパティのスワップ、イベントのトリガー、マクロの欠如)または魔法の数字の使用(wpfバインディング)。

だから、私は泣きますが、私はそれらを使わなければなりません。

于 2011-06-02T08:33:25.327 に答える
1

コードが多いほど、複雑さが増します。複雑さが増すと、バグを隠す場所が増えることになります。つまり、修正サイクルが長くなり、プロジェクト全体のコストが高くなります。

可能な限り、同等の機能を提供するためにコードの量を最小限に抑えることを好みます。理想的には、コード生成ではなく動的(プログラム)アプローチを使用します。リフレクション、属性、アスペクト、ジェネリックは、DRY戦略に多くのオプションを提供し、世代を最後の手段として残します。

于 2009-02-07T18:55:44.777 に答える
1

生成されたコードのコピー/貼り付けタイプ(ORMが作成するような)も非常に便利です...

データベースを作成してから、ORMに、お気に入りの言語で表現されたデータベース定義のコピーを生成させることができます。

元の定義(データベース)を変更し、コンパイルを押すと、ORM(適切な定義がある場合)が定義のコピーを再生成できるという利点があります。これで、データベースへのすべての参照をコンパイラの型チェッカーでチェックできるようになり、存在しなくなったテーブルまたは列を使用しているときにコードのコンパイルに失敗します。

これについて考えてみてください。コードでメソッドを数回呼び出す場合、このメソッドに最初に付けた名前を参照していませんか?私はその名前を何度も繰り返します...言語設計者はこの問題を認識し、解決策として「型安全性」を考え出しました。コピーを削除するのではなく(DRYが推奨するように)、代わりにコピーが正しいかどうかを確認します。

ORMで生成されたコードは、テーブル名と列名を参照するときに同じソリューションをもたらします。コピー/参照を削除するのではなく、データベース定義を(タイプセーフな)言語に移行し、代わりにクラスとプロパティを参照できるようにします。コンパイラの型チェックとともに、これは同様の方法で同様の問題を解決します。古いテーブル(クラス)または列(プロパティ)を参照するときに、実行時エラーではなくコンパイル時エラーを保証します。

于 2011-09-28T18:57:31.273 に答える
1

ジェネリックとコード生成は 2 つの異なるものです。場合によっては、コード生成の代わりにジェネリックを使用できます。それ以外の場合、コード生成は強力なツールです。

なんらかのデータ入力に基づいてコードを生成するだけでよい場合はすべて、コード生成が最適です。最も明白ですが、唯一の例ではありませんが、Visual Studio のフォーム エディターです。ここで、入力はデザイナー データで、出力はコードです。この場合、ジェネリックはまったく役に立ちませんが、VS が GUI レイアウトに基づいてコードを生成するだけであることは非常に優れています。

于 2009-02-07T19:20:32.807 に答える
1

コード ジェネレーターは、ターゲット言語の欠陥または機能の欠如を示すコードの臭いと見なすことができます。

例えば、ここで「持続するオブジェクトは一般化できない」と言いましたが、「データを自動的に持続する C# のオブジェクトは C# で一般化できない」と考えたほうがよいでしょう。さまざまな方法を使用してPythonで。

ただし、Python のアプローチは、operator[ ](method_name as string) を使用して静的言語でエミュレートできます。これは、要件に応じてファンクターまたは文字列を返します。残念ながら、その解決策は常に適用できるわけではなく、ファンクターを返すのは不便な場合があります。

私が言いたいのは、コード ジェネレーターは選択した言語の欠陥を示しており、目前の特定の問題に対してより便利な特殊な構文を提供することで対処できるということです。

于 2009-06-03T02:18:54.373 に答える
1

引用: たとえば、自分自身をインスタンス化すると言うことができるテンプレートを構築する効果的な方法を実際には見つけていません。言い換えれば、私は決してできません:

新しい 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();
    }
} 
于 2011-09-28T19:15:24.580 に答える
0

コピー/貼り付けが非常に高速であることが、なぜ受け入れやすくなるのでしょうか?

それが、私が見ることができるコード生成の唯一の正当化です。

ジェネレーターが必要なすべての柔軟性を提供する場合でも、その柔軟性を使用する方法を学習する必要があります。これは、必要な学習とテストのさらに別のレイヤーです。

また、ゼロ時間で実行されたとしても、コードは肥大化します。

独自のデータ アクセス クラスを作成しました。接続、トランザクション、ストアド プロシージャ パラメーターなどに関するすべてを認識しているため、すべての ADO.NET を 1 回記述するだけで済みました。

接続オブジェクトを含むものを書く (または見る) 必要がなくなってから、かなり時間が経ちました。

于 2009-02-07T19:11:44.900 に答える
0

ジェネリック、テンプレート、およびその他のショートカットと同様に、コード生成は強力なツールです。そして、最も強力なツールと同様に、善と悪のためにユーザーの能力を増幅します。それらを分離することはできません.

したがって、コード ジェネレーターを完全に理解している場合は、コード ジェネレーターが生成するすべてのものとその理由を予測し、正当な理由で生成することを意図して、それを実行してください。ただし、どこに向かっているのか、またはそこへの行き方がわからない場所を通過するために、それ (または他の手法) を使用しないでください。

一部の人々は、現在の問題を解決し、何らかの行動を実装すれば、あなたは成功者だと考えています。次の開発者 (あなた自身かもしれません) のために、あなたが自分の道にどれだけの未熟さと不透明さを残しているかは、必ずしも明らかではありません。

于 2009-02-07T19:37:12.663 に答える