レベルエンター山本大のブログ

面白いプログラミング教育を若い人たちに

BLOCKVROCKリファレンス目次はこちら

Guice2.0 beta 紹介記事の翻訳(4)

原文:IBM Developer : Sorry, that page no longer exists
訳1:Guice2.0 beta 紹介記事の翻訳(1) - 山本大の日記
訳2:Guice2.0 beta 紹介記事の翻訳(2) - 山本大の日記
訳3:Guice2.0 beta 紹介記事の翻訳(3) - 山本大の日記

実装クラスを選択する(Selecting your implementation)

So let's say you have more than one Vehicle in your application. The equally heroic Weasel Girl can't drive the FrogMobile! At the same time, you don't want to hardcode a dependency on the WeaselCopter. Guice solves this problem by letting you annotate your dependencies. Listing 11 shows Weasel Girl requesting a faster mode of transport:


さぁ、では1つ以上の乗り物をアプリケーションに持たせることにしましょう。
ヒーローのイタチガール(Weasel Girl)は、FrogMobileを運転することはできないのです!
同時にイタチコプター(WeaselCopter)の依存性をハードコードしたくもありません。
Guiceは、この問題を依存性に対するアノテーションを付けることで解決します。
リスト11は、イタチガールがより早い移動手段を要求しているところを表しています。

リスト11. 特別な実装を取得するためにアノテーションを使う(Use annotations to request a specific implementation)

@Inject
public WeaselGirl(@Fast Vehicle vehicle) {
  this.vehicle = vehicle;
}

In Listing 12, the HeroModule uses the binder to tell Guice that the WeaselCopter is "fast":


リスト12では、ヒーローモジュールが、「WeaselCopterが"より早い(fast)"」ことをGuiceに伝えるためのバインダーを使っています。


リスト 12. Guiceにモジュールのあなたのアノテーションについて伝える(Tell Guice about your annotation in your Module)

public class HeroModule implements Module {
 public void configure(Binder binder) {
    binder.bind(Vehicle.class).to(FrogMobile.class);
    binder.bind(Vehicle.class).annotatedWith(Fast.class).to(WeaselCopter.class);
  }
}

Notice that I chose an annotation that describes the sort of vehicle I want in abstract terms (@Fast) rather than ones that are too closely tied to the implementation (@WeaselCopter). If you use annotations that describe the intended implementation too precisely, you create an implicit dependency in the minds of your readers. If you use @WeaselCopter and Weasel Girl borrows the Wombat Rocket, it could confuse programmers reading or debugging the code.
To create the @Fast annotation, you need to copy the boilerplate in Listing 13:

実装と密接に結びついた(@WeaselCopter)よりも、抽象的なterms(@Fast)であるを使って、
乗り物の順番を説明するアノテーションとしていることに注意してください。
もし、よりすばらしい実装を説明するアノテーションを代わりに使いたいときにも、
ソースコードの読み手に対して明示的に依存性を作成することができます。
もし@WeaselCopterを使っていて、Weasel Girlががウォンバットロケット(Wombat Rocket)を打つなら、プログラマーがコードを読んだりデバッグをしたりする際に混乱することでしょう。
@Fastアノテーションを作るために、リスト13の中のboilerplateをコピーする必要があります。


リスト13. (Copy-paste this code to create a binding annotation)

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.PARAMETER})
@BindingAnnotation
public @interface Fast {}

If you write a lot of BindingAnnotations, you'll wind up with a lot of these little files, each of which differs only in the name of the annotation. If you find this really annoying or want to do some quick prototyping, you could consider Guice's built-in @Named annotation, which accepts a string attribute. Listing 14 illustrates that alternative:


もし、バインディングアノテーションを沢山書いたとしたら、沢山の小さなファイルのに書かれた、ただ名前の違うだけのアノテーションにイライラさせられることになるでしょう。もし、これが本当に面倒だとおもったら、もしくはいくつかの簡単なプロトタイプを行いたいとおもったら、Guiceにはじめから入っている@Namedアノテーションを使うことを検討してください。このアノテーションは、文字列の属性を受け取ります。
リスト14は、この方法による代替手段を例示したものです。



リスト14. カスタムアノテーションの代わりに@Namedアノテーションを使う(Using @Named instead of a custom annotation)

// in WeaselGirl
@Inject
public WeaselGirl(@Named("Fast") Vehicle vehicle) {
  //...
}

// in HeroModule
binder.bind(Vehicle.class)
  .annotatedWith(Names.named("Fast")).to(WeaselCopter.class);


This works, but because the name lives inside a string, you give up the benefits of compile-time checks and autocompletion. On the whole, I'd rather write my own annotations.
What if you don't want to use an annotation at all? Even adding @Fast or @Named("Fast") makes your class partially responsible for configuring itself. If that troubles you, read on.


これは動作しますが、名前は文字列の中にあります。コンパイル時のチェックと自動的な整合性確保という利益をあきらめなくてはならなくなります。
総合して考えると、私は独自アノテーションを書いたほうがよいと思います。
アノテーションをまったく使いたくないんだというなら、@Fastや@Named("Fast")を追加することでさえ、クラスがそれ自体を構成するのに部分的に責任を負うようになります。もしそれが嫌だというなら、続きを読んでください。