BandBook is based on the AddressBook-Level3 project created by the SE-EDU initiative. It is a project under the CS2103T module, School of Computing, National University of Singapore.
Refer to the guide Setting up and getting started.
The Architecture Diagram given above explains the high-level design of the App.
Given below is a quick overview of main components and how they interact with each other.
Main components of the architecture
Main
(consisting of classes Main
and MainApp
) is in charge of the app launch and shut down.
The bulk of the app's work is done by the following 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.Commons
represents a collection of classes used by multiple other components.
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
.
Each of the four main components (also shown in the diagram above),
interface
with the same name as the Component.{Component Name}Manager
class (which follows the corresponding API interface
mentioned in the previous point.For example, the Logic
component defines its API in the Logic.java
interface and implements its functionality using the LogicManager.java
class which follows the Logic
interface. Other components interact with a given component through its interface rather than the concrete class (reason: to prevent outside component's being coupled to the implementation of a component), as illustrated in the (partial) class diagram below.
The sections below give more details of each component.
The API of this component is specified in Ui.java
The UI consists of a MainWindow
that is made up of parts e.g.CommandBox
, ResultDisplay
, PersonListPanel
, StatusBarFooter
etc. All these, including the MainWindow
, inherit from the abstract UiPart
class which captures the commonalities between classes that represent parts of the visible GUI.
The UI
component uses the 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,
Logic
component.Model
data so that the UI can be updated with the modified data.Logic
component, because the UI
relies on the Logic
to execute commands.Model
component, as it displays Person
object residing in the Model
.API : Logic.java
Here's a (partial) class diagram of the Logic
component:
The sequence diagram below illustrates the interactions within the Logic
component, taking execute("delete 1")
API call as an example.
Note: The lifeline for DeleteCommandParser
should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline continues till the end of diagram.
How the Logic
component works:
Logic
is called upon to execute a command, it is passed to an AddressBookParser
object which in turn creates a parser that matches the command (e.g., DeleteCommandParser
) and uses it to parse the command.Command
object (more precisely, an object of one of its subclasses e.g., DeleteCommand
) which is executed by the LogicManager
.Model
when it is executed (e.g. to delete a person).Model
) to achieve.CommandResult
object which is returned back from Logic
.Here are the other classes in Logic
(omitted from the class diagram above) that are used for parsing a user command:
How the parsing works:
AddressBookParser
class creates an XYZCommandParser
(XYZ
is a placeholder for the specific command name e.g., AddCommandParser
) which uses the other classes shown above to parse the user command and create a XYZCommand
object (e.g., AddCommand
) which the AddressBookParser
returns back as a Command
object.XYZCommandParser
classes (e.g., AddCommandParser
, DeleteCommandParser
, ...) inherit from the Parser
interface so that they can be treated similarly where possible e.g, during testing.API : Model.java
The Model
component,
Person
objects (which are contained in a UniquePersonList
object).Person
objects (e.g., results of a search query) as a separate filtered list which is exposed to outsiders as an unmodifiable ObservableList<Person>
that can be 'observed' e.g. the UI can be bound to this list so that the UI automatically updates when the data in the list change.UserPref
object that represents the user’s preferences. This is exposed to the outside as a ReadOnlyUserPref
objects.Model
represents data entities of the domain, they should make sense on their own without depending on other components)Note: An alternative (arguably, a more OOP) model is given below. It has a Tag
list in the AddressBook
, which Person
references. This allows AddressBook
to only require one Tag
object per unique tag, instead of each Person
needing their own Tag
objects.
API : Storage.java
The Storage
component,
AddressBookStorage
and UserPrefStorage
, which means it can be treated as either one (if only the functionality of only one is needed).Model
component (because the Storage
component's job is to save/retrieve objects that belong to the Model
)Classes used by multiple components are in the seedu.addressbook.commons
package.
This section describes some noteworthy details on how certain features are implemented.
The implementation of the edit feature which allows users to change various fields of an existing contact can be seen in the UML sequence diagram below.
Note: The activation bars for :Ui and logicManager:LogicManager are meant to be deactivated after and within the reference frame respectively. Due to a PlantUML bug, this is unable to be reflected accurately in the diagram.
The find feature mainly allows users to search for contacts based on specific fields. Currently, it only supports
searching by name and instrument. The logic of the find feature is implemented using the FindCommand
class and the
FindCommandParser
class.
FindCommand
is implemented to allow users to search for contacts based on specific fields. Currently, it only
supports searching by name and instrument. It is implemented as such:
FindCommand
is executed by the LogicManager
.Model
to filter the list of contacts based on the search criteria.Model
then returns the filtered list of contacts to the FindCommand
as a CommandResult
object.LogicManager
and then to UI
to display the filtered list of contacts.FindCommandParser
is implemented to parse the user input for the find command. It is implemented as such:
FindCommandParser
is called by the AddressBookParser
to parse the user input.parse
function.FindCommand
object.Aspect: How the find feature executes:
The assign feature mainly allows users to assign an instrument to a contact. Currently, it only supports assigning a
single compulsory instrument to one or more contacts. The logic of the assign feature is implemented using the
InstrumentCommand
class and the InstrumentCommandParser
class.
InstrumentCommand
is implemented to allow users to assign an instrument to one or more contacts. Currently, it only
supports assigning a single compulsory instrument to one or more contacts. It is implemented as such:
InstrumentCommand
is executed by the LogicManager
.Model
to retrieve the list of contacts to be assigned the instrument.Person
object is created and the instrument field is updated with the input instrument.
Model
is updated with the edited Person
object.Model
returns the updated list of contacts to the InstrumentCommand
as a CommandResult
object.LogicManager
and then to UI
to update the instruments assigned to the specified contacts.InstrumentCommandParser
is implemented to parse the user input for the assign command. It is implemented as such:
InstrumentCommandParser
is called by the AddressBookParser
to parse the user input.parse
function.InstrumentCommand
object.Aspect: How the assign feature executes:
The birthday field allows users to store the birthday of a contact. Users can add the birthday to a new contact,
or edit the birthday of an existing contact. The logic of the birthday field is implemented using the
AddCommand
and AddCommandParser
classes or the EditCommand
and EditCommandParser
classes depending on
whether a new contact is being created or existing contact is being edited.
Adding a new contact with the optional birthday field, is implemented as such:
AddCommand
is executed by the LogicManager
.AddCommandParser
which parses the input containing the birthday of the new contact to be
added.Birthday
class, the data undergoes date validation in DateValidatorUtil
to verify that the date entered is a valid date.Person
object is created with the fields entered in the add command.Editing the birthday field of an existing contact, is implemented as such:
EditCommand
is executed by the LogicManager
.EditCommandParser
which parses the input containing the birthday of the existing contact
that is to be set.Birthday
class, the data undergoes date validation in DateValidatorUtil
to verify that the date entered is a valid date.Person
object is created with any existing unchanged fields, as well as the edited fields entered in the
edit command.Target user profile:
Value proposition: Our app is specifically designed for a band administrator with a seamless and efficient way to manage and access their members' details. Also, our app is able to extend capabilities that help make managing a band easier.
Priorities: High (must have) - * * *
, Medium (nice to have) - * *
, Low (unlikely to have) - *
Priority | As a … | I want to … | So that I can… |
---|---|---|---|
* * * | band administrator | create contact information | keep track of members in the band |
* * * | band administrator | view contact & address information | organise transportation by area of residence |
* * * | band administrator | update contact information | keep the address book current |
* * * | band administrator | delete contact information | keep address book updated |
* * | band administrator | indicate birthday information | coordinate celebrations for the members |
* * | band administrator | indicate instrument information | keep track of each member's instrument assignments |
* * | band administrator | indicate matriculation year information | keep track of how long ago the member joined the club |
* * | band administrator | view attendance history | monitor participation and follow up as necessary |
* * | band administrator | update attendance history | keep updated attendance records |
* * | band administrator | filter contacts by instrument | better coordinate performance rehearsals |
(For all use cases below, the System is the BandBook
and the Actor is the band administrator
, unless specified otherwise)
Use case: Delete a person
MSS
Band administrator requests to list persons.
BandBook shows a list of persons.
Band administrator requests to delete a specific person in the list.
BandBook deletes the person.
Use case ends.
Extensions
2a. The list is empty.
Use case ends.
3a. The given index is invalid.
3a1. BandBook shows an error message.
Use case resumes at step 2.
Use case: Indicate a birthday of a member
MSS
Band administrator requests to list persons.
BandBook shows a list of persons.
Band administrator requests to add a birthday to a specific person in the list.
BandBook updates the person's info to reflect their birthday.
Use case ends.
Extensions
2a. The list is empty.
Use case ends.
3a. The given index is invalid.
3a1. BandBook shows an error message.
Use case resumes at step 2.
Use case: Indicate matriculation year of a member
MSS
Band administrator requests to list persons.
BandBook shows a list of persons.
Band administrator requests to add a matriculation year to a specific person in the list.
BandBook updates the person's info to reflect their matriculation year.
Use case ends.
Extensions
2a. The list is empty.
Use case ends.
3a. The given index is invalid.
3a1. BandBook shows an error message.
Use case resumes at step 2.
Use case: Delete all members of a specific matriculation year
MSS
Band administrator requests to list persons.
BandBook shows a list of persons.
Band administrator requests to delete all persons in the list who belong to a specific matriculation year.
BandBook deletes all persons who belong to the specific matriculation year.
Use case ends.
Extensions
2a. The list is empty.
Use case ends.
Use case: Mark attendance for a member
MSS
Band administrator requests to list persons.
BandBook shows a list of persons.
Band administrator requests to mark the attendance of specific person(s) in the list.
BandBook updates the person's info to reflect their attendance for a specific day.
Use case ends.
Extensions
2a. The list is empty.
Use case ends.
3a. The given indexes are invalid.
3a1. BandBook shows an error message.
Use case resumes at step 2.
Use case: Unmark attendance for a member
MSS
Band administrator requests to list persons.
BandBook shows a list of persons.
Band administrator requests to unmark the attendance of specific person(s) in the list.
BandBook updates the person's info to reflect their attendance for a specific day.
Use case ends.
Extensions
2a. The list is empty.
Use case ends.
3a. The given indexes are invalid.
3a1. BandBook shows an error message.
Use case resumes at step 2.
Use case: Assign an instrument to a member
MSS
Band administrator requests to list persons.
BandBook shows a list of persons.
Band administrator requests to assign an instrument to specific person(s) in the list.
BandBook updates the person's info to reflect their instrument.
Use case ends.
Extensions
2a. The list is empty.
Use case ends.
3a. The given index is invalid.
3a1. BandBook shows an error message.
Use case resumes at step 2.
Use case: Find member by name and/or instrument
MSS
Band administrator requests to list persons.
BandBook shows a list of persons.
Band administrator requests to find specific person(s) in the list by name and/or instrument.
BandBook displays a filtered list of persons who match the keywords provided at each prefix.
Use case ends.
Extensions
2a. The list is empty.
Use case ends.
3a. The given keyword cannot be found.
3a1. BandBook shows that 0 persons are listed.
Use case ends.
11
or above installed.Given below are instructions to test the app manually.
Note: These instructions only provide a starting point for testers to work on; testers are expected to do more exploratory testing.
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.
Deleting a person while all persons are being shown
Prerequisites: List all persons using the list
command. Multiple persons in the list.
Test case: delete 1
Expected: First contact is deleted from the list. Details of the deleted contact shown in the status message.
Test case: delete 0
Expected: No person is deleted. Error details shown in the status message. Status bar remains the same.
Other incorrect delete commands to try: delete
, delete x
, ...
(where x is larger than the list size)
Expected: Similar to previous.
Deleting a person while a filtered list is being shown
Prerequisites: List all persons using the list
command. Multiple persons in the list. Filter the list using the find
command.
Test case: delete 1
Expected: First contact in the filtered list is deleted. Details of the deleted contact shown in the status message.
Test case: delete 0
Expected: No person is deleted. Error details shown in the status message. Status bar remains the same.
Other incorrect delete commands to try: delete
, delete x
, ...
(where x is larger than the filtered list size)
Expected: Similar to previous.
Finding person(s) by name while all persons are being shown
Prerequisites: List all persons using the list
command. Multiple persons in the list.
Test case: find n/Alex
Expected: The contacts with the name field containing 'Alex' from the list is shown. Number of contacts listed is shown in the status message.
Test case: find n/Alex Bernice
Expected: The contacts with the name field containing 'Alex' or 'Bernice' from the list is shown. Number of contacts listed is shown in the status message.
Other incorrect find commands to try: find
, find n/
, ...
(where the string after n/ is not alphanumeric)
Expected: Error details shown in the status message. Status bar remains the same.
Finding person(s) by instrument while all persons are being shown
Prerequisites: List all persons using the list
command. Multiple persons in the list.
Test case: find i/Clarinet
Expected: The contacts with the instrument field containing 'Clarinet' from the list is shown. Number of contacts listed is shown in the status message.
Test case: find i/Clarinet Oboe
Expected: The contacts with the instrument field containing 'Clarinet' or 'Oboe' from the list is shown. Number of contacts listed is shown in the status message.
Other incorrect find commands to try: find
, find i/
, ...
(where the string after i/ is not alphanumeric)
Expected: Error details shown in the status message. Status bar remains the same.
Finding person(s) by name and instrument while all persons are being shown
Prerequisites: List all persons using the list
command. Multiple persons in the list.
Test case: find n/Alex i/Clarinet
Expected: The contacts with the name field containing 'Alex' and the instrument field containing 'Clarinet' from the list is shown. Number of contacts listed is shown in the status message.
Test case: find n/Alex Bernice i/Clarinet Oboe
Expected: The contacts with the name field containing 'Alex' or 'Bernice' and the instrument field containing 'Clarinet' or 'Oboe' from the list is shown. Number of contacts listed is shown in the status message.
Other incorrect find commands to try: find
, find n/ i/
, find i/ n/
, ...
(where the string after n/ and i/ is not alphanumeric)
Expected: Error details shown in the status message. Status bar remains the same.
Assigning an instrument to person(s) while all persons are being shown
Prerequisites: List all persons using the list
command. Multiple persons in the list.
Test case: assign 1 i/Clarinet
Expected: First contact in the list is assigned with the instrument 'Clarinet'. Name of the edited contact shown in the status message.
Test case: assign 3 4 i/Flute
Expected: Third and fourth contact in the list is assigned with the instrument 'Flute'. Names of the edited contacts shown in the status message.
Other incorrect assign commands to try: assign
, assign x
, ...
(where x is larger than the list size)
Expected: Error details shown in the status message. Status bar remains the same.
Assigning an instrument to person(s) while a filtered list is being shown_
Prerequisites: List all persons using the list
command. Multiple persons in the list. Filter the list using the find
command.
Test case: assign 1 i/Clarinet
Expected: First contact in the filtered list is assigned with the instrument 'Clarinet'. Name of the edited contact shown in the status message.
Test case: assign 3 4 i/Flute
Expected: Third and fourth contact in the filtered list is assigned with the instrument 'Flute'. Names of the edited contacts shown in the status message.
Other incorrect assign commands to try: assign
, assign x
, ...
(where x is larger than the filtered list size)
Expected: Error details shown in the status message. Status bar remains the same.
Dealing with missing/corrupted data files
data/addressbook.json
is located.addressbook.json
file.Listed below are the features added on top of the original AB3 program, with their corresponding evaluated difficulty
in implementation. Difficulty is represented from a scale of *
to ****
which each asterisk representing an increased
difficulty.
Difficulty | Feature |
---|---|
* | Instrument Field |
* * | Assign Instrument Command |
* * * | Find by Instrument Command |
* * | Birthday Field |
* | Matriculation Year Field |
* * * | Attendance Field |
* * | Delete by Matriculation Year Command |
* | Revamped Ui |
This field was relatively straightforward to implement as it was a simple addition to the existing fields. This additional field was implemented for the existing add and edit feature. For this field, we did not plan to account for any data validation so users are free to key in any instrument they wish depending on their band's needs.
This feature was slightly harder to implement as it required the need to handle multiple indexes and the assignment of an instrument. Similar to the attendance feature, this meant that it was necessary to check for the validity of the indexes entered, and then to carry out the assignment of the instrument to all the indexes. There was also error handling enforced which displays an error message for any invalid indexes or incorrect instrument inputs (according to the parameter constraints).
While this functionality was built upon the current find feature, it was slightly harder to implement as we wanted to provide users with the flexibility to filter by name only, name and instrument, or instrument only. Multiple keywords were also allowed for each of these scenarios, making it much more complex to implement the validation and perform testing.
Relatively straightforward to implement as it serves only as an addition to the other existing fields, without a specific command (utilises the existing add and edit commands). The need for date validation (e.g verifying valid/invalid leap year) was the most complex aspect of the implementation of this Birthday field.
Straightforward to implement as the input must fulfil the strict requirement of being a 4-digit number (enforced using RegEx). As such, most invalid inputs would already have been filtered out. Extra checking was enforced to ensure that the year entered does not exceed the current year.
This feature was harder to implement as it was the first time we introduced the idea of doing bulk operations into the project. This meant allowing the user to input multiple indexes, ensuring that the handling of these indexes are accurate, and then carrying out the addition/deletion of attendance dates to all these indexes. There was also then the proper handling of any resulting exceptions from the parsing of the inputted dates.
Another bulk operation that we introduced to increase the quality of life that the application provides. The operation having to be done across multiple number of records in the application meant the need for additional logic, and more rigorous testing to ensure that the intended behaviour is carried out correctly.
Revamping the UI was not as difficult as we already had a visual reference (Figma mockup) on how we envision the application to look like. The main challenge was amending the various CSS files and formatting of the UI components to ensure that the application looks as intended.
Currently, BandBook only displays generic error messages. This is not ideal as users will need to scrutinise their input to figure out what is causing the error. In the future, we hope to enhance BandBook by displaying more specific error messages to help users understand what went wrong, improving their speed and efficiency when using BandBook.
We can implement this enhancement by improving the respective command parsers to identify which part of the user input
is incorrect, and display an error message that is specific to that part to the user. For example, if the user enters
assign 1 2 3 i/Flute
when there only exists 2 people in the list, BandBook can display an error message that says
the 3rd index entered is invalid.
Currently, BandBook only checks if the user input is in the correct format. However, it does not check if the data entered is valid or not. This is not ideal as users may enter invalid data that may cause potential issues. In the future, we intend to enhance BandBook by implementing stronger data validation for respective fields to ensure that only valid data is entered into BandBook.
We can implement this enhancement by retrieving the valid values for various fields such as email domains and instruments
possibly through an API or a reference list and validating the user input against these values. If the user input does
not match any of the valid values, BandBook will display an error message to inform the user that the data entered is
invalid. For example, if the user enters an invalid string xxx
for the instrument field, BandBook can display an error
message that says the instrument entered is invalid, and display the valid instruments that the user can choose from.
Currently, BandBook only checks if the user is trying to add a duplicate contact based on the name field. This is not ideal as there can be multiple people with the same name. Additionally, other fields such as email and phone number should not be the same for contacts with different names. In the future, we hope to enhance BandBook by implementing a multi-field check criterion for duplicate contacts instead.
We can implement this enhancement by checking if the user is trying to add a contact with the same name, email, and phone number as an existing contact. If this is the case, BandBook will display an error message to inform the user that the specified contact details are already in contact list. Otherwise, it will add the new contact to the contact list successfully.
Currently, BandBook only allows each person to be assigned to one instrument. While the person need not be assigned an instrument upon the addition of the contact details, it is compulsory for the person has to be assigned an instrument for subsequent edits once he/she is assigned to the first instrument. This is not ideal as some people may be able to play multiple instruments within the band while others may not be proficient enough to be assigned an instrument. In the future, we hope to enhance BandBook by allowing each person to be assigned to at least one to possibly multiple instruments.
We can implement this enhancement by modifying Instrument
to be a set of strings instead of a single string. Similar
to Tag
, this will allows users to store multiple instruments for each person using the command edit 1 i/Flute i/Clarinet
.
Additionally, we can modify the Instrument
field to be optional, allowing users to remove any instruments assigned by
using the command edit 1 i/
.
Instrument
field to be a set of strings.
Currently, BandBook only displays the help window when the user enters the help
command. Users will need to click on
the Copy Link button to retrieve the link to our User Guide. This is not ideal as BandBook is optimised for users who
are more proficient in using the Command Line Interface (CLI) and prefer typing to mouse interactions. In the future,
we hope to enhance BandBook by integrating automatic copying of the User Guide link to the user's clipboard upon
entering the help
command.
We can implement this enhancement by modifying the HelpCommand
to automatically copy the link to the User Guide
instead of displaying the help window. This will allow users to retrieve the link to the User Guide more efficiently.
Currently, BandBook only allows users to find person(s) by name and instrument. This is not ideal as users may want to find person(s) by other fields (i.e. phone, email, address, matriculation year, birthday, tag, and attendance). In the future, we hope to enhance BandBook by delivering the same implementation of finding person(s) by name and instrument to other fields.
We can implement this enhancement by modifying the FindCommand
to allow users to find person(s) by all other fields.
For example, users can find person(s) by tag using the command find t/friend
, which returns all person(s) who are
given a 'friend' tag.
FindCommand
to allow users to find person(s) by all other fields.