Developer Guide
- Setting up, getting started
- Introduction
- Purpose
- Target User Profile
- Value Proposition
- Design
- Implementation
- Documentation, logging, testing, configuration, dev-ops
- Appendix: Requirements
- Appendix: Instructions for manual testing
- Appendix: Effort
Setting up, getting started
Refer to the guide Setting up and getting started.
Introduction
Pawbook is a desktop application for dog school managers to facilitate their bookkeeping of puppies and dogs in the school, optimized for input via a Command Line Interface (CLI) which caters to fast-typers who prefer to use a keyboard. You can navigate the application with ease and execute instructions by typing text-based commands in the command box provided without ever having to reach for your mouse!
Purpose
This document aims to serve as a guide for developers, testers and designers who are interested in working on Pawbook. It describes both the design and architecture of Pawbook.
Target User Profile
The target user profile are dog school managers that own and manage the daily operations of the dog schools. They handle a wide range of operations such as keeping track of the dogs under their care, arranging programs and taking care of the dogs on a daily basis. They need a systematic way of maintaining their handle on the operations of their school at all times.
Value Proposition
In Singapore, dog schools are popular among dog owners. Besides day care, they also provide training, grooming and workshops. With many moving parts daily, managing operations can get overwhelming. Pawbook is an all-in-one management system to help dog school managers to maintain organization of their dog schools. Besides keeping track of all the dogs under their care, it also allows dog school managers to plan their schedule and manage programs and classes. At present, there is no such application that helps dog school managers organize and manage their school. This application serves to increase the efficacy of dog schools.
Design
Architecture

