Static methods

Tired of those static methods that make your unit test skills look bad? You want to get rid of those hard to mock static methods? You refuse to use PowerMock? Here’s a simple way of replacing static methods with non-static methods without breaking your entire code base (or worse someone else’s code base).

Example

Let’s say we’ve got the following service class (PostService) which depends on a class with a static method (PostDao).

public class PostService { 
  
  public List getPostsOf(User user){ 
    if(user != null){ 
      return PostDao.findByUser(user); 
    } 
  
    throw new UserNotLoggedInException("User not logged in!!!"); 
  } 
}
public class PostDao { 
  
  public static List findByUser(User user){
    // Some very interesting code for retrieving posts of a given user 
    //.. 
    //.. 
    //.. 
  } 
}

The simplest way would obviously be: remove the keyword “static”, watch all the code (that call this method) brake, fix it and off you go. That sounds easy. But what if you don’t want to replace the references to the static method in a big-bang fashion, for whatever reason. How would you go about that? Here are the steps:

  • Wrap the static method in a non-static method
  • Replace the reference to the static method with the instance method

Wrapping the static method

This is the easiest part. Create an instance method, in the class with the static method, with the same signature and return type. Call the static method from within the instance method.

The class would look like this

public class PostDao { 
  
  public static List findByUser(User user){
    // Some very interesting code for retrieving posts of a given user 
    //.. 
    //.. 
    //.. 
  } 
  public List findBy(User user){ 
    return findByUser(user); 
  } 
}

Now you’re all set to proceed with the second step.

Replacing the references to the static method

Wrapping the static method allows you to replace all the references whenever you want. This enables you to repair your code base at your own pace.

If you want to repair the PostService you should do the following:

  • Create a No-args constructor (for backwards compatibility)
  • Create a constructor which accepts a PostDao instance, for easier testing/mocking purposes
  • Replace the static method call with an instance method call

When all the work is done, the result would be as follows

public class PostService { 
  
  private PostDao postDao; 

  @Deprecated 
  public PostService(){ 
    this(new PostDao()); 
  } 

  public PostService(PostDao postDao) { 
    this.postDao = postDao; 
  } 

  public List getPostsOf(User user){ 
    if(user != null){ 
      return postDao.findBy(user); 
    } 

    throw new UserNotLoggedInException("User not logged in!!!"); 
  } 
}

The PostService will still work, because of the No-args constructor, and does not break any existing code referencing the PostService. The constructor which accepts the PostDao instance allows for easier testing/mocking. You can annotate the No-args constructor with the ‘Deprecated’ annotation. This shows the intent of removing the no-args constructor somewhere in a future release.

If there are no more references to the static PostDao method you can move the logic which resides in the static method into the instance method and delete the static method. Furthermore, if there are no more references to the no-args constructor in the PostService you can remove the deprecated constructor. This can all be done in a non-big-bang-kinda-fashion…

End result

public class PostDao { 
  public List findBy(User user){ 
    // Some very interesting code for retrieving posts of a given user 
    //.. 
    //.. 
    //.. 
  } 
}