Developer Guide for CommanDo

Download ZIP Download TAR View on GitHub

Introduction

CommanDo is a to-do list manager. It is designed to cater to the needs of people who type fast. The user manage his/her to-do list by typing commands on a text input - just like in a Command Line Interface (CLI). To-dos are displayed on a graphical user interface (GUI), split into 2 panels of Events (To-dos with a date range) and Tasks (To-dos without a date range), as shown below:

A typical view of CommanDo in action

This guide describes the development of CommanDo, how it is currently designed and implemented at a technical level, some of its known issues, and some planned developments and extensions for it.

If you are a new developer, we warmly welcome you on board to our CommanDo team! If you are someone interested to join us in this exciting project, we invite you to contact us to help make CommanDo even better.

Development

Target Users

Our main target users (Jim) are characterised by people who...

  • Have most to-dos coming as emails
  • Update their to-do list very often and desire speed in doing so
  • Want to capture the idea of deadlines in their to-dos

Our Product Survey has revealed that many of the existing to-do list managers are unable to satisfy the needs of our main target users, especially in terms of speed of entry and absence of deadlines.

Features

In summary, we are focusing on these features:

  1. 2 types of to-dos: Events and Tasks, displayed in separate panels in chronological order.
  2. Command-line style input, with commands being short, flexible and intuitive.
  3. Able to search through to-dos easily, empowered by a tagging system.
  4. Undoing and redoing to-do list operations.
  5. Importing and exporting to-do list to a human-readable data file.

The full list of features is outlined in our User Stories. To ensure that the interface is user-friendly and the codebase stays maintainable, we also set ourselves some Non-Functional Requirements.

Setting Up

Prerequisites

  1. JDK 1.8.0_60 or later (Install it here)
  2. Eclipse IDE
  3. e(fx)clipse plugin for Eclipse (Do the steps 2 onwards given in this page)
  4. Buildship Gradle Integration plugin from the Eclipse Marketplace
It is also assumed that you have some prior experience with Java, Github/Git, some OOP and UML diagramming. This guide focuses on the use of the Eclipse IDE.

Importing Project into Eclipse

  1. Fork this repo, and clone the fork to your computer.
  2. Open Eclipse (Note: Ensure you have installed the e(fx)clipse and buildship plugins as given in the prerequisites above).
  3. Click File > Import.
  4. Click Gradle > Gradle Project > Next > Next.
  5. Click Browse, then locate the project's directory.
  6. 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).
    • If Eclipse modifies any settings files during the import process, you can discard those changes.

Architecture

This section explains the high level design of the application. The architecture of CommanDo is as follows:

Architecture diagram for CommanDo

The MainApp class is the entry point of the application. It is responsible for:

  • On application launch, initializing all components in the correct sequence, and connecting them up with one another.
  • On application exit, shutting down all components and invoking cleanup methods where necessary.

The application consists of 4 components, each with distinct roles:

  • UI Component: Acts as the middleman between the user and the API provided by Logic (package seedu.commando.ui)
  • Logic Component: Executes commands from the UI, using the API provided by Model and Storage (package seedu.commando.logic)
  • Model Component: Defines how data is represented and holds the data of the application in-memory (package seedu.commando.model)
  • Storage Component: Reads data from and writes data to the file system (package seedu.commando.storage)

To minimize coupling and help with unit testing, the API of each component is defined by a single Java interface known publicly. This Java interface corresponds to the name of component (e.g. Logic has the interface Logic.java). Each component then exposes its functionality using a concrete class implementing its interface, as listed below:

UI Logic Model Storage
UIManager.java which implements UI.java LogicManager.java which implements Logic.java ModelManager.java which implements Model.java StorageManager.java which implements Storage.java
Note that for the Model component, besides the API defined by Model.java, it also contains data structures such as the UserPrefs and ReadOnlyToDo classes that the other components are dependent on.

Underlying all 4 components are the package seedu.commando.commons. It is a collection of utility classes and application constants that are used in all the components. We use Event Driven Design for components to communicate with one another, and manage logging through a centralized Logs Center.

What Happens in a Command Execution

