Java programming best practices - Create interfaces for your Dao classes

One Java programming "best practice" that has been strongly reinforced for me during the last several weeks is making sure you have a declared interface that defines the behavior (signature) of your Dao (data access objects) classes.

Using the Java programming language as an example, what I am specifically saying is that if you have a Dao object that uses JDBC behind the scenes to access a database (DB2, SQL Server, MySQL, Oracle, whatever) named something like As400Dao, you should also declare an interface named something like As400DataSource, and your As400Dao should then implement that interface.

If you're not familiar with this concept, hopefully right now you're asking "Why?"

Programming best practices - A Mock Dao object for testing

The answer is simple: If you want to create unit tests to test your code, having an Interface that defines the signature of your Dao also lets you create a "mock"  Dao object that you can use in your tests.

Let's look at how this works with a real but simple example.

// the interface
public interface As400DataSource
{
  /**
   * Return the price of a product in pennies.
   */
  public int getPrice(String productName);
}


// the class you'll use in production
public class As400Dao implements As400DataSource
{
  public int getPrice(String productName)
  {
    // put your real sql code here ...
    String sql = "SELECT price FROM products WHERE product_name =?";
    // i'm not going to implement it all, but you get the idea
  }
}


// the class you'll use in your unit tests
public class MockAs400Dao implements As400DataSource
{
  public int getPrice(String productName)
  {
    // this is a "mock" version of the getPrice method
    if (productName.equals("pizza")) return 1000;
    if (productName.equals("soft drink")) return 100;
  }
}

Your production code

The next important thing for you to do is to make sure you reference the As400DataSource interface in your code. In your production code you'll have some code like this that really hits the database:

As400DataSource as400 = new As400Dao();
int price = as400.getPrice("pizza");
// do something in your production code with the price

In that code the object I'm creating is really an As400Dao object, but as far as my as400 reference is concerned, it's a As400DataSource.

Your unit test code

But in your unit tests you'll create an instance of the MockAs400Dao instead, like this:

As400DataSource as400 = new MockAs400Dao();
int price = as400.getPrice("pizza");

// do something with the price in your test code, like maybe building
// an Order object:
Order order = new Order();
order.addItem("pizza", price);

// then later on you'll have some form of assertion, like this:
Assert.equals(1000, order.getTotal());

In this code the object I'm creating is really an MockAs400Dao object, but again, as far as my as400 reference is concerned, it's a As400DataSource.

That's a key concept behind this entire approach: your actual objects (the things on the right side of the equal sign) can be any class that implements the As400DataSource interface, but the reference you create on the left side of the equal sign (the as400 reference) is defined only as being a As400DataSource, which is really an interface.

Now you're programming to the interface, and not worrying about the actual implementation(!).

Programming best practices - Create interfaces for your Dao classes

It's hard to write a great example without really diving into this topic, but I hope this "programming best practice" example demonstrates why having the As400DataSource interface is so important. By simply having this interface defined -- and then using it in your code -- you can write real unit tests that don't have to hit the database to properly test your code.

There are a lot of other good reasons for creating interfaces for your classes, but I think it's especially important to do this for your Dao objects. As you can see, this interface-driven approach can be a great help when it comes time to testing.