Crazy Bob is my Hero

by Jacob 20. August 2007 15:43

Bob Lee, creator of Google’s Guice project (the Dependency Injection framework for Java) has twice left comments here urging me to check out his talk introducing Guice. I resisted this because a) I don’t do Java and b) I figured I’d had enough with a later video recommended by Nate. This afternoon, I broke down and watched it and I’m glad that I did.

It turns out that the things that grated on me from the first Guice video I viewed came mainly from Kevin Bourillion—mostly unfair comparisons to alternatives and boosterism. Bob is very personable, open and seems honestly intent on communicating both how Guice works and the reasons for their design choices. He’s also very clear when discussing real-world reasons for using Guice. I found the video both informative and refreshingly free of the taint of propaganda that so permeates a lot of the explanations of dependency injection I’ve encountered so far.

For one, there are several times where Bob describe’s the unit testing origins and impetus of Guice. One objection I raised in my original post on Dependency Injection is that people are largely talking around the major motivation unit testing plays in the adoption of dependency injection. At one point Bob shocked me when he actually said, "If there’s any reason to use [Guice], it is unit testing." Pardon me while I swoon.

Early on, Bob gave a list of benefits (and one detraction) to implementing dependency injection by hand. I’ve taken that list and expanded it a bit because it helped clarify my thinking on dependency injection. Below is a matrix that includes Bob’s original Factory example, his original evaluation of DI by hand, Guise DI (from what I can tell, I’m open to correction on this one), and TypeMock. To understand it, recognize that some of the items involve three practical objects: A client that calls a service that needs a service implementation. The service implementation is the piece you’d mock.

  Factory Manual DI Guise TypeMock
1. Tests bypass dependency manager (i.e. a factory-like entity) close check check check
2. Explicit binding (cannot create client without providing service implementation) close check check N/A
3. Reuse client with multiple service implementations close check check close
4. Client doesn’t have service implementation dependency at compile time close check check check
5. Service doesn’t have service implementation dependency at compile time close check check close
6. No factory needed to create either service or client close close check check
7. Architecturally neutral close close close check
8. No new dependency in non-test code check check close check
9. Able to mock code-generated or external objects without wrapping close close close check

This isn’t an attempt at a complete list, but it does identify the cleft points in the different strategies for me. The key to loose coupling is there in numbers 3 and 5 which is where TypeMock doesn’t achieve the architectural grace that DI can. The advantage that TypeMock enjoys is in numbers 7, 8, and 9. Guise comes close to achieving number 7, actually, but there’s enough of a learning curve needed to grasp the intricacies of DI in Guise (that could really bite you if you failed to fully understand their implications) that I wasn’t quite willing to give it to them.

Now, how you weight those factors for your projects (and you should be weighing them on a per-project basis) will help lead you to where you might be most comfortable. You can guess how I weigh them in relation to the majority of the projects I work on.

Tags: , , , , , , ,

Programming

Comments


August 21. 2007 22:42
Bob Lee
Good comparison. I didn't use any dependency injection frameworks before I created Guice because I thought they did more harm than good, so I definitely understand where you're coming from.

I've been looking into TypeMock ever since your first post. I like some of the stuff they're doing. I wish we had "using" in Java  (we're working on it).

I noticed their return value example uses two independent statements:

  ClassToIsolate.StaticMethod();
  recorder.Return("fake-value");

TypeMock may already support this, but EasyMock makes clever use of thread locals and static methods so you can check the return type at compile time. The above example would be written like this:

  expect(ClassToIsolate.StaticMethod())
    .andReturn("fake-value");

Since you passed a String to expect(), andReturn() will only accept a String.

Second, my primary fear regarding mocking out static methods is people introducing new dependencies (which are a bitch to find when you have millions of lines) and making my tests slow.

In the Java world, we have a tool named JohnAshcroft which can prevent notoriously slow operations like accessing sockets, etc.

TypeMock could simply annotate such tests with [UnitTest] instead of [Test].


August 21. 2007 23:12
Nate Kohari
@Bob: Can JohnAshcroft also sing poorly but with great comedic value? "Let the eeeaaagglllee soooaaaar..." Smile

This seems like a fair comparison, if you're assuming that you're only using DI for unit testing. I just wrapped up a (long-winded) response to the discussion on a whole here: http://kohari.org/2007/08/21/embracing-change/">http://kohari.org/2007/08/21/embracing-change/.


 Don 
August 22. 2007 04:55
Don
If I am not mistaken, you can use DI with TypeMock if the design requires it.
So 3+5 should be When Needed for typeMock


August 22. 2007 13:01
Jacob
@Bob: I like your examples and the type checking in the chained methods. I would also love it if TypeMock would/could emulate some of Rhino Mocks' use of actual class properties instead of strings to pass to things like ExpectMethod calls. I'm not so sure about the JohnAshcroft tool. Sounds like something to avoid to me Smile.

@Don: True enough. Nothing prevents someone from using both DI and TypeMock. I just find it more valuable to evaluate each on its own to recognize overlaps and divergence.


August 23. 2007 16:20
Eli Lopian
Jacob,
You can try NaturalMocks to use the actual class methods.

using (RecordExpectation recorder = RecorderManager.StartRecording())
{
   mockedInstance.MyProperty = 10;
   mockedInstance.SendMessage("fake");
}
}


 Jonas 
August 30. 2007 05:51
Jonas
I realise this is a comparison of techniques, but doesn't the language barrier matter?
AFAIK Guice is Java-only and TypeMock i .Net-only. Are you asking for a JTypeMock?


August 30. 2007 13:33
Jacob
@Jonas: Yeah, comparing TypeMock and Guice is a bit misleading because they are in separate, non-cross-compatable arenas. I'm using Guice as a stand-in for DI frameworks in general and I hope that's a valid equivalence (I'm not familiar enough with .Net DI frameworks to know for sure, but I suspect that there's more than a little cross-pollination going on between frameworks).

And yeah, a JTypeMock would be pretty cool. I wonder if anyone is working on such a beast?

Comments are closed

Information

    Recent Posts

    Calendar

    <<  September 2010  >>
    MoTuWeThFrSaSu
    303112345
    6789101112
    13141516171819
    20212223242526
    27282930123
    45678910

    View posts in large calendar
    Disclaimer
    The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.

    © Copyright 2010 Scruffy-looking Cat Herder