When the user types a command and presses Enter, the UI calls the execute(String) method of Logic with the input string. Logic parses the input string and determines the command type. Then, Logic would call methods of the Model to modify the to-do list, or post events to the Events Center (which would in turn trigger the relevant components to take action). Refer to the following diagram for the execution of command >> add task.

Sequence diagram for executing command >> add task

Typically, a command would modify the to-do list in the Model (add, edit, delete, etc). Within Model, as we have used JavaFX's Observable classes, the modification would trigger a call to the UI to update its view of the to-do list. On top of that, Model would post a ToDoListChangedEvent to the Events Center, which would trigger Logic to call the saveToDoList(ReadOnlyToDoList) method of Storage. Subsequently, when the to-do list is successfully saved to the file system, the event ToDoListSavedEvent would be posted to update the status bar in UI. Refer to the following diagram for a graphical walkthrough of this sequence.

Sequence diagram for to-do list changed event

UI Component

Structure of UI component

The UI component (package seedu.commando.ui) is in charge of:

  • Handing and passing user input to the appropriate methods of the Logic component.
  • Displaying the graphical user interface (GUI).
  • Updating the GUI automatically when data in the Model component changes, done by binding itself to the data using JavaFX's Observable collections.
  • Responding to events posted in EventsCenter that involve a change in the GUI (e.g. opening the help window when ShowHelpRequestEvent is posted).

It uses the JavaFX UI framework (more information about JavaFX here) - it is made up of GUI parts such as CommandBox, ResultDisplay and EventListPanel. Each part has a class inheriting from the abstract UiPart class (which may be loaded with UiPartLoader), and has a layout defined in a corresponding .fxml file of the same name, located in the resources/view folder. For example, the layout of the MainWindow class is specified in resources/view/MainWindow.fxml.

How the GUI Updates

The UI component adds change listeners to 2 Observable lists of UiToDo: one for Events in the EventListPanel class, another for Tasks in the TaskListPanel class. These lists are provided through the API of Logic. When the Model component updates the to-do list, these lists will also update (which will be described in detail later), and this triggers each panel's ListView to update its contents based on the lists.

Logic Component

Structure of Logic component

The Logic component (package seedu.commando.logic) is in charge of:

  • Parsing the string commands from the UI component through the excute(String) method.
  • Calling the appropriate methods of Model and Storage components, or posting the appropriate events on EventsCenter based on the commands.
  • Informing the UI of the results of the commands executed.
  • Responding to any events from EventsCenter that would require an action on the Model or Storage components (e.g. saving the to-do list to the file system with Storage when the ToDoListChangeEvent is posted).
  • Relaying the data of Model to the UI through its methods of getUiEvents(), getUiTasks() and getToDoList().

When execute(String) is Called

When the UI calls execute(String), LogicManager passes the string command to CommandFactory. CommandFactory, with the help of CommandParser, would determine the type of command and parse it accordingly, creating one of the sub-class of the abstract Command class. The Command would then have its execute() method called in LogicManager, producing a CommandResult. The CommandResult is finally returned to UI, which contains the user feedback message and indicates whether the command was successful. Refer to the following diagram for a graphical walkthrough.

Sequence diagram for Logic when command >> finish 2 is executed

Parsing of Datetimes

The DateTimeParser class in charge of taking in an input string with parseDateTime(String), and returning a LocalDateTime if the string represents a valid datetime. Within the class, it first validates and pre-processes the input string (using regex), then delegates the actual parsing to the Natty library.

Model Component

Structure of Model component

The Model component (package seedu.commando.model) is in charge of:

  • Defining how data in CommanDo is represented in the form of classes (e.g. ToDo, ToDoList).
  • Keeping the user's to-do list in memory and supporting CRUD functionality to it.
  • Keeping track of changes to the to-do list and support undoing and redoing of these changes.
  • Exposing Observable collections of Events and Tasks that are to be shown on the GUI, as well as the filtering, sorting and assigning of indices to these to-dos for the GUI.

Changing, Undoing and Redoing the To-Do List

Within ModelManager, the ToDoListManager class is in charge of supporting the editing, undoing and redoing of the to-do list, hinging on the ToDoListChange class. All commands define an edit to the to-do list in a consistent way with the ToDoListChange class and the changeToDoList(ToDoListChange) method, which provides greater flexibility in edits, looser coupling between Model and Logic, and more predictable effects from undoToDoList() and redoToDoList(), which undos or redos the most recent ToDoListChange that has been pushed to Model.