The Architecture Diagram given above explains the high-level design of the App. Given below is a quick overview of each component.
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 local persistent storage.
Each of the four components,
- defines its API in an
interfacewith the same name as the Component. - exposes its functionality using a concrete
{Component Name}Managerclass (which implements the corresponding APIinterfacementioned in the previous point.
For example, the Logic component (see the class diagram given below) defines its API in the Logic.java interface and exposes its functionality using the LogicManager.java class which implements the Logic interface.

How the architecture components interact with each other
The Sequence Diagram below shows how the components interact with each other for the scenario where the user issues the command delete owner 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, EntityListPanel, StatusBarFooter etc. All these, including the MainWindow, inherit from the abstract UiPart class.
The UI component uses JavaFx UI framework. The layout of these UI parts are defined in matching .fxml files that are in the src/main/resources/view folder. For example, the layout of the MainWindow is specified in MainWindow.fxml
The UI component,
- Executes user commands using the
Logiccomponent. - Listens for changes to
Modeldata so that the UI can be updated with the modified data.
Logic component

API :
Logic.java
-
Logicuses thePawbookParserclass to parse the user command. - This results in a
Commandobject which is executed by theLogicManager. - The command execution can affect the
Model(e.g. adding an owner). - The result of the command execution is encapsulated as a
CommandResultobject which is passed back to theUi. - In addition, the
CommandResultobject can also instruct theUito perform certain actions, such as displaying help to the user.
Given below is the Sequence Diagram for interactions within the Logic component for the execute("delete owner 1") API call.

DeleteOwnerCommandParser 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
UserPrefobject that represents the user’s preferences. - stores the pawbook database data.
- exposes an unmodifiable
ObservableList<Entity>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
UserPrefobjects in json format and read it back. - can save the Pawbook Database data in json format and read it back.
Common classes
Classes used by multiple components are in the pawbook.commons package.
Implementation
This section describes some noteworthy details on how certain features are implemented.
Entities: Owner/Dog/Program

Despite having three closely related entities in Pawbook, the actual implementation does not couple the 3 entities together in any ways. Instead of storing a reference between an Owner and their Dog, a symbolic ID number is used to represent these links. This ensures that data objects continue to only store information and leave the control/manipulation of data to the logic side of the application. It is therefore possible for all the various entities to remain immutable as well.
This necessitates that an unique ID number is assigned to every entity during its creation and remain constant throughout its lifetime in the application. A simple numbering system is used here whereby the ID is generated by incrementing from 1 until an unused number is found, gaps between numbers will only be filled after a restart of the application to simplify the code.
The ID system replaces the original implementation that uses the index of every Person in the visible list. This gives the advantage of being able to reference to any entity on any screen, which can be useful since different entities are not displayed together.
The UniqueEntityList contains pairs of ID and entity. This attempts to mimic a map/dictionary while keeping possible to continue using the original UI components with minimal changes to the code. Every entity does not store its ID as an internal attribute due to the fact that ID is dynamically generated, usually after the instantiation of the entity itself. The ability to set or change the ID during the lifetime of the entity will violate the immutability of the entities. Furthermore, there is no need for the any entity to be aware of its ID.
Alternative Implementation: Using a Hashmap as container for unique entities
A hashmap was briefly considered as a candidate for storing the unique entities as it was a natural fit.
Benefits:
- Much faster lookup when retrieving an entity by its ID or to check for ID clashes.
Drawbacks:
- Hashmaps have no inherent order, it will be quickly become expensive to maintain order whenever there are data changes.
- There is no
FilteredListequivalent for maps in JavaFX, filtering cannot be simply achieve withinModeland will need to be done on the GUI side.
This current implementation though not ideal, avoid many potential rewrites since there is no ListView equivalent for maps in JavaFX. Switching to using a hashmap as underlying data structure will mean that a table will need to be used to display all the entries, adding unnecessary complication to the code as filtering and sorting will no longer as be simple. Most of these changes are under-the-hood and does not improve user experience significantly.
Adding/Deleting feature
What it is

Pawbook manages more than one type of entity, each with their own unique attributes. An OOP approach is used here whereby both the AddCommand and DeleteCommand are generic classes that extends the Command class. This way any number of other classes extending entity can be added/deleted as well.
Implementation details
The actual execution of the different add commands are highly similar and often differ only by the extra entity-specific checks, e.g. verifying that the owner ID refers to an actual owner instead of taking in an arbitrary number. The same applies to delete commands as well.

In order to generate the respective commands, the raw input needs to be parsed first. It is required that the user provide a second keyword right after the add/delete command keyword to indicate the correct entity type to be added. Using this information, the arguments can be forwarded to the correct parser from within PawbookParser to generate the actual add/delete commands.
Given below is an example usage scenario and how the add command behaves at each step.
Step 1. The user launches the application and executes add owner n/BRUCE p/92019201 e/bruce@example.com a/BLK 123 Adam Road t/friendly to save an owner.
Step 2. The owner is added to the model.
Below is an example activity diagram for a valid delete command from the user.

The activity diagram for both add and delete commands are mirrored. Based on the name of the entity type supplied, the correct parser will be instantiated to parse the arguments and generate the executable command.
To further illustrate how an actual deletion of an entity is performed, below is an example sequence diagram for a valid delete command from the user.

- The
LogicManageruses thePawbookParserto parse the given user input. - The
PawbookParseridentifies the user command and creates aDeleteDogCommandParserobject. It then calls theDeleteDogCommandParser’sparse()method with user input as the parameter. - In the
parse()method, theDeleteDogCommandParserwill then generate theDeleteDogCommandobject. This is then returned all the way back to theLogicManager. - The
LogicManagerwill then proceed to call theexecute()method. - The
execute()method is further explored below. The high level understanding is that a CommandResult is returned and finally passed back toLogicManager.

This is how the DeleteDogCommand works upon execution:
- The
Dogto be deleted will first be retrieved from theModel. - Using the ID stored in the
Dog, theOwnercan be retrieved fromModelas well. - A new
Ownerwith the same details except without the currentDog’s ID will be created to replace the currentOwnerinstance in theModel. - A list of
Programthat theDogis enrolled in will be generated. - For each of these
Program, it will be edited to remove the currentDog’s ID. - With no more entities referring to the current
Dog, it is safe to callModel#deleteEntity(...)to delete theDog.
The deletion of any entity will typically affect other related entities as well. The various add commands will similarly perform the reverse of the delete command.
Edit feature
What it is
Pawbook allows the user to edit an entity. For instance, the user may want to edit some attributes of an owner. By entering the edit command with the target owner ID, the attributes of the owner will be modified accordingly.
Implementation details
In order to generate the edit command, the user indicates the entity type to be edited, followed by the ID number. Using this information, the arguments can be forwarded to the correct parser from within PawbookParser to be further processed.
Below is an example activity diagram for a valid edit command from the user.

Below is the sequence diagram for the Edit Command.

- The
LogicManageruses thePawbookParserto parse the given user input. - The
PawbookParseridentifies the user command and creates aEditOwnerCommandParserobject. It then calls theEditOwnerCommandParser’sparse()method with user input as the parameter. - In the
parse()method, theEditOwnerCommandParserwill then generate theEditOwnerCommandobject. This is then returned all the way back to theLogicManager. - The
LogicManagerwill then proceed to call theexecute()method. - The
execute()method is further explored below. The high level understanding is that aCommandResultis returned and finally passed back toLogicManager.

Find feature
What it is
Pawbook allows the users to find an entity based on keyword searches. The find function allows for multiple keyword
searches and reveals the entire list of entities that match one or more of the results.
Implementation details
When the user enters a valid command with the search keywords, the arguments are parsed by the FindCommmandParser which
converts the string of arguments into a list. The list is subsequently passed on to a NameContainsKeywordsPredicate object
that uses the list of keywords to find the search results based on the supplied keywords. Take note that Find Command supports
substring searching, so for example if there is an Alice in the program, searching “Ali” will also return Alice as result.
Below is an example activity diagram for a valid find command from the user.

Below is an example sequence diagram for a valid find command from the user.

- The
LogicManageruses thePawbookParserto parse the given user input. - The
PawbookParseridentifies the user command and creates aFindCommandParserobject. It then calls theFindCommandParser’sparse()method with user input as the parameter. - In the
parse()method, theFindCommandParserwill then generate theFindCommandobject. This is then returned all the way back to theLogicManager. - The
LogicManagerwill then proceed to call theexecute()method. - The
execute()method is further explored below. The high level understanding is that a CommandResult is returned and finally passed back toLogicManager.
Here is a more specific breakdown of the command’s execute method.

- Upon calling the
execute()method, theFindCommandupdates the filtered entity list inModelusing aNameContainsKeywordsPredicateas parameter. - It then sorts the entity using the
sortEntities()in increasing order by using aCOMPARATOR_ID_ASCENDING_ORDERcomparator that orders entities in increasing ID order. - From here, Find Command creates a command result and returns it to the
LogicManager.
List feature
What it is
Pawbook allows the users to list an entity based on keyword searches. The list function responds to the current available
entities, which are owner, dog and program, and returns a list of all the entries of the respective entity.
Implementation details
When the user enters a valid command with the entity keyword, the arguments are parsed by PawbookParser, which uses Predicate
to identify which entity owner, dog or program it is. ListCommand is then generated with the predicate to return
a list of all the entries of that entity type.
List command supports the plural forms of the entity keywords.
Below is an example activity diagram for a valid list command from the user.

Below is an example sequence diagram for a valid list command from the user.

- The
LogicManageruses thePawbookParserto parse the given user input. - In
PawbookParser, aPredicateis created based on which entity keyword was given by the user. There are only 3 cases here,owner,dog, orprogram. - A
ListCommandobject will be created based on thePredicate. - The
LogicManagerwill then proceed to call theexecute()method. - The
execute()method is further explored below. The high level understanding is that a CommandResult is returned and finally passed back toLogicManager.
Here is a more specific breakdown of the command’s execute method.

- Upon calling the
execute()method, theListCommandupdates the filtered entity list inModelusing apredicateand anentityTypeas parameters. - It then sorts the entity using the
sortEntities()in increasing order by using aCOMPARATOR_ID_ASCENDING_ORDERcomparator that orders entities in increasing ID order. - From here, List Command creates a command result and returns it to the
LogicManager.
View feature
What it is
Pawbook allows the user to view an entity and all its related entities. For instance, the user may want to view all the dogs of one particular owner or all the dogs enrolled in a program. By entering the correct view command with the correct identification number, the entire list will be generated.
Implementation detail
When the user enters a valid command with the target entity ID, the ViewCommandParser will firstly parse the command and store the ID as an integer that is then passed on to as a parameter into the constructor method of a new ViewCommand instance.
Subsequently, once the new ViewCommand instance has been created, in its execute method, it will retrieve the entity via the ID that was passed in, from the ModelManager. With a handle on the target entity now, we build a list consisting of the entity IDs that are to be shown as search results.
Based on the class type of the target entity, we will reveal the search results accordingly. If the target entity is a Dog, then we will show the relevant owner profile. If the target entity is a Owner, then we will list out all of the owner’s dogs. Similar to owner, for Program, we will reveal the full list of dogs enrolled in that program.
This list is subsequently passed on to the RelatedEntityPredicate that will later be used in the ModelManager’s updatefilteredEntityList()) method to finally reveal the search results.
Take note that this is the order in which results will be displayed, based on target entity searched:
- View Dog: Dog > Owner > Programs enrolled in
- View Owner: Owner > Dogs owned
- View Program: Program > Dogs enrolled
Below is an example activity diagram for a valid view command from the user.

