ezDo is the eziest™ way to keep track of all the user’s tasks efficiently with command line style inputs. It is a Java desktop application with a user-friendly GUI implemented with JavaFX.
ezDo is written in Java and is designed in an Object Oriented Programming (OOP) manner. As such, this guide describes the class design and technical implementation of ezDo. It will help developers (like you) understand how classes within ezDo interact with each other and how you can contribute to its development.
We have organized this guide in a top-down manner so that you can understand the general framework of ezDo before moving on to the more detailed sections of ezDo’s components. Each sub-section is mostly self-contained to provide ease of reference.
From this repository, fork and clone it to your computer.
Ensure that you have installed the e(fx)clipse and Buildship Gradle Integration plugins as given in the prerequisites above.
Click File
> Import
.
Click General
> Existing Projects into Workspace
> Next
.
Click Browse
, then locate the project’s directory.
Finish
.Figure 1 explains the high-level design of ezDo.
The
.pptx
files used to create diagrams in this document can be found in the diagrams folder.To update a diagram, modify the diagram in the
.pptx
file, select the objects of the diagram, and chooseSave as picture
.
Main
has only one class called MainApp
:
At ezDo launch, it is responsible for initializing the components in the correct sequence and connecting them up with each other.
At shut down, it is responsible for shutting down the components and invoking cleanup methods where necessary.
Commons
represents a collection of classes used by multiple other components.
Two of those classes play important roles at the architecture level:
EventsCenter
: This class (written using Google’s Event Bus library) is used by components to communicate with other components using events (i.e. a form of Event Driven design).
LogsCenter
: This class is used by many classes to write log messages to ezDo’s log file.
The rest of ezDo consists of four components:
UI
: The ezDo’s UI
.Logic
: The command executor.Model
: The data of ezDo in-memory.Storage
: The handler of read-write operations to disk.Each of the four components
interface
with the same name as the component.{Component Name} Manager
class.For example, Logic
(see Figure 2) defines its API in the Logic.java
interface and exposes its functionality using the LogicManager.java
class.
Figure 3 shows how the components interact for the scenario where the user issues the command kill 1
.
Note how
Model
simply raises aEzDoChangedEvent
when ezDo data is changed, instead of askingStorage
to save the updates to the hard disk.
Figure 4 shows how 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
EventsCenter
toStorage
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 on each component.
API : Ui.java
UI
consists of a MainWindow
that consists of several parts (as shown in Figure 5). For example: CommandBox
, ResultDisplay
, TaskListPanel
, StatusBarFooter
and TaskCardHeader
. All these, including the MainWindow
, inherit from the abstract UiPart
class.
UI
uses the JavaFX UI
framework. The layout of 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
.
UI
component:
Executes user commands using Logic
.
Binds itself to some data in Model
so that the UI can auto-update when data in Model
changes.
Responds to events raised from various parts of ezDo and updates UI
accordingly.
UI
is designed in such as way that adding/removing a new part is simple, by adding/removing the java
part with its corresponding .fxml
file as well as updating the MainWindow
class. Doing this will not affect the other parts of UI
.
The Model-View-Controller pattern can be observed in ezDo.
Model
stores and maintains all the data in ezDo..fxml
files are responsible for interacting with the user and displaying ezDo’s data. UI
receives data updates from Model
through events.CommandBox
act as ‘Controllers’ for UI
. When the CommandBox
recieves command input from the user, it requests Logic
to execute the command, which may cause changes in Model
.An Observer pattern can be observed in the StatusBarFooter
class, for instance retrieving the latest ezDo storage file path and the last updated time.
API : Logic.java
As shown in Figure 6,
Logic
uses the Parser
class to parse the user command.
A Command
object is executed by the LogicManager
.
The command execution can affect Model
(e.g. adding a task) and/or raise events.
The result of the command execution is encapsulated as a CommandResult
object which is passed back to UI
.
In some Parser classes such as FindCommandParser, due to the huge amount of search parameters supported by ezDo’s power search function (see Find
in UserGuide), a SearchParameter
Object is created with the Builder pattern to contain all the search parameters. This allows future developers to introduce more parameters by changing the SearchParameter
Class instead of changing methods in Model
.
The Command pattern is employed, as the Command
object is passed around and executed.
The sequence diagram (shown in Figure 7) shows the interactions within Logic
for the execute("kill 1")
API call.
API : Model.java
As shown in Figure 8, Model
:
Stores a UserPref
object that represents the user’s preferences.
Stores ezDo
data which includes the Tag
list and Task
list.
Exposes a UnmodifiableObservableList<ReadOnlyTask>
object that can only be ‘observed’ i.e UI
can be bound to this list so that the displayed list on the interface displays changes when the data in the list changes.
Changes are made on a FilteredList. The changes are then raised in an eventBus (see other sections) which mutates the UnmodifiableObservableList<ReadOnlyTask>
. This causes the change within the list to be reflect in UI
.
Changes are made on a FilteredList. The changes are then raised as an event (see other sections) which mutates the UnmodifiableObservableList<ReadOnlyTask>
. This causes the change within the list to be reflect in UI
.
ezDo stores all tasks, regardless done or undone, in one FilteredList (see Storage
section for more information).
As such, commands such as Edit
, Done
and Kill
can be executed easily on a single list instead of keeping track of multiple lists of tasks with different types (done and undone).
This FilteredList is designed with the Singleton Pattern, since only one FilteredList of task is created each time ezDo is run and all mutations and searches are done on this list.
A Predicate and Qualifier interface plays a vital role in mutating the FilteredList, since they allow us to indicate a given Qualifer to expose certain tasks as viewable by a user. (e.g filter tasks which are Done
; filter tasks which have certain Priority
).
ezDo supports undo/redo commands. We saw two ways of doing it:
Save history states.
Remember what actions were taken, and do the logical reverse of them when the undo command is called.
After consideration, we decided to go with saving history states. In a task manager, tasks can be deleted and cleared. We can specify a ‘de-clear’ action, but since data is already lost, we can never actually return to the original state.
As such, our undo/redo functionality is designed with the Memento Pattern. The EzDo
in ModelManager
is the originator while the ModelManager
class that implements Model
is the caretaker. It holds two custom fixed-capacity array-based stacks of size 5. One stack holds history states for the undo command, while the other is for the redo command. We decided to limit the size of the stack in order to prevent stack overflow. This is a real possibility when the task manager holds a lot of data, and the user inputs many commands that keep accumulating history states in the undo stack. We felt that 5 is a good number of history states to save, in that users can undo up to 5 undo-able commands. If the stack is full, the newest history state overwrites the oldest one in the stack, thereby maintaining its size of 5.
Before any undo-able command is fully executed, a copy of the current history state is saved onto the undo stack and the redo stack is cleared.
If a user executes the undo command, the current state would be saved onto the redo stack, and the previous state in the undo stack popped off so that ModelManager
can rollback to it.
In addition, ezDo supports sorting by name, priority, start date or due date. The user’s last used sort criteria and order are remembered across sessions. This is achieved by storing the sort criteria and order in user preferences. To achieve this, the Observer pattern is employed. When the tasks are sorted, the events SortCriteriaChangedEvent
and IsSortedAscendingChangedEvent
will be raised. The MainApp
class listens for these events, and handles them by updating the userPref
object with the updated sort criteria and order.
API : Storage.java
As shown in Figure 9, Storage
:
Saves UserPref
objects in .json
format and read it back.
Saves ezDo data in .xml
format and read it back.
ezDo allows users to specify a new location to save their data. Instead of populating a user’s machine with many duplicates of the saved data by simply copying the old file and creating a new copy, we move the current data file to the new location specified. This new location is saved in Config
so that ezDo knows where to retrieve the right data file in the next session. The Observer pattern is employed. After execution of a SaveCommand
, an event will be posted. The StorageManager
class which listens for such events will handle the event by moving the ezDo data file and updating Config
.
Classes used by multiple components are in the seedu.ezdo.commons
package.
Similar to Jim, our main target users have the following characteristics:
All tests can be found in the ./src/test/java
folder.
GUI Tests - These are system tests that test the entire application by simulating user actions on the GUI. These are in the guitests
package.
Unit tests
These tests target the lowest level methods/classes.
For example: seedu.ezdo.commons.UrlUtilTest
Integration tests
These tests check the integration of multiple code units (i.e. those code units are assumed to be working).
For example: seedu.ezdo.storage.StorageManagerTest
Hybrids of unit and integration tests
These tests check the multiple code units (i.e. how they are connected together).
For example: seedu.ezdo.logic.LogicManagerTest
To run all tests, right-click on the src/test/java
folder and choose Run as
> JUnit Test
.
To run a subset of tests, right-click on a test package, test class, or a test and choose Run as
> JUnit Test
.
See UsingGradle.md to learn how to use Gradle for build automation.
We use Travis CI and AppVeyor to perform Continuous Integration on our projects.
See UsingTravis.md and UsingAppVeyor.md for more details.
See UsingGithubPages.md to learn how to use GitHub Pages to publish documentation to the project site.
Generate a JAR file using Gradle.
Tag the repo with the version number. (For example: v0.1
)
Create a new release using GitHub and upload the JAR file you created.
We use Google Chrome for converting documentation to PDF format, as Google Chrome’s PDF engine preserves hyperlinks used in webpages.
Make sure you have set up GitHub Pages as described in UsingGithubPages.md.
https://cs2103jan2017-w14-b4.github.io/main/docs/UserGuide.html
.Print
option in Chrome’s menu.Save as PDF
, then click Save
to save a copy of the file in PDF format. A project often depends on third-party libraries. For example, ezDo depends on the Jackson library for XML parsing. Gradle can automate downloading the dependencies, which is better than these alternatives.
- Include those libraries in the repo (this bloats the repo size).
- Require developers to download those libraries manually (this creates extra work for developers).
Table 1 describes the user stories relevant to ezDo.
Priorities:
- High (must have) -
* * *
- Medium (nice to have) -
* *
- Low (unlikely to have) -
*
Priority | As a … | I want to … | So that I can… |
---|---|---|---|
* * * |
user | add a floating task | add tasks that need to be done ‘some day’ |
* * * |
user | add a task with deadlines | know when I must finish the task |
* * * |
user | view all the tasks by the order I added them | be more organised |
* * * |
user | delete a task | get rid of tasks I no longer want to track |
* * * |
user | check a task as done (not deleted) | know I have finished it |
* * * |
user | view a history of all the tasks I have done | check what I have done |
* * * |
new user | view the help guide | know the different commands there are and how to use them |
* * * |
user | edit my tasks | update them |
* * * |
user | undo my last command | undo mistakes/typos |
* * * |
user | add events that have a start and end time | know what my day will be like |
* * * |
user | search for tasks by deadline/description | see what task I entered |
* * * |
user | specify where to keep my tasks (file and folder) | move them around if need be |
* * * |
power user | set tags to tasks | group related tasks by tags |
* * * |
power user | search by tags | know everything I have to do related to that tag |
* * |
user | sort tasks by name, deadline, priority, start date or due date | quickly see what tasks I have to finish first |
* * |
user | list tasks | add deadlines to tasks without deadlines |
* * |
power user | use shortened versions of commands | save time when inputting tasks |
* * |
user | add different priorities to my tasks | know which tasks need to be done first |
* * |
user | list my tasks in priority order | see which tasks have different priorities |
* * |
user | undo multiple commands | revert changes |
* * |
user | enter recurring tasks | enter it just once |
* * |
power user | assign standard commands to my preferred shortcut commands | be familiar with my own modified commands |
* * |
user | make tasks that have very close deadlines to appear as special priority | remember to complete them |
* * |
user | set notifications for deadlines for my tasks | be notified |
* * |
power user | set how much time it requires to finish a task | know how long I need to start and finish a task and not leave it halfway |
* * |
user | set tasks that are currently underway | be aware of the tasks I am working on |
* * |
user | redo my last action | reverse accidental undo commands |
* |
user | list the tasks that are due soon | meet my deadlines |
For all use cases below, the **System** is ezDo
and the **Actor** is the user
, unless otherwise specfied.
MSS
Extensions
1a. The user enters an invalid command.
1a1. ezDo shows an error message and prompts the user to retry.
1a2. Use case resumes at step 1.
MSS
Extensions
1a. The user enters an invalid command.
1a1. ezDo shows an error message and prompts the user to retry.
1a2. Use case resumes at step 1.
1b. The indexed task does not exist.
1b1. ezDo shows an error message and prompts the user to select another index.
1b2. Use case resumes at step 1.
MSS
Extensions
1a. The indexed task does not exist.
1a1. ezDo shows an error message and prompts the user to select another index.
1a2. Use case resumes at step 1.
MSS
Extensions
1a. The indexed task does not exist.
1a1. ezDo shows an error message and prompts the user to select another index.
1b1. Use case resumes at step 1.
MSS
Extensions
1a. The folder does not exist.
1a1. ezDo shows an error message and prompts the user to choose another path.
1a2. Use case resumes at step 1.
1b. The user enters an invalid command.
1b1. ezDo shows an error message and prompts the user to try again.
1b2. Use case resumes at step 1.
ezDo should:
Your life, once you start using ezDo.
Windows, Linux, Unix, OS X.
A computer user who uses advanced features which are typically not used by an normal user.
These feautures include computer hardware, operating systems, programs or web sites.
Trello requires most of the work to be done with a mouse (moving of tasks by mouse etc). Moreover, Trello does not sort tasks by deadline or priority. Jim will find it inconvenient if he wishes to view his tasks in a certain order.
Sticky notes is not so good for Jim. Jim follows ‘Inbox Zero’. If he uses Sticky Notes, he no longer has to worry about an inbox full of emails, because he gets a desktop full of notes now instead. Sticky notes require mouse-clicks and Jim prefers typing. Sticky Notes also doesn’t show what has to be done by a certain date.
Wunderlist does not suit Jim’s needs. Though it supports basic task creation with the keyboard alone, it does not allow Jim to record essential details such as the deadlines or priority without using a mouse.
For Jim, the applications allows him to zoom in to tasks or projects that require immediate action. However, this application is restricting him to add tasks or projects using the command line interface. He has to use the graphical interface to edit or delete a task which will decrease his productivity and therefore it is not suitable for him.