Making Code More Testable – Breaking Static Dependencies

August 31st, 2009

Hi guys, it’s been a while that I haven’t posted anything. I was thinking writing all those technical things sometimes is not enough for the reader to visualize the concept. So I came up with a screencast this time. I’ll try to create these screencasts once a week and will cover different topics. This series will contain Making Code More Testable talks only. For other topics, I’ll create different series. Anyways, let’s get back to the overview :)

In this first screencast I’ll try to cover how you guys could break the static dependencies in your constructor. Let me give you some brief overview about these dependencies:

Dependencies

Dependencies are everywhere in our little world. Every unit, every module is depending on something. Sometimes it’s another unit, sometimes it’s another modules, and sometimes it’s another library. And there are lots of discussions currently going on to make your units, modules more scalable and more isolated! All OSGi, maven, DI (Dependency Injection) and SOLID principles are just for this purpose. To help you to break/isolate/modulate your code base.

In this screencast I’m gonna talk about only a single part of whole this picture. Static dependencies within your constructors.

Static Dependencies Within Constructors

This type of dependencies are very evil when it comes to do unit testing. It could turn into a very big puzzle game sometimes. The basic idea is some developers tend to place their dependent services or non-value objects into the constructor and using singleton and/or static methods. Without being aware of what they’re doing, they sometimes even place if/else, try/catch, switch/default statements into this tiny part of the code.

So how it happens? Very easy, let’s consider the following code snippets:

/** My class. */
public class MyClass {
    private Service service;

/** Default constructor */
public MyClass() {
    // lots of logic that shouldn't be here..
    // and
    this.service = Service.getInstance();
    TimeService.recordTime();
}

}

(EDIT) As you may clearly see, it’s very hard to test this unit since it has non-injectable static dependencies. So what do we need to do?

There are couple ways to break these dependencies. Before going into too deep, I want to clarify something here. “DON’T EVER DO THIS”! When you write your code, maybe you don’t follow TDD or anything. But please consider there will be some people that have to deal with this code after you. Then again, if you’re selfish.. There is no more word to say!

Breaking the Dependencies

As I said, there are couple ways to break these sort of dependencies.

Constructor Delegation

First and my favourite is Constructor Delegation. The basic idea for this technique is create another constructor which takes these dependencies for dependency injection and delegate the first constructor to the second one. Please consider following code’s before/after and usage scenarios:

// BEFORE 'constructor delegation'
public class LibraryManager {
    private LibraryService service;

public LibraryManager() {
    this.service = LibraryService.getInstance();
}
// more code

}

// AFTER 'constructor delegation' public class LibraryManager { private LibraryService service;

public LibraryManager() {
    // delegate to the new constructor
    this(LibraryService.getInstance());
}

// new constructor
public LibraryManager(LibraryService service) {
    this.service = service;
}
// more code

}

// USAGE 'in the test' LibraryManager manager = new LibraryManager(mockLibraryService); // ... // do your assertions

Endo Testing

Second technique is from Endo Testing. The technique here is extracting these dependencies to getter equivalents and overriding these methods for returning the mock/stub/fake ones. One thing here is your getter methods should be package private or protected. Please look at the following before/after and usage scenarios again:

// BEFORE 'endo testing'
public class SmartHitter {
    private Exchange exchange;

public SmartHitter() {
    this.exchange = Exchange.getActiveExchange();
}
// more code

}

// AFTER 'endo testing' public class SmartHitter { private Exchange exchange;

public SmartHitter() {
    this.exchange = getActiveExchange();
}

protected Exchange getActiveExchange() {
    return Exchange.getActiveExchange();
}
// more code

}

// USAGE 'in the test' final Exchange mockExchange = mock(Exchange.class); SmartHitter hitter = new SmartHitter() { @Override protected Exchange getActiveExchange() { return mockExchange; } }; // ... // do your assertions

Setter Injection

The last one is not applicable to all scenarios, but it’s another dependency injection mechanism (@see Dependency Injection). For this one, you basically create a setter method for your dependency and allow test to inject this dependency. Let’s look at the example:

// BEFORE 'setter injection'
public class AjaxPriceModifier {
    private CatalogService catalogService;

public AjaxPriceModifier() {
    // initialization..
    this.catalogService = CatalogService(sessionHelper.getStore());
}
// more code

}

// AFTER 'setter injection' public class AjaxPriceModifier { private CatalogService catalogService;

