Developer Guide
Table of contents
- 1. Introduction
- 2. About this document
- 3. Setting up, getting started
- 4. Design
- 5. Implementation
- 6. Documentation, logging, testing, configuration and dev-ops
- Appendix A: Product scope
- Appendix B: Glossary
- Appendix C: User stories
-
Appendix D: Use cases
- D.1. UC01: Add a food item
- D.2. UC02: Delete a food item
- D.3. UC03: Edit a food item
- D.4. UC04: Change the quantity of a food item
- D.5. UC05: Find a food item
- D.6. UC06: List all food items
- D.7. UC07: Clear all food items
- D.8. UC08: Sort food items by expiry date
- D.9. UC09: Sort food items by priority
- D.10. UC10: Sort food items by description
- D.11. UC11: Undo most recent undoable command
- D.12. UC12: Redo most recent undo command
- Appendix E: Non-Functional requirements
- Appendix F: Instructions for manual testing
- Appendix G: Effort
1. Introduction
SimplyKitchen is a desktop application for food inventory management suited for household individuals who manage their kitchens’ food items.
SimplyKitchen is developed by 5 dedicated students who hope to assist and alleviate the problems you might encounter while managing your food inventory. With intuitive and practical features, SimplyKitchen can get your food management tasks done faster and more efficiently!
With a Command Line Interface (CLI), SimplyKitchen is best suited to those who can type fast and prefer using a keyboard. SimplyKitchen also uses a Graphical User Interface (GUI) to provide an aesthetic visualization of your food information for the ideal user experience.
SimplyKitchen hopes to empower you to work towards a Tidy Kitchen, with Tiny Wastage!
2. About this document
This document is a Developer Guide meant to assist project developers in understanding the various aspects in the production of SimplyKitchen. The purpose of this document is to describe the architecture and software design decisions of SimplyKitchen.
The Setting up, getting started section guides you in setting up the code base on your computer and helps you begin working on the project.
The Design section helps you understand the design of the code base as a whole and its various components. This section contains effective UML Diagrams which can help you understand the OOP structure of the code and the execution flow of the app.
The Implementation section contains details about the implementation of some features in SimplyKitchen. It also provides details about design considerations and implementation alternatives. This section allows you to understand our thought process and make your own design considerations.
This is followed by a section consisting of guides for Documentation, Logging, Testing, Configuration and DevOps. Each guide gives specific assistance in the context of the project.
The Appendix section consists of details of the planning stage of the project. It gives an idea of the requirements of the target audience of SimplyKitchen, along with use cases of how they will use the app. The Glossary and Non-Functional Requirements provide other key information relevant to the document and the app.
This document ends with a brief description of our effort for this project.
3. Setting up, getting started
Refer to the guide Setting up and getting started.
4. Design
4.1. Architecture
The Architecture Diagram given above explains the high-level design of the App. Given below is a quick overview of each component.
.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
interface
with the same name as the Component. - exposes its functionality using a concrete
{Component Name}Manager
class (which implements the corresponding APIinterface
mentioned 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.
4.2. UI component
API :
Ui.java
The UI consists of a MainWindow
that is made up of parts e.g.CommandBox
, ResultDisplay
, FoodListPanel
, StatusBarFooter
, ExpiringFoodListPanel
, ExpiredFoodListPanel
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.
4.3. Logic component
API :
Logic.java
-
Logic
uses theFoodInventoryParser
class to parse the user command. - This results in a
Command
object which is executed by theLogicManager
. - The command execution can affect the
Model
(e.g. adding a food item). - The result of the command execution is encapsulated as a
CommandResult
object which is passed back to theUi
. - In addition, the
CommandResult
object can also instruct theUi
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.
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.
4.4. Model component
API : Model.java
The Model
,
- stores a
UserPref
object that represents the user’s preferences. - stores the food inventory data.
- exposes an unmodifiable
ObservableList<Food>
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.
An alternative (arguably, a more OOP) model is given below. It has a
Tag
list in the FoodInventory
, which Food
references. This allows FoodInventory
to only require one Tag
object per unique Tag
, instead of each Food
needing their own Tag
object.
4.5. Storage component
API : Storage.java
The Storage
component,
- can save
UserPref
objects in json format and read it back. - can save the food inventory data in json format and read it back.
4.6. Common classes
Classes used by multiple components are in the seedu.simplykitchen.commons
package.
5. Implementation
This section describes some noteworthy details on how certain features are implemented.
5.1. Undo/Redo feature
Implementation
The feature is implemented with a VersionedFoodInventory
. The VersionedFoodInventory
contains the different states of the food inventory. The states are stored in a foodInventoryStateList
and the current state is tracked with a currentStatePointer
. It also implements the following methods:
-
VersionedFoodInventory#commit()
— Saves the current food inventory state in its states list. -
VersionedFoodInventory#undo()
— Restores the previous food inventory state from its states list. -
VersionedFoodInventory#redo()
— Restores a previously undone food inventory state from its states list.
These operations are exposed in the Model
interface as Model#commitFoodInventory()
, Model#undoFoodInventory()
and Model#redoFoodInventory()
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 VersionedFoodInventory
will be initialized with the initial food inventory state, and the currentStatePointer
pointing to that single food inventory state.
Step 2. The user executes delete 5
command to delete the 5th food item in the food inventory. The delete
command calls Model#commitFoodInventory()
, causing the modified state of the food inventory after the delete 5
command executes to be saved in the foodInventoryStateList
, and the currentStatePointer
is shifted to the newly inserted food inventory state.
Step 3. The user executes add d/Donut …
to add a new food item. The add
command also calls Model#commitFoodInventory()
, causing another modified food inventory state to be saved into the foodInventoryStateList
.
If a command fails its execution, it will not call
Model#commitFoodInventory()
, so the food inventory state will not be saved into the foodInventoryStateList
.
Step 4. The user now decides that adding the food item was a mistake, and decides to undo that action by executing the undo
command. The undo
command will call Model#undoFoodInventory()
, which will shift the currentStatePointer
once to the left, pointing it to the previous food inventory state, and restores the food inventory to that state.
If the
currentStatePointer
is at index 0, pointing to the initial food inventory state, then there are no previous food inventory states to restore. The undo
command uses Model#canUndoFoodInventory()
to check if this is the case. If so, it will return an error to the user rather than attempting to perform the undo.
The following sequence diagram shows how the undo operation works:
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 calls Model#redoFoodInventory()
, which shifts the currentStatePointer
once to the right, pointing to the previously undone state, and restores the food inventory to that state.
If the
currentStatePointer
is at index foodInventoryStateList.size() - 1
, pointing to the latest food inventory state, then there are no undone food inventory states to restore. The redo
command uses Model#canRedoFoodInventory()
to check if this is the case. If so, it will return an error to the user rather than attempting to perform the redo.
Step 5. The user then decides to execute the command list
. Commands that do not modify the food inventory, such as list
, will usually not call Model#commitFoodInventory()
, Model#undoFoodInventory()
or Model#redoFoodInventory()
. Thus, the foodInventoryStateList
remains unchanged.
Step 6. The user executes clear
, which calls Model#commitFoodInventory()
. Since the currentStatePointer
is not pointing at the end of the foodInventoryStateList
, all food inventory states after the currentStatePointer
will be purged. Reason: It no longer makes sense to redo the add d/Donut …
command.
The following activity diagram summarizes what happens when a user executes a new command:
Design consideration:
Aspect: How undo & redo executes
-
Alternative 1 (current choice): Saves the entire food inventory.
- 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 food item being deleted). - Cons: We must ensure that the implementation of each individual command are correct.
- Pros: Will use less memory (e.g. for
5.2. Sort feature
The sort feature allows users to sort the list of food items based on description, expiry date and priority.
Implementation
The sort feature consists of three commands, SortDescCommand
, SortExpiryCommand
and SortPriorityCommand
which extend Command
.
The sorting order is in accordance to what is likely the most useful order for the user.
-
SortDescCommand
sorts the list of food by description, with items of the same description sorted by expiry date from oldest to newest, and items of the same description and expiry date sorted by priority fromHIGH
toLOW
. -
SortExpiryCommand
sorts the list of food by expiry date from oldest to newest, with items of the same expiry date sorted by priority fromHIGH
toLOW
, and items of the same expiry date and priority sorted by description. -
SortPriorityCommand
sorts the list of food by priority fromHIGH
toLOW
, with items of the same priority sorted by expiry date from oldest to newest, and items of the same priority and expiry date sorted by description.
When the sort commands are executed by calling SortDescCommand#execute(Model model)
or SortExpiryCommand#execute(Model model)
or SortPriorityCommand#execute(Model model)
,
the VersionedFoodInventory
attribute in model
is sorted, which hence permanently sorts the ObservableList<Food>
attribute in UniqueFoodList
.
This is done so by calling model#sortFoodInventory(Comparator<Food>... comparators)
method in model
which takes in a variable number of relevant comparators
in order to sort the food list.
Following which, model#setSortingComparators(Comparator<Food>[] sortingComparators)
and userPref#setSortingComparatorsDescription(String sortingComparatorsDescription)
are called to save the sorting information in the user’s preferences.json
file.
When invalid sorting information is read from preferences.json
file, an error message will be displayed in the Result Box of the GUI, and the stored sorting order will be set to the default sorting: by description.
Sorting of the VersionedFoodInventory
attribute in model
is reflected in the GUI dynamically when MainWindow
calls logic#getFilteredFoodList()
.
The following sequence diagram illustrates how the command sortdesc
works:
Design consideration:
Comparators used for sorting are stored as static variables in ComparatorUtil
, allowing for the code to be scalable for future sorting orders and commands.
Sorting information is stored as user preferences, to allow for the information to be retained when the application closes. Thus, the user’s preferred sorting mechanism is stored, to enhance user experience.
Furthermore, this allows for dynamic updates of the food item list according to the stored sorting preference. In other words,
when a food item is added or edited by calling AddCommand
and EditCommand
, the food item will be sorted dynamically according to the stored sorting mechanism. Thus, there is reduced hassle as the user does not need to sort the list again.
Aspect: Permanence of list sorting
-
Alternative 1 (current choice): Permanently sort lists.
- Pros: There is less hassle when refreshing the app, as the specific sorting order preferred by the user is stored.
- Cons: If the user wishes to sort displayed lists temporarily, they may only achieve this by sorting, then undoing the command, which may be a hassle.
-
Alternative 2: Lists are always sorted by description by default, and sorting by priority or expiry date are reflected in displayed lists temporarily.
- Pros: The user is able to sort the lists temporarily if they prefer to do so.<div style="page-break-after: always;"></div>
- Cons: Sorting is not permanent, thus lists stored are sorted by description by default, which is not desirable if the user has other preferred sorting orders.
5.3. Quantity field in food items
A quantity
field for food items is implemented to track the dynamic changes in the quantity of a food in the FoodInventory.
Implementation:
The quantity
field has been implemented as a class in the model.food
package.
- Quantity class contains 2 attributes:
value
andunit
. - The
value
is a positive number with a maximum of 2 decimal places. The maximum value allowed is 100,000.00. - The
unit
is optional. If provided, it must consist of only alphabets. Numbers, space and special characters are not permitted. - If the unit is not provided, a default unit -
unit
- will be given.
Implementation rationale:
The constraints above have been applied after careful consideration of the needs of the target audience.
- The
value
in the quantity field must be a positive value. A negative or zero value does not carry any meaning and would defeat the purpose of the feature. - The maximum
value
allowed is 100,000.00. This value is chosen to accommodate users storing the volume of liquids they have in their kitchens.- Any value bigger than 100,000.00 is not realistic in the context of a domestic household.
- Users would want to track the quantity precisely in some cases. To allow this, SimplyKitchen accepts decimal values as the
value
attribute. - The
value
attribute in the Quantity field has been stored as adouble
value. - Users will have different kinds of units while tracking the quantity of their food items. For example, kg, can, bottle etc.
- To ensure the user’s freedom in choosing the unit, the
unit
attribute in the Quantity class has been stored as aString
field. - Constraints on the content of the
unit
field have been applied to prevent misuse of the feature. - Units are always single words and do not contain special characters or numbers. Hence, these restrictions have been enforced while accepting a quantity from the user.
- The
unit
field is optional to relieve the user of extra work of giving a unit in intuitive cases. For example, while storing the quantity of fish a unit is intuitively the number of fish.
Design consideration:
Aspect: Implementation
-
Alternative 1 (current choice): Value and unit stored as double and string fields in the Quantity class.
- Pros: Easy to implement given the tight project timeframe.
- Cons: Less OOP compared to the other alternative.
-
Alternative 2: Value and Unit extracted to different classes. Quantity class’ attributes are objects of these Value and Unit classes.
- Pros: Improves OOP aspect of the code.
- Cons: Unnecessarily complicates the code.
5.4. Change quantity feature
The change quantity feature allows users to increment or decrement the quantity of a food item by a certain amount.
Implementation:
The ChangeQuantityCommandParser
class parses the command by first extracting the index of the food item within the food list displayed to the user.
Next, the amount
is parsed. It is a non-zero signed double value.
Similar to the constraints applied to the quantity
field, the magnitude of the amount
should be more than -100,000.00 and less than +100,000.00 but not zero.
- Having a
quantity
change of zero is meaningless. - The signed value is used to denote the increment or decrement of the
quantity
value. - The
amount
value is constrained to a maximum of 2 decimal places. Any additional decimal places used will not be meaningful from the user’s point of view. - A unit is not required as it can be derived from the existing unit of the food item when the user wants to change its
quantity
.
A new ChangeQuantityCommand
object is created with the extracted index and amount
. It will retrieve the correct food item from the filtered list of food item provided by the model
object.
The selected food item will have its quantity updated through the changeQuantityCommand#updateFoodQuantity
method.
The method will calculate the new quantity
and throw a CommandException
if the new quantity
is less than or equal to zero, or more than 100,000.00.
- The
oldQuantity#updateQuantityValue
method is called within thechangeQuantityCommand#updateFoodQuantity
method. - In the
updateQuantityValue
method,BigDecimal
is used to do arithmetic operations on the old quantity’s value and theamount
to be incremented/decremented by. This is due to accuracy errors when performing arithmetic operations on double values.
The following sequence diagram illustrates how the command changeqty
works:
Design consideration:
Although the quantity
of a food item can be changed using the edit
command, the command will replace the old quantity
value with a value supplied by the user.
This means that users have to calculate the quantity
themselves and calculation errors may occur as a result.
To minimise such errors and improve the intuitiveness of commands, the changeqty
command allows users to specify how much the quantity should change by.
This allows users to not be burdened by calculations and to focus more on having an accurate inventory stock level.
Aspect: Updating a food item’s quantity
-
Alternative 1 (current choice): Update the
quantity
value of a food item by calling theupdateQuantityValue
method of theQuantity
class.- Pros: Easy to implement given the tight project time frame.
- Cons: All other fields of a
food
object need to be extracted and passed into theFood
constructor.
-
Alternative 2: Use a
Descriptor
class similar to theEditFoodDescriptor
in theEditCommand
class.- Pros: Improves OOP aspect of the code.
- Cons: Unnecessarily complicates the code.
- Cons: Only the
quantity
field of afood
object is changed so aDescriptor
class may be an overkill.
5.5. Find feature
The find feature allows users to search for food items based on description
, expiry date
, priority
and/or tags
.
Implementation:
The find feature is achieved by setting a predicate
on the filteredList
located in ModelManager
. This can be done using the method ModelManager#updateFilteredFoodList(Predicate<Food> predicate)
, which uses the parameter as the predicate
. There are four valid predicates, namely DescriptionContainsKeywordsPredicate
, ExpirySearchPredicate
, PrioritySearchPredicate
and TagSearchPredicate
, all of which implement the Predicate<Food>
interface. Based on the user’s find
command, each of the predicate
is generated with the relevant search parameters. Then, the FindCommand#combinePredicates()
method will combine all the predicates into a single predicate
and is passed to ModelManager#updateFilteredFoodList(Predicate<Food> predicate)
.
The following sequence diagram illustrates how the command find d/apple e/30-9-2020 p/medium t/frozen
works:
The find
command uses ArgumentMultimap
to get the parameters of each prefix
, similar to the add
command. The find
command needs to have at least one prefix
present. If a prefix
is present, then its respective predicate
will be generated.
The following is the class diagram for the Find feature:
Implementation rationale:
Since the user can search for food items based on either the description
, expiry date
, priority
or tags
, the find
command should allow searching for one or more of the above combination. This increases the flexibility in the find
command, which allows the user to define the specificity of their search.
Design consideration:
Each parameter of the search can be mapped to a predicate
. This allows for scalability in the future as when a new attribute is added to Food
, a new predicate
implementing the Predicate<Food>
interface can be created to search for this field without affecting the predicates
of the other attributes.
Aspect: Implementation
-
Alternative 1 (current choice): The
expiry date
in thefind
command looks for a single specificexpiry date
.- Pros: Easy to implement and search is more specific.
- Cons: If the user wants to get all the expiring food items in a certain period, multiple searches will be required.
-
Alternative 2: The
expiry date
in thefind
command can be a date range.- Pros: Able to get all the food items that are going to expire in a certain period with one search.
- Cons: Will need more validation to ensure the date range provided is valid.
6. Documentation, logging, testing, configuration and dev-ops
Appendix A: Product scope
Target user profile:
- has a need to manage kitchen food items
- prefer desktop apps over other types
- prefers typing to mouse interactions
- can type fast
- is reasonably comfortable using CLI apps
Value proposition: With SimplyKitchen, food inventory management is made easy.
Appendix B: Glossary
Term | Definition/Description |
---|---|
CLI | Command Line Interface. It is a form of user and computer interaction where the user inputs commands in the form of text. Users will utilise a CLI to input commands into SimplyKitchen. |
Description | The description of a food item. |
Expiring food item | A food item is “expiring” if its expiry date is from today, to 7 days after today. For instance, if today is 7-11-2020, food items that expire from 7-11-2020 to 14-11-2020 are deemed as “expiring”. |
Expiry date | The expiry date of a food item. |
Food inventory | A complete list of food items stored in Simply Kitchen. |
GUI | Graphical User Interface. It is a form of user and computer interaction that allows the user to interact via graphical icons such as buttons, scroll bars and windows. SimplyKitchen has a GUI for the user to interact with. |
Mainstream OS | Windows, Linux, Unix, OS-X. |
Priority | The priority of a food item. The priority field can either be high , medium or low . |
Quantity | The quantity of a food item. The quantity consists of 2 entities - value and unit . |
Tag | Tags are additional information that can be tagged to food items. |
Appendix C: User stories
Priorities: High (must have) - * * *
, Medium (nice to have) - * *
, Low (unlikely to have) - *
Priority | User role (As a …) | Function (I want to …) | Benefit (So that I can …) |
---|---|---|---|
* * * |
user | add food items | |
* * * |
user | delete food items | |
* * * |
user | edit the fields of a food item | change the details of the food item after adding it |
* * * |
user | search for food items based on keywords of the description | find them easily |
* * * |
user | view a list of all food items I have added | have a complete display of all my food items |
* * * |
user | clear all food items | |
* * * |
user who cares about some food items more | have different priority for different food items | prioritise some food items |
* * * |
user | use more intuitive commands | be more comfortable with using the app |
* * * |
user who likes efficiency | search for food items based on their priorities | know which food items belong to a certain priority |
* * * |
user | search for food items based on their expiry dates | know which food items are expiring on a certain date |
* * * |
busy user | sort my list of food items by their priorities | know which food items are of certain priorities |
* * * |
busy user | sort my list of food items by their expiry dates | know which food items are expiring first |
* * * |
busy user | sort my list of food items by their description | view a systematic list of food items sorted by description |
* * * |
busy user | store my current sorting order | refresh the app while maintaining my current sorting order |
* * * |
user | update the quantity of food items when I use them | have an updated record of food items available in my kitchen |
* * * |
forgetful user | be able to view a list of expired food items | know which food items are expired and can be thrown away |
* * * |
forgetful user | be able to view a list of expiring food items | know which food items are expiring soon and use them before they expired |
* * * |
user | undo and redo my actions | easily fix the mistakes when using the application |
* * |
user | tag food items | add additional information pertaining/relating to them |
* * |
user | search for food items based on their tags | know which food items are tagged with a certain information |
* |
user | see some sample data populated in the app | understand how the app will look like and what benefits it has |
Appendix D: Use cases
For all use cases, the System is SimplyKitchen, and the Actor is the User, unless otherwise specified.
D.1. UC01: Add a food item
Guarantees: The food item is added into the food inventory.
MSS:
1. User requests to add a food item.
2. SimplyKitchen adds the food item to the food inventory and displays a success message.
Use case ends.
Extensions:
1a. SimplyKitchen detects an error in the user’s food item.
-
1a1. SimplyKitchen displays an error message and prompts the user to enter a correct food item.
-
1a2. User enters another food item.
Steps 1a1. - 1a2. are repeated until the food item entered is correct.
Use case resumes from step 2.
D.2. UC02: Delete a food item
Precondition: The food item to be deleted is currently in the food inventory.
Guarantees: If a food item is specified, the food item will be deleted from the food inventory.
MSS:
1. User requests to find a food item (UC05) or list all food items (UC06).
2. SimplyKitchen displays a list of food items.
3. User requests to delete a food item from the list.
4. SimplyKitchen deletes the food item from the food inventory and displays a success message.
Use case ends.
Extensions:
2a. The list is empty.
Use case ends.
3a. SimplyKitchen detects an invalid index corresponding to the food item in the list.
-
3a1. SimplyKitchen displays an error message and prompts the user to enter a correct index.
-
3a2. User requests to delete another index corresponding to the food item in the list.
Steps 3a1. - 3a2. are repeated until the index entered is correct.
Use case resumes from step 4.
D.3. UC03: Edit a food item
Precondition: The food item to be edited is currently in the food inventory.
Guarantees: The food item is edited from the food inventory.
MSS:
1. User requests to find a food item (UC05) or list all food items (UC06).
2. SimplyKitchen displays a list of food items.
3. User requests to edit a food item from the list.
4. SimplyKitchen edits the food item in the food inventory and displays a success message.
Use case ends.
Extensions:
2a. The list is empty.
Use case ends.
3a. SimplyKitchen detects an invalid index corresponding to the food item in the list.
-
3a1. SimplyKitchen displays an error message and prompts the user to enter a correct index.
-
3a2. User requests to edit another food item in the list.
Steps 3a1. - 3a2. are repeated until the index entered is correct.
Use case resumes from step 4.
3a. SimplyKitchen detects an error in the user’s edited food item.
-
3a1. SimplyKitchen displays an error message and prompts the user to enter a correct edited food item.
-
3a2. User enters another edited food item.
Steps 3a1. - 3a2. are repeated until the edited food item entered is correct.
Use case resumes from step 4.
D.4. UC04: Change the quantity of a food item
Guarantees: The food item has its quantity changed.
MSS:
1. User requests to find a food item (UC05) or list all food items (UC06).
2. SimplyKitchen displays a list of food items.
3. User requests to change the quantity of a food item.
4. SimplyKitchen changes the quantity of the food item in the food inventory and displays a success message.
Use case ends.
Extensions:
2a. The list is empty.
Use case ends.
3a. SimplyKitchen detects an invalid index corresponding to the food item in the list.
-
3a1. SimplyKitchen displays an error message and prompts the user to enter a correct index.
-
3a2. User requests to change the quantity of another food item in the list.
Steps 3a1. - 3a2. are repeated until the index entered is correct.
Use case resumes from step 4.
3a. SimplyKitchen detects an error in the user’s input quantity.
-
3a1. SimplyKitchen displays an error message and prompts the user to enter a correct input quantity.
-
3a2. User enters another input quantity.
Steps 3a1. - 3a2. are repeated until the input quantity is correct.
Use case resumes from step 4.
D.5. UC05: Find a food item
Guarantees: All food items in the food inventory that match the query are listed.
MSS:
1. User requests to list food items according to the description, priority, expiry date and/or tag.
2. SimplyKitchen displays all food items matching the search query.
Use case ends.
Extensions:
1a. SimplyKitchen detects an error in the search query.
-
1a1. SimplyKitchen displays an error message and prompts the user to enter a correct search query.
-
1a2. User enters a new search query.
Steps 1a1. - 1a2. are repeated until the search query entered is correct.
Use case resumes from step 2.
D.6. UC06: List all food items
Guarantees: All food items in the food inventory are listed.
MSS:
1. User requests to list all food items in the food inventory.
2. SimplyKitchen displays all food items in the food inventory.
Use case ends.
D.7. UC07: Clear all food items
Guarantees: All food items in the food inventory are cleared.
MSS:
1. User requests to clear all food items in the food inventory.
2. SimplyKitchen removes all food items in the food inventory and displays a success message.
Use case ends.
D.8. UC08: Sort food items by expiry date
Guarantees: The food items in the food list are sorted by expiry date.
MSS:
1. User requests to sort the food list by expiry date.
2. SimplyKitchen sorts the food list by expiry date.
Use case ends.
Extensions:
2a. The list is empty.
Use case ends.
D.9. UC09: Sort food items by priority
Guarantees: The food items in the food list are sorted by priority.
MSS:
1. User requests to sort the food list by priority.
2. SimplyKitchen sorts the food list by priority.
Use case ends.
Extensions:
2a. The list is empty.
Use case ends.
D.10. UC10: Sort food items by description
Guarantees: The food items in the food list are sorted by description.
MSS:
1. User requests to sort the food list by description.
2. SimplyKitchen sorts the food list by description.
Use case ends.
Extensions:
2a. The list is empty.
Use case ends.
D.11. UC11: Undo most recent undoable command
Guarantees The most recent undoable command (add, changeqty, clear, delete, edit, sortdesc, sortexpiry, sortpriority) requested will be undone.
MSS:
1. User requests to undo.
2. SimplyKitchen displays the food list before the most recent undoable command was requested.
Use case ends.
Extensions:
2a. No undoable commands were executed.
Use case ends.
D.12. UC12: Redo most recent undo command
Guarantees It redoes the most recent undo command.
MSS:
1. User requests to redo.
2. SimplyKitchen displays the food list after the most recent undo command was requested.
Use case ends.
Extensions:
2a. No undo commands were executed.
Use case ends.
Appendix E: Non-Functional requirements
- The app should work on any mainstream OS as long as it has Java 11 or above installed.
- The app should be able to hold up to 1000 food items 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.
- A user should be able to see food items clearly on the GUI to facilitate command typing.
Appendix F: 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.
F.1. Launch and shutdown
-
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.
-
F.2. Deleting a food item
-
Deleting a food item while all food items are being shown
-
Prerequisites: List all food items using the
list
command, or usefind
command to display the list of food matching the search fields. There should be multiple food items displayed in the food list. -
Test case:
delete 1
Expected: The first food item is deleted from the food list. Details of the first food item is shown in the result box. -
Test case:
delete 0
Expected: No food item is deleted. An error message is shown in the result box. -
Other incorrect delete commands to try:
delete
,delete x
,...
(where x is larger than the list size)
Expected: Similar to previous.
-
F.3. Changing the quantity of a food item
-
Changing the quantity of a food item while some or all food items are being shown
-
Prerequisites: List all food items using the
list
command, or usefind
command to display the list of food matching the search fields. There should be multiple food items displayed in the list. -
Assumption: The first food item displayed in the food list has a quantity of 5.00.
-
Test case:
changeqty 1 a/+1.00
Expected: The first food item has its quantity updated to 6.00. Updated details of the first food item is shown in the result box. -
Test case:
changeqty 1 a/1.00
orchangeqty 1 a/+1.000
Expected: The first food item remains the same. An error message similar to the one shown below is displayed in the result box. -
Test case:
changeqty 1 a/x
(where x is smaller than or equal to -5.00 OR larger than +99,995.00) Expected: The first food item remains the same. An error message similar to the one shown below is displayed in the result box.
-
F.4. Sorting the food list
-
Sorting the food list while some or all food items are being shown
-
Prerequisites: List all food items using the
list
command, or usefind
command to display the list of food matching the search fields. There should be multiple food items displayed in the list. -
Test case:
sortdesc
Expected: The food items in the list is sorted by description. -
Test case:
sortpriority
Expected: The food items in the list is sorted by priority from high to low. -
Test case:
sortexpiry
Expected: The food items in the list is sorted by expiry date from oldest to newest.
-
F.5. Saving data
-
Dealing with missing/corrupted data files
-
Test case: Delete the
foodInventory.json
file in thedata
folder.
Expected: Status message shows that the data file has not been found and that the application will be starting with a sample food inventory. -
Test case: Remove the
description
field from one of the food items in thefoodInventory.json
file in thedata
folder.
Expected: An error message shown in the status message reporting corrupted data file format. Error message also gives scenarios of how to proceed, either fix the data file or start with a new inventory by adding a food item. -
Test case: Remove any of the other fields -
expiryDate
,priority
,quantity
,tagged
- from a food item in thefoodInventory.json
file.
Expected: Similar to previous.
-
Appendix G: Effort
Overall, our team is satisfied to create SimplyKitchen as a product that is both intuitive and user-friendly for our target audience, domestic individuals who manage their food inventory at home.
Throughout this fulfilling journey, our team has cultivated a good project system and has been able to meet the deadlines of our tasks.
Our team has managed to contribute about 12kLOC, roughly the same amount as that of developing AB3.
The Food
model in SimplyKitchen is more complex as compared to the Person
model in AB3.
The Food
model has attributes such as Expiry Date
and Quantity
where ensuring validation of the inputs was complex.
For example, the Quantity
class includes a compulsory value and an optional unit.
Parsing of the quantity input needs to take into account many different constraints such as the size limit, the number of decimal places, the length of the unit and the characters allowed in the unit.
Restricting the inputs to these various conditions was tedious but necessary and helpful to the user.
A challenge our group had faced was to be concise with the constraints and functionality of our add
and find
commands in the User Guide.
Due to the many parameters of these two commands, our explanations were detailed but quite long.
We had to strike a balance between being concise while ensuring that the users can take full advantage of our commands so that they can have an enriching experience using our application to manage their food inventory.
Another key challenge for our group was to decide on the type of sorting to implement in SimplyKitchen.
To preserve the CLI nature of the application, we decided to introduce three new sorting commands to sort food items based on the expiry date, description and priority.
Sorting by description proved to be difficult as we decided to enhance sorting by lexicographical order to account for uppercase and lowercase characters.
This enables the user to sort the list more intuitively. This way, users would not have items with descriptions differing by the casing of the first characters (e.g. “apple” and “Apple juice”) far apart in the list with a lexicographical order.
We also implemented many new commands such as changeqty
, undo
, redo
, and so on.
These new commands brought about new ways to interact with the application unlike AB3.
For example, the changeqty
command relieves users of the burden of having to calculate a new quantity of the food item every time he or she buys/uses/discards food items.
In terms of UI, a significant change we made which catered very well to our target audience was the creation of a pop-up window to display the list of expired food items.
This pop-up window can also be called by using the expired
command.
Additionally, a side panel showing the list of food items that are expiring within a week was added to the main application window.
We have to ensure that this side panel is constantly updated whenever the user adds/edits a food item that expires within a week from the current date, which was slightly challenging.
Each of these challenges was learning experiences for our team members.
As a team, we are glad to have overcome these challenges to create an impressive, immersive and lasting product, SimplyKitchen.