| layout | page |
|---|---|
| title | Developer Guide |
- Table of Contents {:toc}
Refer to the guide Setting up and getting started.
The Architecture Diagram given above explains the high-level design of the App. Given below is a quick overview of each component.
💡 Tip: The .puml files used to create diagrams in this document can be found in the diagrams folder. Refer to the PlantUML Tutorial at se-edu/guides to learn how to create and edit diagrams.
Main has two classes called Main and MainApp. It is responsible for,
- At app launch: Initializes the components in the correct sequence, and connects them up with each other.
- At shut down: Shuts down the components and invokes cleanup methods where necessary.
Commons represents a collection of classes used by multiple other components.
The rest of the App consists of 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 in an
interfacewith the same name as the Component. - exposes its functionality using a concrete
{Component Name}Managerclass (which implements the corresponding APIinterfacementioned in the previous point.
For example, the Logic component (see the class diagram given below) defines its API in the Logic.java interface and exposes its functionality using the LogicManager.java class which implements the Logic interface.
How the architecture components interact with each other
The Sequence Diagram below shows how the components interact with each other for the scenario where the user issues the command delete 1.
The sections below give more details of each component.
API :
Ui.java
The UI consists of a MainWindow that is made up of parts e.g.CommandBox, ResultDisplay, PersonListPanel, StatusBarFooter etc. All these, including the MainWindow, inherit from the abstract UiPart class.
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
Logiccomponent. - Listens for changes to
Modeldata so that the UI can be updated with the modified data.
API :
Logic.java
Logicuses theAddressBookParserclass to parse the user command.- This results in a
Commandobject which is executed by theLogicManager. - The command execution can affect the
Model(e.g. adding a person). - The result of the command execution is encapsulated as a
CommandResultobject which is passed back to theUi. - In addition, the
CommandResultobject can also instruct theUito perform certain actions, such as displaying help to the user.
Given below is the Sequence Diagram for interactions within the Logic component for the execute("delete 1") API call.
API : Model.java
The Model,
- stores a
UserPrefobject that represents the user’s preferences. - stores the address book data.
- exposes an unmodifiable
ObservableList<Person>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.

API : Storage.java
The Storage component,
- can save
UserPrefobjects in json format and read it back. - can save the address book data in json format and read it back.
Classes used by multiple components are in the seedu.addressbook.commons package.
This section describes some noteworthy details on how certain features are implemented.
The proposed undo/redo mechanism is facilitated by VersionedAddressBook. It extends AddressBook with an undo/redo history, stored internally as an addressBookStateList and currentStatePointer. Additionally, it implements the following operations:
VersionedAddressBook#commit()— Saves the current address book state in its history.VersionedAddressBook#undo()— Restores the previous address book state from its history.VersionedAddressBook#redo()— Restores a previously undone address book state from its history.
These operations are exposed in the Model interface as Model#commitAddressBook(), Model#undoAddressBook() and Model#redoAddressBook() respectively.
Given below is an example usage scenario and how the undo/redo mechanism behaves at each step.
Step 1. The user launches the application for the first time. The VersionedAddressBook will be initialized with the initial address book state, and the currentStatePointer pointing to that single address book state.
Step 2. The user executes delete 5 command to delete the 5th person in the address book. The delete command calls Model#commitAddressBook(), causing the modified state of the address book after the delete 5 command executes to be saved in the addressBookStateList, and the currentStatePointer is shifted to the newly inserted address book state.
Step 3. The user executes add n/David … to add a new person. The add command also calls Model#commitAddressBook(), causing another modified address book state to be saved into the addressBookStateList.
Step 4. The user now decides that adding the person was a mistake, and decides to undo that action by executing the undo command. The undo command will call Model#undoAddressBook(), which will shift the currentStatePointer once to the left, pointing it to the previous address book state, and restores the address book to that state.
The following sequence diagram shows how the undo operation works:
The redo command does the opposite — it calls Model#redoAddressBook(), which shifts the currentStatePointer once to the right, pointing to the previously undone state, and restores the address book to that state.
Step 5. The user then decides to execute the command list. Commands that do not modify the address book, such as list, will usually not call Model#commitAddressBook(), Model#undoAddressBook() or Model#redoAddressBook(). Thus, the addressBookStateList remains unchanged.
Step 6. The user executes clear, which calls Model#commitAddressBook(). Since the currentStatePointer is not pointing at the end of the addressBookStateList, all address book states after the currentStatePointer will be purged. Reason: It no longer makes sense to redo the add n/David … command. This is the behavior that most modern desktop applications follow.
The following activity diagram summarizes what happens when a user executes a new command:
-
Alternative 1 (current choice): Saves the entire address book.
- Pros: Easy to implement.
- Cons: May have performance issues in terms of memory usage.
-
Alternative 2: Individual command knows how to undo/redo by itself.
- Pros: Will use less memory (e.g. for
delete, just save the person being deleted). - Cons: We must ensure that the implementation of each individual command are correct.
- Pros: Will use less memory (e.g. for
{more aspects and alternatives to be added}
{Explain here how the data archiving feature will be implemented}
The proposed find feature mechanism is
The proposed find implementation is facilitated by ModelManager, which extends Model. ModelManager contains FilteredList of each entities:
- Persons
- Modules
- General Events
Given below is an example usage scenario and how the find mechanism behaves at each step. Input: find m/CS2101
Step 1. Your input is parsed into RemindMeParser using the parseCommand method.
Step 2: Based on the command word of your input (i.e., find), a FindCommandParser will be used.
Step 3: In FindCommandParser#parseCommand, your input will be tokenized using ArgumentTokenizer. ArgumentTokenizer uses your input, then searches for the prefixes and returns the ArgumentMultimap.
Step 4: Using the ArgumentMultimap checks the prefixes in your input and returns the respective FindCommandParser.
- Module:
m/:FindModuleCommandPaser - Person:
n/:FindPersonCommandParser - General Event:
g/:FindGeneralEventParser
if it is an unknown prefix,parseCommandwill throw a ParseException and returns aFindMessageUsage. Since the input ism/,FindModuleCommandPaserwill be returned.
Step 5: In FindModuleCommandPaser, FindModuleCommandPaser#parse is called. Again ArgumentMultimap is created using ArgumentTokenizer but only with Module prefix: m/.
Step 6: The parse method does a few checks:
- If there isn't the
PREFIX:m/present, or the preamble of thePREFIXis not empty, or your search input after thePREFIXis whitespaces, thenparsemethod will throwParseExceptionand returns aFindMessageUsageforModule. - Else your inputs is split into individual keywords, and contained as a
List of keywords.
Step 7: The keywords will be stored in TitleContainsKeywordsPredicate as a predicate, then stored in FindModuleCommand.
Step 8: FindModuleCommand is executed:
- Using the
predicate, theModel#updateFilteredModuleListis called withpredicateas input. - Using the
FilteredList<Module>#setPredicatereturns the filtered list of modules with titles matching to any of thekeywordsas aCommandResult.
Step 9: The CommandResult is logged in the logger and using resultDisplay#setFeedacktoUser, returning resultDisplay. Using resultDisplay#setText shows the CommandResult in the GUI.
The following sequence diagram shows how the find operation works:
Target user profile:
- has a need to manage exams or events deadlines
- prefer desktop apps over other types
- tend to forget upcoming events/exams
- prefers typing to mouse interactions
- is reasonably comfortable using CLI apps
Value proposition: manage deadlines and events faster than a typical mouse/GUI driven app
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 instructions help page | refer to help page when I forget how to use the App |
* * * |
student taking numerous modules | add events/exams/assignments deadlines | |
* * * |
user | delete a deadline | view the ones that matter |
* * * |
user | edit a deadline | can adjust schedule when there is a change of plan |
* * |
user | view events in a calendar view | to have a better sense of the upcoming events |
* * |
forgetful student | get reminded about the most urgent events/assignments/exams | finish the deadlines on time |
* |
student | distinguish among modules,exams and assignments | |
* |
student | view which friend of mine is enrolled in the same module/event | seek help from them |
{More to be added}
(For all use cases below, the System is the RemindMe and the Actor is the user, unless specified otherwise)
MSS:
- User enters the details of assignment.
- System adds assignment and displays assignments info.
Use case ends.
Extensions:
- 1a. System detects an error in format in entered data.
- 1a1. System display error message.
Use case ends.
- 1a1. System display error message.
MSS:
- User enters number to delete a assignment.
- System deletes assignment and displays assignments info.
Use case ends.
Extensions:
- 1a. System detects an error in number in entered data (out of range).
- 1a1. System display error message.
Use case ends.
- 1a1. System display error message.
MSS:
- User enters the command to view assignments.
- System shows list of assignments.
Use case ends.
Extensions:
- 1a. System detects an error in formatting of command.
- 1a1. System display error message.
Use case ends.
- 1a1. System display error message.
MSS:
- User enters the command to view events.
- System shows list of events.
Use case ends.
Extensions:
- 1a. System detects an error in formatting of command.
- 1a1. System display error message.
Use case ends.
- 1a1. System display error message.
MSS:
- User wants to turn on reminder for system.
- User enters command to turn on reminder.
- System display message that reminder is on.
Step 1 - 3 are the same for off.
Use case ends at step 3.
Extensions:
- 2a. System detects an error in formatting of command.
- 2a1. System display error message.
Use case ends.
- 2a1. System display error message.
MSS:
- User enters the command to view help.
- System shows help and url for more in depth help.
Use case ends.
Extensions:
- 1a. System detects an error in formatting of command.
- 1a1. System display error message.
Use case ends.
- 1a1. System display error message.
MSS:
- User enters the command to view calendar.
- System shows calendar.
Use case ends.
Extensions:
- 1a. System detects an error in formatting of command.
- 1a1. System display error message.
Use case ends.
- 1a1. System display error message.
MSS:
- User enters the command to sava data.
- System saves data and show saved message.
Use case ends.
Extensions:
- 1a. System detects an error in formatting of command.
- 1a1. System display error message.
Use case ends.
- 1a1. System display error message.
MSS:
- User enters the command to edit data.
- System edit data and show edited message.
Use case ends.
Extensions:
- 1a. System detects an error in formatting of command.
- 1a1. System display error message.
Use case ends.
- 1a1. System display error message.
{More to be added}
- Should work on any mainstream OS as long as it has Java
11or above installed. - Should be able to hold up to 1000 persons and tasks without a noticeable sluggishness in performance for typical usage.
- A user with above average typing speed for regular English text (i.e. not code, not system admin commands) should be able to accomplish most of the tasks faster using commands than using the mouse.
- RemindMe should be able to respond within one seconds.
- RemindMe should be usable by novice who has no prior experience with coding.
{More to be added}
- Mainstream OS: Windows, Linux, Unix, OS-X
- Module: A school module consists of module ID and module name.
- Examination: Consists of a start time, end time and date which it occurs on and the relevant module.
- Event: Consists of a start time, end time, and the date which it occurs on.
- Assignment: Consists of a deadlines and the relevant module.
Given below are instructions to test the app manually.
-
Initial launch
-
Download the jar file and copy into an empty folder
-
Double-click the jar file Expected: Shows the GUI with a set of sample contacts. The window size may not be optimum.
-
-
Saving window preferences
-
Resize the window to an optimum size. Move the window to a different location. Close the window.
-
Re-launch the app by double-clicking the jar file.
Expected: The most recent window size and location is retained.
-
-
{ more test cases … }
-
Dealing with missing/corrupted data files
- {explain how to simulate a missing/corrupted file, and the expected behavior}
-
{ more test cases … }















