ModuLink - Developer Guide
Table of Contents
- Acknowledgements
- Setting up, getting started
- Design
- Implementation
- Documentation, logging, testing, configuration, dev-ops
- Appendix
Acknowledgements
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 addFav A0123456A
.
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 theModuLinkParser
class to parse the user command. - This results in a
Command
object (more precisely, an object of one of its subclasses e.g.,CreateCommand
) which is executed by theLogicManager
. - The command can communicate with the
Model
when it is executed (e.g. to add a person). - 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("addFav")
API call.
AddFavCommandParser
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
ModuLinkParser
class creates anXYZCommandParser
(XYZ
is a placeholder for the specific command name e.g.,CreateCommandParser
) which uses the other classes shown above to parse the user command and create aXYZCommand
object (e.g.,CreateCommand
) which theModuLinkParser
returns back as aCommand
object. - All
XYZCommandParser
classes (e.g.,CreateCommandParser
,EditCommandParser
, …) 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 ModuLink 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)
</div>
Storage component
API : Storage.java
The Storage
component,
- can save both ModuLink data and user preference data in json format, and read them back into corresponding objects.
- inherits from both
ModuLinkStorage
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.modulink.commons
package.
Implementation
This section describes some noteworthy details on how certain features are implemented.
Create A Profile
Implementation
The create
mechanism will allow the user to create a personal profile.
The implementation required the creation of a parser for CreateCommand
as the command does takes in parameters (personal information, module information etc..).
CreateCommand
class updates the Model
class and then returns a new instance of the CommandResult
class.
The GUI will then update to include the created profile and the current user’s profile will be highlighted in the GUI.
After creating a profile, the user can now use other commands in ModuLink.
Usage
To use this function and create a profile, simply enter the command and the required parameters in the command line in the following format.
create n/NAME id/STUDENT_ID p/PHONE e/EMAIL [mod/TAG]...
Example: create n/John Doe id/A1234567Z p/98765432 e/johnd@example.com mod/CS2100 mod/CS2101
The following sequence diagram shows how the create
mechanism works:
Add A Module Tag
Implementation
The addMod
mechanism will allow the user to add a module tag to their profile.
The implementation required the creation of a parser for addModCommand
as the command does takes in parameters.
addModCommand
class updates the Model
class and then returns a new instance of the CommandResult
class.
The GUI will then update to include the tags for the user profile.
Usage
To use this function and create a profile, simply enter the command and the required parameters in the command line in the following format.
addMod [mod/MOD]...
Example: addMod mod/CS2103T
The following sequence diagram shows how the addMod
mechanism works:
Add A Profile As Favourite
Implementation
The addFav
mechanism will allow the user to add a module tag to their profile.
The implementation required the creation of a parser for addFavCommand
as the command does takes in parameters.
addFavCommand
class updates the Model
class and then returns a new instance of the CommandResult
class.
The GUI will then update to show the specified profile as a favourite.
Usage
To use this function and create a profile, simply enter the command and the required parameters in the command line in the following format.
addFav Student_ID
Example: addFav A1234567X
The following sequence diagram shows how the addFav
mechanism works:
List All Favourited Profiles
Implementation
The listFav
mechanism will allow the user to view all the students that he/she has favourited.
The implementation did not require the creation of a parser for ListFavCommand
as the command does not take in any parameters.
ListFavCommand
class updates the Model
class and then returns a new instance of the CommandResult
class.
The GUI will then change the content to display all favourited profiles.
Usage
To use this function to see all favourited profiles, simply enter listFav
in the command line.
The following sequence diagram shows how the listFav
mechanism works:
Filter Profiles By Module and Optionally Group Status
Implementation
The filter
mechanism will allow the user to filter profiles by module and optionally group status.
The implementation required the creation of a parser for filterCommand
as the command does takes in parameters.
filterCommand
class updates the Model
class and then returns a new instance of the CommandResult
class.
The GUI will then update to show the profiles that contain the specified modules and/or group status.
Usage
To use this function and create a profile, simply enter the command and the required parameters in the command line in the following format.
filter mod/MODULE [group/GROUP_STATUS]
Example: filter mod/CS2103T group/SM
The following sequence diagram shows how the filter
mechanism works:
Edit Group Status of Modules
Implementation
The editGroupStatus
mechanism will allow the user to edit the group status of the modules on their profile.
The implementation required the creation of a parser for editGroupStatusCommand
as the command does takes in parameters.
editGroupStatusCommand
class updates the Model
class and then returns a new instance of the CommandResult
class.
The GUI will then update to show the updated group status for the specified module.
Usage
To use this function and create a profile, simply enter the command and the required parameters in the command line in the following format.
editGroupStatus mod/MODULE group/GROUP_STATUS
Example: editGroupStatus mod/CS2103T group/Need member
The following sequence diagram shows how the editGroupStatus
mechanism works:
Documentation, logging, testing, configuration, dev-ops
Appendix: Requirements
Product scope
Target user profile:
- has a need to manage a significant number of contacts
- prefer desktop apps over other types
- can type fast
- prefers typing to mouse interactions
- is reasonably comfortable using CLI apps
- wants to find people to form groups with for his CS modules
Value proposition: search for and contact students in the same modules to quickly form groups.
User stories
Priorities: High (must have) - * * *
, Medium (nice to have) - * *
, Low (unlikely to have) - *
Priority | As a … | I want to … | So that I can… |
---|---|---|---|
* * * |
user | add a contact as a favourite | easily keep track of my favourites’ activity |
* * * |
user | remove a contact as a favourite | remove users I no longer am interested in |
* * * |
new user | create a profile | start using the app |
* * |
potential user exploring the app | view those taking similar mods | easily find potential groupmates |
* * * |
user | list the modules I am taking | allow other users to view me as a potential groupmate |
* * |
user who formed a group | update group status for my modules | let other users know I have a group for a module |
* * |
proficient user | filter profiles by module | save time browsing profiles |
* * |
long time user | update the modules I am taking | find new favourites and groupmates for new modules that I am taking |
* |
user searching for groupmates | view potential groupmates’ github | browse their work to decide if we would work well together |
* |
user looking for a specific profile | find a profile by student ID | quickly view their profile |
Use cases
(For all use cases below, the System is the ModuLink
and the Actor is the user
, unless specified otherwise.
Preconditions: User is logged in.)
Use case: UC1 - Create user profile
MSS
- User boots up ModuLink for the first time.
- User enters their details.
-
ModuLink creates a new profile.
Use case ends.
Extensions
-
2a. The given details are invalid.
- 2a1. ModuLink shows an error message.
- 2a2. ModuLink requests for the correct details.
Steps 2a1 - 2a2 are repeated until the correct details are entered.
Use case resumes at step 2.
Use case: UC2 - Add a profile to Favourites list
MSS
- User requests to add a specific profile to their favourites list.
-
ModuLink adds the profile.
Use case ends.
Extensions
-
1a. The requested profile ID is invalid.
- 1a1. ModuLink shows an error message.
- 1a2. ModuLink requests for the correct ID.
Steps 1a1 - 1a2 are repeated until the correct details are entered.
Use case resumes at step 1.
Use case: UC3 - Remove a profile from Favourites list
MSS
- User requests to remove a specific profile from their favourites list.
-
ModuLink removes the profile from their favourites.
Use case ends.
Extensions
-
2a. The requested profile ID is invalid.
- 2a1. ModuLink shows an error message.
- 2a2. ModuLink requests for the correct ID.
Steps 2a1 - 2a2 are repeated until the correct details are entered.
Use case resumes at step 1.
Use case: UC4 - View Favourites list
MSS
- User requests to display all profiles in their favourites list.
-
ModuLink shows a list of all profiles that the user has added to their favourites list.
Use case ends.
Use case: UC5 - Remove a module from the user’s profile
MSS
- User requests to remove a module from their profile.
-
ModuLink removes the module from the profile.
Use case ends.
Extensions
-
1a. The requested Module is invalid.
- 1a1. ModuLink shows an error message.
- 1a2. ModuLink requests for the correct ID.
-
1b. The requested Module is not present in the users current module list.
- 1b1. ModuLink shows an error message.
- 1b2. ModuLink requests for the correct ID.
Use case: UC6 - Add a module to the user’s profile
MSS
- User requests to add a module from their profile.
-
ModuLink adds the module from the profile.
Use case ends.
Extensions
-
1a. The requested Module is invalid.
- 1a1. ModuLink shows an error message.
- 1a2. ModuLink requests for the correct ID.
Use case: UC7 - Update group status for modules
MSS
- User requests to change a tag for a specific module with their updated group status.
- ModuLink deletes the existing tag for the module in the user’s profile.
-
ModuLink adds the new tag for the module in the user’s profile.
Use case ends.
Extensions
-
1a. The requested module does not exist in the user’s profile.
- 1a1. ModuLink shows an error message.
-
1a2. ModuLink asks the user if they would like to add the module to their profile (UC6) .
Use case resumes at step 1.
Use case: UC8 - Filter profiles by mods
MSS
- User requests to find all profiles with a particular tag.
-
ModuLink shows the list of profiles with the requested tag.
Use case ends.
Extensions
-
1a. The requested tag does not exist.
- 1a1. ModuLink shows an error message.
- 1a2. ModuLink requests for the correct tag.
Steps 1a1 - 1a2 are repeated until the correct tag is entered.
Use case resumes at step 1.
Use case: UC9 - Filter profiles by module
MSS
- User requests to find all profiles which have a particular module(s).
-
ModuLink shows the list of profiles with the requested module(s).
Use case ends.
Use case: UC10 - Find a profile by student ID
MSS
- User requests to find a profile with the specified student ID.
-
ModuLink shows the profile with the requested student ID.
Use case ends.
Extensions
-
1a. The requested student ID does not exist as a profile.
-
1a1. ModuLink shows an error message.
Use case ends.
-
Non-Functional Requirements
-
Interoperability: Should work on any mainstream OS as long as it has Java
11
or above installed. - Capacity/Efficiency: Should be able to hold up to 1000 persons without a noticeable sluggishness in performance for typical usage.
- Quality: 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.
- Performance: Should be able to respond to a command within a response time of 2 seconds.
- Quality: A new user should be able to understand and use ModuLink easily with the help of the UserGuide.
Glossary
- Mainstream OS: Windows, Linux, Unix, OS-X
- Module: A NUS CS module listed on NUSmods
- Student: A NUS CS student Profile: A student registered in ModuLink.
- Group status: The group status of a student for a group project in a module
- Command: A command for the program. A full list of command can be seen in the UserGuide.
- Contact detail: Contact details consist of the user names, email, telegram handle.
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.
-
-
Closing the app
- Type “exit” into the Command Line or click the X in the upper right-hand corner.
Expected: The app will close out and a
.json
file will be created in thedata
folder.
- Type “exit” into the Command Line or click the X in the upper right-hand corner.
Expected: The app will close out and a
Saving data
-
Dealing with missing/corrupted data files
- Open up ModuLink and run a few commands.
- Exit out of ModuLink and a
.json
file will appear under thedata
folder. - You can now edit the
.json
file to have invalid data (e.g. having 2 profiles with the same ID, having invalid emails etc.) -
Re-launch the app by double-clicking the jar file.
Expected: ModuLink will now appear with no data. - To fix this, delete the
.json
file and re-launch the app. Expected: ModuLink will work as normal now, with all changes the user previously made reverted.