I have got a piece of code that initialize Scanner in two possible ways:
no argument constructor creates Scanner that uses stdIO (System.in) as source
contructor with String, which creates Scanner, that uses file as source, where String is a path to file
It looks like this:
public class InputMethod implements IInputMethod {
private final Scanner fileReader;
private final Scanner userInput = new Scanner(System.in);
public InputMethod(String[] args) throws FileNotFoundException {
if (args.length == 1)
fileReader = setFileAsSource(args[0]);
else
fileReader = setStdIOAsSource();
}
private Scanner setFileAsSource(String filename) throws FileNotFoundException {
return new Scanner(new File(filename));
}
private Scanner setStdIOAsSource() {
return new Scanner(System.in);
}
}
In main:
public static void main(String[] args) throws FileNotFoundException {
IInputMethod input= new InputMethod(args);
while (!input.getUserInput().equals("Exit")) {
// awesome stuff
}
input.closeInput();
}
It works great, but it does not look pretty when it comes to exception handling. My dream would be creating a method, in which I will handle possible File-related problems and next one, that will do the job, just like good old Uncle Bob said.
Can anyone take a look at this and maybe suggest some minor changes, to make it clean and friendly?
1 Answer 1
Your design is slightly off, String args[]
works great for terminal programs, but for passing arguments around it's really not efficient. There's no compile time checking to see if you're passing around things that make sense.
Look up Strategy Pattern; You want several independent classes each implementing the interface.
To handle the exception, split your code into two halves:
The first half prepares,
The second half executes.
Additionally, you should split up the responsibility of input source and user input. Right now you'd have to re-implement userInput
for each InputMethod
, which is unwanted.
By splitting up your code to each case, you'll have 1 specific case where you're still in your calling code (you haven't instantiated an InputMethod
yet), but you know that you're going to read from a file. You can handle your exception there.
Your code would be structured like so:
public static void main(String[] args) throws FileNotFoundException {
IInputMethod input = null;
if(args.length == 1){
input = makeFileInputMethod(args);
} else {
input = makeStandardInputMethod();
}
//make user input object
while (!input.getUserInput().equals("Exit")) {
// awesome stuff
}
input.closeInput();
}
In the makeFileInputMethod
you could handle the exception. Then, in main, you could say "well, if input is still null, we didn't instantiate properly and we ought to shut down".
InputMethod
intoFileInputMethod
andStandardInInputMethod
, you can handle the Exceptions during instantiation of theFileInputMethod
. \$\endgroup\$