Preparing for the UI

Within ModelManager, the UiModel class is in charge of processing, sorting and filtering the list of to-dos for the UI. It tracks changes to the actual list of ToDo of Model, and when a change happens, it will update the Observable lists of UiToDo, which are exposed via getUiEvents() and getUiTasks() for the GUI. In an update, it will split the new list of ToDo into Events and Tasks, filter out those which shouldn't be displayed on the GUI, sort them, assign indices to each of them in the correct order, and wraps each ToDo in UiToDo with some additional data.

A similar update is triggered when the user submits a command that calls clearUiToDoListFilter(...) or clearUiToDoListFilter(...) (e.g. the find or recall command).

Storage Component

Structure of Storage component

The Storage component (package seedu.commando.storage) is in charge of the reading of the data for the to-do list and the data for user preferences on the file system, as well as the saving of these data to the file system.

The StorageManager class consists of XmlToDoListStorage, which is in charge of reading/loading the to-do list data, and JsonUserPrefsStorage, which is in charge of reading/loading the user preferences data. The XmlToDoListStorage class saves/loads the to-do list data to the specified file path in XML with the help of Java Architecture for XML Binding. On the other hand, the JsonUserPrefsStorage class saves/loads the user preferences data to the specified file path in JSON with the help of the Jackson JSON Processor library.

Commons Package

The package seedu.commando.commons contains utility classes (in /util), events (in /events), exceptions (in /exceptions), application constants and data structures used in all the components.

EventsCenter and Event Driven Design

For components to inform one another that something has happened, we use Google's Event Bus library, packaged in the EventsCenter class. This is especially important for lower-level components to communicate with higher-level components that they should not be dependent on. An example is the posting of ExitAppRequestEvent by Logic to inform MainApp to close the window.

All events should extend the BaseEvent class and be placed in package seedu.commando.commons.events.

LogsCenter and Logging

We are using the java.util.logging package for logging. The LogsCenter class is used to manage the logging levels and logging destinations. The Logger for a class can be obtained using LogsCenter.getLogger(Class) which will log messages according to the specified logging level.

Currently, log messages are output through the console and to a .log file at the project root.

Logging Levels

  • SEVERE: Critical problems detected which may possibly cause the termination of the application.
  • WARNING: Actions that can be continued, but with caution.
  • INFO: Information showing the noteworthy actions by the application.
  • FINE: Details that are not usually noteworthy but may be useful in debugging (e.g. print the actual list instead of just its size).

Messages

The Messages class contains a list of static String constants that used for displaying user feedback, primarily referenced from the Logic component and the subclasses of Command. All messages displayed to the user should be abstracted to static String constants in this class so that changes to user interaction can be easily made in the same place.

Testing

Tests can be found in the test folder (./src/test/java). We aim to maximise our test coverage, so every class written should be accompanied by a corresponding test class in a similar path within this test folder.

Running Tests

Tests can be run in 2 ways:

  1. In Eclipse - Right-click on the ./src/test/java folder, Run as and then JUnit Test. To run a subset of tests, right-click on a test package, test class, or a test instead.
  2. Using Gradle - See UsingGradle.md for how to run tests using Gradle.
If you are not using a recent Eclipse version (i.e. Neon or later), enable assertions in JUnit tests as described here.

Types of Tests

  1. GUI Tests - They are System Tests that test the entire application by simulating user actions on the GUI. These are in the guitests package.
  2. Headless GUI Testing By applying TestFX library, GUI tests can be run in the headless mode. In the headless mode, GUI tests do not show up on the screen. That means you can do other things on your device while the tests are running. See UsingGradle.md to learn how to run tests in headless mode.
  3. Non-GUI Tests - They include:

    1. Unit tests: targeting the lowest-level methods/classes.
      E.g. seedu.commando.commons.UrlUtilTest
    2. Integration tests: checking the integration of multiple code units (those code units are assumed to be working).
      E.g. seedu.commando.storage.StorageManagerTest
    3. Hybrid tests: testing multiple code units as well as how the are connected together.
      E.g. seedu.commando.logic.LogicManagerTest

