2

My background has largely been manual testing and I started learning core java to be able to work with Selenium. I am wanting to write couple of reusable method, like reading/writing data from csv, excel, word etc.

I created a class named - FileHandler and created method for this. Hence this class deals with all sorts of files - csv, excel etc.

But going by the OOPs concepts (and if I have understood them right) I should be creating an Interface and implementations for this Interface, and instead of directly dealing with specific implementation I should be working with reference of type interface. i.e.

public interface FileHandler {
}

public class ExcelHandler implements FileHandler {
}

public class WordHandler implements FileHandler  {
}

My question - is this right approach in my scenario should I just create one class to handle all file input/output operations? Though I am yet to figure out what goes in interface as methods like -

getExcelData(String filePath, String workSheet, String row, String column)

would be specific to only reference of type - ExcelHandler and does not make much sense keeping them in interface.

4
  • I'm going to edit the code in your example, let me know if I've misrepresented your example :-) Jun 17, 2011 at 9:55
  • From a pure "I want to get the job done" perspective, you might want to look at existing open source APIs that already do this, Apache POI and Apache file commons in particular. However, your question is a good one and it's a great learning exercise, so it's worth carrying on with! Jun 17, 2011 at 9:59
  • Oops, thanks for making the edit. My methods would ultimately be using those opes source APIs I just want to provide more compact way of accessing data from files so client users don't have to go through lots of initialization etc
    – Tarun
    Jun 17, 2011 at 10:11
  • That should've been Apache Commons IO sorry Jun 17, 2011 at 10:16

1 Answer 1

1

I'm not saying you should use an interface is your particular case, but I'll try to cover some of the points you might want to consider.

So, a couple of questions to ask yourself to begin with:

  1. Are there common operations between these FileHandler implementations?
  2. Am I getting the same sort of data from the different sources (e.g. Is where you get the data from a separate concern to what the data is).

Initially it may seem like the first question should be answered with "No", especially when you are thinking about methods such as getExcelData(String filePath, String workSheet, String row, String column).

However, if the data is similar then you might then start to experiment with different ways to represent a getData method that is common across implementations, so perhaps something like:

The interface

public interface FileHandler {
  public byte[] getData();
}

The Excel implementation

public class ExcelHandler implements FileHandler {

  private String filePath, workSheet, row, column;

  public ExcelHandler(String filePath, String workSheet, String row, 
                      String column) {
    // Set the local vars
    ..
  }

  // Pseudo code with no exception handling - yuck!
  @Override
  public byte[] getData() {
    File excelSheet = ApacheCommonsFileLoader.loadFile(filePath);
    return ExcelPOIAPI.readCell(workSheet, row, column);
  }
}

The Word implementation

public class WordHandler implements FileHandler {

  private String filePath;

  public WordHandler(String filePath) {
    this.filePath = filePath;
  }

  // Pseudo code with no exception handling - yuck!
  @Override
  public byte[] getData() {
    return WordPOIAPI.readDoc();
  }
}

The Tests

// Very rough crappy test, note the explicit creation of the ExcelHandler
@Test
public void testGetDataForExcel() {
  FileHandler fileHandler = new ExcelHandler("foobar.xls", "foobar", "A" "23");
  assertNotNull(fileHandler.getData());
}

// Very rough crappy test, note the explicit creation of the WordHandler
@Test
public void testGetDataForWord() {
  FileHandler fileHandler = new WordHandler("foobar.doc");
  assertNotNull(fileHandler.getData());
}

The client

// Very rough crappy client, the fileHandler being passed in 
// was previously created, see explanation below
public void processData(FileHandler fileHandler) {
  byte[] data = fileHandler.getData();
  // Do stuff with data
}

The question you might ask yourself is then "How/where do I create the specific type of FileHandler I want?". Commonly you can hard code it (like I did in the tests), use a Factory, or use Dependency Injection (DI) via an IoC framework such as Guice, Spring or PicoContainer. DI is all the rage at the moment (please use it lightly and wisely) so that might be something for you to explore (I highly recommend Guice for learning this).

Hope that helps a little!

5
  • It does help lot and points me to read on DI also. I guess in "Test" in second method you mean - "testGetDataForWord" is not it?
    – Tarun
    Jun 17, 2011 at 11:32
  • Fixed the test name - thanks! Read Martin Fowler's article on DI and IoC to start with, then the Guice stuff will make sense Jun 17, 2011 at 11:34
  • yup, will do that and I guess your comment - "// Pseudo code with no exception handling - yuck!" is supposed to be "geekily" (if there is such word) funny and I am yet to reach that level
    – Tarun
    Jun 17, 2011 at 11:37
  • No humour was intended - I've just spent too much time teaching people who are new to Java at the coderanch.com. Some of the students like to copy and paste example code thinking it's the 'correct' example when it's pseudo code, or at best example code without the sort of exception handling and std Java practices that polished code would have :) Jun 17, 2011 at 12:08
  • java ranch, I love Head First core java :)
    – Tarun
    Jun 17, 2011 at 13:19

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.