Interface

a point where two systems, subjects, organizations, etc. meet and interact.
Designing an Interface is more important than the code implementation. Blog is focused on designing an Interface for your code implementation.

Experienced developer knows the importance of Interface in Programming. For those who just started Programming or started to learn Interface, You should read the given case study.

Before we start please get familiar with Generics https://docs.oracle.com/javase/tutorial/java/generics/ in Java because all interface designed using generic type.
Case study for beginner
Task has been assigned to Chef Programmer to read XML and CSV file and save users in database. Chef Programmer assigned task to...

Developer1 from department A
Task: Create XMLReader with return type List<User> and provided following details.
  • Business Logic.
  • Sample XML File.
  • Reader Interface.
  • Expected return type List<User>.
Developer2 from department B
Task: Create CSVReader with return type List<User> and provided following details.
  • Business Logic.
  • Sample CSV.
  • Reader Interface.
  • Expected return type List<User>.
Chef Programmer himself worked on saving List<User> returned by XMLReader and CSVReader.

XMLReader

by Developer1
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javainterface.io.FileHolder;
import javainterface.io.reader.Reader;

/**
 * @author Developer1
 */
public class XMLReader implements Reader<List<User>>{

    @Override
    public List<User> read(FileHolder fileHolder) throws IOException {
        List<User> users = new ArrayList<User>(0);
        
        // read xml file
        // Business logic: create {@link User} objects and return
        
        return users;
    }
}				
					

CSVReader

by Developer2
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javainterface.io.FileHolder;
import javainterface.io.reader.Reader;

/**
 * @author Developer2
 */
public class CSVReader implements Reader<List<User>>{

    @Override
    public List<User> read(FileHolder fileHolder) throws IOException {
        List<User> users = new ArrayList<User>(0);
        
        // read csv file
        // Business logic: create {@link User} objects and return
        
        return users;
    }
}				
					

UserDao

by Chef Programmer
Using Reader interface you've achieved following...
  • Pluggable Code: XMLReader and CSVReader created by developer of different department but will work same for Chef Programmer.
  • No changes require in method readAndSave even if new Reader is introduced like XLSReader. You need to just attach it in getReader method.
import java.io.IOException;
import java.util.List;
import javainterface.io.FileHolder;
import javainterface.io.reader.Reader;

/**
 * @author Chef Programmer
 */
public class UserDao {
    public static void main(String[] args) {
        // null check and other preconditions
        UserDao userDao = new UserDao();
        userDao.readAndSave(args[0], new FileHolder(args[1]));
    }
    
    /**
     * This method shows the IMPORTANCE of Interface. For this method it doesn't matter which
     * Reader you are providing. It'll just call `read` method of Reader interface which is implemented by 
     * XMLReader, CSVRead, etc...
     * 
     * Now whenever new Reader(XLSReader) is introduced this method doesn't require any changes.
     * All you got do is attach new Reader in method {@link UserDao#getReader(java.lang.String)}
     * 
     * @param type
     * @param fileHolder 
     */
    public void readAndSave(String type, FileHolder fileHolder){
        // null check and other preconditions
        // You can determine reader using file extension or by passing in argument, etc...
        Reader<List<User>> reader = getReader(type);
        if(reader != null){
            try {
                List<User> users = reader.read(fileHolder);
                // Perform save
            } catch (IOException ex) {
                // log it.
            }
        }
    }
    
    /**
     * Get Reader based on type
     * @param type
     * @return 
     */
    public Reader getReader(String type){
        // null check and other preconditions
        switch(type){
            case "XML":
                // Coded by Developer1
                return new XMLReader();
            case "CSV":
                // Coded by Developer2
                return new CSVReader();
            default:
                return null;
        }
    }
}
					

How to design an Interface?

In simple term "Interface shows the natural characteristics of object/task". In given case study I used Reader interface. For an instance think what could be done by the reader? It should read the data from given object and return the desired value.

While designing the interface don't consider the complete implementation of your code because it ruin the definition of Interface.
It leads to mistakes like
  • public List<User> read(File) fixed return type. You should rather use generic type T.
  • read(File, List<String> columnsPresentInFile) template to validate file. You should rather use constructor to provide extra parameters of reader public XMLReader(List<String> columnsPresentInFile)
  • Throw valid Exception for logging purpose.
  • Depends on Business logic: Restrict developer with fixed input/output parameters read(File file). I used File rather generic type R because I want to restrict the developer that input will be File only. If you check FileTransferProtocol interface then I restricted return type List<RemoteFile> listing(...).