Skip to content

[Pranav Ganesh] iP#477

Open
pranav-ganesh wants to merge 51 commits into
nus-cs2103-AY2122S1:masterfrom
pranav-ganesh:master
Open

[Pranav Ganesh] iP#477
pranav-ganesh wants to merge 51 commits into
nus-cs2103-AY2122S1:masterfrom
pranav-ganesh:master

Conversation

@pranav-ganesh

@pranav-ganesh pranav-ganesh commented Aug 26, 2021

Copy link
Copy Markdown

🔥 DUKE 🔥

“Your mind is for having ideas, not holding them.” – David Allen source

Duke frees your mind of having to remember things you need to do. It's,

  • text-based
  • easy to learn
  • FAST SUPER FAST to use

All you need to do is,

  1. download it from here.
  2. double-click it.
  3. add your tasks
  4. let it manage your tasks for you 😃 😊

And it is FREE!

Duke's features:

  • Managing features
  • Managing deadlines (coming soon)
  • Reminders (coming soon)

If you Java programmer, you can use it to practice Java too. Here's the main method:

public static void main(String[] args) {
    new Duke("./duke.txt").run();
}

@yongxiangng yongxiangng left a comment

Copy link
Copy Markdown

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)

Comment thread src/main/java/duke/Parser.java Outdated
@@ -0,0 +1,60 @@
package duke;

import duke.command.*;

Copy link
Copy Markdown

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

@yongxiangng yongxiangng Aug 30, 2021

Copy link
Copy Markdown

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

https://www.geeksforgeeks.org/split-string-java-examples/

https://nus-cs2103-ay2122s1.github.io/website/se-book-adapted/chapters/codeQuality.html#guideline-maximise-readability

}
}

public void loadTaskListData(TaskList taskList) {

Copy link
Copy Markdown

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

Comment thread 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")) {

Copy link
Copy Markdown

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")

Comment thread 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()) {

Copy link
Copy Markdown

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;
}

Comment thread src/main/java/duke/Storage.java Outdated
task.markAsDone();
}
taskList.addTask(task);
} else {

Copy link
Copy Markdown

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.

@Linxcathyyy Linxcathyyy left a comment

Copy link
Copy Markdown

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() {

Copy link
Copy Markdown

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) {

Copy link
Copy Markdown

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.

@SKCheongBrian SKCheongBrian left a comment

Copy link
Copy Markdown

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.

Comment thread src/main/java/duke/Parser.java Outdated
Comment on lines +19 to +29
} 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);

Copy link
Copy Markdown

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 😄

Comment thread src/main/java/duke/Ui.java Outdated
Comment on lines +52 to +56
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);
}

Copy link
Copy Markdown

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.

Comment thread src/main/java/Duke.java Outdated
Comment on lines +24 to +28
Parser parser = new Parser(command);
if (parser.isExit()) {
break;
}
Command c = parser.parse();

Copy link
Copy Markdown

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.

@Smanmos Smanmos left a comment

Copy link
Copy Markdown

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.

Comment thread src/main/java/duke/Parser.java Outdated
Comment on lines +36 to +38
} 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);

Copy link
Copy Markdown

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.

Comment thread 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.

Copy link
Copy Markdown

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;

Copy link
Copy Markdown

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?

Comment on lines +13 to +14
private static TaskList taskList;
private static Storage storage;

Copy link
Copy Markdown

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 {

Copy link
Copy Markdown

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 {

Copy link
Copy Markdown

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 {

Copy link
Copy Markdown

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;

Copy link
Copy Markdown

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 {

Copy link
Copy Markdown

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;

Copy link
Copy Markdown

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

e0661424 and others added 15 commits September 10, 2021 00:35
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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants