How to simplify this logic/code? - java

I want to write an apps that accepts user command. The user command is used in this format:
command -parameter
For example, the app can have "Copy", "Paste", "Delete" command
I am thinking the program should work like this :
public static void main(String args[]){
if(args[0].equalsIgnoreCase("COPY")){
//handle the copy command
} else if(args[0].equalsIgnoreCase("PASTE")){
//handle the copy command
}/**
code skipped
**/
}
So, it works, but I think it will become more and more complex when I have more command in my program, also, it is different to read. Any ideas to simply the logic?

If you are concerned about handling the command line parameters then Commons CLI is meant for this.
Go through the CommandLineParser
and if you are concerned about the complexity of your if-else then you can use Command Pattern
public interface Command {
void exec();
}
public class Copy implements Command {
void exec() {
// your copy Code
}
}
public class Paste implements Command {
void exec() {
// your Paste Code
}
}
public class Delete implements Command {
void exec() {
// your Delete Code
}
--
then
public static void main(String args[]){
Map commandMap<String,Command> = new HashMap<String,Command>();
commandMap.put("Copy", new Copy());
commandMap.put("Paste", new Paste());
commandMap.put("Delete", new Delete());
if ( commandMap.containsKey(args[0]) ){
commandMap.get(args[0]).exec();
}
}

Depending on how simple your command line syntax is, a simple enum may be your solution
public enum Command {
COPY {
#Override void execute() {
System.out.println("Copying...");
}
},
PASTE {
#Override void execute() {
System.out.println("Pasting...");
}
},
DELETE {
#Override void execute() {
System.out.println("Deleting...");
}
},
;
abstract void execute();
public static void main(String args[]) {
Command c = Command.valueOf(args[0].toUpperCase());
c.execute();
}
}
Compile and run this with java Command paste, java Command bleh, etc. You'll want to pass the rest of args to the enum in your production code. Also, valueOf throws IllegalArgumentException if no enum constant is found with the specified name.
If your syntax grows to be more complex, though, you may want to use libraries specifically designed for command line parsing, e.g. Apache Commons CLI.

Use a library to keep the messiness of command line argument parsing out of your code, for example args4j.

When I see lots of if/then/else code, I immediately think of polymorphism as a possible solution.
A Command interface and a Map would be a fine way to solve this problem. If I were writing this in Java, it might look like this:
public interface Command<T, V>
{
V execute(T parameter) throws Exception;
}
If your operations are multi-threaded, you can simply reuse the Runnable interface for Commands that don't return a value and Callable<T> for ones that do.
In either case, now your if/then/else construct is a Map where the key is the name and the value is the Command object. You look up a Command by providing the name key. You add a new command by writing a new implementation of the Command interface and adding it to the Map. Initializing the Map is something you do on startup. You can even externalize it as configuration so you don't have to modify code to add new ones (Open/Closed Principle).

There are many libraries that can handle this situation instead of writing all the code down.

Related

OOD - Best way to pass config to an external class

In my main method I need to execute a system command. I'm creating an external class to execute the command to keep my main method and app class clean. I'm not sure if the best or cleanest approach would be to do the setup for the command in the main method, or just pass the class the configuration reader and let it pull the necessary things it needs.
Would it make my app more tightly coupled or not follow a good design practice if I just pass the external configuration reader to my SystemCommand class?
Ex - approach one to setup from the main method:
public static void main (String[] args) {
String[] command = {
config.getString("program"),
config.getString("audit.script.name"),
config.getString("audit.script.config")
};
String workingDir = config.getString("audit.directory");
SystemCommand runAudit = new SystemCommand(command, workingDir);
runAudit.start();
}
Or alternatively, I can keep the main method simpler by passing a reference to the config and letting the class pull what it needs from there. It seems this approach is still conceptually simple:
public static void main (String[] args) {
SystemCommand runAudit = new SystemCommand(config);
runAudit.start();
}
There's also a matter of configuring where output and logging is specified, but I haven't thought that through yet.
Keep your main() method simple. Your main() method should not have knowledge about the inner details of other classes in the program. This is because it is an entry point and generally entry points should concern themselves with minimalistic initialization and any other house-keeping tasks. The best way to solve your use case would be :
Create a class SystemCommandFactory which would take in a Config instance as a constructor parameter I assume below that SystemCommand is an interface that could have multiple implementations:
public class SystemCommandFactory
{
private final Config config;
public SystemCommandFactory(Config config)
{
this.config = config;
}
//assume we have a ping system command
public SystemCommand getPingCommand()
{
//build system command
SystemCommand command1 = buildSystemCommand();
return command;
}
//assume we have a copy system command
public SystemCommand getCopyCommand()
{
//build system command
SystemCommand command2 = buildSystemCommand();
return command;
}
}
Now your main method would be as simple as :
public static void main(String[] args)
{
SystemCommandFactory factory = new SystemCommandFactory(new Config());
//execute command 1
factory.getPingCommand().execute();
//execute command 2
factory.getCopyCommand().execute();
}
This way you can see that main() method is simple clean and this design is definitely extensible. Adding a new command say MoveCommand is as simple as :
Create a implementation of the SystemCommand interface for the new
command.
Expose a new method within the factory to get this new MoveCommand
In main() call this new factory method to get the new command and
call execute within it.
Hope this helps.

