-
Notifications
You must be signed in to change notification settings - Fork 454
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
[Pranav Ganesh] iP #477
base: master
Are you sure you want to change the base?
[Pranav Ganesh] iP #477
Conversation
Merge branch branch-Level-7 into Master
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.
There are many Javadocs missing, it would be good to write header comments for all public classes and methods see here
It might also be good to be consistent with the number of new lines at the end of your files rather than no or dangling new lines. I believe it is good to have a single new line at the end.
There are several places where System.out.println
was directly used, possibly violating the abstraction from Ui.printMessage
(I guess this might not really matter once you start implementing the GUI, you wouldn't be able to use System.out.println
to directly print to your UI)
src/main/java/duke/Parser.java
Outdated
@@ -0,0 +1,60 @@ | |||
package duke; | |||
|
|||
import duke.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.
You might want to avoid wild card imports even if you have to import everything
https://se-education.org/guides/conventions/java/intermediate.html#package-and-import-statements
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.
For the parse
method below
Perhaps a switch statement here would help to improve readability or you could modify the code by splitting the string by the empty character delimiter twice so you don't have to do another if
inside the external if
Maybe your InvalidCommand can be an exception, and your doneCommand can throw the exception so you don't have to do all the checking within this method which could make the code easier to read
} | ||
} | ||
|
||
public void loadTaskListData(TaskList taskList) { |
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 may want to document public methods with javadocs
https://se-education.org/guides/conventions/java/intermediate.html#comments
The method here is also quite lengthy. It might be a good idea to abstract the other logic into various methods
https://nus-cs2103-ay2122s1.github.io/website/se-book-adapted/chapters/codeQuality.html#avoid-long-methods
src/main/java/duke/Storage.java
Outdated
System.out.println(str); | ||
String[] parts = str.split("\\|", 4); | ||
String subStr = parts[0].substring(3).trim(); | ||
if (subStr.equals("duke.task.Todo") || subStr.equals("duke.task.Todo")) { |
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 might be wrong here but doesn't subStr.equals("duke.task.Todo") || subStr.equals("duke.task.Todo")
do the same as subStr.equals("duke.task.Todo")
src/main/java/duke/Storage.java
Outdated
public void loadTaskListData(TaskList taskList) { | ||
try { | ||
Scanner s = new Scanner(this.file); // create a Scanner using the File as the source | ||
if (!s.hasNext()) { |
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 logic here is quite deeply nested, perhaps it might be good if you handled the unusual case with a guard clause
https://nus-cs2103-ay2122s1.github.io/website/se-book-adapted/chapters/codeQuality.html#make-the-happy-path-prominent
if (!s.hasNext()) {
// code here...
return;
}
src/main/java/duke/Storage.java
Outdated
task.markAsDone(); | ||
} | ||
taskList.addTask(task); | ||
} else { |
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 may want to use a switch statement for this long if else. It may be good because you're comparing strings and it can directly be used for your cases.
Additionally the else statement here captures all other cases of subStr, not necessarily when it is an Event
. If new requirements come in and there are new type of Task
, the developer might forget to update the logic here and the new type of Task
will automatically fall into the else case and treated like an Event
.
The default case in a switch statement could be used to catch invalid cases. I believe the default case is optional in Java
https://www.geeksforgeeks.org/switch-statement-in-java/
The style guide suggests that
Always include a default branch in case statements.
Furthermore, use it for the intended default action and not just to execute the last option. If there is no default action, you can use the default branch to detect errors (i.e. if execution reached the default branch, raise a suitable error). This also applies to the final else of an if-else construct. That is, the final else should mean 'everything else', and not the final option. Do not use else when an if condition can be explicitly specified, unless there is absolutely no other possibility.
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.
Good job overall! Just one thing to take note of: try to use small and simple functions to handle your complex logic, don't put everything into one function. It makes readers confusing and it is also hard to do unit testing~
this.command = command; | ||
} | ||
|
||
public Command parse() { |
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.
Perhaps try not to write deeply nested loops in your function? You might consider using 'switch' for this function?
} | ||
} | ||
|
||
public void loadTaskListData(TaskList taskList) { |
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 might want to break it down into smaller functions here? This function seems to be too deeply nested.
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.
Good job! Your code seems very well done.
src/main/java/duke/Parser.java
Outdated
} else { | ||
if (command.startsWith("todo")) { | ||
return new todoCommand(command); | ||
} else if (command.startsWith("deadline")) { | ||
return new deadlineCommand(command); | ||
} else if (command.startsWith("event")) { | ||
return new eventCommand(command); | ||
} else if (command.startsWith("delete")) { | ||
return new deleteCommand(command); | ||
} else { | ||
return new InvalidCommand(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.
You can consider using a switch statement here 😄
src/main/java/duke/Ui.java
Outdated
public static void doneResponse(Task task) { | ||
System.out.println("Nice! I've marked this task as done:"); | ||
System.out.println(task); | ||
storage.writeToFile("./duke.txt", taskList); | ||
} |
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.
Good idea to write to file everytime a task is edited. This way the state of the tasks are not lost incase the app crashes.
src/main/java/Duke.java
Outdated
Parser parser = new Parser(command); | ||
if (parser.isExit()) { | ||
break; | ||
} | ||
Command c = parser.parse(); |
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 can consider making parse()
a static method, that way you would not have to create a new parser object everytime a command is given.
Merge branch-A-JavaDoc into Master
Merge branch-Level-9 into Master
Merge add-gradle-support into Master
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.
There were some violations of code (in particular class name capitalization). There was also a questionable design decision of writing to the file every time a new task was inserted or deleted, which can case performance issues.
But overall, it's a good program design.
src/main/java/duke/Parser.java
Outdated
} else if (command.startsWith("done") && Character.isDigit(command.charAt(command.length() - 1)) && command.length() <= 8 | ||
&& !Character.isAlphabetic(command.charAt(command.length() - 2)) && Character.isDigit(command.charAt(5))) { | ||
return new doneCommand(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.
This if block's condition could be simplified, with only the command type being checked in the main condition, and the other checks could be further done inside the body.
src/main/java/duke/Parser.java
Outdated
/** | ||
* Checks if the user types the command 'bye' or the user clicks enter without typing any command. | ||
* | ||
* @return True or False. |
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 return value could be further elaborated.
* Deals with making sense of the user command | ||
*/ | ||
public class Parser { | ||
private 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.
The string name command
can be confusing, because a class called Command is in this project, but command is not a Command object.
Maybe change it to commandString
?
private static TaskList taskList; | ||
private static Storage storage; |
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.
Why are taskList and storage static?
/** | ||
* Represents the user command when the user enters a deadline. | ||
*/ | ||
public class deadlineCommand extends 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.
Class name should be PascalCase: DeadlineCommand
/** | ||
* Represents the user command when the user enters an event. | ||
*/ | ||
public class eventCommand extends 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.
Class name should be PascalCase: EventCommand
|
||
import duke.Ui; | ||
|
||
public class findCommand extends 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.
Class name should be PascalCase: FindCommand
Ui.printMessage("Here are the matching tasks in your list:"); | ||
String[] parts = this.command.split(" ", 2); | ||
String wordToFind = parts[1]; | ||
int count = 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.
count should start at 0 instead of 1, to make things more intuitive
/** | ||
* Represents the user command when the user wants to view the task list. | ||
*/ | ||
public class listCommand extends 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.
Class name should be PascalCase: ListCommand
* An abstract class that represents the various types of commands that can be entered by the user. | ||
*/ | ||
public abstract class Command { | ||
private 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.
Perhaps consider making command
protected
instead of private
? It would make the code much cleaner since subclasses make use of this variable a lot
Merge branch-Level-10 into Master
None of the existing classes have assertions to detect the source of logical flaws in the code. The addition of assertions will increase the probability of identifying bugs in the program that are caused by violation of certain assumptions in the program logic. Let's add assertions to the relevant parts of the code to define certain assumptions about the program state. Using assertions is greatly advantageous as assertions are easy to implement and help document and verify key assumptions that should hold at various points in the code.
Add assertions to document important assumptions in the code
There are several instances in the code where code quality can be further enhanced. Good quality of code makes sure that code is written in such a way that makes them highly readable by a human. Let's improve the code quality by critically examining the code and refactoring parts of it to make it more readable and make sure it complies with the code quality commonly practiced guidelines. Doing it this way will help eliminate common code quality problems such as weak SLAP, arrow-head style code, too-long methods and too-deep nesting.
🔥 DUKE 🔥
Duke frees your mind of having to remember things you need to do. It's,
FASTSUPER FAST to useAll you need to do is,
And it is FREE!
Duke's features:
If you Java programmer, you can use it to practice Java too. Here's the
main
method: