Skip to content

Latest commit

 

History

History
899 lines (587 loc) · 32.2 KB

DeveloperGuide.adoc

File metadata and controls

899 lines (587 loc) · 32.2 KB

Xpire - Developer Guide

1. Setting up

Refer to the guide here.

2. Design

2.1. Architecture

ArchitectureDiagram
Figure 1. Architecture Diagram

The Architecture Diagram given above explains the high-level design of the App. Given below is a quick overview of each component.

💡
The .puml files used to create diagrams in this document can be found in the diagrams folder. Refer to the Using PlantUML guide 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 method where necessary.

Commons represents a collection of classes used by multiple other components. The following class plays an important role at the architecture level:

  • LogsCenter : Used by many classes to write log messages to the App’s log file.

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 interface with the same name as the Component.

  • Exposes its functionality using a {Component Name}Manager class.

For example, the Logic component (see the class diagram given below) defines it’s API in the Logic.java interface and exposes its functionality using the LogicManager.java class.

LogicClassDiagram
Figure 2. Class Diagram of the Logic Component

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.

ArchitectureSequenceDiagram
Figure 3. Component interactions for delete 1 command

The sections below give more details of each component.

2.2. UI component

UiClassDiagram
Figure 4. Structure of the UI Component

API : Ui.java

The UI consists of a MainWindow that is made up of parts e.g.CommandBox, ResultDisplay, ItemListPanel, 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 Logic component.

  • Listens for changes to Model data so that the UI can be updated with the modified data.

2.3. Logic component

LogicClassDiagram
Figure 5. Structure of the Logic Component

API : Logic.java

  1. Logic uses the XpireParser class to parse the user command.

  2. This results in a Command object which is executed by the LogicManager.

  3. The command execution can affect the Model (e.g. adding an item).

  4. The result of the command execution is encapsulated as a CommandResult object which is passed back to the Ui.

  5. In addition, the CommandResult object can also instruct the Ui to 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.

DeleteSequenceDiagram
Figure 6. Interactions Inside the Logic Component for the delete 1 Command
ℹ️
The lifeline for DeleteCommandParser should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of diagram.

2.4. Model component

ModelClassDiagram
Figure 7. Structure of the Model Component

API : Model.java

The Model,

  • stores a UserPref object that represents the user’s preferences.

  • stores the Xpire data.

  • exposes an unmodifiable ObservableList<Item> 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.

ℹ️
As a more OOP model, we can store a Tag list in Xpire, which Item can reference. This would allow Xpire to only require one Tag object per unique Tag, instead of each Item needing their own Tag object. An example of how such a model may look like is given below.

BetterModelClassDiagram

2.5. Storage component

StorageClassDiagram
Figure 8. Structure of the Storage Component

API : Storage.java

The Storage component,

  • can save UserPref objects in json format and read it back.

  • can save the Xpire data in json format and read it back.

2.6. Common classes

Classes used by multiple components are in the io.xpire.commons package.

3. Implementation

This section describes some noteworthy details on how certain features are implemented.

3.1. [Proposed] Replenish List

3.1.1. Implementation

Items are added to the replenish list by the user using the replenish command. When an item expires, the item is automatically tagged as "expired". This enables the user to search for a list of expired items by searching for the "expired" tag. With this, the user is able to view the list of expired items and decide which items to add to the replenish list. On the other hand, when an item has run out, the user is prompted to replenish the item using the replenish command.

ItemManagerClassDiagram

3.1.2. Design Considerations

Aspect: How item is added to the replenish list
  • Alternative 1 (current choice): Once an item expires or runs out, the user is prompted to shift the item to the replenish list by typing the replenish command and item index.

    • Pros: User has flexibility in deciding what to add to the replenish list.

    • Cons: User has to manually type in a short command to add an item to the replenish list.

  • Alternative 2: Once an item expires or runs out, item is transferred to the replenish list.

    • Pros: User need not manually key in item details to transfer it to the replenish list.

    • Cons: User may not want the item in the list and as such would expect a delete functionality for the to-replenish list.

