Developer Guide
MedInfo is a desktop application that empowers clinics and hopitals to manage their patients.
This Developer Guide provides an in-depth documentation on how MedInfo is designed and implemented. It covers the architecture of MedInfo and provides detailed descriptions regarding the implementation design.
You can use this guide to maintain, upgrade, and evolve MedInfo.
Table of contents
- Getting Started
- Design
- Implementation
- Appendix: Requirements
- Appendix: Instructions for Manual Testing
- Appendix: Planned Enhancements
Setting up, getting started
Refer to the guide Setting up and getting started.
Design
.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.
Architecture
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
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.
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),
- defines its API in an
interface
with the same name as the Component. - implements its functionality using a concrete
{Component Name}Manager
class (which follows the corresponding APIinterface
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.
UI 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,
- executes user commands using the
Logic
component. - listens for changes to
Model
data so that the UI can be updated with the modified data. - keeps a reference to the
Logic
component, because theUI
relies on theLogic
to execute commands. - depends on some classes in the
Model
component, as it displaysPerson
object residing in theModel
.
Logic component
API : Logic.java
Here’s a (partial) class diagram of the Logic
component:
How the Logic
component works:
- When
Logic
is called upon to execute a command, it uses theMedInfoParser
class to parse the user command. - This results in a
Command
object (more precisely, an object of one of its subclasses e.g.,AddCommand
) which is executed by theLogicManager
. - The command can communicate with the
Model
when it is executed (e.g. to add a patient). - The result of the command execution is encapsulated as a
CommandResult
object which is returned back fromLogic
.
The Sequence Diagram below illustrates the 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.
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:
- When called upon to parse a user command, the
MedInfoParser
class creates anXYZCommandParser
(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 aXYZCommand
object (e.g.,AddCommand
) which theMedInfoParser
returns back as aCommand
object. - All
XYZCommandParser
classes (e.g.,AddCommandParser
,DeleteCommandParser
, …) inherit from theParser
interface so that they can be treated similarly where possible e.g, during testing.
Model component
API : Model.java
The Model
component,
- stores the address book data i.e., all
Person
objects (which are contained in aUniquePersonList
object). - stores the currently ‘selected’
Person
objects (e.g., results of a search query) as a separate filtered list which is exposed to outsiders as an unmodifiableObservableList<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. - stores a
UserPref
object that represents the user’s preferences. This is exposed to the outside as aReadOnlyUserPref
objects. - does not depend on any of the other three components (as the
Model
represents data entities of the domain, they should make sense on their own without depending on other components)
Storage component
API : Storage.java
The Storage
component,
- can save both address book data and user preference data in json format, and read them back into corresponding objects.
- inherits from both
MedInfoStorage
andUserPrefStorage
, which means it can be treated as either one (if only the functionality of only one is needed). - depends on some classes in the
Model
component (because theStorage
component’s job is to save/retrieve objects that belong to theModel
)
Common classes
Classes used by multiple components are in the seedu.medinfo.commons
package.
Implementation
This section describes some noteworthy details on how certain features are implemented in MedInfo.
Adding a patient
In MedInfo, a user can add a patient using the add
command.
Implementation
- The
add
command takes in 2 compulsory fields (name and NRIC) and 1 optional field (status) - It is supported by the
AddCommandParser
that extracts the relevant fields from the entered command.
The following activity diagram summarizes what happens when a user enters an add
command:
Details:
- The user enters an
add
command with the name and NRIC specified. - If the user entered a
Status
(prefixed bys/
), the patient created will have that status. - The created patient is added to the model.
Adding a ward
In MedInfo, a user can add a patient using the addward
command.
Implementation
- The
add
command takes in 1 compulsory field (ward name) and 1 optional field (capacity) - It is supported by the
AddWardCommandParser
that extracts the relevant fields from the entered command.
The following activity diagram summarizes what happens when a user enters an addward
command:
Details:
- The user enters an
addward
command with the ward name specified. - If the user entered a
Capacity
(prefixed byc/
), the ward created will have that capacity. - The created ward is added to the model.
Editing a patient
In MedInfo, a user can edit a patient using the edit
command.
Implementation
- The
edit
command takes in 1 compulsory argument (index) and up to 3 optional fields (status, ward and discharge date). - It is supported by the
EditCommandParser
that extracts the relevant fields from the entered command.
The following activity diagram summarizes what happens when a user enters an edit
command:
Details:
- The index is based on the last displayed list of patients. This design choice was made as:
- A user would most likely perform a
find
orlist
operation to confirm the patient to edit. - Finding patient by NRIC would be too cumbersome for the user.
- A user would most likely perform a
- Name and NRIC are not editable as these are identifying fields of a patient.
Deleting a patient
In MedInfo, a user can edit a patient using the delete
command.
Implementation
- The
delete
command takes in 1 compulsory argument (index). - It is supported by the
DeleteCommandParser
that extracts the index from the entered command.
The following activity diagram summarizes what happens when a user enters a delete
command:
Details:
- When a user executes this command, they are greeted with an alert window to confirm deletion.
- Clicking ‘OK’ at this point will let MedInfo proceed with the deletion.
- Clicking ‘Cancel’ or closing the window will abort the deletion and trigger a
list
operation.
- Aborting a deletion leads to a
list
operation so that the user can view all patients. - The index is based on the last displayed list of patients. This design choice was made as:
- A user would most likely perform a
find
orlist
operation to confirm the patient to delete. - Finding patient by NRIC would be too cumbersome for the user.
- A user would most likely perform a
Finding patients
In MedInfo, a user can find patients matching certain conditions using the find
command.
Implementation
- The
find
command takes in 1 compulsory field (one of either name, NRIC or status). - It is supported by the
FindCommandParser
which extracts one of the possible fields:- Name entered in the command (prefixed by
name/
) - NRIC entered in the command (prefixed by
nric/
) - Status entered in the command (prefixed by
s/
)
- Name entered in the command (prefixed by
- If the user enters multiple fields, MedInfo highlights the error to the user.
The following activity diagram summarizes what happens when a user enters a find
command:
List all patients
In MedInfo, a user can list all patients using the list
command.
Implementation
- The
list
command does not take in any arguments.
The following activity diagram summarizes what happens when a user enters a find
command:
[Proposed] Data archiving
{Explain here how the data archiving feature will be implemented}
Documentation, logging, testing, configuration, dev-ops
Appendix: Requirements
Target user profile
- has a need to manage a significant number of patients coming into an A&E in a private hospital
- can type fast
- prefers typing to execute commands and allocating patients by their status to their respective wards
- is reasonably comfortable using CLI apps
Value proposition
- solve the problem of slow and multiple step process of allocating patients to their respective wards in an A&E
- provide faster access to a particular patient’s details for hospital admin staff
- provide a more efficient process of managing patients by their status to cater to patients who are in urgent need of care, which in turn provides a better quality of service
- provide a simple system to keep track and update a patient’s discharge date
User stories
Priorities: High (must have) - * * *
, Medium (nice to have) - * *
, Low (unlikely to have) - *
Priority | As a … | I want to … | So that I can… |
---|---|---|---|
* * * |
staff member | add a patient | record more information later |
* * * |
staff member | add a ward | assign patients to the ward later |
* * * |
staff member | add personal particulars to a patient | record their name and NRIC |
* * * |
staff member | add current status of patient | keep track of patient status |
* * * |
staff member | add current ward of patient | keep track of patient location |
* * * |
staff member | add a discharge date to hospitalised patients | keep track of discharge dates |
* * * |
staff member | view the list of commands | use the system proficiently |
* * * |
staff member | search for patients by personal particulars | do a basic search to find a certain patient |
* * * |
staff member | search for patients by discharge date | plan for future patient discharges |
* * * |
staff member | update personal particulars of a patient | keep the personal particulars of a patient up to date |
* * * |
staff member | update patient ward | move patients to different wards |
* * * |
staff member | update the status of a patient | keep the status of a patient up to date |
* * * |
staff member | update the discharge date of hospitalised patients | change the discharge date of a hospitalised patient due to unexpected medical complications |
* * * |
staff member | remove a patient | put the patient on hold or remove duplicate entries |
* * * |
staff member | remove the discharge date of a patient | put the patient’s discharge date on hold while awaiting further assessment |
* * |
staff member | view the list of patients sorted by discharge date | plan for future patient discharges |
* * |
staff member | see patients with approaching discharge dates | be aware of approaching discharge patients |
* * |
staff member | view patients by ward | find patients in a ward and check the occupancy within certain wards |
* * |
staff member | view patients by status | address higher priority patients more quickly |
* * |
staff member | view list of wards | see current wards in system at a glance |
* * |
staff member | view list of patients | see current patients in system at a glance |
* * |
staff member | update the name of a ward | keep the name of a ward up to date |
* * |
staff member | update the capacity of a ward | keep the maximum number of patients in a ward up to date |
* * |
staff member | view the current total occupancy | see the total number of patients currently admitted |
* * |
staff member | view the total capacity of a ward | see the maximum number of patients I can admit to this ward |
* * |
staff member | view the current occupancy of a ward | see the number of patients currently admitted to a ward, and to know if a ward is full |
* * |
staff member | confirm a deletion of a patient | avoid accidentally deleting a patient, which cannot be undone |
Use cases
(For all use cases below, the System is the MedInfo
and the Actor is the user
, unless specified otherwise)
Use case: UC01 - Add a patient
MSS
- User requests to add a new patient to MedInfo.
- The user enters patient details.
- The following are required information:
- Name
- NRIC
- The following are non-required information:
- Status
- Ward
- The following are required information:
- The system adds the user into the MedInfo system.
-
The system shows the new created user in the patient list.
Use case ends.
Extensions
-
2a. If any of the required fields are not completed.
- 2a1. the user is informed of this and show the correct format for the command
Use case resumes at step 2.
-
2b. If the entered NRIC is already present in another record in the system.
- 2b1. the user is informed that the NRIC is already present in the system.
Use case resumes at step 2.
-
2c. If the input field is invalid.
- 2c1. the user is informed of this, and correct format for the command is displayed.
Use case resumes at step 2.
-
2d. If the entered ward is not present in the system.
- 2d1. the user is informed that the ward does not exist in the system.
Use case resumes at step 2.
Use case: UC02 - Delete a patient
MSS
- User requests to list filtered patients
- MedInfo shows a list of filtered patients
- User requests to delete a specific patient in the list by index number
- MedInfo shows confirmation window
-
MedInfo deletes the patient
Use case ends.
Extensions
-
2a. The list is empty.
Use case ends.
-
3a. The requested patient’s index number is invalid.
-
3a1. MedInfo shows an error message.
Use case resumes at step 2.
-
-
4a. The user cancels the deletion in the confirmation window
-
4a1. MedInfo shows the patient list
-
4b1. MedInfo shows an error message.
Use case resumes at step 2.
-
Use case: UC03 - Edit a patient
MSS
- User requests to list filtered patients
- MedInfo shows a list of filtered patients
- User requests to edit a specific patient in the list by index number
- The following can be edited:
- Status
- Ward
- Discharge Date
- The following cannot be edited:
- Name
- NRIC
- The following can be edited:
-
MedInfo edits the patient
Use case ends.
Extensions
-
2a. The list is empty.
Use case ends.
-
3a. The requested patient’s index number is invalid.
-
3a1. MedInfo shows an error message.
Use case resumes at step 2.
-
-
3b. The prefixes entered are invalid.
-
3b1. MedInfo shows an error message.
Use case resumes at step 2.
-
-
3b. The Status entered is invalid.
-
3b1. MedInfo shows an error message.
Use case resumes at step 2.
-
-
3b. The Ward entered is invalid.
-
3b1. MedInfo shows an error message.
Use case resumes at step 2.
-
-
3b. The Discharge Date entered is invalid.
-
3b1. MedInfo shows an error message.
Use case resumes at step 2.
-
-
3d. User tries to edit a non-editable field (Name/NRIC).
-
3d1. MedInfo shows an error message.
Use case resumes at step 2.
-
Use case: UC04 - Find a patient
MSS
- User requests to find specific patients by either NRIC or Name or Status or Ward
-
MedInfo shows a list of patients
Use case ends.
Extensions
-
1a. The requested patient’s NRIC does not exist in the system.
-
1a1. MedInfo does not list any patients.
Use case ends.
-
-
1b. The requested patient’s Name does not exist in the system.
-
1b1. MedInfo does not list any patients.
Use case ends.
-
-
1c. The requested patient’s Status does not exist in the system.
-
1c1. MedInfo does not list any patients.
Use case ends.
-
-
1d. The requested patient’s Ward does not exist in the system.
-
1d1. MedInfo does not list any patients.
Use case ends.
Use case: UC05 - Clear all patients
MSS
- User requests to clear all the patient records in the system
- MedInfo shows confirmation window
-
MedInfo deletes all patients in the system
Use case ends.
- 3a. The user cancels the deletion in the confirmation window
- 3a1. MedInfo shows the patient list
Use case: UC06 - Add a new ward
MSS
- User requests to add a new ward to MedInfo.
- The user enters ward details.
- The following are required information:
- Name
- The following are non-required information:
- Capacity
- The following are required information:
- The system adds the ward into the MedInfo system.
-
The system shows the new created ward in the ward list.
Use case ends.
Extensions
-
2a. If any of the required fields are not completed.
- 2a1. the user is informed of this and show the correct format for the command
Use case resumes at step 2.
-
2b. If the entered Name is already present in another record in the system.
- 2b1. the user is informed that the Name is already present in the system.
Use case resumes at step 2.
-
2c. If the input field is invalid.
- 2c1. the user is informed of this, and correct format for the command is displayed.
Use case resumes at step 2.
Use case: UC07 - Delete a ward
MSS
- User requests to list wards
- MedInfo shows a list of wards
- User requests to delete a specific ward in the list by index number
- MedInfo shows confirmation window
-
MedInfo deletes the patient
Use case ends.
Extensions
-
2a. The ward list is empty.
Use case ends.
-
3a. The requested ward’s index number is invalid.
-
3a1. MedInfo shows an error message.
Use case resumes at step 2.
-
-
3b. The requested ward has patients inside
- 3b1. MedInfo shows an error message.
Use case resumes at step 2.
-
4a. The user cancels the deletion in the confirmation window
-
4a1. MedInfo shows the patient list
Use case resumes at step 2
-
Use case: UC08 - Sort Patients
MSS
- User requests to list patients
- MedInfo shows a list of patients
- User requests to sort all the patients by a specific order
- MedInfo sorts all the patients
-
MedInfo displays the sorted list
Use case ends
Extensions
-
- The patient list is empty
Use case ends.
- 3a. The requested sorting order is invalid
-
3a1. MedInfo shows an error message.
Use case resumes at step 2.
-
- 3b. The requested sorting field is invalid
-
3b1. MedInfo shows an error message.
Use case resumes at step 2.
-
Non-Functional Requirements
- Should work on any mainstream OS as long as it has Java
11
or above installed. - Should be able to hold up to 1000 patients without a noticeable sluggishness in performance for typical usage.
- A user with above average typing speed for regular English text (i.e. not code, not system admin commands) should be able to accomplish most of the tasks faster using commands than using the mouse.
- Should mask the NRIC of patients when listing (e.g. XXXXX264G).
- The product is not required to validate the medical records.
Glossary
- Mainstream OS: Windows, Linux, Unix, OS-X
- CLI: Command Line Interface
- Use case: It describes an interaction between the user and the system for a specific functionality of the system.
-
Priority Level: Level of seriousness of a patient’s health condition (e.g.
Stable
,Mild
,Severe
) - Medical Record: Blood type, allergies, medical cases and history of medical conditions
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 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.
-
Delete a patient
-
Deleting a patient while all patients are being shown
-
Prerequisites: List all patients using the
list
command. Multiple patients 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. Timestamp in the status bar is updated. -
Test case:
delete 0
Expected: No patient 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.
-
Save data
- Dealing with missing data files
- MedInfo will display sample data if data files cannot be found in the data directory.
- Dealing with corrupted data files
- MedInfo will clear the current data if the data files are corrupted or modified invalidly.
Appendix: Planned Enhancements
Given below are a few enhancements we hope to bring into future iterations of MedInfo:
Date-time validation:
Currently, MedInfo allows the user to input dates in the past (e.g.01/01/1000 1000
). While there may be reason to
input past date-times, such as if the user forgot to enter dates previously, MedInfo is meant to be a current
patient tracking system. As such, inputting dates from the past would not make sense as the patients would have been
discharged already (and hence have no reason to be recorded in MedInfo).
Also, MedInfo currently allows entering time in non HHmm format (e.g. ‘210.4’). This shall be looked into while
improving validation overall.
Possible Implementation:
- Future validation could be implemented by adding a method in
Discharge.java
to check if a given date is a valid future discharge date (by comparing to the current date) - The method created above would then be called within
parseDischarge()
inParserUtil.java
to ensure that a valid future discharge date-time was entered
Strict NRIC validation:
Currently, MedInfo checks whether a valid NRIC has been entered based on a validaton regex within
Nric.java
(^[STFG]\d{7}[A-Z]$
). This regex restricts the NRIC to be a capital letter (either
S/F/T/G) followed by 7 numbers and a capital letter. True valid NRICs make use of stronger validation
logic, involving check digits. Such validation would need to be added before using MedInfo in a
real-life scenario. However, due to the constraints it would place on testing during development,
it shall be implemented in the future instead.
UI component behaviour on window resizing
On resizing, the status bar maintains its centered location as from the full-size window. As a result, the information in it gets truncated. As this information is critical, future enhancements should address this, and other UI components that get cut off on window resizing.
Possible implementations:
- adjusting padding
- setting position constraint
- setting a higher minimum window width
Multiple parameter search
Currently, MedInfo only allows finding patients by onw of four parameters:
- name (
name/
) - NRIC (
nric/
) - status (
s/
) - ward name (
w/
)
The find
command does not allow multiple parameters to be used at once. For example, attempting to find critical
patients in ward ‘ER1’ with the command find s/red w/ER1
would result in an error. However, as a hospital
staff, finding patients matching multiple criteria is a valid use-case. Hence, this is planned as a future enhancement.
Find by ward
Currently, the find
command in MedInfo finds patients by wards as it does patients by name, i.e. by displaying
all patients that match any of the keywords supplied. As a result, the logic is slightly flawed. Consider the
scenario of trying to find patients in a ward named ‘Class A’, when the other wards in the system include ‘Class B’
and ‘Class C’. Entering find w/Class A
would also display patients in the other 2 wards due to the common keyword
‘Class’. This should be addressed in future iterations of MedInfo by making the find
command match ward name
exactly.
Handling long names
Currently, long names are truncated (with ...
) once they go past the maximum displayable length. This makes it
impossible to get long patient names after entry into the system. This would need to be addressed in the future.
Possible implementation:
- limit name input to 40 characters: While simple to implement (change validation regex in
Name.java
to[\\p{Alnum}][\\p{Alnum} ]{0,39}
, it is not recommended, as it does not handle the case of patients with names longer than 40 characters - text wrapping to display the whole name within the patient card in the UI
Expand help
command
Currently, entering the help
command in MedInfo opens a small dialog box with a link to MedInfo’s website. While
the user can read the user guide from the website to learn how to use the commands, perhaps a quick command summary
could be added to this window for returning users who do not wish to open the website but just need a quick refresher
on the commands.
Possible implementation:
- add command summary in text to help window display