java style メタプログラミング-自己説明的なコード-チュートリアル、記事、書籍




naming conventions java (6)

私はプログラミングスキルを向上させることに目を向けています(実際に私はジェフアトウッドが書いたように、毎年少なくなるように努力しています)ので、私はメタプログラミングと自己説明的なコードについて読むことを考えていました。

私はこれに馬鹿のガイドのようなものを探しています(ダウンロードのための無料の書籍、オンラインリソース)。 また、私はあなたの平均的なwikiページと、言語にとらわれないもの、あるいはJavaの例を用いることが望ましい。

あなたは、そのすべてを効率的に実践できるようなリソースを知っていますか?経験はたくさんありますが、流れの悪い決定を回避するエクスペリエンスを作りたいと思っています。

編集:

Pragmatic Programmerのこの例のようなもの:

...単純な図面パッケージを制御するミニ言語を実装する...言語は一文字のコマンドで構成されています。 いくつかのコマンドの後には、単一の番号が続きます。 たとえば、次の入力は四角形を描画します。

P 2 # select pen 2
D # pen down
W 2 # draw west 2cm
N 1 # then north 1
E 2 # then east 2
S 1 # then back south
U # pen up

ありがとうございました!


Tclは、ジェネリックプログラミング機能を必要とするところまで複雑になってきたため、ドメイン特有の言語を作成する方法としてはじまりました。 さらに、それは言語の重要なユースケースなので、あなた自身のコマンドを正確に追加するのは非常に簡単です。

Javaと統合された実装を希望するJaclJaclはJava Tcl 実装しており、DSLに焦点を当てたスクリプト性を提供し、Javaオブジェクトへのアクセスにもアクセスします。