Is it a good idea to use reflections in a Web application?

I have developed below code with the intention to remove if else conditions so that code cyclomatic complexity should be less.
For this I have used reflection api and wrote method which takes condition as an argument and called respective method on the condition name basis.
This works fine, I want to know is it a good idea to use reflection (This code) in web application, so that I am free from checking conditions.
For example in below code we have different method with prefix state ex: stateSUBMIT, stateWithdraw etc.
we can call stateSUBMIT method by passing only "SUBMIT".
public class Participate {
public String execute(String methodName) {
String st = null;
try {
Method method = this.getClass().getDeclaredMethod(
"state" + methodName);
method.invoke(this);
} catch (Exception e) {
e.printStackTrace();
}
return st;
}
public void stateSUBMIT() {
System.out.println("in SUBMIT");
}
public void stateWithdraw() {
System.out.println("in Withdraw");
}
public void state() {
System.out.println("in state ");
}
public void statenull() {
System.out.println("in null ");
}
public static void main(String[] args) {
Participate p = new Participate();
p.execute("SUBMIT");
}
}
This is valid code, but can be achieved without reflections.
Step One: Define an interface
public interface Command {
public void execute();
}
Step Two: Create Concrete Implementations
public class StateCommand implements Command {
public void execute() {
// Your code.
}
}
Step Three: Add a collection of these to your original class
private Map<String, Command> commands;
Step Four: Populate
public MyClass() {
commands = new HashMap<String, Command>();
commands.put("state", new StateCommand());
}
Get that class and execute
public String callMethod(String name) {
Command command = commands.get(name);
if(command != null) {
command.execute();
}
}
This is just a relatively simple alternative to using reflections, which should be considered as a last resort.
I would avoid it. There are better alternatives. You could pick one of all the numerous web frameworks or you could code something similar without reflection. For example, use a HashMap from the action (SUBMIT, ...) to an object that implements an interface. That way you can call a method with parameters without reflection, which is slow and which provides no compile-time validations. This is not a recommendation (go with a framework!), but it is a better way of doing what you are doing right now.
Your implementation is beneficial in case if you are doing for making this Generic approach for all other other classes in your project.Its good if you are having re usability of this in many other scenarios.
But if its only for specific implementation which is not generalized then there are many simple ways to do this job, because if you will use java reflections than there is some amount of time complexity involved which is comparatively less if you do it without using reflectns.

How to give a programmatic support to a class with a main

I'm sorry for the title but I can't really find another way to express it. I need to create a class with a double function, if you give to it a file as input from the console or terminal it gives back a print of it's calculations, but the class can be also used as subroutine and give a file to another class for further calculation.
To implement the first task I must define a main to accept input from console like this
java MyClass myfile.file
But then I can not simply get an instance the class inside something else like this
MyClass myClass = new MyClass(file);
cause I will always get an error from the main(IndexOutOfBound since args it's just an empty array).
How can I fix this? I must use the same class to do so, I can not build another class for the subroutine function.
Something like:
public class MyClass {
public MyClass(String nameOfFile) {
...
}
public void doSomething() {
}
public static void main(String[] args) {
MyClass myClass = new MyClass(args[0]);
myClass.doSomething();
}
}
So your main method simply interprets the incoming arguments (as file names or similar), then instantiates and executes your class as another library might.

How to protect method signature in java called from other language (javascript)

I have a question about combining java with javascript. In our application we have gui build in javascript and server side build in java. In javascript we write that we want to call methodX from classY in java. The problem is that java doesen't know anything about javascript so when we change something in java we could break javascript code. Even plain refactor option in eclipse can break our javascript without knowing (changing method name, removing params, renaming setter and getter in DTO object). The question is how to counteract against it. I was thinking about writing some annotations in java so after changing method signature you will get compilation error (is it even possible to write this kind of annotation) but I don't want to reinvent the wheel again if there is some kind of tool which will do it for me. I would be grateful for any help.
The question is how to counteract against it.
Probably the most practical solution is to develop a set of automated tests (e.g. unit or system tests) that are specifically designed to "exercise" all of the cases where there is a Java API that is called from Javascript (or vice-versa)
I think there are a couple of solutions(workarounds) for your problem.
1)Mapping certain strings with methods.
public class JavascriptCallable {
private static final String jsIdentifierMethod1 = "method1";
private static final String jsIdentifierMethod2 = "method2";
/**
* All requests from JS should be redirected to this method.
*
* #param methodName Name of the method
*/
public void requestFromJavascript (String methodName) throws Exception {
if (methodName.equals(jsIdentifierMethod1)){
method1();
} else if (methodName.equals(jsIdentifierMethod2)){
method2();
} else{
throw new Exception("Method not supported");
}
}
public void method1(){
// Do something
}
public void method2() {
// Do something
}
}
2)Having separate methods eligible for js calling. This will help if you are using reflections to call the methods
public class JavascriptCallable {
/*----------------Methods to be called by js. Never refractor------------------*/
public void noRefractorMethod1() {
method1();
}
public void noRefractorMethod2() {
method2();
}
/*-------------------------------------------------------------------------------*/
/*---------Methods with business logic. Refractoring these will not mess your js-----------*/
public void method1() {
// Business logic
}
public void method2() {
// Business logic
}
/*-------------------------------------------------------------------------------*/
}
Please let me know if this helps.