3.2. Auto-sorting of items by name then date

3.2.1. Implementation

The auto-sorting mechanism is facilitated by SortedUniqueItemList which replaces UniqueItemList.

SortedUniqueItemList supports the following new function(s):

  • SortedUniqueItemList#setMethodOfSorting() — Specifies the MethodOfSorting and comparator to be used for the list.

In SortedUniqueItemList, items are stored in a SortedList<Item> and sorted based on the comparator specified.

Given below is an example usage scenario and how the auto-sorting mechanism behaves at each step.

The following sequence diagram shows how the auto-sorting mechanism works:

The following activity diagram summarizes what happens when a user executes a new command:

3.2.2. Design Considerations

Aspect: How auto-sorting executes
  • Alternative 1 (current choice): Automatic sorting with the addition of every item.

    • Pros: Slightly more efficient algorithm for viewing items in O(1) time.

    • Cons: Slightly less efficient algorithm for adding items.

  • Alternative 2: Sort only when items are viewed.

    • Pros: Slightly more efficient algorithm for adding items in O(1) time.

    • Cons: Slightly less efficient algorithm for viewing items.

Aspect: Data structure to store the auto-sorted items
  • Alternative 1 (current choice): SortedList<Item>.

    • Pros: Smooth integration with the internal ObservableList. Comparator can also be easily changed when necessary.

    • Cons: Sorted List can only be viewed when asUnmodifiableObservableList() in SortedUniqueItemList is called.

  • Alternative 2: TreeSet<Item>.

    • Pros: Disallows addition of identical items to the set.

    • Cons: May not be as compatible with the internalList which is of type ObservableList.

3.3. Set Reminders for expiring items

3.3.1. Implementation

{Explain here how the set reminder feature is implemented}

Given below is an example usage scenario and how the mechanism behaves at each step.

The following sequence diagram shows how the operation works:

The following activity diagram summarizes what happens when a user executes a new command:

3.3.2. Design Considerations

Aspect: How set reminder executes
  • Alternative 1 (current choice):

    • Pros:

    • Cons:

  • Alternative 2:

    • Pros:

    • Cons:

Aspect:
  • Alternative 1 (current choice):

    • Pros:

    • Cons:

  • Alternative 2:

    • Pros:

    • Cons:

3.4. Undo/Redo feature

3.4.1. Implementation

The undo/redo mechanism is facilitated by CloneModel and StackManager. It is a separate class that stores a state of the model at any command in time.
Internally, it runs three private functions that copy the data over.

The mechanism is supported by a StackManager which stores internally all the states and
decides when to pop or clear, depending on the command. There are two stacks that are stored in StackManager internally, the Undo and the Redo stack. These stacks are initialised and cleared upon beginning/ending every session.

At every command (Other than undo/redo/help/exit), the state is stored internally.
When an undo command is executed, it will pop the previous state and update the model via updateModel.
The state that was undid will then be pushed into the Redo stack, should the user types in a redo command.

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 two internal stacks in StackManager will be initialised.

Both stacks should be empty as there are no previous commands by the user. The current state is s0, the initial state of Xpire.

UndoRedoStep1

Step 2. The user executes delete|5 command to delete the 5th item in Xpire. The delete will then save the previous state, s0 by pushing it into the Undo Stack.

The current state will be the new state s1 that has the 5th item in Xpire deleted.

UndoRedoStep2

Step 3. The user executes add|Apple|30/10/2019|3 to add a new item. Similar to Step 2, The add command will then save the previous state, s1 by pushing it into the Undo Stack.

The current state will be the new state s2 with the item Apple added.

UndoRedoStep3
ℹ️
If a command fails its execution, it will not save the previous state, thus the Xpire state will not be pushed into the UndoStack.

Step 4. The user now decides that adding the item was a mistake, and decides to undo that action by executing the undo command. The undo command will then update the current model with the model in the previous state.

