web-dev-qa-db-ja.com

ソースコードの自動生成-良いアイデアか、それとも悪夢か?

Javaソースコードの生成)に関する私の質問 への応答として、 この回答 に、潜在的なメンテナンスの問題についての警告が表示されました。

  1. 自動生成されたコードを混在させると、将来、誰かが小さな動作を微調整するためにコードを変更するリスクが常に発生します。この変更が失われるのは、次のビルドの問題だけです。
  2. 開発者がそうするのを防ぐために、自動生成されたソースの上にあるコメントのみに依存する必要があります。
  3. version-controlling-someMethod()のテンプレートを更新すると、ソースの更新が自動生成されている場合でも、すべてのソースファイルのバージョンが更新されます。冗長な履歴が表示されます。

彼が提案した代替案は、バイトコード生成を使用して実行時にクラスを拡張することです。

生成されたコードを既存のソースコードファイルに挿入すると保守性が向上すると考えていました。背後でいくつかの操作を実行する代わりに、何が行われているのかが明確になるからです。

したほうがいい:

  1. 生成されたコードを既存のソースコードに追加するツールを作成します。または

  2. 実行時にバイトコード生成を使用してクラスを拡張しますか?

これらのアプローチのいずれかであなたの経験は何でしたか?

13
Tony the Pony

中型のJavaプロジェクト(約300クラス)を複数の Maven モジュールで実行し、DSLからドメインクラスを自動生成(約100クラス)しました素晴らしい Eclipse Xtext プロジェクトで、私はもう一度やります:)

ここで、私が(今日まで)言及したカンバーストーンにうまく成功した方法についてのヒントを示します。

私のプロジェクトはmavenでビルドされたので、自動生成されたコードを処理するためにmavenの方法を使用しました。つまり、私のxtext dslとジェネレータープロジェクトもmavenによって処理され、フルビルドのたびにすべての生成コードを新しく作成します(あるはずです)。参照: maven tychoを使用したxtextプロジェクトのビルド 。したがって、私のプロジェクトでは「mavenパッケージ」を実行するだけで済みます。

生成されたコードと継承を介して入力した手を分割しました(複数のファイルのクラスにまたがるc#の方法は嫌いです)。

/* Generated code, will not be in revision control */
abstract class AbstractFoo {
    //getters and setters
    //collection accessors
    //helper methods like toString equals hashCode
}

/* Generated one time, will be in revision control */
class Foo extends AbstractFoo{
    //business logic if needed
}

Xtextジェネレータープロジェクトを使用すると、1回だけ作成する必要があるファイルを定義することができます。そのため、具体的なクラスを1回だけ作成し、Gitリポジトリに保持しました。生成された具象クラスは2ライナーに過ぎないため、メソッドを追加しなくてもクラスを使用できます。

2つのテンプレート(抽象と具象)について、抽象クラス用と具象用の2つのテストクラステンプレートを作成しましたが、具象テストクラスも、1回と2つのライナーを生成するだけです。

生成されたコードが配置されている私のmavenモジュールで、私はこのレイアウトを使用しました(ほとんどのmaven規則):

myproject/src/main/Java -> concrete generated classes, one time
myproject/src/test/Java -> generated tests, one time
myproject/target/generated-sources/mydsl -> abstract generated classes, always
myproject/target/generated-sources/mydsltests -> auto generated tests, always

テンプレートを変更すると、(常に)生成されたソースが含まれないため、Xtextジェネレータープロジェクトのテンプレートのみがリビジョンコントロールで変更されます。

したがって、Eclipse Xtextを試してみることをお勧めします。サンプルプロジェクトを開始すると、1時間未満でプロトタイプが実行されます。

15
moritz

このアプローチを少しはしたくありません。私の好みには謎が多すぎます。

アスペクトやデコレータを好むのは、アスペクトを生成するのではなく実際に記述する必要があり、それらを織り込むときに何をしているのかを明確にするためです。

7
duffymo

私が見てきたことから、ソースコードの生成は次の場合に最適に機能します。

  1. 生成されたクラスのコードを変更する理由がない場合、または
  2. 一度変更したクラスのコードを再生成する理由はありません(足場アプローチ)、または
  3. あなたは、クラスを複数のファイルにまたがらせることができるC#のような言語で作業しています。 (自動生成されたコードを含む1つのファイルと、コントリビューションを含む別のファイルを作成できます)、または

あなたの質問に基づいて、これらのどれもおそらく真実ではないと思います。個人的にはバイトコードの生成を行っていませんが、GWTなどのよく使われているツールがそのアプローチを選択しているので、おそらく望ましい方法です。

ただし、最終的に達成しようとしていることを聞いて、より標準的なJavaプラクティスを使用するより良い方法がないかどうかを確認するように同僚に依頼します。

5

ビルドプロセスでコードを生成し、それをjarし、依存プロジェクトのクラスパスに含めることができます。これにより、不正な開発者が生成されたソースを変更する問題が回避されます。生成されたjarのバージョンを設定する必要はなく、生成されたメタデータだけをバージョンアップする必要はありません。

これは、XMLBeansなどのツールで過去に使用した方法であり、かなりうまくいきました。

4
nsfyn55

Eclipse Modeling Framework は、非常に優れたコード生成を行いますが、理解するのが複雑です。明らかに、モデルが再生成されるたびにそれらの変更を元に戻すことなく、モデルコードにユーザーコードを追加できるようになっています。また、NetbeansのMattise UIエディターは、ユーザーインターフェイスのすべての生成を行い、最新の状態に保ちます。

2
Chris Dennett

実際にマネージC++フォームでは、自動コードと手動コードの両方が.hファイルに混在しています。自動コードは、デザイナーモードでフォームを開き、何かを変更して保存するたびに更新されます。別のファイルでコードを生成したのと同様に機能します。

1
AareP