Please notice that for the most part, these are nitpick details and refer to the general best practice of structuring code, however I'd be arrogant to assume to know how you should write your program.
That being said, lets look at #1:
Solution #1
// Name of class containing main should usually be called Main and
// Main in of itself is a single responsibility class, meaning it does nothing
// other than launch your program
public class App {
public static void main(String[] args)
{
// Here, "App" should be a more significant name relevant to what it does.
// Perhaps "Pipe" would be better suited?
App app = new App();
AppInput input = app.readInput();
AppOutput output = app.processInputToOutput(input);
app.writeOutput(output);
}
// These methods would obviously belong to Pipe and not to App/Main
public AppInput readInput() { .. }
public AppOutput processInputToOutput(AppInput input) { .. }
public void writeOutput(AppOutput output) { .. }
}
Solution #2
// Same discussion as above with name of class containing Main
public class App {
public static void main(String[] args)
{
// Correcting minor error using "app" in the place of "worker"
AppWorker worker = new AppWorker();
AppInput input = worker.readInput();
AppOutput output = worker.processInputToOutput(input);
worker.writeOutput(output);
}
}
// AppWorker seems to uphold the suggestions mentioned above, but the name is a problem.
// "Worker" makes me think of threads. If it isn't a thread, you would probably be better
// off calling it with a name appropriate for its job (again, I propose Pipe as
// it takes input and writes output).
public class AppWorker {
// "readInput" and "writeOutput" are redundant. Better left as "read/write"
public AppInput readInput() { .. }
public AppOutput processInputToOutput(AppInput input) { .. }
public void writeOutput(AppOutput output) { .. }
}
Solution #3
// Same discussion as above with name of class containing Main
public class App {
public static void main(String[] args)
{
// This is simply moving the job of Main to another class.
// In more complicated programs, this may even be smart. Controller classes
// are usually used when Main begins to be cluttered, leaving the logic of
// argument handling in Main and putting the rest in the controller class.
// However in this case, "AppWorker" does nothing more than the work of App/Main
// which makes AppWorker simply redundant.
AppWorker worker = new AppWorker();
worker.doYourWork();
}
}
public class AppWorker {
public void doYourWork()
{
// You mean to use this here I assume?
// App app = new App();
AppInput input = this.readInput();
AppOutput output = this.processInputToOutput(input);
this.writeOutput(output);
}
// If AppWorker is controller as it seems to be, the following methods need to be
// protected or private as this class controls and is not controlled. Only
// public methods aside from "execute" method should be to set optional parameters.
public AppInput readInput() { .. }
public AppOutput processInputToOutput(AppInput input) { .. }
public void writeOutput(AppOutput output) { .. }
}
My Solution
If I may be so bold, applying the points above, I would write it as the following:
public class Main{
public static void main(String[] args)
{
Pipe pipe = new Pipe();
PipeInput input = pipe.read();
PipeOutput output = pipe.processInputToOutput(input);
pipe.write(output);
}
}
public class Pipe {
public PipeInput read() { .. }
public PipeOutput processInputToOutput(PipeInput input) { .. }
public void write(PipeOutput output) { .. }
}
Notice that the logic hasn't been removed from Main, but it is still left simple. If I saw that my Main were getting cluttered, I would consider creating a class to handle some of the more trivial details, but not to the point where I would create a class that does everything Main does. Not even when I want to create a controller class do I port all the logic. Controller can make some assumptions about the input, and Main can provide the necessary tests.
The work of App
is now called Pipe
. Notice that it follows the single responsibility principle. If I wanted to add more logic, I would be careful not to automatically add it to Pipe, since Pipe already does everything it should and nothing more. And finally, note that the names of the methods previously called readInput
and writeOutput
are now simply read
and write
, since in the context of Pipe
, it is clear what is intended by the parameters passed.
Again, these are nitpicky details. I'm simply following the best practices that I've learned over the years. I hope that you can also benefit from these tips!
app.read/process/write
should beworker.read/process/write
, at 3 it should bethis.
).