Developer Guide
- Setting Up
- Design
- Implementation
- Testing
- Continuous Integration
- Making a Release
- Managing Dependencies
- Appendix A: User Stories
- Appendix B: Use Cases
- Appendix C: Non Functional Requirements
- Appendix D: Glossary
- Appendix E : Product Survey
Setting up
Prerequisites
-
JDK
1.8.0_60
or laterHaving any Java 8 version is not enough.
This app will not work with earlier versions of Java 8. - Eclipse IDE
- e(fx)clipse plugin for Eclipse (Do the steps 2 onwards given in this page)
- Buildship Gradle Integration plugin from the Eclipse Marketplace
Importing the project into Eclipse
- Fork this repo, and clone the fork to your computer
- Open Eclipse (Note: Ensure you have installed the e(fx)clipse and buildship plugins as given in the prerequisites above)
- Click
File
>Import
- Click
Gradle
>Gradle Project
>Next
>Next
- Click
Browse
, then locate the project’s directory - Click
Finish
- If you are asked whether to ‘keep’ or ‘overwrite’ config files, choose to ‘keep’.
- Depending on your connection speed and server load, it can even take up to 30 minutes for the set up to finish (This is because Gradle downloads library files from servers during the project set up process)
Activity Diagram
The Activity Diagram given above explains the flow of the activity present in the App.
Object Oriented Domain Model
The Object Oriented Domain Model given above explains the static design of the App from a prototypical perspective.
Design
The Architecture Diagram given above explains the high-level design of the App.
Given below is a quick overview of each component.
Main
has only one class called MainApp
. It is responsible for,
- At app launch: Initializes the components in the correct sequence, and connect them up with each other.
- At shut down: Shuts down the components and invoke clean up method where necessary.
Commons
represents a collection of classes used by multiple other components.
Two of those classes play an important role at the architecture level.
EventsCenter
: This class (written using Google’s Event Bus library) is used to by components to communicate with other components using events (i.e. a form of Event Driven design)LogsCenter
: Used by many classes to write log messages to the App’s log files.
The rest of the App consists four components.
UI
: The UI of the App.Logic
: The command executor.Model
: Holds the data of the App in-memory.Storage
: Reads data from, and writes data to, the hard disk.
Each of the four components
- Defines its API an interface with the same name as the Component.
Logic.java
- Exposes its functionality using a
{Component Name}Manager
class e.g.LogicManager.java
Sequence Diagram
Delete Command
The Sequence Diagram below shows how the components interact for the scenario where the user issues the
command delete 1
.
Note how the
Model
simply raises aModelChangedEvent
when the model is changed, instead of asking theStorage
to save the updates to the hard disk.
The diagram below shows how the EventsCenter
reacts to that event, which eventually results in the updates
being saved to the hard disk and the status bar of the UI being updated to reflect the ‘Last Updated’ time.
Note how the event is propagated through the
EventsCenter
to theStorage
andUI
withoutModel
having to be coupled to either of them. This is an example of how this Event Driven approach helps us reduce direct coupling between components.
The sections below give more details of each component.
UI component
API : Ui.java
The UI consists of a MainWindow
that is made up of parts e.g.CommandBox
, ResultDisplay
, TagListPanel
, PriorityListPanel
, TaskListPanel
, StatusBarFooter
etc. All these, including the MainWindow
inherits from the abstract UiPart
class
and they can be loaded using the UiPartLoader
.
The UI
component uses JavaFx UI framework. The layout of these UI parts are defined in matching .fxml
files
that are in the src/main/resources/view
folder.
For example, the layout of the MainWindow
is specified in
MainWindow.fxml
The UI
component,
- Executes user commands using the
Logic
component. - Binds itself to some data in the
Model
so that the UI can auto-update when data in theModel
change. - Responds to events raises from various parts of the App and updates the UI accordingly.
Logic component
API : Logic.java
Logic
uses theParser
class to parse the user command.- This results in a
Command
object which is executed by theLogicManager
. - The command execution can affect the
Model
(e.g. adding a task) and/or raise events. - The execution of the command is recorded in
CommandHistory
class, which contains multiple instances of Command objects which can be recalled for undo. - The result of the command execution is encapsulated as a
CommandResult
object which is passed back to theUII
Model component
API : Model.java
The Model
,
- Stores a
UserPref
object that represents the user’s preferences - Stores the Task Scheduler data
- Exposes a
UnmodifiableObservableList<ReadOnlyTask>
that can be ‘observed’ e.g. the UI can be bound to this list so that the UI automatically updates when the data in the list change. - Does not depend on any of the other three components.
Storage component
API : Storage.java
The Storage
component,
- can save
UserPref
objects in json format and read it back. - can save the Task Scheduler data in xml format and read it back.
Common classes
Classes used by multiple components are in the seedu.taskscheduler.commands
package.
Implementation
Logging
We are using java.util.logging.Logger
as our logger, and LogsCenter
is used to manage the logging levels
of loggers and handlers (for output of log messages)
- The logging level can be controlled using the
logLevel
setting in the configuration file (See Configuration) -
The
Logger
for a class can be obtained usingLogsCenter.getLogger(Class)
which will log messages according to the specified logging level - Currently log messages are output through:
Console
and.log
Logging Levels
- SEVERE
- Critical use case affected, which may possibly cause the termination of the application
- WARNING
- Can continue, but with caution
- INFO
- Information important for the application’s purpose
- e.g. update to local model/request sent to cloud
- Information that the layman user can understand
- Information important for the application’s purpose
- FINE
- Used for superficial debugging purposes to pinpoint components that the fault/bug is likely to arise from
- Should include more detailed information as compared to
INFO
i.e. log useful information!- e.g. print the actual list instead of just its size
Configuration
Certain properties of the application can be controlled (e.g App name, logging level) through the configuration file
(default: config.json
):
Testing
In Eclipse:
If you are not using a recent Eclipse version (i.e. Neon or later), enable assertions in JUnit tests as described here.
- To run all tests, right-click on the
src/test/java
folder and chooseRun as
>JUnit Test
- To run a subset of tests, you can right-click on a test package, test class, or a test and choose to run as a JUnit test.
Using Gradle:
- See UsingGradle.md for how to run tests using Gradle.
Tests can be found in the ./src/test/java
folder.
-
GUI Tests - These are System Tests that test the entire App by simulating user actions on the GUI. These are in the
guitests
package. -
Non-GUI Tests - These are tests not involving the GUI. They include,
- Unit tests targeting the lowest level methods/classes.
e.g.seedu.taskscheduler.commons.UrlUtilTest
- Integration tests that are checking the integration of multiple code units
(those code units are assumed to be working).
e.g.seedu.taskscheduler.storage.StorageManagerTest
- Hybrids of unit and integration tests. These test are checking multiple code units as well as
how the are connected together.
e.g.seedu.taskscheduler.logic.LogicManagerTest
- Unit tests targeting the lowest level methods/classes.
Headless GUI Testing :
Thanks to the (TestFX) library we use,
our GUI tests can be run in the headless mode.
In the headless mode, GUI tests do not show up on the screen.
That means the developer can do other things on the Computer while the tests are running.
See UsingGradle.md to learn how to run tests in headless mode.
Continuous Integration
We use Travis CI to perform Continuous Integration on our projects. See UsingTravis.md for more details.
Making a Release
Here are the steps to create a new release.
- Generate a JAR file using Gradle.
- Tag the repo with the version number. e.g.
v0.1
- Create a new release using GitHub and upload the JAR file your created.
Managing Dependencies
A project often depends on third party libraries. For example, Task Scheduler depends on the
Jackson library for XML parsing and PrettyTime library for date parsing. Managing these dependencies can be automated using Gradle. For example, Gradle can download the dependencies automatically, which is better than these alternatives.
a. Include those libraries in the repo (this bloats the repo size)
b. Require developers to download those libraries manually (this creates extra work for developers)
Appendix A : User Stories
Priorities: High (must have) - * * *
, Medium (nice to have) - * *
, Low (unlikely to have) - *
Priority | As a … | I want to … | So that I can… |
---|---|---|---|
* * * |
new user | see usage instructions | refer to instructions when I forget how to use the App |
* * * |
user | add a new task | create a new task |
* * * |
user | list all tasks | see all the tasks |
* * * |
user | find a task by specific parameters | locate details of tasks without having to go through the entire task list |
* * * |
user | set the data file path | change the working directory to where i want |
* * * |
user | delete a task | remove entries that I no longer need |
* * * |
user | clear all tasks | start a fresh task list |
* * * |
user | edit a task | edit details without re-entry |
* * * |
user | undo a command | revert the previous action |
* * * |
user | mark a task as complete | manage my task list easily |
* * * |
user | have flexibility in the command format | type a few natural variations of the command format |
* * * |
user | create floating tasks | tasks can be created without specific times |
* * * |
user | exit the task list | close the task list |
* * |
user | use up arrow or down arrow to reuse previous command(s) | revert the previous command |
* * |
user | tags the task | group the tasks into categories |
* * |
user | indicate overdue tasks with color code (red) | easily to track overdue task |
* * |
user | indicate a completed task with color code (green) | easily to track done task |
* * |
user | make a task recurring | duplicate a task for specific number of days |
* * |
user | have a ui that display useful information | manage my task list easily |
* * |
user | sort my task by date/time | see the task that needs to be done first |
* * |
user | export data | make a copy elsewhere |
* * |
user | import data | load my data |
* |
user | select a task | display and refer to the task’s command |
* |
user | unmark a task | unmark the task that is accidentally marked as completed |
Appendix B : Use Cases
(For all use cases below, the System is the MustDoList
and the Actor is the user
, unless specified otherwise)
Use case 1: Help
MSS
- User requests for help
- MustDoList shows the user guide through a html file
Use case ends.
Use case 2: Add task
MSS
- User requests to add tasks
- MustDoList adds the task
- MustDoList shows a list of added tasks
Use case ends.
Extensions
1a. The add task request has invalid format
1a1. MustDoList shows an error message
Use case resumes at step 1
1b. The add task request has a duplicate task name
1b1. MustDoList shows an error message
Use case resumes at step 1
Use case 3: List task
MSS
- User requests to list tasks
- MustDoList shows a list of tasks
Use case ends.
Extensions
2a. The list is empty
Use case ends
Use case 4: Find task
MSS
- User requests to find tasks
- MustDoList shows a list of found tasks
Use case ends.
Extensions
1a. The find task request has an invalid parameter
1a1. MustDoList shows an error message
Use case resumes at step 1
2a. The list is empty
Use case ends
Use case 5: Delete task
MSS
- User requests to list tasks
- MustDoList shows a list of tasks
- User requests to delete a specific task in the list by the task’s index
- MustDoList deletes the task
Use case ends.
Extensions
2a. The list is empty
Use case ends
3a. The given index is invalid
3a1. MustDoList shows an error message
Use case resumes at step 3
Use case 6: Clear task
MSS
- User requests to clear tasks
- MustDoList clears all entries of tasks
Use case ends.
Use case 7: Edit task
MSS
- User requests to list task
- MustDoList shows a list of tasks
- User requests to edit a specific task in the list by the task’s index
- MustDoList edits the task
Use case ends.
Extensions
2a. The list is empty
Use case ends
3a. The edit task request has invalid format
3a1. MustDoList shows an error message
Use case resumes at step 3
3b. The given index is invalid
3b1. MustDoList shows an error message
Use case resumes at step 3
Use case 8: Undo task
MSS
- User requests to undo task
- MustDoList undo the task
Use case ends.
Extensions
2a. The task list is at initial stage
2a1. MustDoList shows an error message
Use case ends.
Use case 9: Mark task
MSS
- User requests to list task
- MustDoList shows a list of tasks
- User requests to mark a specific task as completed in the list by the task’s index
- MustDoList marks the task as completed
Use case ends.
Extensions
2a. The list is empty Use case ends
3a. The given index is invalid
3a1. MustDoList shows an error message
Use case resumes at step 2
Use case 10: Set storage path
MSS
- User requests to change default storage path
- MustDoList changes the path of default storage
Use case ends.
Extensions
1a. The set storage path task request has invalid format
1a1. MustDoList shows an error message
Use case resumes at step 1
Use case 11: Exit task list
MSS
- User requests to exit task list
- MustDoList closes the task list
Use case ends.
Use case 12: Recur a task
MSS
- User requests to list task
- MustDoList shows a list of tasks
- User requests to recur a specific task in the list by the task’s index
- MustDoList recurs the task with a specific numbers of days
Use case ends
Extensions
2a. The list is empty
Use case ends
3a. The recur task request has invalid format
3a1. MustDoList shows an error message
Use case resumes at step 3
3b. The given index is invalid
3b1. MustDoList shows an error message
Use case resumes at step 3
Use case 13: Select task
MSS
- User requests to list tasks
- MustDoList shows a list of tasks
- User requests to select the index of a specific task in the list
- MustDoList highlight the selected task in the list Use case ends.
Extensions
2a. The list is empty
Use case ends
3a. The given index is invaild
3a1. MustDoList shows an error message
Use case resumes at step 3
Use case 14: Tag task
MSS
- User requests to list tasks
- MustDoList shows a list of tasks
- User requests to tag the index of a specific task in the list
- MustDoList tag the selected task with given tag name(s) in the list Use case ends.
Extensions
2a. The list is empty
Use case ends 3a. The given index is invalid 3a1. MustDoList shows an error message
Use case resumes at step 3
3b. The given tag name has invalid format
3b1. MustDoList shows an error message
Use case resumes at step 3
Use case 15: Unmark task
MSS
- User requests to list task
- MustDoList shows a list of tasks
- User requests to unmark a specific task as completed in the list by the task’s index
- MustDoList unmarks the task as completed
Use case ends.
Extensions
2a. The list is empty Use case ends
3a. The given index is invalid
3a1. MustDoList shows an error message
Use case resumes at step 2
Use case 16: Export task’s data
MSS
- User requests to export data
- MustDoList will export current data to desire path
Use case ends.
Extensions
1a. The export task request has invalid format
1a1. MustDoList shows an error message
Use case resumes at step 1
Use case 17: Import task’s data
MSS
- User requests to import data
- MustDoList will import data from specific path
Use case ends.
Extensions
1a. The import task request has invalid format
1a1. MustDoList shows an error message
Use case resumes at step 1
Appendix C : Non Functional Requirements
- Should work on any mainstream OS as long as it has Java
1.8.0_60
or higher installed. - Should be able to hold up to 1000 tasks.
- Should come with automated unit tests and open source code.
- Should favor DOS style commands over Unix-style commands.
- Should backup the MustDoList to prevent data-loss
- Should have a small overall program size
- Should have fast response time.
- Should be accessible and usable only by authorized users
- Should protect task information
http://www.comp.nus.edu.sg/~cs2103/AY1617S1/contents/handbook.html#handbook-project-constraints
Appendix D : Glossary
Mainstream OS
Windows, Linux, Unix, OS-X
Appendix E : Product Survey
Todoist
Summary
- Todoist is a online task management application and to do list.
Strength
- Access task everywhere (on mobile, web browser)
- Collaborate on shared task in real-time
- Powerful recurring dates by creating repeating due dates.
Weakness
- A few important features not available to free user
- Search function is limited in the free plan
- Does not have a backup option for free users. Premium level is available at $29-per-year.
Google Calendar
Summary
- Google Calendar is an online calendar that keep track of life’s important events all in one place.
Strength
- Supports multiple calendars for a single user
- Schedule meeting using keyword like Suggested Time or Find a Time
- Share calendar with others.
Weakness
- User must sign up for the service
- Offline version is available for viewing only
- Cannot categorize calendar events based on event type.
- User cannot operate primarily using keyboard