public AjaxPriceModifier() {
    // initialization..
    this.catalogService = CatalogService(sessionHelper.getStore());
}

public void setCatalogService(CatalogService catalogService) {
    this.catalogService = catalogService;
}
// more code

}

// USAGE 'in the test' AjaxPriceModifier modifier = new AjaxPriceModifier(); modifier.setCatalogService(mockCatalogService); // ... // do your assertions

As you may notice, without a getter of that dependency your code still has the dependencies. It’s very wise to place a getter for that dependency and use that getter (as in Endo Testing) method in the constructor.

Summary

My personal favourite is Constructor Injection since it’s more intuitive when you’re coding the test. It clearly describes what dependencies you need to test that unit. Okay, now you can watch the screencast. Hope it turns some lights on :) All comments are welcome!


TDD

10 Comments

Maximizing Reuse Minimizes Use

August 13th, 2009

A nice modularity tip that should be considered when you’re designing a modular system:

Maximizing reuse minimizes use.
 

Clemens Szyperski

Quotes

No Comments

Naming the Java Implementation Classes

July 18th, 2009

Today I was reading an answer to a question (http://bit.ly/FkgKB) about naming the implementation classes. People in these days are using Impl suffix to their implementation classes which implements a certain interface. For instance, if your interface name is Item, your implementation class name would be ItemImpl. Honestly I hate this bullshit naming convention. And I’ll forever blame the guy who invented such a crappy naming. Actually I first saw this naming convention in the IBM Developerworks articles. I guess it is some sort of IBM crap (I never got along with any of IBM related thing so far though). Anyways, let me tell you why it’s crappy:

First of all, it shows me that most likely you can’t come up with any good name to your class that could represent the responsibility of it. It basically smells like hell. Second which name are you going to give to the next implementation of same class? Of course you can’t find a good name for that too. Most likely scenario will be like this: Item, ItemImpl, CatalogItemImpl and so on.. Lots of duplication. And third, by looking at the class name, you can’t tell what this implementation does actually. Please consider Item and ItemImpl. As you may easily figure, it’s very hard to tell what ItemImpl does in the context without looking at the code itself.

Another weird idea to me is putting I prefix before interface names. I can’t get it too. Are you doing this just to separate your interfaces from classes? Excuse me, which IDE is not showing whether it is interface or not? Look at these: IPerson, PersonImpl.. What happened to my Person domain model? It’s just ugly.

So what I think? I think that if you’re placing an interface, implementation class name should tell you what does that class do in that context. For instance, if you have a XMLParser interface, your implementations should be XMLFileParser, XMLInputStreamParser etc.. If you cannot find a decent name for your class, maybe your should consider your design again. Maybe it’s not fitting well in the context. I don’t like creating domain object names as interfaces either. It just doesn’t make sense to me. Look at this: Customer (interface), CustomerImpl is implementation. Why don’t you create a Customer implementation which implements Identity? Or instead of LineItem, LineItemImpl couple, maybe you should consider naming them like LineItem implements Listable, Sortable? Basically what I’m saying is actually your interface design should be accurate to represent the context. Because all of your APIs will interact with these domain models.

When you’re applying Law of Demeter, you shouldn’t forget names as well as class fields and methods so that we can understand which class is actually doing what.

There is a really nice explanation of this naming problem. I’ll quote it directly from mockobjects.com:

Sometimes we see code with classes that are named by adding “Impl ” to the single interface they implement. This is better than leaving the class name unchanged and prefixing an “I ” to the interface, but not much. A name like FooImpl is duplication, it says exactly the same as implements Foo , which is a code smell. We would not tolerate such obvious duplication elsewhere in our code, so we ought to refactor it away.

It might just be a naming problem. There’s always something specific about an implementation that can be included in the class name: it uses a bounded collection, it communicates over HTTP, it uses a database for persistence, and so on. A bridging class is even easier to name, since it will belong in one domain but implement interfaces in another: for example, SnipersTableModel (a user interface class) implements SniperListener and PortfolioListener (from the application core).

If there really isn’t a good implementation name, it might mean that the interface is poorly named or designed. Perhaps it’s unfocussed because it has too many responsibilties, or it’s named after its implementation rather than its role in the client, or (just occasionally) that it’s a value not an object—this discrepancy sometimes turns up when writing unit tests

Java

10 Comments