Internally within StackManager, the most recent state, s1, will be popped from the Undo Stack to become the current state. At the same time, s2, the new state with the added item, will be pushed into the Redo Stack.

UndoRedoStep4
ℹ️
If there are no commands to undo (e.g. at the start of a new Xpire session), undo will return an Error to the user instead. This is done by checking whether the UndoStack is empty.

The following sequence diagram shows how the undo operation works (TO BE UPDATED):

UndoSequenceDiagram
ℹ️
The lifeline for UndoCommand should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of diagram.

The redo command does the opposite — It will pop the latest state from the Redo Stack and set it as the current state whilst pushing the current state into the Undo Stack.

ℹ️
Similarly, if there are no commands to redo, redo will return an Error to the user. This is done by checking if the Redo Stack is empty.

From Step 4, there are 3 scenarios which showcases the behaviour of StackManager after an Undo Command has been executed.

Step 5a. The user suddenly decides that he should not have undid the previous AddCommand, thus he wants to redo the action. This is done by inputting 'redo' in Xpire.

Internally within Stack Manager, the current state will be the popped state, s2, from the Redo Stack. The current state, s1, will then be psuehd back into the Undo Stack.

The current states and their locations should be the same as after the execution of the Add command in Step 3.

UndoRedoStep5a

Step 5b. The user decides to further undo his actions, which now includes the first Delete command. The initial state, s0, will then be popped from the Undo Stack and set as the current state.

The current state, s1, will then be pushed into the Redo Stack.

UndoRedoStep5b

Step 5c. The user may also decide to execute some other command (which is the most likely scenario) other than Undo/Redo. For instance, the user inputs tag|2|#Fruit

When this happens, the existing states in the Redo Stack will be cleared. The state s1, will then be pushed into the Undo Stack whilst the current state will be the new state s3 that includes the new Tag command.

UndoRedoStep5c
ℹ️
Not all commands will save states to StackManager. Exit and Help commands will not save states. Undo and Redo commands should only act on commands that update the items or change the view of the items to the user.

The following activity diagram summarises what happens when a user executes a new command:

UndoRedoActivityDiagram

3.4.2. Design Considerations

Aspect: How undo & redo executes
  • Alternative 1 (current choice): Saves the entire model.

    • 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 item being deleted).

    • Cons: We must ensure that the implementation of each individual command are correct.
      Hard to do when we are applying stackable search/sort commands.

Aspect: Data structure to support the undo/redo commands
  • Alternative 1 (current choice): Use a list to store the history of model states.

    • Pros: Easy for new Computer Science student undergraduates to understand, who are likely to be the new incoming developers of our project.

    • Cons: Logic is duplicated twice. For example, when a new command is executed, we must remember to update the filtered list shown to the user and the backend Xpire data.

  • Alternative 2: Use HistoryManager for undo/redo

    • Pros: We do not need to maintain a separate list, and just reuse what is already in the codebase.

    • Cons: Requires dealing with commands that have already been undone: We must remember to skip these commands. Violates Single Responsibility Principle and Separation of Concerns as HistoryManager now needs to do two different things.

3.5. [Proposed] Data Encryption

{Explain here how the data encryption feature will be implemented}

Given below is an example usage scenario and how the mechanism behaves at each step.

The following sequence diagram shows how the operation works:

The following activity diagram summarizes what happens when a user executes a new command:

3.5.1. Design Considerations

Aspect: How set reminder executes
  • Alternative 1 (current choice):

    • Pros:

    • Cons:

  • Alternative 2:

    • Pros:

    • Cons:

Aspect:
  • Alternative 1 (current choice):

    • Pros:

    • Cons:

  • Alternative 2:

    • Pros:

    • Cons:

3.6. Spelling correction with alternative recommendations

3.6.1. Implementation

The spelling correction mechanism is based primarily on the Damerau–Levenshtein distance algorithm, which computes the edit distance between two strings. This distance is based on the number of substitutions, deletions, insertions or transpositions of characters, needed to convert the source string into the target string. Relevant functions supporting this operation are implemented in StringUtil.

Given below is an example usage scenario and how the mechanism behaves at each step.

The following sequence diagram shows how the sort operation works with recommendations:

The following sequence diagram shows how the search operation works with recommendations:

The following activity diagram summarizes what happens when a user executes an unknown command:

3.6.2. Design Considerations

Aspect: How recommendations execute
  • Alternative 1 (current choice): Displays recommendations after user inputs command that fails to produce results.

    • Pros: Simpler and straightforward implementation.

    • Cons: May be less intuitive to the user as opposed to auto-completed commands.

  • Alternative 2: Auto-completion of commands.

    • Pros: Lowers likelihood of spelling mistakes in user input to begin with.

    • Cons: We must ensure that the structure of every single command and their variations are taken into consideration.

Aspect: Data structure to store the recommendations
  • Alternative 1 (current choice): Use a TreeMap to store entries that comprise a set of recommendations and their corresponding edit distance.

    • Pros: Entries are automatically sorted by their edit distance, thus words with a smaller edit distance will be recommended first. Duplicate entries are also prohibited.

    • Cons: May have performance issues in terms of memory usage.

  • Alternative 2: Store all possible recommendations in a long list.

    • Pros: Simpler implementation.

    • Cons: Not closely related words may also be recommended to the user.

3.7. Logging

We are using java.util.logging package for logging. The LogsCenter class is used to manage the logging levels and logging destinations.

  • The logging level can be controlled using the logLevel setting in the configuration file (See Section 3.8, “Configuration”)

  • 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: Console and to a .log file.

Logging Levels

  • SEVERE : Critical problem detected which may possibly cause the termination of the application

  • WARNING : Can continue, but with caution

  • INFO : Information showing the noteworthy actions by the App

  • FINE : Details that is not usually noteworthy but may be useful in debugging e.g. print the actual list instead of just its size

3.8. Configuration

Certain properties of the application can be controlled (e.g user prefs file location, logging level) through the configuration file (default: config.json).

4. Documentation

Refer to the guide here.

5. Testing

Refer to the guide here.

6. Dev Ops

Refer to the guide here.

Appendix A: Product Scope

Target user profile:

  • Has a preference for command-line interfaces (CLI)

  • Able to type fast

  • Has a need to track the expiry dates of numerous items

  • Prefers desktop applications over other forms

  • Prefers typing over mouse input

  • Wants to be able to search up an item’s expiry date quickly

  • Has a need for items to be tagged appropriately

  • Needs items to be organised into what has not expired and what to buy/replenish

  • Wants to be notified of items that are soon expiring or has expired

  • Tech-savvy and familiar with CLI

  • Requires an app to check what items are about to expire for a particular recipe [v2.0]

  • Wants to save recipes in a convenient format [v2.0]

Value proposition: manage tracking of items' expiry dates faster than a typical mouse/GUI driven app

Appendix B: User Stories

Priorities: High (must have) - * * *, Medium (nice to have) - * *, Low (unlikely to have) - *

Priority As a …​ I want to …​ So that I …​

* * *

new user

see usage instructions

can refer to instructions when I forget how to use the application

* * *

user

input the names of items

* * *

user

input the expiry dates of items

* * *

user

save the list of items I am tracking

can come back to it after closing the application

* * *

user

view the list of things I am tracking

know which items are expiring soon

* * *

user

add items to the tracking list

am able to track new items

* * *

user

delete items from the tracking list

can remove items that I do not need to track anymore

* * *

user

exit from the application

do not have to be on the application all the time

* * *

user

be reminded of items that are expiring soon

can use them before they expire or prepare to replenish them

* * *

user

view the list of expired things that are to be replenished

know what to replenish

* * *

user

sort my items according to name or date

can find my items more easily

* * *

user

search up my items by their tags or names

can find my items more easily

* *

user

set quantity of my items

can take note of items that are soon running out or need using before the expiry date

* *

user

input description of items

can write small notes or annotate about the item

* *

user

search items and delete

can delete an item easily without having to remember their ID

* *

user

undo my previous command

can return to the previous state/list if I have accidentally executed a command I do not want

* *

user

tag items

categorise and organise them better

* *

user

edit items

can update their details easily when I need to

*

user

import tracking list into phone via QR Code

can remind my other friends when their items are expiring

*

user

track items and their quantity

know what items have run out and need replenishing

{More to be added}

Appendix C: Use Cases

(For all use cases below, the System is Xpire and the Actor is the user, unless specified otherwise. Additionally, any references made to the list refers to both the tracking list and the to-buy list, unless specific otherwise.)

Use case: UC01 - Add item

MSS

  1. User requests to add an item to the list.

  2. Xpire adds the item.

    Use case ends.

Extensions

  • 1a. Xpire detects an error in the input.

    • 1a1. Xpire shows an error message.

      Use case ends.

Use case: UC02 - Delete item

Precondition: Display board is showing a list of items.

MSS

  1. User requests to delete a specific item in the list.

  2. Xpire deletes the item.

    Use case ends.

Extensions

  • 1a. The given index is invalid.

    • 1a1. Xpire shows an error message.

      Use case resumes at step 1.

Use case: UC03 - Search item(s)

Precondition: Display board is showing a list of items.

MSS

  1. User requests to search for specific item(s) in the list.

  2. Xpire shows the searched item(s).

    Use case ends.

Extensions

  • 1a. The given keyword(s) has no matching results.

    • 1a1. Xpire shows an empty list.

      Use case ends.

Use case: UC04 - Clear list

MSS

  1. User views all items in the list (UC05).

  2. User requests to clear the list.

  3. Xpire removes all items from the list.

    Use case ends.

Use case: UC05 - View all items

MSS

  1. User requests to view all items in the list.

  2. Xpire shows the full list of items.

    Use case ends.

Use case: UC06 - View help

MSS

  1. User requests for help.

  2. Xpire shows the help messages.

    Use case ends.

Use case: UC07 - Terminate Xpire

MSS

  1. User requests to exit the program.

  2. Xpire closes.

    Use case ends.

Use case: UC08 - Check for expiring items

MSS

  1. User requests to view list of expiring items.

  2. Xpire shows list of expiring items.

    Use case ends.

Extensions

  • 1a. The list is empty

    • 1a1. Xpire shows an empty list.

      Use case ends.

Use case: UC09 - Tag item

Precondition: Display board is showing a list of items.

MSS

  1. User requests to tag an item in the list.

  2. Xpire tags the item.

    Use case ends.

Extensions

  • 1a. The given index is invalid.

    • 1a1. Expire shows an error message.

      Use case resumes at step 1.

Use case: UC10 - Sort items

Precondition: Display board is showing a list of items.

MSS

  1. User requests to sort the items.

  2. Xpire sorts the items in the list.

    Use case ends.

{More to be added}

Appendix D: Non Functional Requirements

Accessibility

  1. The app shall be accessible by people who have downloaded the JAR file.

  2. The app shall be accessible to people who are colour blind, to the extent that they shall be able to discern all text and other information displayed by the system as easily as a person without colour blindness.

Availability

  1. The app shall be available once it is started up and running.

  2. Reminders shall only be available on the app.

  3. Reminders shall only be available after the app is started.

Efficiency

  1. The app should start up within 5 seconds.

  2. The response to any user action should become visible within 5 seconds.

Performance

  1. The app list should be able to hold up to 1000 items without a noticeable sluggishness in performance for typical usage.

  2. The app should be able to sort up to 1000 items without any sags in performance.

Reliability

  1. The app shall only accept and process user actions written in the correct format.

  2. The app shall throw appropriate exceptions when any user action is in an invalid format.

  3. The app shall throw appropriate exceptions when any user action fails to be processed.

