OOD - Best way to pass config to an external class - java

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.

Related

Execute java instance method via terminal

I have an instance. Basic structure is ;
class Instance{
public void load(){
...
}
public boolean execute(){
...
return true;
}
}
As normally we can execute this instance in static void main(String args[]) but how can we execute this instance -> load() -> execute() from terminal or compiled file .class is called within a main method than using reflection to execute defined methods.
Because this instance acts like a script on out project, but we do not define main function into class.
Anyone helps?
I recommend simply adding a public static void main(String args[]) that calls load() and execute() so that your class can be executed from the command line in the usual way. There is little point in over-complicating the problem by building a reflection-based wrapper that will just need its own public static void main(String args[]) anyway.
how can we execute this instance -> load() -> execute() from terminal
You can't.
It'll probably be implemented in Java 9, but for now there is no official way to run methods from the command line.
or compiled file .class is called within a main method than using reflection
As you said, use reflection:
File pathToClass = new File("C:\\Some Folder\\");
Class<?> loaded = null;
try {
ClassLoader loader = new URLClassLoader(new URL[] {pathToClass.toURL()});
loaded = loader.loadClass("some.package.foo.Instance");
} catch(Exception e) {
//do something
}
Object i = loaded.newInstance();
Method method = loaded.getMethod("execute");
Boolean returnValue = (Boolean) method.invoke(i);
I'd recommend not doing this though - there's usually a better way and it just overcomplicates everything.

Access one class's members after running it from another class

I recently wrote a class that implements the run method and then parses a video file while grabbing meaningful information. Now I've created a new class that performs a similar operation on the same file but uses a different method of parsing while grabbing other meaningful information. Long story short, I'm required to use two different methods of parsing because some data cannot be extracted by one and some cannot be extracted by the other. The problem I'm facing is that both classes implement the run method, but now I need to start the new class, grab information, start the other class, grab information, then compare the information and print it to the console. This is the gist of what I'm trying to do:
public class first {
[public member variables]
....
public void run(String[] args) {
// parse the file from args and store data
}
public static void main(String[] args) {
new first().run(args); // <------ A
}
}
public class second {
[public member variables]
....
public void run(String[] args) {
// parse the file from args and store data
}
public static void main(String[] args) {
new second().run(args);
}
}
What I'm trying to do is call the first class's main method in order to keep a reference to the class and grab the data from it when it's finished. So I added something like this in the second class:
public class second {
[public member variables]
first firstClass;
int dataFromFirst = 0;
....
public void run(String[] args) {
// parse the file from args and store data
firstClass = new first();
firstClass.main(args); // <------ B
dataFromFirst = firstClass.getSomeData(); // <------ C
}
public static void main(String[] args) {
new second().run(args);
}
}
When I start the second class, everything runs fine, the parser does it's job with both the second and first classes, but when I try to extract the data found by the first class, it's null. I figure once the first class's main method finishes after 'B', once 'A' goes out of scope, everything from the first class is lost. So when I try to get data at 'C', there's nothing there. If this is the case, is there any way I can access the first class's data before it's lost?
I don't have as much knowledge about multithreaded programs so this may just be a very simple solution that I've never seen before.
The reason this doesn't work is that each main method creates its own instance of the class and uses it locally. This has nothing to do with threads, and in fact as far as I can tell your program doesn't actually use multithreading at all.
To fix it, don't call from one main method to the other. In fact, don't even have two main methods in the first place, there's almost never a reason to have more than one. Instead, simply call run directly, like this:
public void run(String[] args) {
// parse the file from args and store data
firstClass = new first();
firstClass.run(args);
dataFromFirst = firstClass.getSomeData();
}

Understanding Command Pattern and why do we need an interface?

I am trying to reduce the if else constructs which I use to display appropriate information in a ListView (Android)
I have created a simple Command Interface for learning purpose and here it is:
interface CommandPattern {
void execute();
}
public class CommandA implements CommandPattern {
public void execute(){
System.out.println("I am Command A");
}
}
public class CommandB implements CommandPattern{
public void execute(){
System.out.println("I am Command B");
}
}
Then my Main is as follows:
public class MainClass {
static Map<String,CommandPattern> myCommand; //= new Map<String, CommandPattern>();
public static void main(String[] args){
myCommand = new HashMap<String, CommandPattern>();
myCommand.put("A",new CommandA());
myCommand.put("B",new CommandB());
// In an ideal condition I will invoke the below by supplying values I get from the Database
// myCommand.get(valuefromDB).execute();
myCommand.get("B").execute();
myCommand.get("A").execute();
}
}
What I have done above can be achieved without using the interface and extending from one by simply calling the execute method of an appropriate class. What is the reason of using an interface?
Secondly does it mean that for each if - else branch I have to construct a new class? Cant this be done using an enum?
The background of the problem:
I have a database and I fetch values based on this data anda number of flags I process data to be displayed in each row. This if else construct has gone beyond what I can ever maintain. So I want to introduce a Command pattern.
Implementing an interface: ClassA has some behavior (i.e., one or more methods), defined by an InterfaceB, that it supports.
Extending a class says that ClassA is a 'special case' of the ClassB being extended; i.e., that ClassA has all of the characteristics (data and methods) of ClassB plus additions and/or changes.
You can implement the Command pattern with either one; which one is appropriate depends on the specific situation. What is to be avoided is using inheritance where the 'special case' does not apply; put another way, do not use inheritance just to have a common method among classes.
EDIT: as to "Can't this be done using an Enum?", it isn't clear what you mean by 'this'.
To demonstrate the power of using an interface:
public class MainClass {
static List<CommandPattern> myCommand;
public static void main(String[] args){
myCommand = new ArrayList<>();
myCommand.add(new CommandA());
myCommand.add(new CommandB());
for (CommandPattern command: myCommand) {
command.execute();
}
}
}
This example shows that two different commands can be executed using the interface. The for-loop is only aware of the fact that it can call èxecute() on the object, but the actual code being executed varies depending on the concrete object adhering to the interface.
Since it is if-else branching you wish to get rid of, I think you might want to look into the Strategy Pattern as well.

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 simplify this logic/code?

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.

Categories

Resources