Pragmatic Programmerは、コード ジェネレーターの使用を推奨しています。プロジェクトでコード ジェネレーターを作成しますか? はいの場合、それらを何に使用しますか?
26 に答える
「PragmaticProgrammer」では、HuntとThomasがパッシブコードジェネレーターとアクティブコードジェネレーターを区別しています。
パッシブジェネレーターは1回実行され、その後、結果を編集します。
アクティブなジェネレーターは必要な頻度で実行されます。結果は置き換えられるため、結果を編集しないでください。
IMO、後者はDRY(自分で繰り返さない)の原則に近づくため、はるかに価値があります。
プログラムへの入力情報を2つの部分に分割できる場合、ほとんど変更されない部分(A)(メタデータやDSLなど)と、プログラムの実行ごとに異なる部分(B)(ライブ入力) 、Aのみを入力として受け取るジェネレータプログラムを記述し、Bのみを入力として受け取るアドホックプログラムを書き出すことができます。(これの別名は部分評価です。)
ジェネレータプログラムは、AとBではなく、入力Aを通過するだけでよいため、より単純です。また、頻繁に実行されないため、高速である必要はなく、メモリリークを気にする必要もありません。
アドホックプログラムは、ほとんど常に同じ入力を通過する必要がないため、より高速です(A)。AとBではなく、入力Bについてのみ決定する必要があるため、より簡単です。
生成されたアドホックプログラムは非常に読みやすく、エラーを簡単に見つけることができるようにすることをお勧めします。ジェネレーターからエラーを削除すると、エラーは永久になくなります。
私が取り組んだあるプロジェクトでは、チームが2インチの厚さの設計仕様と長い実装スケジュールを備えた複雑なデータベースアプリケーションを設計し、パフォーマンスへの懸念を抱えていました。コードジェネレーターを作成することで、3か月で2人が作業を行い、ソースコードリスト(C)の厚さは約0.5インチで、生成されたコードは問題にならないほど高速でした。アドホックプログラムは、わずかな費用で毎週再生されました。
したがって、アクティブなコード生成は、それを使用できる場合、双方にメリットがあります。そして、これがまさにコンパイラーが行うことであることは偶然ではないと思います。
ハードウェア設計では、「スタック」のいくつかのレベルでこれを行うのがかなり一般的です。たとえば、DMA エンジンとクロスバー スイッチのさまざまな幅、トポロジ、および構造の Verilog を出力するコード ジェネレーターを作成しました。これは、このパラメーター化を表現するために必要な構造が、合成およびシミュレーション ツール フローでまだ成熟していなかったからです。
また、SRAM、キャッシュ、レジスタ ファイル構造など、アルゴリズムで表現および生成できる非常に規則的なもののレイアウト データに至るまで、論理モデルを発行することも日常的です。
また、システム オン チップ上のすべてのレジスタの XML 記述を取得し、HTML を出力するコード ジェネレーターの作成にもかなりの時間を費やしました (はい、はい、XSLT について知っています。 Verilog、SystemVerilog、C、アセンブリなど、さまざまなチーム (フロントエンドおよびバックエンドの ASIC 設計、ファームウェア、ドキュメントなど) が使用するそのデータの「ビュー」(およびこの単一の XML「コードベース」によって一貫性を保ちます)。それは重要ですか?
また、人々はコード ジェネレーターを作成して、たとえば、有限状態マシンなどの非常に一般的なものの簡潔な記述を作成したり、より冗長な命令型言語コードを機械的に出力してそれらを効率的に実装したりすることも好みます (例: 遷移テーブルやトラバーサル コード)。
コードジェネレーターは、正しい引数なしで広く使用されると、コードが理解しにくくなり、保守性が低下します (ちなみに動的 SQL と同じです)。個人的には、いくつかの ORM ツールと一緒に使用しています。なぜなら、ここでの使用法はほとんど明らかであり、最近では「手作業」で維持するように設計されていない検索パーサー アルゴリズムや文法アナライザーなどの場合もあるためです。乾杯。
コード ジェネレーターを使用して、データ エンティティ クラス、データベース オブジェクト (トリガー、ストアド プロシージャなど)、サービス プロキシなどを生成します。パターンに従って反復的なコードが多く、多くの手作業が必要な場合は、コード ジェネレーターが役立ちます。ただし、保守性が苦痛になるほど使いすぎるべきではありません。それらを再生成したい場合にも、いくつかの問題が発生します。
Visual Studio や Codesmith などのツールには、ほとんどの一般的なタスク用の独自のテンプレートがあり、このプロセスを簡単にします。ただし、自分で展開するのは簡単です。
仕様からコードを生成するコード ジェネレーターを作成すると便利なことがよくあります。タイプミスや省略によるエラーが発生する可能性を減らします。
はい、AAA プロトコル Diameter (RFC 3588) 用に独自のコード ジェネレータを開発しました。直径アプリケーションの文法を記述した XML ファイルから読み取る直径メッセージの構造と API を生成できます。
これにより、完全な直径インターフェース (SH/CX/RO など) を開発する時間が大幅に短縮されました。
コードジェネレーターは通常、長期間使用すると管理しにくいコードを生成します。
ただし、コードジェネレーターを使用することが絶対に必要な場合(スイング開発用のEclipse VEは私が時々使用するものです)、生成されているコードを確認してください。私を信じてください、あなたはあなたが精通していないあなたのアプリケーションのコードを望まないでしょう。
私の意見では、優れたプログラミング言語はコードジェネレーターを必要としません。なぜなら、イントロスペクションとランタイムコード生成は、Python メタクラスや新しいモジュールなどの言語の一部になるからです。
多くのコード ジェネレーターが存在する可能性がありますが、コードをより理解しやすくし、使用しているフレームワークとガイドラインに適合させるために、常に独自のコード ジェネレーターを作成しています。
すべての新しいコードにジェネレーターを使用して、コーディング標準に従っていることを確認します。
最近、社内の C++ ジェネレーターをCodeSmithに置き換えました。ツールのテンプレートを作成する必要がありますが、ツールを自分で保守する必要がないことが理想的です。
最近ジェネレーターが必要になったのは、ハードウェアからデータを読み取り、最終的に「ダッシュボード」UI にポストするプロジェクトでした。その中間には、いくつかのデータ ポイントのモデル、プロパティ、プレゼンター、イベント、インターフェイス、フラグなどがありました。設計に問題がないことに満足するまで、いくつかのデータ ポイントのフレームワークを作成しました。次に、慎重に配置されたコメントの助けを借りて、Visual Studio マクロに「ジェネレーション」を配置し、マクロを微調整してクリーンにし、マクロ内の関数にデータポイントを追加してジェネレーションを呼び出しました。 ?) 最終的には。
マクロの力を過小評価しないでください:)
また、 CodeRush のカスタマイズ機能について理解を深めて、よりローカルな生成要件に対応できるようにしようとしています。コード ブロックを生成するときにオンザフライで意思決定が必要な場合は、強力なものがあります。
何人探していますか?私は 2 つのメジャーなものと多数のマイナーなものを作成しました。主要なものの最初のものでは、1500 行のプログラム (ギブ オア テイク) を生成することができました。このプログラムは、ファミリーに非常に似ていますが、データベース内のさまざまなテーブルに調整されており、それを高速かつ確実に行うことができました。
コード ジェネレーターの欠点は、生成されたコードにバグがある場合 (テンプレートにバグが含まれているため)、多くの修正が必要になることです。
ただし、ほぼ反復的なコーディングが多く行われる言語またはシステムの場合、優れた (十分な) コード ジェネレーターはメリットです (「ドグル」よりもメリットがあります)。
SQL テーブルに対して実行する独自のコード ジェネレーターがあります。データ、データ アクセス層、およびビジネス ロジックにアクセスするための SQL プロシージャを生成します。私のコードと命名規則を標準化するのに驚異的でした. データベース テーブル内の特定のフィールド (id 列や更新された日時列など) を想定しているため、データ設計の標準化にも役立ちました。
組み込みシステムでは、フラッシュにバイナリ データの大きなブロックが必要になることがあります。たとえば、ビットマップ フォント グリフを含むテキスト ファイルを取り、興味深い定数 (最初の文字、最後の文字、文字の幅、高さなど) を宣言する .cc/.h ファイルのペアに変換し、実際のデータを次のように宣言するものがあります。大きなstatic const uint8_t[]
。
C++ 自体でそのようなことをしようとすると、最初のパスなしでコンパイル時にフォント データが自動生成されるため、面倒で、ほとんどの場合判読できなくなります。手動で .o ファイルを作成することは論外です。方眼紙を分解し、バイナリにエンコードし、それらすべてを入力することも同様です。
私見、この種のことはコードジェネレーターの目的です。コンピュータがあなたのために働くことを決して忘れないでください。
ところで、ジェネレーターを使用する場合は、生成された各ファイルの先頭と末尾の両方に常に次のような行を含めます。
// This code was automatically generated from Font_foo.txt. DO NOT EDIT THIS FILE.
// If there's a bug, fix the font text file or the generator program, not this file.
コードを書くつもりがないのなら、他の誰かが生成したコードに慣れることができますか?
独自のコードまたはコードジェネレーターを作成する方が、時間的にも長期的にも$$$の方が安いですか?
DTDまたはスキーマに準拠した方法でデータベースからXMLデータを出力する数百のクラス(java)を構築するコードジェネレーターを作成しました。コード生成は一般的に1回限りのことであり、コードはさまざまなビジネスルールなどでスマート化されます。出力はかなり衒学的な銀行向けでした。
ビルドプロセス中に呼び出される独自のコードジェネレーターを主にT-SQLで作成します。
メタモデルデータに基づいて、トリガー、ロギング、C#const宣言、INSERT / UPDATEステートメント、データモデル情報を生成して、アプリが期待されるデータベーススキーマで実行されているかどうかを確認します。
生産性を高め、仕様を増やし、コーディングを減らすために、フォームジェネレーターを作成する必要があります;)
いくつかのコードジェネレーターを作成しました。テンプレートを使用するSQLストアドプロシージャ用のパッシブコードジェネレーターがありました。これにより、ストアドプロシージャの90%が生成されました。
Entity Frameworkに切り替えてから、Visual Studio内でT4(テキストテンプレート変換ツールキット)を使用してアクティブなコードジェネレーターを作成しました。これを使用して、エンティティの基本的なリポジトリ部分クラスを作成しました。非常にうまく機能し、コーディングの束を節約します。また、特定の属性でエンティティクラスを装飾するためにT4を使用します。
コードジェネレーターは、プログラミング言語の制限に対する回避策です。私は個人的にコードジェネレーターよりもリフレクションを好みますが、コードジェネレーターの方が柔軟性が高く、実行時にコードが明らかに高速になることに同意します。C#の将来のバージョンには、ある種のDSL環境が含まれることを願っています。
はい、私はいくつかを維持しなければなりませんでした。CORBA やその他のオブジェクト通信スタイルのインターフェイスは、おそらく私が最初に考える一般的なものです。これから説明するインターフェイスによって提供されるオブジェクト定義がありますが、これらのオブジェクトをコードで構築する必要があります。コード ジェネレーターをビルドして実行することは、かなり日常的な方法です。これは、一部のレガシー通信チャネルをサポートするためだけにかなり長いコンパイルになる可能性があり、単純にするために CORBA にラッパーを配置する傾向が強いため、事態はさらに悪化します。
一般に、大量の構造体がある場合、または使用する必要がある急速に変化する構造体があるが、メタデータを介してオブジェクトを構築することによるパフォーマンスの低下を処理できない場合は、コード ジェネレーターを作成する必要があります。
EMF-Eclipse Modeling Frameworkが提供するコード生成機能を使用します。
私が使用する唯一のコード ジェネレーターは、Web サービス パーサーです。個人的には、新しい従業員や引き継ぎ後の別のチームのメンテナンスの問題があるため、コード ジェネレーターには近づきません。
独自のコード ジェネレーターをゼロから作成する必要があったプロジェクトは思い浮かびませんが、既存のジェネレーターを使用したプロジェクトはいくつかあります。(エンタープライズ ソフトウェア用の Java でパーサーとモデルを構築するために、Antlr と Eclipse Modeling Framework の両方を使用しました。) 他の誰かが作成したコード ジェネレーターを使用する利点は、作成者がその分野の専門家である傾向があり、問題を解決したことです。まだ存在すら知らなかったこと。これにより、時間とフラストレーションが軽減されます。
そのため、目の前の問題を解決するコードを書くことができるかもしれませんが、コードをより速く生成することができ、私が書いたものよりもバグが少なくなる可能性が高くなります.
コード ジェネレーターは多くの場合、特にある形式から別の形式にマッピングする場合に非常に役立ちます。IDL から C++ へのコード ジェネレーター、データベース テーブルから OO 型へのコード ジェネレーター、コードのマーシャリングなどを行ってきました。
著者が言おうとしているのは、あなたが開発者なら、コンピューターを自分のために働かせることができるはずだということだと思います。コードの生成は、自動化すべき明らかなタスクの 1 つにすぎません。
私はかつて、IDL から C++ へのマッピングを手動で行うと主張した人と一緒に仕事をしました。プロジェクトの最初は、私たちの残りの部分が何をすべきかを理解しようとしていたので、彼は追いつくことができましたが、最終的に彼はボトルネックになりました. Perl でコード ジェネレーターを作成したところ、数分で彼の「作業」をほぼ完了できました。
プログラム変換に基づく「ユニバーサル」コード ジェネレーターを参照してください。
私はアーキテクトであり、主要な実装者です。このジェネレーターのかなりの部分が、このジェネレーターを使用して生成されていることに注意してください。