2010-12-07 15 views
3

WebにはGroovyの無数のメタプログラミング機能を紹介するリソースが豊富にありますが、実際にこのような機能を実際に使用するための包括的な「ベスト・プラクティス」ガイドの近くには何も見つかりません。イディオム・メタプログラミング

別に、過剰な使用方法の典型的な買主の危険負担警告から、私が読んだ助言の最も具体的な作品は本当に古いイディオムを補強するもうひとつの方法である(可能な場合メタクラスを増大させるのに有利なカテゴリを使用することを提案しています「限定された範囲」)。

私の些細なプロジェクトには常識は十分でしたが、私はますます野心的な仕事に取り組む際に、貧弱な/矛盾した先例からの構築にますます関心を寄せています。

Groovyのアドバイス、リソース、具体例(または言語に依存しない - Rubyについての私の短い経験から、同様にしたいと思っていた)メタプログラミングのベストプラクティスが大いにありがたいです。 3*new Rational(num:1, den:2)は明らかにMissingMethodExceptionを生み出す試みて、それでも

@Immutable class Rational{ 
    int num, den 

    Rational multiply(Integer v){ 
     new Rational(num:num*v, den:den) 
    } 
} 
assert new Rational(num:1, den:2) * 3 == new Rational(num:3, den:2) 

トピックを明確にするために、私は(非常に)を提供しますが、いくつかの異なる方法でメタプログラミングを採用する可能性が合理的な数のプロジェクトを簡素化。

static { 
    Integer.metaClass.multiply = {Rational fraction -> fraction*delegate} 
} 
... 
assert 3*new Rational(num:1, den:2) == new Rational(num:3, den:2) 

しかし、これは実際には、結果として、グローバル、むしろ剛性である:コミュニケーションプロパティを追加の

最も簡単、かつおそらく最も脆弱な手段は、Rationalクラスの静的初期化子ブロックとなるであろう。

より汎用性、そしておそらくより組織的なアプローチは、オプションのブートストラップのいくつかの種類を次のようになります。今、私たちは、機能(複数可)を有効にするオプションを持っている

class BootStrap{ 
    static void initialize(){ 
     Integer.metaClass.multiply = {Rational fraction -> fraction*delegate} 
    } 
} 

我々は持っていることを望みます。しかし、これにより、すべての依存関係の問題が発生する可能性があります。

そして正確に便利...安全明示的ではなく、カテゴリがあります:一般的に

@Category(Integer) class RationalCategory{ 
    Rational multiply(Rational frac){ 
     frac*this 
    } 
} 
use(RationalCategory){ 
    assert 3*new Rational(num:1, den:2) == new Rational(num:3, den:2) 
} 

が、私は私が新しい動作を追加しているとき、メタクラスを変更するが、私はかもしれたときにカテゴリを使用見つけますが変更されました。既存の動作。たとえば、除算演算子をオーバーライドして分数を生成すると、カテゴリ内に含まれることが最適です。したがって、通常の使用法を変更するのではなく、単にIntegerクラスに振る舞いを追加するだけなので、ソリューション1または2は「受け入れ可能」になります。

誰もその感想に同意していますか?または、おそらくいくつかの優れた方法論を知っていますか? (ここではミックスインは省略しています。)

+1

私は多くが文脈に依存すると思います。メタメソッドは、グローバルに、または特定のコンテキストでのみ有用ですか?私の最大の問題は、メタメソッドが追加された場所を覚えていること、そして現在の状況でそれを保持していることです。私はカテゴリとしてそれを使用し、それがアプリケーションで世界的により良く適合し、リファクタの一部としてそこに追加されたことが何度もありました。 – dstarh

+0

@dstarhそれは理にかなっています - これは、インプレースとブートストラップの方法論をリストする私のモチベーションの一部でした。メタメソッドをブートストラップクラスに統合することは、最も組織化されたアプローチだと思います。私は間違っている可能性がありますが、それはGrailsで一般的に取られているアプローチだと思います。それはあなたに何が追加されるのか、いつ追加されるのかを制御します。私は脆弱性の要素が気に入らず、ビルド手順を複雑にする必要もありません。カテゴリーから始めるのは、リファクタリングが容易なためですが、確かに論理的なアプローチです。 – Northover

+0

多くの場合、これが最も理にかなっていることに同意します。別の開発者が.toUrl()メソッドがStringクラスに追加される場所が不思議に思えるような面白い問題を防ぐことができます。ある場所に集中させると混乱することはありません。特にクラスを別のクラスに渡すことができます。そこでは、参照されているクラスに、コールスタックのどこかにメタメソッドが追加されています。 – dstarh

答えて

1

Groovyのアクションでメタプログラミングに関する章があります。第1版は非常に古くなっているため、特にメタプログラミングの対象であるため、第2版を入手してください(印刷版はまだ入手できませんが、電子形式で早期のアクセス権を得ることができます)。

+0

私のリストにあります。しかし、http://www.manning.com/koenig2/によれば、関連する「MEAP」の章はまだリリースされていないので、これは待たなければならないかもしれません。 – Northover

関連する問題