Modulation of adding new Strings -> Method calls

If I have a program that does the following:
if(input=='abc'){do x}
if(input=='def'){do y}
In the future, I may want to add another piece of code like so:
if(input=='ghy'){do x}
As you can see, I am adding a new 'if' statement for a different conditional BUT using the SAME function X.
The code in future has potential to have lots of different IF statements (or switches) all of which are comparing a string vs a string and then performing a function. Considering the future expansion, I was wondering if there is a possible 'neater', 'modular' way of achieving the same results.
It's a shame I can't combine the String with a Method call in a hashtable (String, method) in Java. That way I could just store any new procedures inside a hashtable and grab the relevant method for that String.
Any ideas?
Thank you
EDIT: Thank you for everyone's solutions. I was surprised by the quantity and quality of replies I received in such a small amount of time.
Maybe you can use enum. Example:
public enum InputType
{
abc, def
{
#Override
public void x()
{
System.out.println("Another method");
}
},
ghy;
public void x()
{
System.out.println("One method");
}
}
And further:
InputType.valueOf("abc").x();
Cheers!
I guess you could always use a Map<String, Runnable> and map to anonymous Runnable implementations:
myMap.put("abc", new Runnable() { public void run() { do x } });
...
myMap.get(input).run();
You should take a look at the command pattern. There are several ways of implementing it, and frameworks such as Spring can help you do with in a clean way.
But in a simple manner here's what you could do:
1-Create a Command interface with a method that your program will have to call to do the task, say doTask()
2-Create classes for command X and Y, implementing the Command interface.
3-Create a Map<String, Command> that will map your commands (X and Y) to logical names
4-Create a configuration file of your choice, say a .properties file that will map your input to your command names: abc=X, def=Y, ghi=X
5-Your program then does lookups on the config file to know which command to run according to the input.
A lot of ifs always tell us that we could do this better. In your case better option is to use design pattern e.g. Chain of responsibility. You will have good implementation which you can dynamic change and your code will be easier to maintenance than ifs implementation.
Take a look at this adaptation chain of responsibility to your case:
Main:
public static void main(String[] args) {
ClassA classA = new ClassA(Arrays.asList("abc", "ghi"));
ClassB classB = new ClassB(Arrays.asList("def"));
classA.setNextInChain(classB); // you can always write Builder to do this
String input = "def";
classA.execute(input);
}
BaseClass:
public abstract class BaseClass {
private Collection<String> patterns = Collections.EMPTY_LIST;
protected BaseClass nextInChain;
protected abstract void doMethod(); // your doA, doB methods
public void execute(String input) {
// this replace many ifs in your previous implementation
if (patterns.contains(input)) {
doMethod();
} else {
nextInChain.execute(input);
}
}
public void setPatterns(Collection<String> patterns) {
this.patterns = patterns;
}
public void setNextInChain(BaseClass nextInChain) {
this.nextInChain = nextInChain;
}
}
Class in chain:
public class ClassA extends BaseClass {
ClassA(Collection<String> patterns) {
setPatterns(patterns);
}
#Override
protected void doMethod() {
// do A
}
}
public class ClassB extends BaseClass {...}

Categories

Resources