Skip to content
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

Open
wants to merge 53 commits into
base: master
Choose a base branch
from

Conversation

aegis-bot
Copy link

Duke Increments

j-lum and others added 14 commits August 6, 2019 15:25
Add toolVersion block in to Gradle code sample to prevent errors.
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.
@aegis-bot aegis-bot changed the title Hong Wen [Hong Wen] Duke increments Jan 26, 2020
Copy link

@yjskrs yjskrs left a 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.

src/main/java/seedu/java/util/Ui.java Outdated Show resolved Hide resolved
return "Affirmative. Adding a to-do task :) \n" + "added: " + task + "\n" + totalTask();
}

private String addDead(String task, String timing) {
Copy link

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?

Copy link
Author

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

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.

Copy link
Author

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

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)

Copy link

@alcen alcen left a 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 Exceptions! You mentioned that you did not know how to create your own, and that could have led to the widespread general Exception usage. Hope you will change it, if possible!

  • Long if/else and switch 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) {
Copy link

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;
Copy link

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 {
Copy link

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;

Copy link

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

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

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

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

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

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?

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."
Copy link

@alcen alcen Feb 3, 2020

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

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.

Copy link

@teo-jun-xiong teo-jun-xiong left a 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:

  1. Improve readability by inserting new lines appropriately, rather than clumping the code into one large block
  2. Detailed JavaDocs comments, though not exactly a requirement at this stage of the iP
  3. Abstract duplicated code out, e.g. in Deadline and Event, to its superclass, Task

@@ -0,0 +1,4 @@
T/0/borrow book

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 {

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

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
*/

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

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 {

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

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

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.

@sinhayash
Copy link

Good effort!

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.

None yet

7 participants