Below is an example sequence diagram for a valid view command from the user.

- The
LogicManageruses thePawbookParserto parse the given user input. - The
PawbookParseridentifies the user command and creates aViewCommandParserobject. It then calls theViewCommandParser’sparse()method with user input as the parameter. - In the
parse()method, theViewCommandParserwill then generate theViewCommandobject. This is then returned all the way back to theLogicManager. - The
LogicManagerwill then proceed to call theexecute()method. - The
execute()method is further explored below. The high level understanding is that a CommandResult is returned and finally passed back toLogicManager.
Here is a more specific breakdown of the command’s execute method.

- In the execute method of
ViewCommand, it first generates a list of related entity IDs by calling thegenerateRelatedIdList()which accesses the data in the model. - This list is then passed into the constructor method of
IdMatchPredicateand is then passed intoupdateFilteredEntityList()method. TheupdateFilteredEntityList()updates the filtered entity list in model. - Next,
ViewCommandcreates aViewCommandComparatorand uses it to sort the ordering of the filtered entity list. - From there,
ViewCommandgenerates theCommandResultbased on the filtered entity list. This portion is not shown here as it is trivial.
Schedule feature
What it is
Pawbook allows the user to display the schedule of all programs.
For instance, the user may want to view the schedule of all programs on a specific date. By entering the correct schedule command with the correct date, the entire list of programs on the specific date will be generated.
Implementation details
When the user enters a valid command with the date, the arguments are parsed by the ScheduleCommandParser that converts
the argument string into a Date that is subsequently passed on to a ProgramOccursOnDatePredicate object.
Using the IsEntityPredicate for program and the ProgramOccursOnDatePredicate, the list of programs is retrieved via
the ModelManager using the updateFilteredEntityList() method.
Below is an example activity diagram for a valid schedule command from the user.

Below is an example sequence diagram for a valid schedule command from the user.

Here is a more specific breakdown of the command’s execute method.

- In the execute method of
ScheduleCommand, it first creates aProgramOccursOnDatePredicateobject. - The
IsEntityPredicateof Program and theProgramOccursOnDatePredicateis then passed intoupdateFilteredEntityList()method. TheupdateFilteredEntityList()updates the filtered entity list in model. - From there,
ScheduleCommandgenerates theCommandResultbased on the filtered entity list. This portion is not shown here as it is trivial.
Enrol feature
What it is
Pawbook supports the enrolling of specific dogs into specific programs.
Implementation details
In order to enrol a dog into a program, the raw input needs to be parsed first. It is required that the user provides 2 parameters, namely dogId and programId. These inputs have the prefix /d and /p, and is followed by an integer. Using this information, the arguments will be forwarded to the EnrolCommandParser from within PawbookParser, which converts the String input to int.
Below is an example activity diagram for a valid enrol command from the user.

Below is an example sequence diagram for a valid enrol command from the user.

- The
LogicManageruses thePawbookParserto parse the given user input. - The
PawbookParserwill identify the command given by the user based on the first command word and pass the user input down toEnrolDropCommandParser. - The
EnrolDropCommandParserwill then create anenrolCommandobject with the user inputdogIdSetandprogramIdSetas input parameters, in this case,dogIdSetwill be[2]andprogramIdSetwill be[3]. - The
EnrolDropCommandParserwill then return anenrolCommandobject. - The
LogicManagerwill now call theexecutemethod in theenrolCommandobject. - The
EnrolCommandwill now call theupdateFilteredEntityListmethod of the existingModelobject. - The high level understanding is that a
CommandResultis returned and finally passed back toLogicManager.
Here is a more specific breakdown of the command’s execute method.

- The
LogicManagerwill call the execute method in theEnrolCommandobject. - The
EnrolCommandwill then call thecheckIdValiditymethod of the existingModelobject. - If the ID is valid, the
EnrolCommandwill create anIdMatchPredicateobject. - The
EnrolCommandwill call theupdateFilteredEntityListmethod of the existingModelobject update theIdMatchPredicateobject into Pawbook. - The
EnrolCommandthen creates aCommandResultobject and returns it, indicating the successful updating of theIdMatchPredicateobject.
Drop feature
What it is
While Pawbook allows the enrolling of dogs into programs, conversely it supports dropping previously-enrolled dogs from the programs.
Implementation details
To drop a dog from a program, the raw input is parsed and goes through several checks to ensure that the provided dog and program IDs are both valid and are indeed referring to dog and program objects respectively. Subsequently, the arguments will be forwarded to DropCommandParser followed by PawbookParser where they are converted from the String input to int.
Below is an example activity diagram for a valid drop command from the user.

Below is an example sequence diagram for a valid drop command from the user.

