Developer Guide
- Design
- Implementation
- Appendix: Requirements
- Appendix: Instructions for manual testing
- Appendix: Effort
Design
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.
UI component
API :
Ui.java
The UI consists of a MainWindow
that is made up of parts e.g.CommandBox
, ResultDisplay
, EmployeeListPanel
, 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.
Logic component
API :
Logic.java
-
Logic
uses theEmployeeTrackerParser
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 employee). - 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.
DeleteCommandParser
should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of diagram.
Model component
API : Model.java
The Model
,
- stores a
UserPref
object that represents the user’s preferences. - stores the address book data.
- exposes an unmodifiable
ObservableList<Employee>
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.
Storage component
API : Storage.java
The Storage
component,
- can save
UserPref
objects in json format and read it back. - can save the Employee Tracker data in json format and read it back.
Common classes
Classes used by multiple components are in the employeetracker.commons
package.
Implementation
Add feature
Implementation of add feature
The add
command is implemented using the AddCommand
class, which extends the Command
class; and the AddCommandParser
class, which implements the Parser
class. Upon receiving a user command that has add
as the first word, the following object interactions will occur, resulting in the instantiation of an AddCommand
object:
-
MainWindow
object callsLogicManager#execute(commandText)
, wherecommandText
is the user’s input string; -
LogicManager
object callsEmployeeTrackerParser#parseCommand(commandText)
to parse the user command, wherecommandText
is the user’s input string; -
EmployeeTrackerParser#parseCommand()
calls AddCommandParser#parse(arguments), wherearguments
are the parameters incommandText
such asn/NAME
ands/SALARY
; -
AddCommandParser#parse() calls
AddCommand(employee)
to instantiate anAddCommand
object, whereemployee
is anEmployee
object that is constructed usingarguments
.
Next, the following object interactions will occur to save the new employee record to the Model
object;
-
LogicManager
object callsAddCommand#execute(model)
, wheremodel
is theModel
object; -
AddCommand#execute()
callsModel#addEmployee(toAdd)
to add the newemployee
, wheretoAdd
is theEmployee
object to be stored.
The following sequence diagram shows the object interactions when LogicManager#execute(commandText)
is called:
AddCommandParser
should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of diagram.
The following activity diagram shows what happens when a user executes an add command:
Find feature
Implementation of find feature
The find operation is implemented using FindCommand
, which extends Command
.
Upon receiving an input string that has find
as the first word, the Employee Tracker
object will instantiate an FindCommand
object with the fullCommand
string, which is the input entered by the user.
The user is flexible to find the keywords by name, by role, by address, by date of birth, by phone number.
-
find n/Alice
: find by name based on the keywords. -
find r/Developer
: find by role based on the keywords. -
find a/Serangoon
: find by address based on the keywords. -
find b/1992-05-28
: find by date of birth based on the keywords. -
find p/910
: find by phone number based on the keywords with at least 3 digits long.
These operations are exposed in the FindCommand()
class.
- Step 1: The user executes the find command.
- Step 2: The FindCommand() class will check with NameContainsKeywordsPredicate in Model to see if match the user instruction keywords.
- Step 3: Then check the keywords one by one and return matched Employee records.
- Step 4: Create command result and display the matched Employee records to the user.
The following sequence diagram shows how the find operation works:
The following activity diagram summarizes what happens when a user executes a find command:
Sort feature
Implementation of sort feature
The sort
command implemented using the SortCommand
class, which extends the Command
class, and the sortCommandParser
class, which implements the Parser<SortCommand>
class. Upon receiving an input string that has sort
as the fist word, the Employee Tracker
object will instantiate an sortCommand
object with the fullCommand
string, which is the input entered by the user. The user can sort the employee records by n, s, j, b.
-
sort n
the employee records will be sorted based by name in alphabetical order. -
sort s
the employee records will be sorted based on salary in increasing order. -
sort j
the employee records will be sorted based on date of joining from the earliest date to the latest date. -
sort b
the employee records will be sorted based on date of birth from the earliest date to the latest date.
These operations exposed in the SortCommand()
class.
- Step 1: The user executes
sort n
command to sort the employee records by name. - Step 2: The
LogicManager
object callsEmployeeTrackerParser#parseCommand(commandText)
to parse the user command; - Step 3: The
EmployeeTrackerParser#parseCommand()
callssortCommandParser#parse(String args)
, whereargs
isn
; - Step 4: The
sortCommandParser#parse(args)
callssortCommand(args)
to instantiate ansortCommand
object. - Step 5: The
sortCommand#execute()
callsmodel#sortEmployee(sortField)
to sort employee records by name, wheresortField
isn
. - Step 6: The
commandResult()
will feedbackMESSAGE_SORT_EMPLOYEE_SUCCESS
to user.
The following sequence diagram shows how the sort operation works:
The following activity diagram summarizes what happens when a user executes a sort command:
Stats feature
Implementation of stats feature
The stats
command implemented using the StatsCommand
class, which extends the Command
class, and the statsCommandParser
class, which implements the Parser<StatsCommand>
class. Upon receiving an input string that has stats
, the Employee Tracker
object will instantiate an stats
object with the statement
string. The user can see stats for all employee.
-
stats
the stats of all employee will be state on the UI.
These operations exposed in the StatsCommand()
class.
- Step 1: The user executes
stats
command to see employee stats. - Step 2: The
LogicManager
object callsEmployeeTrackerParser#parseCommand(commandText)
to parse the user command; - Step 3: The
EmployeeTrackerParser#parseCommand()
callsstatsCommandParser#parse()
; - Step 4: The
statsCommandParser#parse()
callsstatsCommand()
to instantiate anstatsCommand
object. - Step 5: The
statsCommand#execute()
callsmodel#UniqueEmployeeList
to state stats for all employee. - Step 6: The
util#EmoloyeeTracker
will call thegetStatements()
and state the stats on UI.
The following sequence diagram shows how the stats operation works:
The following activity diagram summarizes what happens when a user executes a stats command:
Appendix: Requirements
Product scope
Target user profile: This app is targeted towards small business owners who wish to keep track of their employees information such as name, phone number, salary and role.
Value proposition: This app shall allow users to consolidate employees information on a single platform. This increases their productivity because they no longer need to access multiple data sources to retrieve/update employees information.
User stories
Priorities: High (must have) - * * *
, Medium (nice to have) - * *
, Low (unlikely to have) - *
Priority | As a … | I want to … | So that I can… |
---|---|---|---|
* * * |
new user | access a user manual | learn how to use the available features |
* * * |
user | add an employee record | keep track of the data of a particular employee |
* * |
user | edit an employee record | modify an employee record without having to delete and readd |
* * * |
user | delete an employee record | remove an employee record that I no longer need |
* * * |
user | list all employee records | view all my employees’ information |
* * |
user | clear all employee records | start afresh with the app |
* * * |
user | find an employee record by name | look at the particular employee’s information |
* * * |
user | find employee records by role | look at the information of the employees with this role |
* * * |
user | find employee records by address | look at the information of the employees with this address |
* * * |
user | find employee records by date of birth | look at the information of the employees with this date of birth |
* * * |
user | find employee records by phone number | look at the information of the employees with this phone number |
* * * |
user | sort employee records by salary | view the salary structure in my company |
* * * |
user | sort employee records by name | view employee records in alphabetical order |
* * * |
user | sort employee records by date of joining | find the employees who stayed the shortest/longest in the company |
* * * |
user | sort employee records by date of birth | find the youngest/oldest employees in the company |
* * * |
user | view summary statistics | obtain a basic overview of my workforce |
Use cases
(For all use cases below, the System is the Employee Tracker
and the Actor is the user
, unless specified otherwise)
Use case: Add an employee record
MSS
- User enters new employee record.
- Employee Tracker displays a success message together with the updated list of employee records.
Use case ends.
Extensions
- 1a. The command entered is in the wrong format.
- 1a1. Employee Tracker shows an error message.
Use case ends.
- 1a1. Employee Tracker shows an error message.
Use case: Delete an employee record
MSS
- User requests to list employee records.
- Employee Tracker displays a list of all employee records.
- User requests to delete a specific employee record in the list.
- Employee Tracker deletes this employee record.
Use case ends.
Extensions
-
2a. The list is empty
Use case ends. -
3a. The given index is invalid.
- 3a1. Employee Tracker shows an error message.
Use case resumes at step 2.
- 3a1. Employee Tracker shows an error message.
Use case: Find an employee record by name
MSS
- User requests to find employee records by name.
- Employee Tracker displays a success message together with the matched employee records.
Use case ends.
Extensions
- 4a. The command entered is in the wrong format.
- 4a1. Employee Tracker shows an error message.
Use case ends.
- 4a1. Employee Tracker shows an error message.
Use case: Find employee records by role
MSS
- User requests to find employee records by role.
- Employee Tracker displays a success message together with the matched employee records.
Use case ends.
Extensions
- 5a. The command entered is in the wrong format.
- 5a1. Employee Tracker shows an error message.
Use case ends.
- 5a1. Employee Tracker shows an error message.
Use case: Sort employee records by name
MSS
- User requests to sort employee records by name.
- Employee Tracker displays a success message together with the sorted employee records.
Use case ends.
Extensions
- 6a. The command entered is in the wrong format.
- 6a1. Employee Tracker shows an error message.
Use case ends.
- 6a1. Employee Tracker shows an error message.
Non-Functional Requirements
- The app should work on any mainstream OS with Java
11
or above installed. - The response time for each command should not exceed
3
seconds. - A user with average typing speed should be able to enter any one command within
20
seconds. - After using each command for at least
5
times, a user with no cognitive disability should be able to use all the app features without having to reference the user guide.
Glossary
- Mainstream OS - Windows 7, Windows 10, Linux, Unix, OS-X
Appendix: Instructions for manual testing
Given below are instructions to test the app manually.
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 employee records. 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.
-
Viewing help
-
Accessing the user guide
-
Test case:
help
Expected: A help window is presented. -
Click on the copy url button, paste the url in your browser’s address bar and access this website.
Expected: The Employee Tracker product website is displayed.
-
Adding an employee record
-
Adding a new employee record
-
Test case:
add n/Rachel Lee r/Designer p/91648917 e/rachel@example.com a/BLK 730 Woodlands Road #15-150 b/1988-01-02 j/2020-09-01 s/8000 t/Founder t/l33tCoder
Expected: A new employee record is be added to the end of the list. -
Test case (Duplicate employee): Repeat the same command used in the previous test case.
Expected: No employee is added. Error details are shown in the result display box. -
Test case (Missing mandatory field):
add n/Rachel Lee r/Designer e/rachel@example.com a/BLK 730 Woodlands Road #15-150 b/1988-01-02 j/2020-09-01 s/8000 t/Founder t/l33tCoder
Expected: No employee is added. Error details are shown in the result display box. -
Test case (Invalid value):
add n/Rachel Lee r/Designer p/91648917 e/rachel@example.com a/BLK 730 Woodlands Road #15-150 b/1988/01/02 j/2020-09-01 s/8000 t/Founder t/l33tCoder
Expected: No employee is added. Error details are shown in the result display box.
-
Listing all employee records
-
Showing all employee records
-
Test case:
list
Expected: All employee records are displayed. -
Test case (Redundant parameter):
list abc
Expected: All employee records are displayed.
-
Finding employee records
-
Finding employee records by name
-
Test case:
find n/David Bernice
Expected: Employee records withDavid
and/orBernice
in its role is displayed. -
Test case (Invalid value):
find n/
Expected: List of employee records is not updated. Error details are shown in the result display box. -
Test case (Missing
TYPE
parameter):find David Bernice
Expected: List of employee records is not updated. Error details are shown in the result display box. -
Test case (Missing
TYPE
parameter and value):find
Expected: List of employee records is not updated. Error details are shown in the result display box.
-
-
Finding employee records by role
-
Test case:
find r/Developer
Expected: Employee records withDeveloper
in its role are displayed. -
Test case (Invalid value):
find r/
Expected: List of employee records is not updated. Error details are shown in the result display box.
-
Editing an employee record
-
Editing an employee record while all employee records are being shown
-
Prerequisites: List all employee records using the
list
command. Ensure that there is at least one employee record in the list. -
Test case:
edit 1 p/91821748 s/9000 t/Mentor t/l33tCoder
Expected: First employee record is updated with the new phone number, salary and tags. -
Test case (Invalid value):
edit 1 p/91 s/9000 t/Mentor t/l33tCoder
Expected: No employee record is edited. Error details are shown in the result display box. -
Other incorrect edit commands to try:
edit
,edit x [OTHER_PARAMETERS]…
(where x is larger than the list size)
Expected: No employee record is edited. Error details are shown in the result display box.
-
Deleting an employee record
-
Deleting an employee record while all employee records are being shown
-
Prerequisites: List all employee records using the
list
command. Ensure that there is at least one employee record in the list. -
Test case:
delete 1
Expected: First employee record is deleted from the list. Details of the deleted employee is shown in the result display box. -
Test case (Invalid index):
delete 0
Expected: No employee record is deleted. Error details are shown in the result display box. -
Other incorrect delete commands to try:
delete
,delete x
(where x is larger than the list size)
Expected: No employee record is deleted. Error details are shown in the result display box.
-
Sorting employee records
-
Sorting employee records by name
-
Test case:
sort n
Expected: Employee records is sorted based on name in alphabetical order. -
Test case (Missing
TYPE
parameter):sort
Expected: List of employee records is not updated. Error details are shown in the result display box.
-
Viewing summary statistics
-
Displaying summary statistics
-
Test case:
stats
Expected: Summary statistics is shown in the result display box. -
Test case (Redundant parameter):
stats abc
Expected: Summary statistics is shown in the result display box.
-
Appendix: Effort
Difficulty level
The difficulty level of this project is estimated to be around 70 - 80% of the difficulty level of AB-3. It is a rough estimation based on the justifications given in the subsequent sections.
Challenges faced
-
Although AB-3 already provided the base architecture and skeleton of the app, it was a non-trivial task to understand the existing 6 KLoC codebase before being confident enough to make changes to it.
-
The project planning and management had to take into account the drastic differences in terms of commitment among the team members. In order for this project to succeed, the workload had to be carefully distributed so that each member was able to complete the assigned tasks given their individual constraints. In addition, contingency plans had to be made on the fly when assigned tasks were not completed on time.
Effort required
-
Refactored various names of packages, classes, methods and variables to make them sound more relevant to the Employee Tracker app. This process was unexpectedly tedious because the team had to manually look through the proposed changes by the IDE to ensure they did not break the app. A significant number of existing test cases had to be modified to take into account the changes made by the refactoring process.
-
Added new fields, such as role, date of birth and salary, to the
Employee
(previously known asPerson
) component. This made the newEmployee
component much more complex than the existingPerson
component. The addition of new fields broke at least half the existing test cases. These test cases had to be modified in order to accommodate the changes. In addition, many new test cases had to be added to maintain the same level of code coverage for the affected classes. -
Added new features such as sort and stats. The implementation of these new features had to take into account how the AB-3 is designed and therefore it was more difficult compared to enhancing our own codebase. Most members added test cases to maintain the code coverage, but not all members managed to do so for their new features before the deadline.
Achievements
-
Managed to modify or add more than 3 KLoC (functional and test codes) to the existing AB-3 codebase.
-
Managed to maintain code coverage of test cases at 68%, which is only 4% lower than AB-3.
-
Managed to update the original design section in DG to reflect the modifications made to the original AB-3 architecture.