-
Notifications
You must be signed in to change notification settings - Fork 205
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
[Hong Wen] Duke increments #66
base: master
Are you sure you want to change the base?
Conversation
Add toolVersion block in to Gradle code sample to prevent errors.
Change file mode on `gradle` to be executable (nus-cs2103-AY1920S2#9)
Gradle defaults to an empty stdin which results in runtime exceptions when attempting to read from `System.in`. Let's add some sensible defaults for students who may still need to work with the standard input stream.
Add configuration for console applications
The OpenJFX plugin expects applications to be modular and bundled with jlink, resulting in fat jars that are not cross-platform. Let's manually include the required dependencies so that shadow can package them properly.
…duke to new classes.
… more functions to tasklist.
adding gradle support to duke
…Main.java in place
…& testReadCommand() to ParserTest
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.
Like how you give user instructions at bot start up! Also really clean code and liked that you incorporated exceptions.
return "Affirmative. Adding a to-do task :) \n" + "added: " + task + "\n" + totalTask(); | ||
} | ||
|
||
private String addDead(String task, String timing) { |
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 feel that this method deserves a better name... What do you think?
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.
Certainly XD
storage = new Storage(filePath); | ||
try { | ||
tasks = new TaskList(storage.load()); | ||
} catch (Exception e) { |
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.
Pokemon catching!! I think it might be better to specify the exact exceptions you want to catch (e.g. FileNotFoundException) and also for those methods where you just throw Exception, might be better to be more specific.
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.
Thanks! I was wondering how to create custom exceptions until i reviewed other people's work!
/** | ||
* Prints the logo & gives instructions. | ||
*/ | ||
public void intro() { |
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 consider using more descriptive names for this class (i.e. introduceBot, readInput or something)
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, you made a really commendable effort!! I feel that you took great care in following general Object-Oriented principles, and including documentation for methods that may not be so understandable.
That being said, I have left comments on some areas of improvement to work on below, and I hope the comments are helpful!! Do add to the discussion as you read along so we can strive for an improved program
-
Javadocs are present for most methods, but I feel that more details can be given in some cases (see comments below for some examples)
-
Many
Exception
s! You mentioned that you did not know how to create your own, and that could have led to the widespread generalException
usage. Hope you will change it, if possible! -
Long
if
/else
andswitch
statements are quite common, which could affect future extensibility of the program -
I feel like you don't have to commit the .class files, as these can be easily compiled from the source code
* @param cmd - a piece of text | ||
* @return Command | ||
*/ | ||
public static Command convert(String cmd) { |
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 feel like another way you could do this, is by instantiating each Command constant with a String
Example:
public enum Command {
ERROR("error"),
TODO("todo"),
..., // all your other commands
FIND("find");
private final String cmd;
Command(String cmd) {
this.cmd = cmd;
}
public static Command convert(String cmd) {
for (Command c : Command.values()) {
if (c.cmd.equals(cmd)) {
return c;
}
}
return ERROR; // maybe you could throw an Exception instead
}
This would avoid the lengthy if/else statements and allow you to add new Commands easily!
package seedu.java.util; | ||
|
||
public class Complete { | ||
private boolean yesOrNo; |
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 per the coding style conventions, this could be named something like isComplete
instead
@@ -0,0 +1,18 @@ | |||
package seedu.java.util; | |||
|
|||
public class Complete { |
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.
Seems like this class is only used in Task! I'm not very sure why a Complete
class is used to wrap a boolean value here, could you please share the rationale? To me, I feel that encapsulation should not be used where it is not required
|
||
public class Event extends Task { | ||
private String timing; | ||
|
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.
Seems like Event
could make use of java.time.LocalDate
as well, just like Deadline
! In fact, I think it is a good idea to make both Event
and Deadline
extend some abstract class with concrete methods for formatting a String
into a LocalDate
, to ensure that code is not duplicated. Just a minor note for future extension
public void run() { | ||
ui.intro(); | ||
ui.output(tasks.listToPrint()); | ||
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.
To me, a while (true)
loop makes it unclear whether the program will eventually exit the loop or not. Granted, the code inside the loop is quite short, and it is quite obvious that the program will break out of the loop when some condition is met. What are your thoughts?
return "You have " + (taskArr.size()) + " task on your list."; | ||
} | ||
|
||
private String addTodo(String task) { |
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.
Again, possible violation of Open-Closed Principle where a new method will need to be created for every new Task! I feel that it would be better to have a general addTask(Task t)
method to add all possible Tasks
return toPrint; | ||
} | ||
|
||
private String listToPrint(ArrayList<Task> tasks) { |
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.
Seems like unnecessary code duplication! (the two listToPrint
methods)
Would it be a better idea to just use the one with signature listToPrint(ArrayList<Task> tasks)
and pass in this.taskArr
when required? It may also make it more evident which list you are printing
private String findTask(String keyword) { | ||
ArrayList<Task> matchedTask = new ArrayList<>(); | ||
for (Task x: taskArr) { | ||
if(x.getTask().contains(keyword)) { |
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 think that there should be a space after the if
and before the brackets, following the common coding style conventions
public String read(String input) { | ||
try { | ||
Command cmd = Parser.readCommand(input); | ||
switch (cmd) { |
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.
To me, this switch statement feels like it could be improved, as it is another potential violation of Open-Closed Principle. Adding a new command will require a new case
, and even a new method in class TaskList
!
It would be quite tedious to solve this issue though. One way I have in mind would be to expand Command
into a full class, and have it implement a method executeCommand(ArrayList<Task> tasksList, String task, String timing, ...)
(you can use String[]
or String...
for the many Strings) so you would just call executeCommand
here, regardless of what the command actually is. But that would require an overhaul of a large portion of the code
Any thoughts?
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 a great comment! Now it makes more sense as to why one of the increments suggested adding Commands and its subclasses now. At that point I didn't see much sense in it, but now, maybe I'll integrate that into my own Duke!
+ "\n" + "DELETE -- Deletes a task. Type 'delete' & a task number to delete that task." | ||
+ "\n" + "LIST -- If you want to view what's on your tasklist, key in 'list'." | ||
+ "\n" + "FIND -- Too many Task that you're not sure which is which? key in 'find' & the key word. A list of task based on the keyword will be printed." | ||
+ "\n" + "BYE -- When you're sick of using this useless software and want to quit, type 'bye' & I'll terminate operation." |
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.
Like yjskrs said, interesting start-up message! Quite informative, though a bit long
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 a way is unclutter the startup message would be to simply show "HELP -- Show a list of commands Duke can understand.", and place the code under that.
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 logic of the code and the coding style is well done. Some pointers are:
- Improve readability by inserting new lines appropriately, rather than clumping the code into one large block
- Detailed JavaDocs comments, though not exactly a requirement at this stage of the iP
- Abstract duplicated code out, e.g. in Deadline and Event, to its superclass, Task
@@ -0,0 +1,4 @@ | |||
T/0/borrow book |
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 it would make sense to exclude files like this being committed to GitHub, since the list of Tasks will always be added at the initialization.
* @return Command | ||
* @throws Exception | ||
*/ | ||
public static Command readCommand(String input) throws Exception { |
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 think that the javadocs for this method can be clearer, e.g. why is the Exception being thrown? Also, adding on to @alcen, it would be clearer to perhaps create a custom exception like InvalidCommandException.
String[] arr = input.split(" "); | ||
String task = ""; | ||
int i = 1; | ||
while (i < arr.length && !arr[i].startsWith("/")) { |
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.
Adding new lines to separate blocks of code (while loop, if-block) increases readability!
* Loads up a txt file and converts it to an Arraylist of Task. | ||
* @return ArrayList of Tasks | ||
* @throws FileNotFoundException means your text file is missing/corrupted | ||
*/ |
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 javadocs is clear and concise, documenting the reason for the thrown Exception.
return arr; | ||
} | ||
|
||
private static boolean toBool(String com) { |
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.
Just a pointer, this function can be simplified to
return com.equals("1");
@@ -0,0 +1,47 @@ | |||
package seedu.java.util; | |||
|
|||
public class Task { |
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 making Task an abstract class can be considered, since a Task is never created. Todo, Event, and Deadline can simply extend it. Methods such as Task#completeTask, Task#getTask can be kept, while perhaps abstract methods can be implemented.
public String read(String input) { | ||
try { | ||
Command cmd = Parser.readCommand(input); | ||
switch (cmd) { |
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 a great comment! Now it makes more sense as to why one of the increments suggested adding Commands and its subclasses now. At that point I didn't see much sense in it, but now, maybe I'll integrate that into my own Duke!
+ "\n" + "DELETE -- Deletes a task. Type 'delete' & a task number to delete that task." | ||
+ "\n" + "LIST -- If you want to view what's on your tasklist, key in 'list'." | ||
+ "\n" + "FIND -- Too many Task that you're not sure which is which? key in 'find' & the key word. A list of task based on the keyword will be printed." | ||
+ "\n" + "BYE -- When you're sick of using this useless software and want to quit, type 'bye' & I'll terminate operation." |
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 a way is unclutter the startup message would be to simply show "HELP -- Show a list of commands Duke can understand.", and place the code under that.
Good effort! |
…o handle fxml files
…. Modified Duke to read and output as an application.
…ction to Tasklist
Duke Increments