- The
LogicManageruses thePawbookParserto parse the given user input. - The
PawbookParserwill identify the command given by the user based on the first command word and pass the user input down toEnrolDropCommandParser. - The
EnrolDropCommandParserwill then create adropCommandobject with the user inputdogIdSetandprogramIdSetas input parameters, in this case,dogIdSetwill be [2] andprogramIdSetwill be [3]. - The
EnrolDropCommandParserwill then return aenrolCommandobject. - The
LogicManagerwill now call the execute method in thedropCommandobject. - The
DropCommandwill now call theupdateFilteredEntityListmethod of the existingModelobject. - The high level understanding is that a
CommandResultis returned and finally passed back toLogicManager.
Here is a more specific breakdown of the command’s execute method.

- The
LogicManagerwill call the execute method in theDropCommandobject. - The
DropCommandwill then call thecheckIdValiditymethod of the existingModelobject. - If the ID is valid, the
DropCommandwill create anIdMatchPredicateobject. - The
DropCommandwill call theupdateFilteredEntityListmethod of the existingModelobject update theIdMatchPredicateobject into Pawbook. - The
DropCommandthen creates aCommandResultobject and returns it, indicating the successful updating of theIdMatchPredicateobject.
Alternate Implementation: Enrol/Drop features
As dogs and programs can also be identified by their respective names instead of IDs, another implementation could be replacing the parameters of dogId and programId with their respective names.
However, this requires there to be no duplicate dog or program names.
Documentation, logging, testing, configuration, dev-ops
Appendix: Requirements
Product Scope
Target user profile:
- Has a need to manage a significant number of dogs and owners
- Prefers desktop apps over other types
- Is a fast typist
- Prefers typing to mouse interactions
- Is reasonably comfortable using CLI apps
- Prefers a portable and lightweight application
Value proposition:
- Manages customer data faster than a typical mouse/GUI driven app
- Saves significant time for the business owner, who beforehand had to manage the details of dogs and owners
- Consolidates information on dogs, owners and programs into one place
- Clutter-free user interface
- Application is optimized for keyboard navigation
User Stories
Priorities: High (must have) - * * *, Medium (nice to have) - * *, Low (unlikely to have) - *
| Priority | As a … | I want to … | So that I can… |
|---|---|---|---|
* * * |
Dog school manager | Have a list of dogs, owners, and programs in the school | Keep track of the operations and dogs we are responsible for |
* * * |
Dog school manager | Easily switch between the different lists for dogs, owners and programs | Quickly view all the profiles of one entity type |
* * * |
Dog school manager | Add dog/owner/program profiles | Keep track of the operations and parties involved in the school |
* * * |
Dog school manager | Delete dog/owner/program profiles | Keep track of the operations and parties involved in the school |
* * * |
Dog school manager | Edit a dog/owner/program profile | Correct/update a profile when needed |
* * * |
Dog school manager | View a dog/owner/program profile | Easily find out information on the target entity |
* * * |
Dog school manager | Find profiles using keywords instead of ID | Easily find a target dog/owner/program very quickly |
* * * |
Dog school manager | Enrol dogs into a specific dog program | Add dogs who recently joined a program to the class list |
* * * |
Dog school manager | Drop dogs out of a specific dog program | Remove dogs that have left a program from the class list |
* * * |
Dog school manager | See the schedule for any day | Easily view my schedule to know what programs are happening on that day |
* * |
Dog school manager | Autosave the data after every command | Regularly save the data and protect sensitive data in the event that the system crashes |
* * |
Advanced user | Edit in bulk quickly | Save time and effort when making changes to multiple profiles/programs |
* * |
Beginner user | Have a help command with a command summary available | Refer to it when I am unsure of the command |
Use Cases
(For all use cases below, the System is the Pawbook and the Actor is the user, unless specified otherwise)
Use case: UC01 - Add a dog/owner profile or program
MSS
- User requests to add a dog/owner profile or program to the list.
-
Pawbook adds the dog/owner.
Use case ends.
Extensions
- 1a. Missing mandatory dog/owner/program details.
- 1a1. Pawbook shows an error message.
-
1a2. User supplies missing details.
Steps 1a1-1a2 are repeated until the command entered is correct.Use case resumes at step 2.
- 1b. Entity already exists in the program.
- 1b1. Pawbook shows an error message.
-
1b2. User supplies an entity with different details.
Steps 1b1-1b2 are repeated until the command entered is correct.Use case resumes at step 2.
Use case: UC02 - Delete a dog/owner profile or program
MSS
- User requests to delete a specific dog/owner profile or program in the list.
-
Pawbook deletes the dog/owner profile or program.
Use case ends.
Extensions
- 1a. The given dog/owner/program ID is invalid or not specified.
- 1a1. Pawbook shows an error message.
-
1a2. User supplies the corrected dog/owner/program ID.
Steps 1a1-1a2 are repeated until the command entered is correct.Use case resumes at step 2.
- 1b. The given dog/owner/program ID does not match the entity specified.
- 1b1. Pawbook shows an error message, indicating the entity expected.
-
1b2. User supplies the corrected dog/owner/program ID.
Steps 1b1-1b2 are repeated until the command entered is correct.Use case resumes at step 2.
Use case: UC03 - Edit a dog/owner profile or program
MSS
- User requests to edit a specific dog/owner/program in the list.
-
Pawbook edits the dog/owner/program.
Use case ends.
Extensions
- 1a. The given dog/owner/program ID is invalid or does not correspond to the entity specified.
- 1a1. Pawbook shows an error message.
-
1a2. User supplies the corrected dog/owner/program ID.
Steps 1a1-1a2 are repeated until the command entered is correct.Use case resumes at step 2.
- 1b. The user failed to provide any mandatory details to be edited.
- 1b1. Pawbook shows an error message.
-
1b2. The user provides one or more mandatory details to be edited. Steps 1b1-1b2 are repeated until the command entered is correct.
Use case resumes at step 2.
Use case: UC04 - Show the specified entity list
MSS
- User requests to list dogs/owners/programs.
-
Pawbook lists the related dogs/owners/programs.
Use case ends.
Extensions
- 1a. User requests to list something that is none of the three entities.
- 1a1. Pawbook shows an error message, suggesting the accepted entities.
-
1a2. User supplies the corrected dog/owner/program parameter.
Steps 1a1-1a2 are repeated until the command entered is correct.Use case resumes at step 2.
Use case UC05 - View an entity and all its related entities
MSS
- User types in view command with the target ID.
-
Pawbook supplies the results of all the related entities of that ID.
Use case ends.
Extensions
- 1a. The ID is not provided.
- 1a1. Pawbook shows an error message.
-
1a2. User supplies a valid ID.
Steps 1a1-1a2 are repeated until the command entered is correct.Use case resumes at step 2.
- 1b. The ID is invalid (negative, out of bounds, not in database etc.).
- 1b1. Pawbook shows an error message.
-
1b2. User supplies a valid ID.
Steps 1b1-1b2 are repeated until the command entered is correct.Use case resumes at step 2.
Use case UC06 - Find entity by keyword(s)
MSS
- User types in find command with one or more keywords.
-
Pawbook supplies the results matching the keyword(s).
Use case ends.
Extensions
- 1a. The keyword is not provided.
- 1a1. Pawbook shows an error message and requests keyword.
-
1a2. User supplies keywords.
Steps 1a1-1a2 are repeated until the command entered is correct.Use case resumes at step 2.
Use case: UC07 - Enrol dog to a program
MSS
- User requests to enrol dog to program.
-
Pawbook enrols the dog to the correct program.
Use case ends.
Extensions
- 1a. The dog/program ID is invalid/not specified.
- 1a1. Pawbook shows an error message.
-
1a2. User supplies correct dog/program ID.
Steps 1a1-1a2 are repeated until the command entered is correct.Use case resumes at step 2.
- 1b. The user requests to enrol multiple dogs to multiple programs.
- 1b1. Pawbook shows an error message.
-
1b2. User changes request to either enrolling one dog to one program, one dog to multiple programs, or multiple dogs to one program.
Steps 1b1-1b2 are repeated until the command entered is correct.Use case resumes at step 2.
Use case: UC08 - Drop dog from program
MSS
- User requests to drop dog from program.
-
Pawbook drops dog from the correct program.
Use case ends.
Extensions
- 1a. The dog/program ID is invalid/not specified.
- 1a1. Pawbook shows an error message.
-
1a2. User supplies correct dog/program ID.
Steps 1a1-1a2 are repeated until the command entered is correct.Use case resumes at step 2.
- 1b. The user requests to drop multiple dogs from multiple programs.
- 1b1. Pawbook shows an error message.
-
1b2. User changes request to either dropping one dog from one program, one dog from multiple programs, or multiple dogs from one program.
Steps 1b1-1b2 are repeated until the command entered is correct.Use case resumes at step 2.
Use case: UC09 - View schedule
MSS
- User requests to view schedule with a specified date.
-
Pawbook shows the schedule.
Use case ends.
Extensions
- 1a. The date is invalid/not specified.
- 1a1. Pawbook shows an error message.
-
1a2. User supplies correct date.
Steps 1a1-1a2 are repeated until the command entered is correct.Use case resumes at step 2.
Use case: UC10 - View Help Window
MSS
- User enters
helpcommand into the command box and presses enter. -
Pawbook opens a help window containing the link to the user guide and also a command summary for the user.
Use case ends.
Extensions
- 1a. The given command/format is invalid.
- 1a1. Pawbook shows an error message to the user.
-
1a2. User supplies the correct command.
Steps 1a1-1a2 are repeated until the command entered is correct.Use case resumes at step 2.
Use case: UC11 - Exit Pawbook
MSS
- User enters the
exitcommand into the command box and presses enter. - Pawbook shows goodbye message.
-
Pawbook terminates.
Use case ends.
Extensions
- 1a. The given command/format is invalid.
- 1a1. Pawbook shows an error message to the user.
-
1a2. User supplies the correct command.
Steps 1a1-1a2 are repeated until the command entered is correct.Use case resumes at step 2.
Non-Functional Requirements
- Should work on any mainstream OS as long as it has
Java 11or above installed. - Should be able to hold up to 100000 dogs, owners and dog programs without a noticeable sluggishness in performance for typical usage.
- Should be usable by a tech novice who is not familiar with CLI.
- Should respond within 2 seconds.
- 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 simple interface that is easy to navigate.
- Not required to handle finance-related bookkeeping.
- Pawbook does not require internet connection to run.
- Able to work in all different time zones, regardless of where the system is operated in the world.
- Features should be implemented such that they can undergo automated testing.
- Pawbook data should be saved locally. Not possible to be hacked from external machines. Only way to access is through the local machine.
- Only one Pawbook program can run on a local machine at any time.
- Pawbook program file size should not exceed beyond 1GB.
- Pawbook should be able to recover from exceptions and error handling and not freeze on the user.
Glossary
- Mainstream OS: Windows, Linux, Unix, OS-X
- JSON: JSON is short for JavaScript Object Notation which is a lightweight format for data storage
Appendix: Instructions for manual testing
Given below are instructions to test the app manually. These instructions should be complemented with the user guide for comprehensive testing. The state of the application is assumed to contain the sample data from when the application is first launched.
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.
-
-
Exiting the app
- With the application still open, enter
exitin the command box or click on the close window button [X].
Expected: Application terminates.
- With the application still open, enter
-
For the sake of all manual testing, we will be using the preset typical entities loaded from Pawbook database.
Add Command
-
Adding a dog
-
Prerequisites: Pawbook is launched and running. Ensure that an owner with ID 1 is present.
-
Test case:
add dog n/Bruce b/Chihuahua d/12-02-2019 s/Male o/1 t/playful t/active
Expected: If database does not already contain a Bruce, a successful command result should show. -
Test case:
add dog o/1 b/Chihuahua d/12-02-2019 n/Bruce s/Male t/playful t/active
Expected: Similar to previous. -
Test case :
add dog o/1 b/Chihuahua d/12-02-2019 n/Bruce t/playful t/active
Expected: Missing parameters, status message indicates invalid command format.
-
-
Adding an owner
-
Prerequisites: Pawbook is launched and running.
-
Test case:
add owner n/John Doe p/98765432 e/johnd@example.com a/311, Clementi Ave 2, #02-25 t/friends t/owesMoney
Expected: If database does not already contain a John Doe, a successful command result should show. -
Test case:
add owner n/John Doe a/311, Clementi Ave 2, #02-25 e/johnd@example.com p/98765432 t/friends t/owesMoney
Expected: Similar to previous. -
Test case :
add owner n/John Doe e/johnd@example.com a/311, Clementi Ave 2, #02-25 t/friends t/owesMoney
Expected: Missing parameter, status message indicates invalid command format.
-
-
Adding a program
-
Prerequisites: Pawbook is launched and running.
-
Test case:
add program n/Obedience Training s/01-02-2021 18:00 t/puppies
Expected: If database does not already contain a Bruce, a successful command result should show. -
Test case:
add program s/01-02-2021 18:00 n/Obedience Training t/puppies
Expected: Similar to previous. -
Test case :
add program t/puppies
Expected: Missing parameters, status message indicates invalid command format.
-
Delete Command
-
Deleting an owner while all owners are being shown
-
Pre-requisites
-
Start with an empty database by deleting all entities.
-
Add a sample owner with
add owner n/John Doe p/98765432 e/johnd@example.com a/311, Clementi Ave 2, #02-25 t/friends t/owesMoney. Ensure John Doe has ID 1. -
Add a sample dog with
add dog n/Bruce b/Chihuahua d/12-02-2019 s/Male o/1 t/playful t/active. Ensure Bruce has ID 2. -
Add a sample program with
add program n/Obedience Training s/01-02-2021 18:00 t/puppies. Ensure program has ID 3. -
List owners using
list owner.
-
-
Test case:
delete owner 1
Expected: Owner with ID 1 is deleted from the list. All the dogs belonging to the first owner is also deleted. Details of the deleted contact shown in the status message. Timestamp in the status bar is updated. -
Test case:
delete owner 0
Expected: No owner is deleted. Error details shown in the status message. Status bar remains the same. -
Test case:
delete owner 2
Expected: No owner is deleted as ID 2 is not an owner. Error details shown in the status message. Status bar remains the same. -
Other incorrect delete commands to try:
delete owner,delete owner x,delete owner -x(where x is larger than list size or negative)
Expected: Similar to previous. -
Prerequisites: Refer to above. List dogs using
list dog. -
Test case:
delete dog 2
Expected: Dog with ID 2 is deleted from the list. The dogs will also be removed from all programs they were previously enrolled in. -
Test case:
delete dog 0
Expected: No dog is deleted. Error details shown in the status message. Status bar remains the same. -
Test case:
delete dog 1
Expected: No dog is deleted as ID 1 is not a dog. Error details shown in the status message. Status bar remains the same. -
Other incorrect delete commands to try:
delete dog,delete dog x,delete dog -x(where x is larger than list size or negative)
Expected: Similar to previous.
-
-
Deleting a program while all programs are being shown
-
Prerequisites: Refer to above. List programs using
list program. -
Test case:
delete program 3
Expected: Program with ID 3 is deleted from the list. The dogs that were enrolled in the program will no longer be enrolled in that program. -
Test case:
delete program 0
Expected: No program is deleted. Error details shown in the status message. Status bar remains the same. -
Test case:
delete program 1
Expected: No program is deleted as ID 1 is not a program. Error details shown in the status message. Status bar remains the same. -
Other incorrect delete commands to try:
delete program,delete program x,delete program -x(where x is larger than list size or negative)
Expected: Similar to previous.
-
Edit Command
-
Pre-requisites
-
Start with an empty database by deleting all entities.
-
Add a sample owner with
add owner n/John Doe p/98765432 e/johnd@example.com a/311, Clementi Ave 2, #02-25 t/friends t/owesMoney. Ensure John Doe has ID 1. -
Add a sample dog with
add dog n/Bruce b/Chihuahua d/12-02-2019 s/Male o/1 t/playful t/active -
Add a sample program with
add program n/Obedience Training s/01-02-2021 18:00 t/puppies -
Add another sample owner with
add owner n/James Bond p/90139122 e/jamesbond@example.com a/322, Clementi Ave 2, #02-25 t/friends t/owesMoneyEnsure James Bond has ID 4.
-
-
Editing a dog
-
Test case:
edit dog 2 n/Milo
Expected: Successfully renamed Bruce to Milo. -
Test case:
edit dog 2 n/Bruce o/4
Expected: Successfully renamed Milo to Bruce and changed owner from John Doe to James Bond. -
Test case:
edit dog 3 n/Milo o/4
Expected: Error status message shown, indicating dog ID provided is invalid.
-
-
Editing an owner
-
Test case:
edit owner 1 p/91234567
Expected: Successfully changes John Doe’s number. -
Test case:
edit owner 1 p/97538642 e/ilovedogs@sample.com
Expected: Successfully changed John Doe’s number and updated his email. -
Test case:
edit owner 3 n/Keith
Expected: Error status message shown, indicating owner ID provided is invalid.
-
-
Editing a program
-
Test case:
edit program 3 n/Kennel Training
Expected: Successfully renamed Obedience Training to Kennel Training. -
Test case:
edit program 3 n/Kennel Training s/01-02-2021 17:00
Expected: Successfully renamed Obedience Training to Kennel Training and changes the session date to 1700 from 1800. -
Test case:
edit program 4 n/Kennel Training s/01-02-2021 17:00
Expected: Error status message shown, indicating program ID provided is invalid.
-
Find Command
-
Find valid entities
-
Pre-requisites
-
Start with an empty database by deleting all entities.
-
Add a sample owner with
add owner n/John Doe p/98765432 e/johnd@example.com a/311, Clementi Ave 2, #02-25 t/friends t/owesMoney. Ensure John Doe has ID 1. -
Add a sample dog with
add dog n/Bruce b/Chihuahua d/12-02-2019 s/Male o/1 t/playful t/active -
Add a sample program with
add program n/Obedience Training s/01-02-2021 18:00 t/puppies -
Add another sample owner with
add owner n/James Bond p/90139122 e/jamesbond@example.com a/322, Clementi Ave 2, #02-25 t/friends t/owesMoneyEnsure James Bond has ID 4.
-
-
Test case:
find John
Expected: Alice with ID 1 is shown on the display list. Status message says “1 entity listed!” -
Test case:
find Jo
Expected: Similar to previous. -
Test case:
find John James
Expected: John and James are displayed on the list. Status messages says: “2 entities listed!”
-
-
Finding invalid entities
-
Test case:
find InvalidName
Expected: Zero entities listed. -
Test case:
find 12345
Expected: Zero entities listed.
-
List Command
-
Listing dogs
- Test case:
list dog
Expected: All the dogs in the school listed.
- Test case:
-
Listing owners
- Test case:
list owner
Expected: All the owners in the school listed.
- Test case:
-
Listing program
- Test case:
list program
Expected: All the programs in the school listed.
- Test case:
-
Invalid List commands
-
Test case:
list
Expected: Error message indicates unknown entity, shows supported entities. -
Test case:
list invalidEntity
Expected: Similar to previous.
-
View Command
-
Pre-requisites
-
Start with an empty database by deleting all entities.
-
Add a sample owner with
add owner n/John Doe p/98765432 e/johnd@example.com a/311, Clementi Ave 2, #02-25 t/friends t/owesMoney. Ensure John Doe has ID 1. -
Add a sample dog with
add dog n/Bruce b/Chihuahua d/12-02-2019 s/Male o/1 t/playful t/active -
Add a sample program with
add program n/Obedience Training s/01-02-2021 18:00 t/puppies -
Enrol Bruce into Obedience Training with
enrol d/2 p/3 -
Ensure that Bruce is successfully added to the Obedience Training program.
-
-
Viewing owner
- Test case:
view 1
Expected: John’s and Bruce’s contacts are listed. John Doe’s contact is at the top, followed by Bruce.
- Test case:
-
Viewing dog
- Test case:
view 2
Expected: John, Bruce and Obedience Training program is listed. Bruce’s contact is at the top, followed by John, followed by Obedience Training.
- Test case:
-
Viewing program
- Test case:
view 3
Expected: Bruce and Obedience Training program is listed. Obedience training details are at the top, followed by Bruce’s details.
- Test case:
-
Invalid view ID
-
Test case:
view 4
Expected: Error status message is provided, indicating invalid ID. -
Test case:
view -1
Expected: Error status message is provided, indicating ID must be positive.
-
Schedule Command
-
Pre-requisites
-
Start with an empty database by deleting all entities.
-
Add a sample program with
add program n/Obedience Training 1 s/[TODAY'S DATE] 18:00 t/puppies. Fill in today’s date in the[TODAY'S DATE]field in dd-mm-yyyy format. -
Add a sample program with
add program n/Obedience Training 2 s/01-02-2021 18:00 t/puppies -
Ensure that sample programs are successfully added.
-
-
Viewing schedules on a valid day
-
Test case:
schedule
Expected: Successful status message, shows the sample Obedience Training 1 happening today. -
Test case:
schedule 01-02-2021
Expected: Successful status message, shows the sample Obedience Training 2 happening on 01-02-2021.
-
-
Viewing schedules on an invalid day
-
Test case:
schedule 31-02-2021
Expected: Error status message thrown, indicating day of the month does not exist. -
Test case:
schedule 031-02-2021
Expected: Error status message thrown, indicating that date format should be in dd-MM-yyyy format.
-
Enrol Command
-
Pre-requisites
-
Start with an empty database by deleting all entities.
-
Add a sample owner with
add owner n/John Doe p/98765432 e/johnd@example.com a/311, Clementi Ave 2, #02-25 t/friends t/owesMoney. Ensure John Doe has ID 1. -
Add a sample dog with
add dog n/Bruce b/Chihuahua d/12-02-2019 s/Male o/1 t/playful t/activeEnsure Bruce has ID 2. -
Add a sample program with
add program n/Obedience Training s/01-02-2021 18:00 t/puppiesEnsure Obedience Training has ID 3.
-
-
Enrol valid dog into valid program
- Test case:
enrol d/2 p/3
Expected: Bruce is successfully added to the Obedience Training program.
- Test case:
-
Enrol valid dog into invalid program
- Test case:
enrol d/2 p/4
Expected: Error status message stating program ID is invalid.
- Test case:
-
Enrol invalid dog into valid program
- Test case:
enrol d/3 p/3
Expected: Error status message stating dog ID is invalid.
- Test case:
-
Enrol multiple valid dogs into valid program
-
Repeat Pre-requisites
-
Add another sample dog with
add dog n/Apple b/Golden Retriever d/28-04-2020 s/Female o/1 t/friendlyEnsure Apple as ID 4. -
Test case:
enrol d/2 d/4 p/3
Expected: Bruce and Apple are successfully added to the Obedience Training program. Remember to drop Bruce from the program if he was enrolled previously!
-
-
Enrol one valid dog into multiple valid programs
-
Repeat Pre-requisites
-
Add another sample program with
add program n/Potty Training s/14-03-2021 12:00 t/puppiesEnsure Potty Training has ID 4. -
Test case:
enrol d/2 p/3 p/4
Expected: Bruce is successfully added to the Obedience Training program and the Potty Training program. Remember to drop Bruce from the program if he was enrolled previously!
-
-
Enrol multiple valid dogs into multiple valid programs
-
Repeat Pre-requisites
-
Add another sample dog with
add dog n/Apple b/Golden Retriever d/28-04-2020 s/Female o/1 t/friendlyEnsure Apple has ID 4. -
Add another sample program with
add program n/Potty Training s/14-03-2021 12:00 t/puppiesEnsure Potty Training has ID 5. -
Test case:
enrol d/2 d/4 p/3 p/5
Expected: Error messaging stating that enrollment of multiple dogs into multiple programs is not supported.
-
-
Invalid enrol command
- Test case:
enrol invalidCommandExpected: Error status message indicating wrong command format.
- Test case:
Drop Command
-
Pre-requisites
-
Start with an empty database by deleting all entities.
-
Add a sample owner with
add owner n/John Doe p/98765432 e/johnd@example.com a/311, Clementi Ave 2, #02-25 t/friends t/owesMoney. Ensure John Doe has ID 1. -
Add a sample dog with
add dog n/Bruce b/Chihuahua d/12-02-2019 s/Male o/1 t/playful t/active. Ensure Bruce has ID 2. -
Add a sample program with
add program n/Obedience Training s/01-02-2021 18:00 t/puppiesEnsure Obedience Training has ID 3.
-
-
Drop valid dog from valid program
-
Enrol dog into program with:
enrol d/2 p/3 -
Test case:
drop d/2 p/3
Expected: Bruce is successfully dropped from Obedience Training program.
-
-
Drop valid dog from invalid program
-
Enrol dog into program with:
enrol d/2 p/3 -
Test case:
drop d/2 p/4
Expected: Error status message stating program ID is invalid.
-
-
Drop invalid dog from valid program
-
Enrol dog into program with:
enrol d/2 p/3 -
Test case:
drop d/3 p/3
Expected: Error status message stating dog ID is invalid.
-
-
Drop multiple valid dogs from valid program
-
Repeat Pre-requisites
-
Add another sample dog with
add dog n/Apple b/Golden Retriever d/28-04-2020 s/Female o/1 t/friendlyEnsure Apple as ID 4. -
Enrol dogs into program with:
enrol d/2 d/4 p/3 -
Test case:
drop d/2 d/4 p/3
Expected: Bruce and Apple are successfully added to the Obedience Training program.
-
-
Drop one valid dog from multiple valid programs
-
Repeat Pre-requisites
-
Add another sample program with
add program n/Potty Training s/14-03-2021 12:00 t/puppiesEnsure Potty Training has ID 4. -
Enrol dog into programs with:
enrol d/2 p/3 p/4 -
Test case:
drop d/2 p/3 p/4
Expected: Bruce is successfully added to the Obedience Training program and the Potty Training program.
-
-
Drop multiple valid dogs from multiple valid programs
-
Repeat Pre-requisites
-
Add another sample dog with
add dog n/Apple b/Golden Retriever d/28-04-2020 s/Female o/1 t/friendlyEnsure Apple has ID 4. -
Add another sample program with
add program n/Potty Training s/14-03-2021 12:00 t/puppiesEnsure Potty Training has ID 5. -
Enrol dog into program with:
enrol d/2 p/3andenrol d/4 p/5 -
Test case:
drop d/2 d/4 p/3 p/5
Expected: Error messaging stating that dropping of multiple dogs from multiple programs is not supported.
-
-
Invalid drop command
- Test case:
drop invalidCommand
Expected: Error status message indicating wrong command format.
- Test case:
Help Command
- Opening the help window
- Test case:
help
Expected: Opens a pop-up window that shows the command summary and provides a link to the user guide.
- Test case:
Exit Command
- Test case:
exit
Expected: The program should exit and close.
Appendix: Effort
Throughout the development, our team wanted to make Pawbook easy to use, intuitive and presentable. After countless group discussions, physical meetings and additional effort leading up to submission, we managed to pull through and present a usable and functioning product that we are proud of. Amassing over 14,000 lines of code combined, we had to stick to strict internal deadlines, manage conflicts and maintain a culture of open communication and transparency. We also took the liberty to call for group meetings whenever needed, going beyond just the usual meetings to make sure everyone is in sync.
The first step of development was abstracting the “entity” that was used in AddressBook. Instead of just a Person entity, we realized that we needed to create three entities: Dog, Owner and Program. This included a great deal of refactoring and involved the abstraction of an Entity class that is inherited by all three classes. The alternative was a simple solution would be to duplicate the Person class 3 times and have 3 separate containers alongside 3 different GUI components. However, this naive implementation is only good as a proof-of-concept, as it greatly violated the DRY principle.
The second challenge was deciding what type of data structure we wanted to use for storing all the entities. Because of the relationship between owners, dogs and programs, we knew that there must be a way for the entities to call on each other. However, we did not want to store the related objects directly in each entity as that would lead to very high coupling. We came up with an ID system that allows us to refer to each entity by ID. However, we were stuck when trying to implement the hashmap data structure that we were initially thinking of using. This was because changing the internal data structure would greatly impact all aspects of the application, including UI, testing and functionality. We then decided to refactor the internal list structure to accept a Pair class, containing the ID as the key and the object as the value. This was yet another huge refactoring that we had to work through to migrate from the index-based system over to an ID-based one.
Once the bottleneck on the underlying data structure was finally completed, we had to think of how to refactor the functions such that they were able to accept all three entities. Additionally, we had to think of all the features that we wanted to accomplish to help us achieve our target proposition. With all of us taking one or more commands, we worked in parallel to push out new commands such as list, view, schedule, enrol, drop while heavily refactoring existing commands and improving on them to not just work with the three new entities, but also change the way the results were displayed. We decided that we wanted the display results not to follow numerical ordering, but in order of relevance and sense from the user perspective.
In terms of testing, we are proud to say that our test coverage is over the 77% mark, above the original coverage of AB3 which was 72%. This was because the team really pulled together to bring our coverage up leading to the final submission, ensuring that our tests were comprehensive enough to not only cover majority of the functional code, but also the possible corner cases.
We also placed emphasis on GUI, making sure that our GUI was suitable and aesthetically pleasing for users. Through the process, we also had to learn a great deal of FXML syntax as we did away with SceneBuilder which we thought was hard to use and inflexible. Hence, we directly edited the code instead. It was also necessary to edit the CSS to change the theme of the application.
While Pawbook inherited a GUI from AddressBook, we made a conscious effort to not revolve the product too heavily on the GUI. Instead of having separate tabs for each of the entities, we decided to make use of the existing ListView to display the various types of entities, allowing the user to switch between them using the list command rather than requiring that the user leave their keyboard to reach for their mouse in order to perform a trivial task like this.
Finally, the team made additional effort into making sure that the documentation was organised, comprehensive and easy to read. We all had to pick up PlantUML notation to create the UML diagrams such as activity diagrams and sequence diagram. Before submission, we made sure to standardize and make the formatting consistent, positioning of diagrams and overall flow and logic of the User Guide and this Developer Guide.