Dev Ops

Build Automation

We use gradle for build automation - see UsingGradle.md to learn how.

Continuous Integration

We use Travis CI to perform Continuous Integration on our projects (link to our project's Travis), and we use Coveralls to track our code coverage (link to our project's Coveralls). See UsingTravis.md for more details.

Making a Release

  1. Generate a .jar file using Gradle.
  2. Tag the repo with the version number. e.g. v0.1
  3. Create a new release using GitHub and upload the .jar file you created.

Managing Dependencies

Our project's dependencies are automated using Gradle. Gradle downloads the dependencies automatically for the new developer, which is better than the alternatives of:

  • Including those libraries in the repo (this bloats the repository size).
  • Requiring developers to download those libraries manually (this creates extra work for developers).

Currently, our project's dependencies include:

Troubleshooting

Frequently Asked Questions

Eclipse reports compile errors after new commits are pulled from Git.

It is likely that Eclipse failed to recognise the new files that appeared in the new commits. Refresh the project in Eclipse by right-clicking the project in the package explorer panel and choosing Gradle > Refresh Gradle Project.

Eclipse reports some required libraries missing.

Libraries used by the project might not have been downloaded during project import, or new ones might have been added. Run tests using Gradle once to refresh the libraries in Eclipse.

Known Issues & Future Plans

High RAM Usage

The application currently consumes quite a bit of RAM, up to 150-200+ MB of RAM when we add more than 50 to-dos. We wish to make it less resource-consuming in order to create a better user experience for those with slower systems.

Quick Access Keyboard Shortcut

One of the nice-to-have features is to allow the user to quickly summon CommanDo using a customizable keyboard shortcut, even when the application is closed. This would bring convenience to users who would view and edit their to-do list frequently.

Real-time Syntax Highlighting