(メタプログラミングはプログラムを書くプログラムですが、いくつかの言語は他の言語よりもはるかに優れています。実行時にスクリプトを許可するスクリプト言語はすべて、メタプログラミングがより柔軟になるように記述されているため、メタプログラミングが容易になる傾向があります。


上記の私のコメントでは、C ++テンプレートのメタプログラミングについて触れました。 したがって、C ++テンプレートのメタプログラミングを使用した簡単な例を提供しましょう。 私はあなたがあなたの質問をjavaでタグ付けしたことを知っていますが、これは洞察力があるかもしれません。 私はあなたがC ++コードを理解できることを願っています。

例によるデモンストレーション:

フィボナッチ系列 (0,1,2,3,5,8,13、...)を生成する次の再帰関数を考えてみましょう。

unsigned int fib(unsigned int n)
{
    return n >= 2 ? fib(n-2) + fib(n-1) : n;
}

フィボナッチシリーズから項目を取得するには、この関数、たとえばfib(5)を呼び出し、値を計算して返します。 今のところ特別なものはありません。

しかし、C ++では、テンプレートを使ってこのコードを書き直すことができます(Javaのジェネリックに似ています)ので、フィボナッチシリーズは実行時には生成されませんが、 コンパイル 時に生成されます

// fib(n) := fib(n-2) + fib(n-1)
template <unsigned int n>
struct fib                     // <-- this is the generic version fib<n>
{
    static const unsigned int value = fib<n-2>::value + fib<n-1>::value;
};

// fib(0) := 0
template <>
struct fib<0>                  // <-- this overrides the generic fib<n> for n = 0
{
    static const unsigned int value = 0;
};

// fib(1) := 1
template <>
struct fib<1>                  // <-- this overrides the generic fib<n> for n = 1
{
    static const unsigned int value = 1;
};

このテンプレートを使用してフィボナッチシリーズからアイテムを取得するには、単純にfib<5>::valueの定数値を取得しfib<5>::value

結論(「メタプログラミングとは何が関係していますか?」):

テンプレートの例では、実行中のプログラムではなく、コンパイル時にFibonacciシリーズを生成するのはC ++コンパイラです。 (これは最初の例では関数を呼び出しているが、テンプレートの例では定数値を取得していることから明らかです)フィボナッチ数を計算する関数を書かずにフィボナッチ数を取得します。 その関数をプログラミングする代わりに、コンパイラが明示的に設計されていないことをあなたに向けてプログラムしました。これは非常に顕著です。

したがって、これはメタプログラミングの一形態です:

メタプログラミングは、他のプログラム(またはそれ自身)をそのデータとして書き込むか、または操作するコンピュータプログラムの書き込みであり、そうでなければ実行時に実行されるコンパイル時の作業の一部である

- 私が追加Metaprogramming定義。

(上記のテンプレートの例の副作用にも注意してください:コンパイラがあなたのフィボナッチ数をあらかじめ計算するようになると、どこかに格納する必要があります。プログラムのバイナリのサイズは、 fib<n>::valueという用語。実行時に計算時間を節約できます。


メタプログラミングについてのPluralsightに関するコースがあります。これは、良いエントリーポイントになるかもしれません。https://app.pluralsight.com/library/courses/understanding-metaprogramming/table-of-contents


メタプログラミングの素晴らしい世界へようこそ:)メタプログラミングは実際に多くのことに関係しています。 私は何が私の心に来るのかを列挙しようとします:

  • マクロ プログラミング言語の構文と意味を拡張する能力は、用語マクロの下で最初に探究されました。 いくつかの言語はマクロに似た構造を持っていますが、選択肢はもちろんLispです。 メタプログラミングに興味があるなら、Lispとマクロシステム(そしてコードとデータが同じ表現を持つ言語のホモ接合性)を理解することが絶対必要です。 JVM上で動作するLispの方言が必要な場合は、 Clojureに移動してください。 いくつかのリソース:

    そうでなければ、Lispに関する多くのリソースがあります。

  • DSL 。 1つの言語構文とセマンティクスを拡張する能力は、今や「DSL」という言葉の下で改められています。 DSLを作成する最も簡単な方法は、 インタプリタのパターンです。 その後、 流暢なインターフェイスと外部DSL(Fowlerの用語に従う)で内部DSLに来る。 最近私が見た素敵なビデオがあります:

    その他の回答はすでにこの分野のリソースを指しています。

  • 反射 。 メタプログラミングは、不可分の形式の反映でもあります。 実行時にプログラム構造に反映する能力は非常に強力です。 それでは、 introspectionintercession 、そしてreificationが何であるかを理解することは重要です。 IMHOでは、リフレクションには2つの広範なカテゴリがあります。1.コンパイル時に構造がわからないデータの操作(実行時にデータの構造が提供され、プログラムが反映されます)。 2. ダイナミックプロキシ 、ファクトリなどの強力なプログラミングパターンSmalltalkは、 すべてが反映されている、反射を探索する選択肢です。 しかし、私はRubyもメタプログラミングを活用したコミュニティで、そのための良い候補だと思っています(しかしRubyについては自分自身についてはあまりよく分かりません)。

    反射に関する豊富な文献もあります。

  • 注釈 。 アノテーションは言語の反映能力のサブセットとして見ることができますが、独自のカテゴリに値すると思います。 注釈が何であるか、そしてそれらをどのように使うことができるのか、私はすでに答えました。 注釈は、コンパイル時または実行時に処理できるメタデータです。 Javaは、 アノテーションプロセッサツールPluggable Annotation Processing API 、およびミラーAPIを 使用してJava APIを適切にサポートしています

  • バイトコードまたはAST変換 。 これは、コンパイル時または実行時に行うことができます。 これは何らかの理由で低レベルのアプローチですが、メタプログラミングの一形態と考えることもできます(ある意味では、非同型言語のマクロと同じです)。

結論:メタプログラミングとは、プログラムが自分自身を推論したり、自分自身を修正する能力です。 メタスタックのオーバーフローのように、スタックオーバーフロー自体について質問する場所です。 メタプログラミングは、特定の手法ではなく、むしろコンセプトとテクニックのアンサンブルです。

いくつかのことがメタプログラミングの傘の下にある。 あなたの質問から、あなたはマクロ/ DSLの部分にもっと興味があるようです。 しかし、すべてが最終的には関連しているので、メタプログラミングの他の側面も見逃せません。

PS:私が提供したリンクのほとんどは、チュートリアルや入門記事ではないことがわかっています。 これらは私が好きなリソースです。メタプログラミングの概念と利点を説明しています。これはもっと面白いと思います



あなたの例から、 ドメイン固有言語 (DSL)、具体的には内部DSLについて話しているようです。

HereはDSLに関する一般的な書籍の一覧(SQLのようなDSLについて)があります。

Martin Fowlerは進行中の作業であり、現在onlineある本を持っていonline

AyendeはブーイングでDSLに関する本を書いた。

更新 :(コメントに続く)

Metaprogrammingとは、他のプログラム(またはそのデータ)を制御するプログラムを作成すること、時にはDSLを使用することです。 この点で、バッチファイルとシェルスクリプトは、他のプログラムを呼び出して制御するので、メタプログラミングと見なすことができます。

あなたが持っている例は、ペイントプログラムを制御するためにメタプログラムによって使用されるDSLを示しています。





coding-style