Integrity

  1. The precision of calculations with derived data shall be at the same degree of precision as the originating source data.

  2. All dates entered will be parsed accurately as to the original date format.

Product Scope

  1. The product is not required to handle items without expiry dates.

  2. The product is not required to handle items without names.

  3. The product is not required to produce reminders when the app is inactive.

Usability

  1. 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.

  2. The user interface should be self-explanatory and intuitive enough for first-time users or users who are not IT-savvy.

Maintainability

  1. A development programmer who has at least one year of experience supporting this software application shall be able to add a new product feature, including source code modifications and testing, with no more than two days of labour.

  2. The app code base shall be easy to read and interpret by a developer with at least one year of experience.

Modifiability

  1. Function calls shall not be nested more than two levels deep.

Installability

  1. The installation process shall be convenient. The application shall be downloaded as a JAR file from the newest tagged release.

  2. The software shall be installed from Github, a popular portable medium.

Interoperability

  1. Should work on any mainstream OS as long as it has Java 11 or above installed.

{More to be added}

Appendix E: Glossary

Command

Executes user input in the application

CommandBox

UI component that takes in user input

FXML

XML-based user interface markup language for defining user interface of a JaxaFX application

ItemCard

UI component that displays information on an item

ItemListPanel

UI component that displays list of items

JavaFX

Software platform for creating and delivering desktop applications and rich Internet applications

JSON

An open-standard file format that uses human-readable text to transmit data objects consisting of attribute–value pairs and array data types

Logic

Handles user input for the application and returns the application’s output

MainWindow

Provides the basic application layout containing a menu bar and space where other JavaFX elements can be placed

Model

Represents data in the expiry date tracker and exposes immutable items list

Parser

Converts user input into a Command object

SceneBuilder

Visual layout tool that allows developers to design JavaFX application user interfaces

Storage

Manages data in the expiry date tracker in local storage

Mainstream OS

Windows, Linux, Unix, OS-X

Appendix F: Product Survey

Fridgely

Author: Justin Ehlert

Pros:

  • Able to sync with multiple devices.

  • Has barcode scanner to automatically add item.

Cons:

  • Cannot efficiently change the location tag of the item. To change the location tag, user has to manually recreate the same item with another tag and delete the current item.

Expiry Date Tracker Lite

Author: Lalit Kumar Verma

Pros:

  • Has the option to use it in multiple languages.

  • Provides a summary view of "expiring" and "expired" items.

Cons:

  • Forces user to take photo of every item while adding to the list.

Appendix G: Instructions for Manual Testing

Given below are instructions to test the app manually.

ℹ️
These instructions only provide a starting point for testers to work on; testers are expected to do more exploratory testing.

G.1. Launch and Shutdown

  1. Initial launch

    1. Download the jar file and copy into an empty folder

    2. Double-click the jar file
      Expected: Shows the GUI with a set of sample contacts. The window size may not be optimum.

  2. Saving window preferences

    1. Resize the window to an optimum size. Move the window to a different location. Close the window.

    2. Re-launch the app by double-clicking the jar file.
      Expected: The most recent window size and location is retained.

{ more test cases …​ }

G.2. Deleting an item

  1. Deleting an item while all items are listed

    1. Prerequisites: List all items using the list command. Multiple items in the list.

    2. Test case: delete 1
      Expected: First item is deleted from the list. Details of the deleted item shown in the status message. Timestamp in the status bar is updated.

    3. Test case: delete 0
      Expected: No item is deleted. Error details shown in the status message. Status bar remains the same.

    4. Other incorrect delete commands to try: delete, delete x (where x is larger than the list size) {give more}
      Expected: Similar to previous.

{ more test cases …​ }

G.3. Saving data

  1. Dealing with missing/corrupted data files

    1. {explain how to simulate a missing/corrupted file and the expected behavior}

{ more test cases …​ }