Showing posts with label Dependency Injection. Show all posts
Showing posts with label Dependency Injection. Show all posts

Friday, April 8, 2011

RoboGuice (Gone, baby, Gone)

So after fiddling around a bit with RoboGuice, I looked at how to design the application and not incur the cost of using "extends" and remove extraneous jars and annotations.  What I ended up with was (actually) simple, just have all of the components wired together in the "Application" class:

public class BeaconApplication extends Application {
public IGameMapLoader mapLoader;

public BeaconApplication () {
mapLoader = new GameMapLoader(this);
}
}


...then in my Activity:

public class BeaconActivity extends Activity {
IGameMapLoader gameMapLoader;

public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
BeaconApplication ba = (BeaconApplication)getApplication();
this.gameMapLoader = ba.mapLoader;
}


Generally speaking, I don't like the fact that the Activity now needs to know about the Application, but I sure like it a helluva lot more than:


public class BeaconApplication extends RoboApplication {
   protected void addApplicationModules(List modules) {
       modules.add(new BeaconModule()); 
   }
}


public class BeaconModule extends AbstractAndroidModule{
  private Application application;

public BeaconModule(Application application) {
this.application = application;
}

protected void configure() {
IGameMapLoader mapLoader = new GameMapLoader(this.application);
bind(IGameMapLoader.class).toInstance(mapLoader);
    }
}


public class BeaconActivity extends RoboActivity {
@Inject IGameMapLoader gameMapLoader;
} 


I could go back and utilize a "Module" to construct and swap out depending on the environment, but for the time being I'm not coupled to all this extension and annotation nonsense. Also, I could use "get()" methods rather than instance variables on the Application class which could provide me with a way to lazyily create things (although in practice thats usually not a good idea), but anyways for normal operation, the tradeoff to use Guice/RoboGuice in an Android application just seems like a bad idea. (You pay alot for not so much).

RoboGuice and why Android Needs DI (at it's core)

So I've been playing around with RoboGuice, which is built from the semi-popular Guice Dependency Injection Framework.  This is my first experience with Guice, I've always thought Crazy Bob was a smart dude, and I  thought it'd be nice to give Guice a try, I never gave it a chance because Spring caught on like wildfire.

So my impressions so far are well good and bad...

I like:

  • modules - instead of xml files from Spring, you write a Module class and this class binds things together) 
  • Everything happens in the Application class, this makes sense.


I don't like:
extends -- I have to use the RoboGuice class heirarchy (i.e.)
public class BeaconActivity extends RoboActivity

verses
public class BeaconActivity extends Activity


annotations -  make the code less portable, and not have code with silly @Inject tags everywhere

more specifically in cases where you want to configure "library" code.  (You are using a library module and you need to configure it in your code (or module)... Also if you develop library code (i.e. ContourMap generator I created) I don't want to put @Inject annotations everywhere and force people to add this dependency to get it to work for Android.)
(Side note: I think this is why Crazy Bob has been trying to make @Inject a standard Java Notation, because (I fear) people don't want to ship any library code that uses Guice because it will require library users to also include guice.)

lifecycle - you need to understand how RoboGuice configures itself and when in the Android Application Lifecycle, I originally had a bunch of NPE's because I was trying to log out a value in onCreate() and it wasn't available until onStart().

Frankly I understand where the RoboGuice Team is going with the project, but it seems based on the idea that they can make things "more convenient" and get rid of boilerplate and make it "more testable".  But you also have to make sacrifices... new jar dependencies to guice-2.0-no-aop.jar and roboguice1.1.1.jar


Here's the creator giving an overview


It got me thinking, though, really what Android needs is a good DI framework, and not some "Bolt on solution" (no offense, but that is what Robo-Guice is).  Android needs DI at it's very core.

Although currently people are arguing that DI systems are too "heavyweight" or resource intensive" keep in mind how android currently handles the R resource... (all this is done "pre" deployment time)...  the same could apply for Dependency Injection, if done correctly... ok well.. more later (on Why Android Needs DI)