Developer Aspirations

YAPB - Yet Another Programming Blog

Thursday

07

April 2011

Inline Objects

by Colin Miller, on Design, Java, Musings, Object Oriented Programming, Reusable Code

I like to be able to test my code in an automated fashion as much as possible. A lot of code is connected to other code, so testing a specific section can be tricky because you end up testing the coupled code as well. This breaks the main idea of unit testing and is one of the reasons that code coupling can lead to harder to maintain code. We solve this problem by programming to interfaces, using dependency injection, and using mock frameworks for our tests. It can work wonderfully if you're disciplined enough to avoid shortcuts.

 

This has nothing to do with inline objects or code coupling. It is instead a set of cosplay outfits from comic-con in '10

Some developers like to use a particular construct while writing code that creates instances of interfaces using anonymous inner classes. The basic idea is to create a new instance of an interface with the definition inline in your code. I suppose it's for readability on short code, since you can easily see what it will be doing without having to change to another class. Here's an example:

public void someMethod() {  
  ExecutorService service = new Executors.newSingleThreadExecutor();
  service.execute(
    new Runnable() { // This is an interface that we're making an inline object of
      public void run() {
        //Do thread stuff here
      }
    }
  );
}

This can be pretty useful at times. Something may be run in a thread but logically belong to a part of a method's logic. Unfortunately there's no easy way to run this method without also spawning a thread. The thread logic might be using libraries that need to be stubbed out, and that's even more difficult if used as an anonymous inner class. Also, testing the functionality of the run() method itself is more difficult because it can only be accessed within the context of the containing method. Not the best scenario for testing.

There's no real difference (not completely true) between a class implemented inline and a class defined in its own file or as an inner class to the one you're working on. What's more, you'll have the ability to instiate the class directly if it's not anonymous and test it's functionality separate from the containing class. Decoupling this code can make it a lot easier to test and debug. Since the majority of the time spent on code is maintaining it, adding the additional effort to break it out into its own class can pay off in the long run.

Now I said that there's no real difference and also noted that that's not completely true. The main functionality that you lose when you turn an anonymous inner class into a hard class (even an inner class) is actions to the containing method's final variables.

public void someMethod(final String usefulValue) {  
   ExecutorService service = new Executors.newSingleThreadExecutor();
   service.execute(
     new Runnable() { // This is an interface that we're making an inline object of
       public void run() {
         String modifiedUsefulValue = usefulValue + " other stuff"
         //Do thread stuff here
      }
    }
  );
}

The variable usefulValue is accessible from within the the inline object. If the object was created from a non-anonymous inline class then it wouldn't be directly accessible. However that just allows for some modification such as creating an instance variable inside of that class to hold references to those final variables. Not an insurmountable task.

My point is that there is a lot of code tricks that you can use in Java and any other language that will make it faster to write code. However, using those tricks has to be weighed against testability and the maintenance costs that additional coupling can provide. Being able to write a class in 10 minutes means nothing if you have to spend the next 3 months debugging it. Coding defensively might seem to take longer at the start, but you'll have to fiddle with your already produced code less often.

And then you have more time to write new code!

comments powered by Disqus