-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Assignment 2 #2
base: master
Are you sure you want to change the base?
Assignment 2 #2
Conversation
|
||
protected void getGameState(String command) { | ||
String[] commandSplitted = command.split(" "); | ||
if (commandSplitted.length > 3) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the length is less than 3 it will continue and get an index out of bounds error in line 41.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Isn't there a return at line 39? It should just reenter the loop in main.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah there is indeed a return, so it'll return to the main loop.
return; | ||
} | ||
System.out.println("Current game sequence: "); | ||
for(int i = 0; i < gameSequence.toArray().length; i++) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of converting to an array you can just get the length of the ArrayList
using .size()
.
System.out.println("Exiting control room"); | ||
System.exit(0); | ||
} | ||
System.out.println("Invalid command"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These error messages could be replaced by constants (e.g. String INVALID_COMMAND_MESSAGE = "Invalid command"
). If you then ever want to change the message you won't have to change it everywhere where this message is repeated.
protected void setGameState(String command) { | ||
String[] commandSplitted = command.split(" "); | ||
if (commandSplitted.length != 4) { | ||
if(commandSplitted[0].equals("EXIT") && commandSplitted.length == 1){ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is already handled in Main
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This part should indeed be redundant, if it isn't then there is something wrong with your if statements in main, or with your while loop.
System.out.println("The gamestate of " + gameName + " is " + state); | ||
} | ||
|
||
protected void setGameSequence(String command) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you call this function multiple times it will keep adding to the same game sequence rather than "setting" it to the parameters. Is this intended? If so, the name of the function is a little bit misleading.
Map<String, String> games; | ||
ArrayList<String> gameSequence; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These can be private.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And they can also be final.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can see how gamesequence may be used for other things in the future hence the public class. Otherwise why not private.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Clear naming of variables. Package and Import statements consistent with google guidelines.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Readable code, well formatted and follows good naming convention.
String[] commandSplitted = command.split(" "); | ||
if (commandSplitted.length < 3) { | ||
System.out.println("Invalid command"); | ||
return; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This code is repeated in a lot of the functions. Perhaps some kind of a Command
class would be interesting with a function to parse the String
into a Command
object (that stores the parameters and opcode) or something similar.
} | ||
String gameName = commandSplitted[2]; | ||
String state = commandSplitted[3]; | ||
if (!(state.equals("PLAY") || state.equals("PAUSED") || state.equals("FINISHED"))) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could add a list stateOptions
that contains these strings. Then this if statement could be simplified to if(!stateOptions.contains(state)) { ... }
.
commandHandler.getGameState(command); | ||
} else if(command.contains("SET GAMESEQUENCE")) { | ||
commandHandler.setGameSequence(command); | ||
}else if(command.contains("GET GAMESEQUENCE")) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Small indentation mistake
if(command.contains("SET GAMESTATE")) { | ||
commandHandler.setGameState(command); | ||
} else if(command.contains("GET GAMESTATE")) { | ||
commandHandler.getGameState(command); | ||
} else if(command.contains("SET GAMESEQUENCE")) { | ||
commandHandler.setGameSequence(command); | ||
}else if(command.contains("GET GAMESEQUENCE")) { | ||
commandHandler.getGameSequence(); | ||
} else if(command.contains("EXIT")) { | ||
System.out.println("Exited the Squid Game Control Room"); | ||
break; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure if this should be in Main
. Maybe a function in CommandHandler
that does this?
public static void main (String[] args) { | ||
CommandHandler commandHandler = new CommandHandler(); | ||
System.out.println("Welcome to the Squid Game Control Room"); | ||
while (true) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The entire while block can be formatted better, as right now it is hard to read
System.out.println("Welcome to Software Design"); | ||
public static void main (String[] args) { | ||
CommandHandler commandHandler = new CommandHandler(); | ||
System.out.println("Welcome to the Squid Game Control Room"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is best practice to hide string literals behind constants for reusability, so you can make this more reusable by using a constant with the value of the string literal
System.out.print("> "); | ||
Scanner scanner = new Scanner(System.in); | ||
String command = scanner.nextLine(); | ||
if(command.contains("SET GAMESTATE")) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This can also be abstracted behind constants
} | ||
|
||
protected void setGameState(String command) { | ||
String[] commandSplitted = command.split(" "); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is repeated a lot, consider splitting the string in Main
and passing the array to the individual handlers.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
String[] commandSplitted = command.split(" ");
And
String gameName = commandSplitted[2];
Are repeated for all instances, so these could be generalized. The other splits are more specific so thats ok.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The code is readable and clear. I have put suggestions for a CLI
class in a comment on your Main
file and I also added a few command parsing suggestions.
Also: consider extending your gitignore file to also exclude .idea and .gradle folders. This will make it easier to track meaningful changes in your commits.
Scanner scanner = new Scanner(System.in); | ||
String command = scanner.nextLine(); | ||
if(command.contains("SET GAMESTATE")) { | ||
commandHandler.setGameState(command); | ||
} else if(command.contains("GET GAMESTATE")) { | ||
commandHandler.getGameState(command); | ||
} else if(command.contains("SET GAMESEQUENCE")) { | ||
commandHandler.setGameSequence(command); | ||
}else if(command.contains("GET GAMESEQUENCE")) { | ||
commandHandler.getGameSequence(); | ||
} else if(command.contains("EXIT")) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Parsing commands
You parse by getting an input string and checking if this string contains a specific command. This is error-prone as the contains()
method does not capture small errors with whitespace or capitalization (like "SET GAMESTATE" or "set GAMESTATE" would not be recognized as valid commands).
If you want to use the contains()
method, I would suggest converting your command
String from line 12 to uppercase first using Java's String.toUpperCase()
method. This would resolve capitalization errors. To further improve, you can split your raw command
String into an array of Strings. If you split the String on whitespace, you can easily parse commands and eliminate parsing errors due to incorrect whitespace.
Naming and separation of concerns
It is not really clear why you parse commands in Main
when you also have a CommandHandler
class. I would suggest making a CLI
or similar named class in which you do all the parsing. If you move your functionality from the current CommandHandler
class to a specific Game
class, you can do all parsing and command handling in the CLI
class and let this CLI
class call the appropriate methods in your Game
class. In my opinion separation of concerns is covered better this way.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Regarding the command parsing, you split on whitespace repetitively in your CommandHandler
methods, as per @petaripetrov's comment, consider centralizing this in main or in the suggested CLI
class.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Case sensitive commands might not be the best choice. Consider converting strings to upper / lower case before parsing them.
public CommandHandler() { | ||
games = new HashMap<>(); | ||
gameSequence = new ArrayList<String>(); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since there is only one central CommandHandler
defined in Main
you could consider making this a singleton object.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unless your going to use combinations of commands with multiple instances of the game as an example, a singleton may make your intentions on how your going to use the program more clear.
Map<String, String> games; | ||
ArrayList<String> gameSequence; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And they can also be final.
System.out.println("Invalid command"); | ||
return; | ||
} | ||
String gameName = commandSplitted[2]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider using newlines between blocks of code that handle different things
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did mine a bit late so I read throught the comments of others as well.
Map<String, String> games; | ||
ArrayList<String> gameSequence; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can see how gamesequence may be used for other things in the future hence the public class. Otherwise why not private.
public CommandHandler() { | ||
games = new HashMap<>(); | ||
gameSequence = new ArrayList<String>(); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unless your going to use combinations of commands with multiple instances of the game as an example, a singleton may make your intentions on how your going to use the program more clear.
} | ||
|
||
protected void setGameState(String command) { | ||
String[] commandSplitted = command.split(" "); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
String[] commandSplitted = command.split(" ");
And
String gameName = commandSplitted[2];
Are repeated for all instances, so these could be generalized. The other splits are more specific so thats ok.
protected void setGameState(String command) { | ||
String[] commandSplitted = command.split(" "); | ||
if (commandSplitted.length != 4) { | ||
if(commandSplitted[0].equals("EXIT") && commandSplitted.length == 1){ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This part should indeed be redundant, if it isn't then there is something wrong with your if statements in main, or with your while loop.
|
||
protected void getGameState(String command) { | ||
String[] commandSplitted = command.split(" "); | ||
if (commandSplitted.length > 3) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Isn't there a return at line 39? It should just reenter the loop in main.
@@ -1,7 +1,27 @@ | |||
package softwaredesign; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In general your commandhandler class is sufficiently deep with simple functionality, so that is good.
And the idea of ielajazdeev of making input commands generalized by first capitalizing them to avoid errors is a simple implementation to make your system more bug proof.
Also, as Woutuuur commented you can save on lines by avoiding reusing the same code by making a class to handle strings for example.
Finally, right now if you enter an invalid command you don't get feedback. There are also no instructions to operate the system. It also only responds to capitalized letters.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You have a lot of gradle
, build
and idea
files that bloat your changes. If you included more of these in you .gitignore
file, it would be easier to see what actually changed. See here for an example of a comprehensive .gitignore
file for Java. See here for how to apply a .gitignore
file to an existing repo.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You use a lot of string literals directly. You could put them in constants to make sure you only have to change them in one place.
The naming of your methods, classes, and variables overall is good and follows consistent style.
if (commandSplitted.length < 3) { | ||
System.out.println("Invalid command"); | ||
return; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is repeated code, a method to safely split the command could avoid this.
System.out.println("The game " + gameName + " does not exist!"); | ||
return; | ||
} | ||
System.out.println("The gamestate of " + gameName + " is " + state); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of the early return, it could have just been an if... else block.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You should actually omit as many elses as possible, so that would be a bad practice.
System.out.println("Exited the Squid Game Control Room"); | ||
break; | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Make sure you close your Scanner
properly.
public static void main (String[] args) { | ||
CommandHandler commandHandler = new CommandHandler(); | ||
System.out.println("Welcome to the Squid Game Control Room"); | ||
while (true) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This loop is the CLI prompt which handles the input of commands. Should this really be in main()
? In my opinion it could go into the CommandHandler
class, or a CLIHandler
or something similar.
Scanner scanner = new Scanner(System.in); | ||
String command = scanner.nextLine(); | ||
if(command.contains("SET GAMESTATE")) { | ||
commandHandler.setGameState(command); | ||
} else if(command.contains("GET GAMESTATE")) { | ||
commandHandler.getGameState(command); | ||
} else if(command.contains("SET GAMESEQUENCE")) { | ||
commandHandler.setGameSequence(command); | ||
}else if(command.contains("GET GAMESEQUENCE")) { | ||
commandHandler.getGameSequence(); | ||
} else if(command.contains("EXIT")) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Case sensitive commands might not be the best choice. Consider converting strings to upper / lower case before parsing them.
Map<String, String> games; | ||
ArrayList<String> gameSequence; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Clear naming of variables. Package and Import statements consistent with google guidelines.
String[] commandSplitted = command.split(" "); | ||
if (commandSplitted.length < 3) { | ||
System.out.println("Invalid command"); | ||
return; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As previously mentioned the code is repeated.
} | ||
|
||
System.out.println("Set the game sequence to:"); | ||
for(int i = 0; i < gameSequence.toArray().length; i++) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can use .size() instead of converting to an array.
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall looks very good. Code was clear and readable, easy to understand.
public static void main (String[] args) { | ||
CommandHandler commandHandler = new CommandHandler(); | ||
System.out.println("Welcome to the Squid Game Control Room"); | ||
while (true) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree that the while loop could be better formatted for better readability and the if statements can be a separate block. Also I would personally format the else if statements differently but I guess it is based on one's choice.
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Presently the app works in a command line interface but if it had to be extended to a gui it would have to be redone. Maybe it is a good idea to separate command line outputs with functions. So that regardless of implementation the main function need not be changed that much.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall good code, only issues are the if-else block from main which should possibly be in command handler and commandSplitter being repeated.
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Most comments I made have already been made. Clear readable code, got nothing else to add. With the slight improvements it should be good for further implementation in assignment 3.
public static void main (String[] args) { | ||
CommandHandler commandHandler = new CommandHandler(); | ||
System.out.println("Welcome to the Squid Game Control Room"); | ||
while (true) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The command handler can possibly include this functionality that is now in main, but that's a matter of taste. Could be formatted differently as well (maybe a switch statement?)
} | ||
|
||
protected void setGameState(String command) { | ||
String[] commandSplitted = command.split(" "); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Splitting of command is repeated code, and can be handled before this function (possibly combined with the if statements in main)
System.out.println((i + 1) + ": " + gameSequence.get(i)); | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall the functionality of the command handler looks good, especially if you include the if-else block in main inside this file.
public static void main (String[] args) { | ||
CommandHandler commandHandler = new CommandHandler(); | ||
System.out.println("Welcome to the Squid Game Control Room"); | ||
while (true) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am also not sure if this part must be in main or not
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Most of things were already written, so I did not add them again.Other than these small issues, I think you have done it really well.
The only thing I can add is that personally, I like writing short comments on my codes such as at the beggining of the classes/functions etc. They make me understand the reason better why I use sth in there, so maybe you can try that. But as I said, it is something that I like personally, so it is up to you! Good luck in your project
No description provided.