A nice-to-have feature is colour-coding the input command in real-time as the user types to reflect the different fields of the command. For example, as the user types >> add event from 10 Oct 2016 9pm to 10pm weekly in the command box, "add" (the command word), "event" (one of the command's fields) and "from" (a keyword in the command) could appear in different colours and the feedback box could state the command format for command word. This allows users to easily validate that their command visually does what they intend it to.

Appendices

Appendix A: User Stories

Priority As a... I want to... So that I can...
* * * user add to-dos start viewing and managing my to-dos
* * * user delete to-dos remove any outdated or invalid to-dos
* * * user edit the description of my to-dos correct any typos or update the details of my to-dos over time
* * * user edit the time constraints of my to-dos correct any typo or update to-dos' timings after they are postponed or confirmed
* * * user view upcoming Events in chronological order, from the current day onwards figure out what is happening next
* * * user view my list of unfinished Tasks figure out what I can do when I am free
* * * user mark my Tasks as done dismiss pending Tasks that I have done
* * * user with many to-dos add tags to to-dos, and search for to-dos by tags quickly determine what kind of classification the to-dos are when I skim through my to-do list
* * * user with many to-dos search for to-dos by their description or tags navigate through a long list of to-dos
* * * user undo my recent edits to the to-do list revert any mistakes made
* * * user redo my previous undos revert any mistakes made
* * * user export or import to-dos to a specified folder backup my to-do list or share the to-do list across multiple devices
* * * user with multiple devices and a cloud-syncing service specify a save/load location for my to-do list keep my to-do list synchronized across multiple devices
* * * new user view a list of commands with a help command learn about the functionality of the application while using it
* * * new user view the correct command syntax and sample commands after inputting a command wrongly learn the correct command syntax while using it
* * user clear all the to-dos on my to-do list start afresh with my to-do list
* * user set events and tasks with due dates as recurring avoid having to enter identical events and tasks periodically
* * user use command keywords (e.g. "from", "to", "by") in titles of my to-dos avoid having to change how I write my to-do because of the command keywords
* * user with many to-dos view all to-dos within a specified date range be able to preview or review the to-dos that are upcoming or done at a glance
* * user browse and search through my past Events and finished Tasks to review and refer to what I have done in the past
* * user receive a visual confirmation of the details of the to-do I have added/edited be able to verify modifications to my to-do list
* very active user summon the application and have it ready for input immediately via a keyboard shortcut quickly be able to add to or remove from my to-do list when I have to
* new user view syntax highlighting of the various fields of a command while inputting, in real time be clear about how the application parses my to-do’s fields and avoid unintended errors in input

Priorities:

  • * * * - High (Must have)
  • * * - Medium (Nice to have)
  • * - Low (Unlikely to have)

Appendix B: Use Cases

In all the listed use cases, the System is our application and the Actor is the user.

UC01 - Add an Event

MSS:
  • 1. User types in an add command with details of the Event, including a title, a date range, a recurrence (if any) and tags (if any).
  • 2. Application adds the Event to the current to-do list and updates the GUI to reflect the changes.
  • Use case ends.
Extensions:
  • 1a. Command word is mistyped.
    • 1a1. Application updates the GUI to inform the user that command word is unknown.
    • Use case ends.
  • 1b. Title is missing.
    • 1b1. Application updates GUI to inform the user that the title is missing.
    • Use case ends.
  • 1c. Either of the start or end of the date range (i.e. from ... to ...) is not in a valid datetime format.
    • 1c1. Application updates GUI to inform the user that the which of start date or end date is invalid.
    • Use case ends.
  • 1d. Both start and end of the date range (i.e. from ... to ...) are not in valid datetime formats.
    • 1d1. Application considers the date range clause as part of a title, adds a corresponding Task to the current to-do list, and updates the GUI to reflect the changes.
    • Use case ends.
  • 1e. The start of the date range (i.e. from ... to ...) is after its end.
    • 1e1. Application updates GUI to inform user that the start of the date range must not be after its end.
    • Use case ends.
  • 1f. The specified recurrence's interval is shorter than the specified date range.
    • 1f1. Application updates GUI to inform user that the recurrence is invalid.
    • Use case ends.

UC02 - Add a Task

MSS:
  • 1. User types in an add command with details of the Task, including a title, a due date and its recurrence (if any), and tags (if any).
  • 2. Application adds the Task to the current to-do list and updates the GUI to reflect the changes.
  • Use case ends.
Extensions:
  • 1a. Command word is mistyped.
    • 1a1. Application updates the GUI to inform the user that command word is unknown.
    • Use case ends.
  • 1b. Title is missing.
    • 1b1. Application updates GUI to inform the user that the title is missing.
    • Use case ends.
  • 1c. The due date (i.e. by ...) is not in a valid datetime format.
    • 1c1. Application considers the due date clause as part of a title, adds a corresponding Task to the current to-do list, and updates the GUI to reflect the changes.
    • Use case ends.

UC03 - Delete an Event or Task

MSS:
  • 1. User types in a delete command with the index of the to-do to delete.
  • 2. Application removes the to-do with the specified index from the current to-do list, and updates the GUI to reflect the changes.
  • Use case ends.
Extensions:
  • 1a. Command word is mistyped.
    • 1a1. Application updates the GUI to inform the user that command word is unknown.
    • Use case ends.
  • 1b. Index of the to-do is not specified.
    • 1b1. Application updates GUI to inform the user that the index is missing.
    • Use case ends.
  • 2a. Index of the to-do is invalid.
    • 2a1. Application updates GUI to inform the user that the index is invalid.
    • Use case ends.

UC04 - Searching through upcoming Events and unfinished Tasks

MSS:
  • 1. User types in a find command, including a list of search keywords and tags.
  • 2. Application searches through the to-do list and updates the GUI to show only upcoming Events and unfinished Tasks that match the search filter.
  • Use case ends.
Extensions:
  • 1a. Command word is mistyped.
    • 1a1. Application updates the GUI to inform the user that command word is unknown.
    • Use case ends.
  • 1b. No search keywords or tags specified.
    • 1b1. Application updates GUI to show all upcoming Events and unfinished Tasks.
    • Use case ends.
  • 2a. No to-dos were found in the search.
    • 2a1. Application updates GUI to inform user that no to-dos were matched.
    • Use case ends.

UC05 - Edit to-do item

MSS:
  • 1. User types in a edit command with the index of the to-do to edit, including the new title, date range, due date, and tags to edit to.
  • 2. Application modifies the target to-do to the current to-do list and updates the GUI to reflect the changes.
  • Use case ends.
Extensions:
  • 1a. Command word is mistyped.
    • 1a1. Application updates the GUI to inform the user that command word is unknown.
    • Use case ends.
  • 1b. Index of the to-do is not specified.
    • 1b1. Application updates GUI to inform the user that the index is missing.
    • Use case ends.
  • 2a. Index of the to-do is invalid.
    • 2a1. Application updates GUI to inform the user that the index is invalid.
    • Use case ends.
  • 2b. A due date is to be added to a Event with a date range.
    • 2b1. Application informs the user that a to-do cannot have both a due date and a date range.
    • Use case ends.
  • 2c. A date range is to be added to a Task with a due date.
    • 2c1. Application informs the user that a to-do cannot have both a due date and a date range.
    • Use case ends.
  • 2d. A date range or due date is to be added to a Task with no time constraints.
    • 2d1. Application attaches the date range or due date to the Task and updates the GUI to reflect the changes.
    • Use case ends.

Appendix C: Non Functional Requirements

  1. Should start-up in at most 3s
  2. Should process every command in at most 1s
  3. Should work on any mainstream OS as long as it has Java 8 or higher installed
  4. Should be able to hold up to 1000 to-dos
  5. Should come with automated unit tests
  6. Should make the code be open source
  7. Should favor DOS style commands over Unix-style commands
  8. Should not use more than 300MB of RAM
  9. Should keep the number of existing files that has to be edited to add new commands at most 2
  10. Should not take more than 1 hour for new user to learn the commands and their syntax

Appendix D: Glossary

  • Mainstream OS: Refers to Windows, Linux, Unix and OS-X.
  • Event: A to-do that has a date range.
  • Task: A to-do without a date range, and optionally has a deadline.
  • Index of to-do item: The number visually tagged to a to-do item on the UI (changes with how to-dos are listed).
  • MSS: Main Success Scenario of a use case.
  • CRUD: Create, Read, Update and Delete.

Appendix E: Product Survey

We tested a few existing to-do managers and analysed how much they would meet the needs of our main target user Jim:

Product (Reviewer) Positive points Negative points
Google Keep (Zhiwen) + It has high level of simplicity (clear and simple UI)
+ It can be easily accessed from anywhere
+ It supports native sync and integration with Google
+ Mark things done easily
+ Support photos, audios and lists in content
- It is unable to do text formatting
- Its search function only supports titles
- It is unable to prioritise activities
Trello (Sheng Xuan) + It supports multiple platforms (Web, mobile, desktop)
+ It has due date function, which is suitable for tasks with deadlines
+ It can search by keyword of a task
+ It archives completed tasks
+ It has check list to track the progress of each task
+ It can attach files to a task (ie. forms to reply in a email)
- It needs at least 2 clicks (taps) to add a new task
- It costs money to use the calendar view functionis. In free version, no timeline is provided. Adding events that happen in specific dates are not supported
- It is unable to undo
Anydo (Conan) + It is able to push tasks to a later date
+ It can easily reorder tasks
+ It has user-friendly interface (4 major groups)
+ It can be used on mobile and on browser
+ It supports double confirmation of deleting a task when complete
+ It can add details in later
- It has no clear distinguishing of the 3 types of tasks
- It has little sense of timeline, and ends up with just tasks to complete by the end of the day
- Its deadlines are not shown unless the task is clicked
- It does not support search function (however, you can Ctrl+F, though no content search)
- Its other 2 groups “Upcoming” and “Someday” are kind of ambiguous
Google Calendar (Yun Chuan) + It is able to mark as done, and undo “done”
+ It has clean, simple interface which is not cluttered
+ It can autocomplete based on crowd-sourced or history (but doesn’t feel very “intelligent”)
+ It can push notifications for reminders/events
+ It is able to repeat events
+ It is automatically synchronised both on mobile and on website
+ It has “All-day” events
+ It supports “Schedule” view which lists everything in chronological order, starting from today
+ It is able to “zoom in” (day view) and “zoom out” (month view)
+ Its items are split into: “events” and “reminders”. Events have start to end time while reminders only have a reminder time
- It cannot export to data file online
- It is unable to mark deadlines accurately (not an “event”)
- It cannot search for to-dos
- It has too many screens or user actions to add a task