본문 바로가기

이생각 저생각

Guice 라고 쓰고 Juice 라고 읽는다.

최근에 학습하다가 중단한 Google 의 DI 프레임워크인 Guice

DI에 특화된 프레워크이며 객체 생성 속도가 (지들 말로는) 스프링의 100배쯤이라고 한다. (설마! 근데, 혹자는 1000배라는 이야기도..-_-);;

또한 XML 대신에 annotaion 을 사용하여 injection 을 처리한다.

== Injection 처리 ==
public class Client {
    private final Service service;
 
    @Inject
    public Client(Service service) {
        this.service = service;
    }
    public void go() {
        service.go();
    }
}

== Bind 처리 ==

public class MyModule implements Module {
    public void configure(Binder binder) {
        binder.bind(Service.class)
          .to(ServiceImpl.class)
          .in(Scopes.SINGLETON);
    }
}

== 논란의 핵심 (implementBy) ==

@ImplementedBy(ServiceImpl.class)
public interface Service {
    void go();
}

여담인데 한가지 아쉬운건, Guice 개발자가 두명인데, 그중 한명인 Bob lee 는 의사소통에 다소 문제가 있지 싶다.

(BOB LEE의 BLOG 난장판임... -_-;; spring sucks!! 라는 발언까지...)

어쨌든 XML Hell 을 annotation 으로 풀어보겠다는 의지는 확실한듯.

이하 소개 비디오와 '스프링과 피코 컨테이너와 Guice의 비교' 글은 한 번쯤 봐둘만은 하다.


Guice 소개 비디오
http://video.google.com/videoplay?docid=6068447410873108038

Comparison between Guice, PicoContainer and Spring
http://www.christianschenk.org/blog/comparison-between-guice-picocontainer-and-spring/


Lies, Damned Lies, and XML - Bob lee (논쟁의 중심)
http://crazybob.org/2007/06/lies-damned-lies-and-xml.html

커플링에 대한 Kevin Bourrillion 의 의견과 논쟁
http://smallwig.blogspot.com/2007/06/coupling.html

== 이하는 읽어도 그만, 안 읽어도 그만~ ==


The point I was trying to make is the following. Lets take the (evil) @ImplementedBy annotation: you annotate an interface with it and tell Guice that it's implemented by the supplied class. This could be problematic in two ways:
1. the interface suddenly knows its implementing class. That's not what you want if you aim for loose coupling.
2. this leads to the second point: with this annotation you're probably breaking a well-designed package structure. Suppose you've got some class that needs the interface in a package "foo", the interface is in package "foo.bar" and an implementation of the interface is in "foo.bar.impl". That's a nice tree: the class uses the interface, while the implementation of the interface uses -well- the interface. There are no circles; only unidirectional links between the packages. If you now use the @ImplementedBy annotation it gets circular: the interface has a link back to "foo.bar.impl" and isn't independent from the implementation anymore.

You might say that a) the annotation is a kind of documentation as it just points out what's in the code anyway and b) that these cases were you want to have super-independent packages are rare. While I would be on your side, all I wanted to say was, that you can see it this way too and that there might be people who choose Spring instead of Guice (because of these artificial arguments) because... -well- they are fussy.

Finally I'd like to correct my conclusion. You'll probably use @Inject and some implementations of Module (e.g. one for tests and one for production use) and that'll be it. This doesn't couple your code tight to Guice and the annotations don't hurt at all. Whether there's one more JAR on my classpath (whether on compile- or runtime) or not doesn't bother me, because I'm using Maven so this just comes down to some few lines in the POM.

------------------------

"Lets take the (evil) @ImplementedBy annotation:"
...
"1. the interface suddenly knows its implementing class. That's not what you want if you aim for loose coupling."

I can tell you that from a maintenance perspective the ImplementedBy annotation could actually be beneficial. Why? Because when you are browsing through code and you hit an interface, you are no longer faced with a brick wall (you don't know which implementation is being used). With the aforementioned annotation you could navigate to the implementation with a single click. Sure you can do a search for the implementation but in some situations there are multiple candidates, and thats where you can start wasting serious time (if you are unfamiliar the the code).