Introduction

This portfolio is to document my contributions to project NUStudy, which is a software engineering project under Module CS2103T at National University of Singapore. Our team consists of five students majoring in Computer Science. We decided to morph an existing Java application Address Book 3 into NUStudy, which is a desktop application with command line for user input and a JavaFX GUI for display. NUStudy supports notes management, quiz practice, revision task records, and usage statistics to help with revision.

You may take note of the following symbols and formatting used in this portfolio unless otherwise specified:
overdue - The monospaced text indicates that it is a user input.
Task - An italicised word indicates that it is a class name.
#11 - A number with # sign indicates the Pull Request or Issue number.
PR - Abbreviation for "Pull Request".
monospaced text in Developer Guide has different meanings. If the first letter of each word is capitalized, then the monospaced text refers to a class or interface name. If the text comes with a bracket () at the end, then the text refers to a method name. Otherwise, the text refers to user command.

Summary of Contributions

This section summarises my contributions to the project, including feature enhancements, documentation and project management.

Enhancement added: I implemented revision task management features (starting from PR #37).

  • What it does: These features support tasks for revising a note or a question at a particular point of time. Users can perform operations with revision tasks such as addition, deletion, searching, editing, marking done, listing finished/unfinished/overdue tasks etc.

  • Justification: This feature allows users to set their revision plans and goals. It makes the revision more structured and organised. The task is designed in a way that each task only supports revision of one note or question. Having this "one tiny easy revision task at a time" approach, users would find it easier to start the revision. This helps to stop procrastination to some extent.

  • Highlights: This enhancement is dependent on Note and Question classes implemented by my teammates. There might be regressions of my task features if my teammates decide to change their implementations. Therefore, I did a thorough analysis of the design pattern and the project architecture to use as least information as possible from their classes in order to reduce coupling. The task management features require a decent amount of effort because they need to support a wide range of operations.

Code contributed: You may feel free to check my code here.

Other contributions:

  • Project management:

    • I was the project leader for NUStudy.

    • I was in charge of overall team coordination, scheduling, facilitating discussion during weekly team meetings and communicating with the tutor.

    • I issued the first version of project plan (#26).

    • I did the pre-release of mid-v1.3 on GitHub (mid-v1.3).

  • Documentation:

    • Redesigned class diagrams for UI and Model components in Developer Guide (#75).

    • Added command summary to User Guide (171).

  • Team work and community contribution:

    • Reported bugs of teammate’s feature (#165, 166).

    • Reviewed other teams' PRs (#14, #97).

Contributions to the User Guide

This section summarises my contributions to the User Guide.

Revision tasks

You will know more about how to work with revision tasks in this section. The revision tasks help you plan your revision of notes and questions. You can do various operations on tasks, including addition, deletion, searching etc.

The revision tasks are not synchronised with the note or the question. Once created, the task content will not change if you modify the corresponding note or question.
Revision tasks with the same heading, date and time are considered duplicate tasks and cannot co-exist.

Adding a revision task for a note: rn

You can add a revision task for a note to the current revision task list with this command. The heading will copy the title. The GUI will display all tasks upon completing the command.
Format: rn t/TITLE_OF_NOTE dt/DATE tm/TIME

TITLE_OF_NOTE is case sensitive.

Example:

  1. Type rn t/CS2103T UML diagram dt/01/11/2019 tm/0900 in the command input box, and press Enter to execute it, as shown in the diagram below.

    600
  2. The result box will display the message "Revision task added: [N] NOTE : CS2103T UML diagram by: 01 November 2019 09:00". The task is added to the task list shown in the middle panel, as shown in the diagram below.

    600

Adding a revision task for a question: rq

You can add a revision task for a question to the current revision task list with this command. The heading will copy the question body. The GUI will display all tasks upon completing the command.
Format: rq i/INDEX_OF_QUESTION dt/DATE tm/TIME
Example:
rq i/1 dt/11/11/2019 tm/1500

For constraints on DATE and TIME input, you may refer to Adding a revision task for a note: rn.

Removing revision task: rdelete

You can remove a particular revision task from current list with this command. The GUI will display the current list (all-task, done-task, not-done-task or overdue-task) view.
Format: rdelete INDEX_OF_TASK
Example: rdelete 2

Marking the revision task as done: rdone

You can mark a task as done once you finished it. The GUI will display the current list (all-task, done-task, not-done-task or overdue-task) view.
Format: rdone INDEX

Example:

  1. Type rdone 1 in the command input box, and press Enter to execute it, as shown by the diagram below.

    600
  2. The result box will display the message "Revision task marked as done: [Y] …​" with the task details. The status icon of the task turns from "[N]" (not done) to "[Y]" (done). You may refer to the diagram below.

    600
    You cannot use "undone" (marking a task as not done) feature. People usually "undone" a task because they realise that some parts of the task are not fully completed. In this case, you should create a new task with a new date or time (same as "re-scheduling" in the real world).

Editing a revision task: redit

You can edit a revision task with this command. You need to provide non-empty arguments with prefix h/, dt/ and tm/ for fields you want to change. Please take note that at least one field must be provided.
Format: redit INDEX [h/HEADING] [dt/DATE] [tm/TIME]
Example:
redit 1 h/CS2100 Logic Circuit dt/15/08/2019 tm/1200

HEADING can be the title of a note or the question body of a question. The edited HEADING must be an existing title or question body.
HEADING is case sensitive.

Viewing all revision tasks: rlist

You may view the whole revision task list using this command.
Format: rlist

Viewing completed revision tasks: finished

You may use this command to view the list of revision tasks that you have completed.
Format: finished

Viewing uncompleted revision task: unfinished

You may use this command to the list of revision tasks that you have not completed.
Format: unfinished

Viewing overdue revision tasks: overdue

You may use this command to view the revision tasks which you have not done but having passed the scheduled time.
Format: overdue

Finding tasks with specified details: rfind

You may use this command to search for tasks with specified details. You may key in keyword(s) of the heading, or the date, or the time, with prefix h/ dt/ tm/ respectively. The GUI will display a task list of all tasks with the field (heading or date or time) that matches your input.
Format: rfind h/WORD [WORD]…​ or rfind dt/DATE or rfind tm/TIME

Words for headings are case insensitive for rfind.

Example:
rfind h/hello world - This command gives you all tasks with headings containing "hello" or "world" or "hello world".
rfind dt/01/11/2019 - This command gives you all tasks on 1 November 2019.
rfind tm/1200 - This command gives you all tasks at 12:00 (12pm), regardless of date.

The priority of the fields are h/ > dt/ > tm/. When multiple prefixes (fields) are provided for search, only the field with the highest priority will be considered. The rest will be ignored.
A heading is considered matching with the keywords as long as one of the words in the heading is the same as one of the words in the input keywords. Please note that the minimum matching unit is a word (not characters) in the heading. Words in the headings are separated by a space.

Clearing current revision plan: rclear

You can remove all revision tasks with this command.
Format: rclear

Apart from the documentation of my individual feature, I also helped the team by adding a command summary of everyone’s feature. You may refer to the Command Summary section in the User Guide.

Contributions to the Developer Guide

This section summarises my contributions to the Developer Guide. For a full list of all task commands, please refer to the beginning of section "Revision task management - Implementation" in the Developer Guide.

Revision task management

Revision task management involves addition, deletion, editing, searching and many other operations on tasks. This section explains how task management features are implemented.

Implementation

Revision task management is facilitated by Model. Commands related to task manipulation extend Command class. The commands update the Model interface which is implemented by ModelManager class. The ModelManager then updates AppData which stores all the revision tasks in an internal data structure TaskList. TaskList is essentially an ObservableList of Task. Local data will be updated in the end by LogicManager.

Taking AddTaskForNoteCommand as an example, the following process illustrates the mechanism of adding a revision task for note to the task list (adding a revision task for question has a similar command but different parameters).

Step 1. The user enters command rn t/UML diagram dt/01/01/2019 tm/1200 for adding a task for note. The command is parsed by AddTaskForNoteCommandParser. AddTaskForNoteParser then creates an AddTaskForNoteCommand. The high-level logic of parsing and creating the command is similar to the process of deleting a note from the note list as illustrated by the sequence diagram for deleting a note. However, the execution stage of AddTaskForNoteCommand differs from that of deleting a note.

Step 2. The Logic Manager calls Command#execute(Model) which essentially calls AddTaskForNoteCommand#execute(Model) because of polymorphism.

Step 3. AddTaskForNoteCommand calls its own private method hasValidNote(Model) which checks if the Note with Title "UML diagram" exists in Model. If not, a CommandException will be thrown and execute(Model) stops because non-existing note title is not allowed to be the heading of any tasks.

Step 4. AddTaskForNoteCommand calls Model#hasTask(Task) to check whether the Model has a task identical to the one the user is adding. If there is an existing identical task, a CommandException will be thrown and execute(Model) stops to avoid duplicate tasks.

Step 5. AddTaskForNoteCommand calls Model#addTask(Task) to add the new task to the Model. Model calls AppData#addTask(Task) to add the task to AppData which keeps track of all data of the app. AppData then calls TaskList#add(Task) to add the task to TaskList, which is the underlying data structure storing tasks.

Step 6. A CommandResult is created and returned to the LogicManager to inform the user of successful addition of a new task to the revision plan.

The following sequence diagram illustrates the interaction between classes when calling AddTaskForNoteCommand#execute(Model).

AddTaskForNoteCommandExecuteSequenceDiagram
Figure 1. Sequence diagram for execute(Model) of AddTaskForNoteCommand

Zooming in to Step 3, when calling hasValidNoteForTask(Model), AddTaskForNoteCommand creates a new Note with a Title "UML diagram" and a Content "dummy entry". The entry of Content is not important because AddTaskForNoteCommand only records the Title of a Note and the existence of a Note is checked against its Title only (if the title is in the note list, then the note exists in the list). The detailed process is illustrated by the sequence diagram below.

HasValidNoteSequenceDiagram
Figure 2. Sequence diagram for checking existence of a Note in the model when AddTaskForNoteCommand calls its own hasValidNoteForTask(Model)

The following activity diagram summarizes the whole process of adding a task for note.

AddTaskForNoteActivityDiagram
Figure 3. Activity diagram for adding a task for note

Design considerations

Aspect: Design of Task
  • Alternative 1 (current implementation): We implement Task as a concrete class with two subclasses to support task for notes and questions respectively.

    • Pros: It supports different behaviours of task for Note and task for Question by polymorphism. The concrete Task class will also allow adding of general tasks in v2.0.

    • Cons: We need to implement two different AddTask commands to support addition of the two different types of tasks. Hence we need to write more pieces of code.

The class diagram below illustrates how Task class is designed:

TaskClassDiagram
Figure 4. Design of Task class
  • Alternative 2: We design Task as an interface to be implemented by two different classes.

    • Pros: This approach is better in data hiding. The client classes know less information about internal properties of Task.

    • Cons: We need to implement all methods in the interface and hence more code snippets are needed. Both implementing classes have to include the field in common such as isDone, which results in duplicate code snippets.

  • Alternative 3: We wrap everything in one concrete Task class to support both lecture notes and questions.

    • Pros: We need to write less code.

    • Cons: It violates the principle of Separation of Concern, making it hard to maintain or extend in the future if more types of tasks are needed.

Aspect: Design of command for adding a task
  • Alternative 1 (current implementation): We implement the command as two independent classes, namely AddTaskForNoteCommand and AddTaskForQuestionCommand to support adding TaskForNote and TaskForQuestion respectively.

    • Pros: The two types of commands, although similar in logic, receive different parameters and interact with different classes (one interacting with TaskForNote while another one interacting with TaskForQuestion). Therefore, it is better to separate the concerns by implementing the commands as two separate classes. If TaskForNote and TaskForQuestion classes deviate more significantly in the future in terms of their behaviour, this approach makes it easier to maintain the adding commands.

    • Cons: We need to write more code. There might be some duplicate code snippets involving the logic shared by both commands. We also need to implement different parsers for the two commands, which involes some extra work.

  • Alternative 2: We implement only one class of adding command to support both TaskForNote and TaskForQuestion.

    • Pros: We can write less code as there would be fewer duplicate code snippets and we do not need to implement separate command parsers.

    • Cons: This approach leads to lower level of abstraction as all concerns of Task, regardless of TaskForNote or TaskForQuestion, are wrapped into the same class. It could be difficult to maintain if the behaviors of TaskForNote and TaskForQuestion get more complex and diverse.

Use case: Add a revision task for note to revision plan (Shui Yao)

Preconditions: lecture note list is not empty

MSS

  1. Student keys in revision task command and specifies the title of the note he/she wants to add to revision plan, with starting date and starting time

  2. NUStudy adds the task to revision plan

  3. NUStudy informs the Student about successful addition of the task

Use case ends

Extensions

  • 1a. NUStudy detects missing entry for note title

    • 1a1. NUStudy requests for input of note title

    • 1a2. Student enters correct input

    • Steps 1a1 - 1a2 are repeated until the input is valid

  • Use case resumes from Step 2

  • 1b. NUStudy detects a note title entry that is non-existent in the note list

    • 1b1. NUStudy requests for a valid input of note title (a note that exists in the note list)

    • 1b2. Student enters valid note title

    • Steps 1b1 - 1b2 are repeated until the input is valid

  • Use case resumes from Step 2

  • 1c. NUStudy detects missing starting date or time

    • 1c1. NUStudy requests for correct input with starting date and time

    • 1c2. Student enters correct input following the format

    • Steps 1c1 - 1c2 are repeated until getting a correct input with valid starting date and time

  • Use case resumes from Step 2

  • 1d. NUStudy detects invalid date or time

    • 1d1. NUStudy requests for valid date and time

    • 1d2. Student enters correct input with valid date and time

    • Steps 1d1 - 1d2 are repeated until getting a correct input with valid date and time

  • Use case resumes from Step 2

Apart from addition to my individual features, I also modified the diagrams of the UI and Model components. You may refer to Figure 4. Class diagram of the UI component, Figure 5. Detailed class diagram for Panels package and Figure 8. Class diagram of the Model component in the Developer Guide.