CodeConnect Developer Guide

Welcome to the CodeConnect Developer Guide!


Acknowledgements

Thank you to the developers of the original addressbook-level3 for creating the brownfield project that served as the basis for CodeConnect!

Code Reused:

  • ChatGPT
    • Generating Regex strings used for parsing and validating user inputs
  • Regex101
    • Building and Testing Regex strings generated by ChatGPT
  • Mokito
    • Used to mock the MailApp for testing purposes.

Getting Started

Before you begin your development journey in CodeConnect, make sure that you meet the minimum requirements needed to run CodeConnect on your development device!

Minimum Requirements

CodeConnect uses Java 11 with JavaFX. If you are not sure how to install Java 11 and JavaFX, refer to this section in our User Guide to install and start CodeConnect.

⚠️ This step is crucial to ensure that you set up the environment correctly before you start developing for CodeConnect!

What’s Next?

Now that you have installed Java 11 and JavaFX, you are all ready to get started on introducing new features or fix bugs in CodeConnect!

  • Want to start introducing new ideas to CodeConnect or contemplating on how to integrate your new features? Refer to the Design section for more information on how CodeConnect was built!

  • Want to know more about our existing features? Refer to the Implementation section to kickstart your understanding of how CodeConnect works!

  • Want to integrate our best practices into your own project? Refer to the Documentation, Logging, Testing, Configuration and DevOps section for more information on how we documented, tested and developed CodeConnect!

  • Want to understand our motivation behind developing CodeConnect? Refer to the Appendix: Requirements section for a clearer picture on how we tailored and scoped CodeConnect for our target audience!


Design

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 (consisting of classes Main and MainApp) is in charge of the app launch and shut down.

  • At app launch, it initializes the other components in the correct sequence, and connects them up with each other.
  • At shut down, it shuts down the other components and invokes cleanup methods where necessary.

The bulk of the app's work is done by the following four components:

  • UI: The UI of the App.
  • Logic: The command executor.
  • Model: Holds the data of the App in memory.
  • Storage: Reads data from, and writes data to, the hard disk.

Commons represents a collection of classes used by multiple other components.

How the 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 API interface mentioned in the previous point.

For example, the Logic component defines its API in the Logic.java interface and implements its functionality using the LogicManager.java class which follows the Logic interface. Other components interact with a given component through its interface rather than the concrete class (reason: to prevent outside component's being coupled to the implementation of a component), as illustrated in the (partial) class diagram below.


 

The sections below give more details of each component.

UI component

The API of this component is specified in Ui.java

Structure of the UI Component

The UI consists of a MainWindow that is made up of parts e.g.CommandBox, ResultDisplay, ContactListPanel, 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 the UI relies on the Logic to execute commands.
  • depends on some classes in the Model component, as it displays Contact object residing in the Model.

Logic component

The API of this component is specified in Logic.java

Here's a (partial) class diagram of the Logic component:

The sequence diagram below illustrates the interactions within the Logic component, taking execute("delete 1") API call as an example.

Interactions Inside the Logic Component for the `delete 1` Command
 
ℹ️ The lifeline for DeleteCommandParser should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline continues till the end of diagram.

How the Logic component works:

  1. When Logic is called upon to execute a command, it is passed to a CodeConnectParser object which in turn creates a parser that matches the command (e.g., DeleteCommandParser) and uses it to parse the command.
  2. This results in a Command object (more precisely, an object of one of its subclasses e.g., DeleteCommand) which is executed by the LogicManager.
  3. The command can communicate with the Model when it is executed (e.g. to delete a contact).
    Note that although this is shown as a single step in the diagram above (for simplicity), in the code it can take several interactions (between the command object and the Model) to achieve.
  4. The result of the command execution is encapsulated as a CommandResult object which is returned back from Logic.

Here are the other classes in Logic (omitted from the class diagram above) that are used for parsing a user command:

How the parsing works:

  • When called upon to parse a user command, the CodeConnectParser class creates an XYZCommandParser (XYZ is a placeholder for the specific command name e.g., AddCommandParser) which uses the other classes shown above to parse the user command and create a XYZCommand object (e.g., AddCommand) which the CodeConnectParser returns back as a Command object.
  • All XYZCommandParser classes (e.g., AddCommandParser, DeleteCommandParser, ...) inherit from the Parser interface so that they can be treated similarly where possible e.g, during testing.

Model component

The API of this component is specified in Model.java

The Model component,

  • stores the address book data i.e., all Contact objects (which are contained in a UniqueContactList object).
  • stores the currently 'selected' Contact objects (e.g., results of a search query) as a separate filtered list which is exposed to outsiders as an unmodifiable ObservableList<Contact> 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 changes.
  • stores a UserPref object that represents the user’s preferences. This is exposed to the outside as a ReadOnlyUserPref 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)
ℹ️ An alternative (arguably, a more OOP) model is given below:
  • It has a Tag list in the CodeConnect, which Contact references. This allows CodeConnect to only require one Tag object per unique tag, instead of each Contact needing their own Tag objects.

Storage component

The API of this component is specified in 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 CodeConnectStorage and UserPrefStorage, 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 the Storage component's job is to save/retrieve objects that belong to the Model)

Common classes

Classes used by multiple components are in the seedu.address.commons package.

Contact Class

The Contact class is a fundamental component of the contact management system within the application. It represents an individual contact entry, encapsulating various details such as name, contact information, address, GitHub username, associated tech stack, tags, and a profile picture.

Take note that while contacts may not always have all valid details, such as a missing profile picture, these null cases should be handled separately within each Attribute's class (in this context, the ProfilePicture class). A contact's attribute should never be left null. This ensures that such invalid cases are always handled in that separate class, keeping the Contact class lean.

Team Class

The Team class is another fundamental component of the contact management system. Teams are created to keep track of groups of contacts, and hold aggregate data about these contacts. These teams are used by the user to keep track of hackathon teams. Multiple teams are kept track by ModelManager.


 
ℹ️ With the use of UniqueTeamList, each contact in a team is guaranteed to be unique. However, each contact may belong in more than one team.

Every time a new contact is added to a team, team aggregate statistics is recalculated and TeamStats is replaced.

ModelManager keeps track of all Contacts and Teams. Only existing contacts can be added to a Team. They are added to a team by passing the reference of an existing contact.


Implementation

This section describes some noteworthy details on how certain features are implemented.

ℹ️ Note from Developers:
  • With many commands having similar underlying implementations, our team has deliberately chosen to reduce the length of this section by focusing on unique implementations of features.
  • This aligns with the purpose of minimising the overhead from writing and maintaining developer documentation.

General Commands

ℹ️ Commands Included:
List, Add, Edit, Find, Find by Tags, Find by Tech Stack, Rate, Delete, Clear, Exit, Help

General commands follow the same flow, with only differences deep within the execute method of each command.

In this section, we will focus on the FindCommand as an example.

The following sequence diagram models the interactions between the different components of CodeConnect for the execution of the Find Command.


 

Details:

  1. The user inputs the command to find contacts containing the word "John".
  2. FindCommandParser parses the user input.
  3. An FindCommand object is created.
  4. The FindCommandParser returns the FindCommand object.
  5. The LogicManager invokes the execute method of FindCommand, which finds the contacts containing the word "John" and returns these contacts.

Team Commands

Team commands follow either one of the two sequences stated below, depending on the command type. Within each flow, the only differences lie in the execute method of each command.

Sequence 1

ℹ️ Commands Included:
Team - Add, Team - Add Contact, Team - Delete Contact

In this section, we will focus on the AddTeamCommand as an example.

The following sequence diagram models the interactions between the different components of CodeConnect for the execution of the AddTeamCommand.


 

Details:

  1. The user inputs the command to add a team called "NUS HACKERS".
  2. TeamCommandParser and AddTeamCommandParser parses the user input.
  3. An AddTeamCommand object is created.
  4. The TeamCommandParser and AddTeamCommandCommandParser return the AddTeamCommand object.
  5. The LogicManager invokes the execute method of AddTeamCommand, which creates a new team called "NUS HACKERS".

Sequence 2

ℹ️ Commands Included:
Team - List, Team - Delete, Team - Export

In this section, we will focus on the ExportTeamCommand as an example.

The following sequence diagram models the interactions between the different components of CodeConnect for the execution of the ExportTeamCommand.


 

Details:

  1. The user inputs the command to copy the details of a team specified at index 1.
  2. TeamCommandParser parses the user input.
  3. An ExportTeamCommand object is created.
  4. The TeamCommandParser return the ExportTeamCommand object.
  5. The LogicManager invokes the execute method of ExportTeamCommand, which copies the details of the team members of the team specified at index 1.

Command History

This feature saves previously entered commands so that the user can easily view them again.

The following sequence diagram shows what happens as the user requests to view the command history, and what happens after the command is executed:

Sequence Diagram for Command History

Details:

  1. User focuses the command input.
  2. User presses the Up Arrow Key to view the previous command in history, or Down Arrow Key to view the next.
  3. updateCommandInput() saves the currently edited command to the command buffer.
  4. next()/previous() in CommandHistoryView is called and if a next/previous command exists, the command text field is updated.

Possible Improvements

  • The history size could be made to be configurable by the user.
  • The history could be saved to disk so that it persists between app launches.

Send Email Directly

This feature enables the user to simply click on a contact's email address to send him/her an email.

The following sequence diagram shows what happens as the user double-clicks on the email address:

Sequence Diagram for sending an email

Details:

  1. The user clicks on the email address of a contact in the contact list.
  2. The handleEmailClicked() method of the MailApp class is invoked.
  3. The MailApp class checks if the associated contact object and its email address are not null.
  4. If the email address is valid, the openDefaultMailApp() method is called with the email address as a parameter.
  5. The openDefaultMailApp() method attempts to open the default mail application with a new email composition window addressed to the recipient's email address.

Possible Improvements

  • There can be a feature where multiple emails can be selected to send a mass email to them.
  • There can be a check that ensures a valid email address has been input, following the correct format of what is expected of an email address.

Documentation, logging, testing, configuration, dev-ops


Appendix: Requirements

Product scope

Target user profile:

  • Student developers
  • hopes to connect and collaborate with other student developers
  • 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

Value proposition:

  • keep track of other student developers
  • reach out easily to those with relevant skills for collaboration opportunities when forming hackathon teams.

User stories

Priorities: High (must have) - * * *, Medium (nice to have) - * *, Low (unlikely to have) - *

Priority As a …​ I want to …​ So that I can…​
* * * Student save the contacts of student developers remember them
* * * Student see the contacts of student developers reach out to them
* * * Student delete the contacts of student developers remove entries that I no longer need
* * * Student search for the contacts of student developers locate details of contacts without having to go through the entire list
* * * Student update the details of contacts that I already have in my address book keep my contact details up to date
* * Student search for contacts by tags locate a category of student developers easily
* * Student categorise the contacts I have saved into the projects I am working on have an organised address book
* * Forgetful Student add profile pictures for each contact know who I am contacting
* * * Student search for contacts based on their technical skills form teams for hackathons more easily
* * Student rate technical skills of my contacts get apt members for my hackathon team
* Student view my most used commands while typing save time typing out the full command
* * * Student create teams of contacts keep track of my teammates when participating in hackathons
* * * Student add contacts to a team can update my team as it changes
* Student signing up for a hackathon export the contact details of my team easily sign up for events
* Student place reminders for meetings with my contacts keep track of them
* * New user import existing contacts into this application reuse contacts that I have saved previously
* * * Student add notes to different contacts remember specific details
* * Student integrate my contacts with calendar events schedule meetings directly from the application
* Student tag contacts based on their time zone take note of different time zones when scheduling meetings
* * * Student link GitHub profiles or personal portfolio websites to contacts easily access their projects and contributions
* Student be given smart suggestions for potential contacts based on my current network and interests find new like-minded student developers
* Student integrate messaging apps to initiate conversations directly from the application interact with new contacts that I have made
* New user have a tutorial feature that shows me how to use the app
* * Student attending conferences or events quickly exchange contact information with fellow attendees through QR codes quickly add new contacts
* * Team Lead have access to integrated online learning platforms to track the courses or certificates completed by my contacts understand their evolving skills
* * * Student endorse or rate the skills of my contacts keep track of their expertise and choose the right team members

Use cases

(For all use cases below, the System is the CodeConnect and the Actor is the user, unless specified otherwise)

Use case: UC01 - Delete a contact

MSS

  1. User requests to delete a specific contact in his list of contacts.
  2. CodeConnect deletes the contact.
    Use case ends.

Extensions

  • 1a. The list is empty.

    • 1a1. CodeConnect shows an error message.
      Use case ends.
  • 1b. The given index does not exist in CodeConnect.

    • 1b1. CodeConnect shows an error message.
      Use case ends.

Use case: UC02 - Add a contact

MSS

  1. User requests to add a Student’s contact information into his list of contacts.
  2. CodeConnect saves the new contact and displays it at the top of the contact list.
    Use case ends.

Extensions

  • 1a. The contact already exists in the system.

    • 1a1. CodeConnect shows an error message.
      Use case ends.
  • 1b. No fields are entered.

    • 1b1. CodeConnect shows an error message.
      Use case ends.

Use case: UC03 - Update a contact

MSS

  1. User requests to update a Student’s contact information into his list of contacts.
  2. CodeConnect updates the contact.
    Use case ends.

Extensions

  • 1a. The given index to identify contact is invalid.

    • 1a1. CodeConnect shows an error message.
      Use case ends.
  • 1b. No fields are entered.

    • 1b1. CodeConnect shows an error message.
      Use case ends.
  • 1c. Updated value does not follow format of the specific field.

    • 1b1. CodeConnect shows an error message.
      Use case ends.
  • 1d. Updated contact matches another existing contact

    • 1b1. CodeConnect shows an error message.
      Use case ends.

Use case: UC04 - View all contacts

MSS

  1. User requests to view all his contacts.
  2. CodeConnect displays all contacts.
    Use case ends.

Use case: UC05 - Search a contact by name

MSS

  1. User requests to look up contacts with a specific substring in their name.
  2. CodeConnect checks each contact’s name in the list that contains the substring.
  3. CodeConnect shows a list of contacts that match the criteria.
    Use case ends.

Extensions

  • 1a. No substring is given.

    • 1a1. CodeConnect shows an error message.
      Use case ends.
  • 1b. There are no contacts in the list that match the criteria.

    • 1b1. CodeConnect shows an empty list.
      Use case ends.

Use case: UC06 - Search a contact by tags

MSS

  1. User requests to look up contacts with specific tags.
  2. CodeConnect checks each contact’s tags in the list.
  3. CodeConnect shows a list of contacts that match the criteria.
    Use case ends.

Extensions

  • 1a. No tag is given.

    • 1a1. CodeConnect shows an error message.
      Use case ends.
  • 1b. There are no contacts in the list that match the criteria.

    • 1b1. CodeConnect shows an empty list.
      Use case ends.

Use case: UC07 - Search a contact by tech stack

MSS

  1. User requests to look up contacts with specific tech stack.
  2. CodeConnect checks each contact’s tech stack in the list.
  3. CodeConnect shows a list of contacts that match the criteria.
    Use case ends.

Extensions

  • 1a. No tech stack is given.

    • 1a1. CodeConnect shows an error message.
      Use case ends.
  • 1b. There are no contacts in the list that match the criteria.

    • 1b1. CodeConnect shows an empty list.
      Use case ends.

Use case: UC08 - Rate a tech stack of a contact

MSS

  1. User requests to rate specific tech stack of specific contact.
  2. CodeConnect checks specified tech stack in specified contact’s tech stack.
  3. CodeConnect rates specified tech stack of specified contact with rating.
    Use case ends.

Extensions

  • 1a. No tech stack is given.

    • 1a1. CodeConnect shows an error message.
      Use case ends.
  • 1b. No rating is given.

    • 1b1. CodeConnect shows an error message.
      Use case ends.
  • 1c. No index is given.

    • 1c1. CodeConnect shows an error message.
      Use case ends.
  • 1d. The specified contact does not have specified tech stack.

    • 1d1. CodeConnect shows an error message.
      Use case ends.

Use case: UC09 - Sending an email to a specific contact

MSS

  1. User clicks on the email address of a specific contact.
  2. CodeConnect detects the user action and retrieves the email address associated with the clicked contact.
  3. CodeConnect opens the default desktop mail application.
  4. CodeConnect populates the recipient field of the mail application with the retrieved email address.
    Use case ends.

Extensions

  • 1a. The default desktop mail application is not available on the system.
    • 1a1. CodeConnect displays an error message indicating that the desktop mail application is not supported.
      Use case ends.

Use case: UC10 - Viewing command history

MSS

  1. User selects command input.
  2. User requests to view previous or next command in history.
  3. CodeConnect retrieves the command from the command history.
  4. CodeConnect updates the contents of the command input. Use case ends.

Extensions

  • 3a. CodeConnect does not find any previous/next command in the command history.
    Use case ends.

Use case: UC11 - Export team members' details

MSS

  1. User requests to export the details of team members of a specific team.
  2. CodeConnect retrieves the details of the team members.
  3. CodeConnect copies the teams' details to the clipboard.
    Use case ends.

Extensions

  • 2a. An invalid index is passed into the command.

    • 2a1. CodeConnect shows an error message.
      Use case ends.
  • 2b. CodeConnect does not find any team members in the team.

    • 2b1. CodeConnect shows an error message.
      Use case ends.

Use case: UC12 - Adding a team

MSS

  1. User requests to add a team.
  2. CodeConnect adds the team and displays it in the team list.
    Use case ends.

Extensions

  • 1a. No name is provided.

    • 1a1. CodeConnect shows an error message.
      Use case ends.
  • 2a. Another team with the same name already exists in CodeConnect.

    • 2a1. CodeConnect shows an error message.
      Use case ends.

Use case: UC13 - Delete a team

MSS

  1. User requests to delete a specific team.
  2. CodeConnect deletes the team.
    Use case ends.

Extensions

  • 1a. The given index does not exist in CodeConnect.
    • 1a1. CodeConnect shows an error message.
      Use case ends.

Use case: UC14 - List a team's members

MSS

  1. User requests to list a specific team's members.
  2. CodeConnect shows the members of the team.
    Use case ends.

Extensions

  • 1a. The given index does not exist in CodeConnect.
    • 1a1. CodeConnect shows an error message.
      Use case ends.

Use case: UC15 - Add a contact to a team

MSS

  1. User requests to add a contact from the contact list to a team.
  2. CodeConnect saves the new contact and displays it in the team list. Use case ends.

Extensions

  • 1a. The given contact index does not exist in CodeConnect.

    • 1a1. CodeConnect shows an error message. Use case ends.
  • 1b. The given team index does not exist in CodeConnect.

    • 1b1. CodeConnect shows an error message. Use case ends.

Use case: UC16 - Delete a contact from a team

MSS

  1. User requests to delete a contact from a team.
  2. CodeConnect removes the contact from the team. Use case ends.

Extensions

  • 1a. The given contact index does not exist in CodeConnect.

    • 1a1. CodeConnect shows an error message. Use case ends.
  • 1b. The given team index does not exist in CodeConnect.

    • 1b1. CodeConnect shows an error message. Use case ends.

{More to be added}

Non-Functional Requirements

  • Should work on any mainstream OS as long as it has Java 11 or above installed.
  • Should be portable, and be able to run without any installation process.
  • This program should only be used by a single user.
  • 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 be able to hold up to 1000 contacts without a noticeable sluggishness in performance for typical usage.
  • Should be able to respond within 2 seconds of user input.
  • Should be able to launch and load its saved data below 10 seconds.
  • Should be able to run basic commands (add, list, update, delete) without a network connection.
  • Any stored data should be in a human-readable format.
  • Must support a minimum window size of 800x600.

Glossary

  • Mainstream OS: Windows, Linux, MacOS
  • Argument: A word or number or a sequence of words or numbers that represent.
  • CLI: A Command Line Interface is a text-based interface where users can interact with the software by typing commands.
  • Command: A sequence of words that represents an action that CodeConnect can understand and execute.
  • GUI: A Graphical User Interface is a visual interface where users can interact with the software through on-screen elements like buttons and windows.
  • JAR: A file that contains all the resources needed for CodeConnect to run.
  • Java: A general-purpose programming language on which CodeConnect is built on.
  • Contact: An entry that holds information about someone that the user wants to save.
  • Private contact detail: A contact detail that is not meant to be shared with others
  • Details of contact:
    • Name: The name of the contact (String).
    • GitHub username: The username associated with the contact's GitHub account (String).
    • Tags: Descriptive keywords or labels associated with the contact (List).
    • Phone number: The phone number of the contact (String).
    • Address: The physical or mailing address of the contact (String).
    • Email: The email address of the contact (String).
    • Profile Picture: The image associated with the contact (Image).
    • Tech stack: The technologies or programming languages known or used by the contact (List).
    • Rating: The rating given to the contact's specific tech stack (Integer).

Appendix: Planned Enhancements

Team size: 5

1. Automatically update team in contacts list when delete-contact is run

When the members of a team are shown in the contacts list, deleting a member of that team does not update the contact list.

A known workaround is to run the command to list the members of the team again, which will show the updated members of the team.

In the future, the delete-contact command should be enhanced to detect if the contact list is showing the current members of the team, and automatically update the contact list to show the updated team if necessary.

2. Support special characters in names for contacts and teams

Currently, CodeConnect does not allow for special characters to be used in names. For example, s/o cannot be used in names even though it would be a valid name because it contains the special character /. Other examples include . in Harry S. Truman, or - in T-Pain.

In the future, we plan to expand the restrictions on names to also include special characters such as /, . and -.

The parser in CodeConnect already should be able to parse most special characters without issue, except for /, since it is used to separate prefixes from their values. To solve this problem, we could either use another character instead of / for the prefixes, or use a delimiter to mark the start and end of names so that the parser can ignore any occurrences of special characters in them.

3. Allow different contacts to have the same name

Currently, CodeConnect does not allow for contacts to share the same names. However, different people can have the same names. Since GitHub usernames already need to be unique, we can use them to prevent duplicate contacts from being added into CodeConnect, instead of requiring both names and GitHub usernames to unique.

4. Detect when tags with same name but in different case are entered

Currently, CodeConnect does not check if tags with the same name but with different capitalisation exist. For example, t/friend and t/Friend can both be added to a contact, which should not be allowed.

In these situations, CodeConnect should treat these two tags as identical. For example, adding t/friend and t/Friend to a contact should display an error saying that identical tags cannot be added to a contact.

To achieve this, the Tag::equals method can be modified to use String::equalsIgnoreCase instead of String::equals to compare tags. When displaying tags, they should all be displayed either in upper or lower case, to show to the user that tags are treated with case-insensitivity.

5. Detect when tech stacks with same name but in different case are entered

Currently, CodeConnect does not check if tech stacks with the same name but with different capitalisation exist. For example, ts/C and ts/c can both be added to a contact, which should not be allowed.

In these situations, CodeConnect should treat these two tech stacks as identical. For example, adding ts/C and ts/c to a contact should display an error saying that identical tech stacks cannot be added to a contact.

To achieve this, the TechStack::equals method can be modified to use String::equalsIgnoreCase instead of String::equals to compare tech stacks. We can also consider saving tech stacks in upper case, which shows a consistent style and prevents the problem of one contact having ts/Javascript but another contact having ts/JaVaScRipT. Instead, both contacts would show that they have ts/JAVASCRIPT.

6. More specific error messages when parsing INDEX

For commands such as edit, delete, and rate, inputting an invalid INDEX gives a generic error message, which is unhelpful for the user. For example, delete 0 returns Invalid command format!.

The command parsers for all commands that take in INDEX as an argument should be enhanced to detect when an invalid input has been given, and output a more specific error message such as INDEX should be a positive non-zero integer and not greater than the index of the last contact in the list.

7. Phone number validation

The current implementation allows a user to add/edit phone numbers with lengths greater than 15 digits. Additionally, there's ambiguity regarding the format of phone numbers, especially for Singaporean and International contexts.

Since CodeConnect is an application that can be used by anyone around the world, we will ensure that the number of digits a phone number can contain is between 3 and 15. This gives the user the flexibility to add contacts from anywhere across the world, which presents especially useful when he/she would like to invite the recipient to join an online hackathon.

8. Inconsistent rate command errors

The current implementation allows a user to input an Integer rating only, not a Double or a Long etc. Hence, the error messages for the different numbers vary. When the user inputs large numbers, such as 100000000 (an Integer) and 10000000000 (a Long), error messages, Rating should be between 0 and 10. and Invalid command format! are displayed respectively.

We intend to enhance the rate feature by separating the error handling for ParseException and NumberException into two with respective error messages.

9. Prevent adding and editing contacts with duplicate email addresses and phone numbers

Our current implementation supports users to add and edit contacts with email addresses and phone numbers that already exist in the contact list. However, we understand that this is not applicable in the real life scenario, as every email address and phone number has to be unique.

We intend to enhance the add and edit features by implementing a check within the contact list. This check will verify whether the email address and phone number intended for addition or modification already exists within the contact list.


Appendix: Instructions for manual testing

Given below are instructions to test the app manually.

ℹ️ Note:
These instructions only provide a starting point for testers to work on; testers are expected to do more *exploratory* testing.

Launch and shutdown

  1. Initial launch

    1. Download the jar file and copy into an empty folder

    2. Double-click the jar file Expected: Shows the GUI with a set of sample contacts. The window size may not be optimum.

  2. Saving window preferences

    1. Resize the window to an optimum size. Move the window to a different location. Close the window.

    2. Re-launch the app by double-clicking the jar file.
      Expected: The most recent window size and location is retained.

Adding a contact

  1. Adding a contact to empty list

    • Prerequisites: Clear the contact list using the clear command.

    • Test case: add n/John Doe p/98765432 e/johnd@example.com a/John street, block 123, #01-01 g/johnDoee ts/Java
      Expected: Contact is added to the contact list with correct details. Details of added contact shown in status message.

  2. Adding contact to non-empty list

    • Prerequisites: List all contacts using the list command. Contact list must be non-empty.

    • Test case: add n/Betsy Crowe t/friend e/betsycrowe@example.com a/Newgate Prison p/1234567 g/betBetty t/criminal ts/Flutter
      Expected: Contact is added to the end of the contact list with correct details. Details of added contact shown in status message.

  3. Adding invalid contact to empty list

    • Prerequisites: Clear the contact list using the clear command.

    • Test case: add n/John Doe
      Expected: Contact is not added to the contact list. Error message shown in status message.

  4. Adding invalid contact to non-empty list

    • Prerequisites: List all contacts using the list command. Contact list must be non-empty.

    • Test case: add n/Betsy Crowe
      Expected: Contact is not added to the contact list. Error message shown in status message.

Deleting a contact

  1. Deleting a contact while all contacts are being shown

    • Prerequisites: List all contacts using the list command. Multiple contacts in the list.

    • Test case: delete 1
      Expected: First contact is deleted from the list. Details of the deleted contact shown in the status message.

    • Test case: delete 0
      Expected: No contact is deleted. Error details shown in the status message. Contact list remains the same.

    • Other incorrect delete commands to try: delete, delete -1, delete x, (where x is larger than the list size)
      Expected: Similar to previous.

  2. Deleting a contact when list is empty

    • Prerequisites: No contacts shown in filtered list. Use find command e.g. find someonethatdoesntexist to show empty contact list.

    • Test case: delete 1
      Expected: No contact is deleted. Error details shown in the status message. Contact list remains the same.

Editing a contact

  1. Editing a contact while all contacts are being shown

    • Prerequisites: List all contacts using the list command. Multiple contacts in the list.

    • Test case: edit 1 ts/C ts/Java
      Expected: First contact's tech stacks are updated to contain C and Java. Details of edited contact shown in status message.

    • Test case: edit 0 ts/C ts/Java
      Expected: No contact is edited. Error details shown in the status message. Contact list remains the same.

    • Other incorrect edit commands to try: edit, edit 0, edit 1 invalid/field
      Expected: Similar to previous.

  2. Edited contact matches another existing contact in CodeConnect.

    • Prerequisites: List all contacts using the list command. Multiple contacts in the list.

    • Test case: edit 2 n/SAME_NAME (where SAME_NAME is the name of the first contact)
      Expected: No contact is edited. Error details shown in the status message. Contact list remains the same.

Finding a contact by name

  1. Searching for a contact with a single keyword

    • Prerequisites: List all contacts using the list command. Multiple contacts in the list. In the following test cases, we assume we have contacts named Alex, Bernice, David, and John.

    • Test case: find John
      Expected: The search should return contacts matching the keyword John. The search is case-insenstive and matches only the name.

    • Test case: find XYZ
      Expected: The search should return no contacts since there are no matches for the keyword XYZ.

    • Test case: find BERNICE
      Expected: The search should return contacts matching the keyword BERNICE in a case-insensitive manner. It should match contacts with names like Bernice, bernice, BERNICE, etc.

    • Test case: find Dav Expected: The search should return no contacts because the search only matches full keywords. Partial matches like Dav won't match David.

  2. Searching for contacts with multiple keywords

    • Prerequisites: List all contacts using the list command. Multiple contacts in the list.

    • Test case: find alex david
      Expected: The search should return contacts matching either of the keywords alex or david. The order of the keywords do not matter, and partial matches will not be considered.

Finding a contact by tag

  1. Finding a contact by tag while all contacts are shown

    • Prerequisites: List all contacts using the list command. Multiple contacts in the list. In the following test cases, we assume we have contacts containing only the tag friend.

    • Test case: find-tags friend
      Expected: All contacts with tag friend are shown in list. The search is case-insenstive and matches only the tag.

    • Test case: find-tags doesnotexist
      Expected: No contacts are shown in list.

    • Other incorrect find tags command to try: find-tags, find-tags
      Expected: No contact is found. Error details shown in the status message.

Finding a contact by tech stack

  1. Finding a contact by tech stack while all contacts are shown

    • Prerequisites: List all contacts using the list command. Multiple contacts in the list. In the following test cases, we assume we have contacts containing only the tech stack Java.

    • Test case: find-ts Java
      Expected: All contacts with tech stack Java are shown in list. The search is case-insenstive and matches only the tech stack.

    • Test case: find-ts doesnotexist
      Expected: No contacts are shown in list.

    • Other incorrect find tech stack command to try: find-ts, find-ts
      Expected: No contact is found. Error details shown in the status message.

Rating a contact's tech stack

  1. Rating a contact's tech stack while all contacts are shown

    • Prerequisites: List all contacts using the list command. Multiple contacts in the list.

    • Test case: rate 1 ts/Java r/8
      Expected: Tech stack Java of contact at index 1 is rated with a rating 8.

    • Test case: rate 0 ts/Java r/8
      Expected: Given tech stack of given contact is not rated. Error details shown in the status message.

    • Other incorrect rate tech stack command to try: rate -1 ts/Java r/8, rate 1 ts/Java r/18, rate 1 ts/Java r/-8
      Expected: Given tech stack of given contact is not rated. Error details shown in the status message.

  2. Rating a contact's tech stack when contact list is empty

    • Prerequisites: No contacts shown in filtered list. Use find command e.g. find someonethatdoesntexist to get empty list showing.

    • Test case: rate 1 ts/Java r/8
      Expected: Given tech stack of given contact is not rated. Error details shown in the status message.

Adding a team

  1. Adding a team

    • Prerequisites: Added team should not already exist in CodeConnect.

    • Test case: team add n/NUS HACK 2024
      Expected: Team is added to the team list. Details of team shown in status message.

  2. Adding an invalid team

    • Prerequisites: Should be run after test case Adding a team. Team NUS HACK 2024 should exist in the team list.

    • Test case: team add n/NUS HACK 2024
      Expected: No team is added. Error details shown in the status message. Team list remains the same.

    • Other incorrect commands to try: team add, team add NUS.
      Expected: Similar to previous.

Adding members to a team

  1. Adding a contact to a team

    • Prerequisites: Ensure there are several contacts and teams in the list. A contact that needs to be added to a team should not already be a member of that team.

    • Test case: team 1 add-contact 1
      Expected: The contact at index 1 of the contact list should be added to the first team in the team list. After executing the command, verify that the contact is added to the team by entering team 1.

    • Test case: team 0 add-contact 1
      Expected: This command will return an error message indicating that the index is not a non-zero unsigned integer. The contact will not be added to the team.

    • Test case: team add-contact 1
      Expected: This command will return an error message indicating that the team index provided is invalid as it does not exist.

  2. Adding a contact that is already in the team

    • Prerequisites: View the members of the team with the team INDEX command. Ensure that the contact already exists in the team. We assume contact 2 already exists in team 2 for the test case below.

    • Test case: team 2 add-contact 2 Expected: A message indicating that the contact already exists in the team is displayed.

Listing members of a team

  1. List members of a team

    • Prerequisites: Team list contains one or more teams. First team in list should have > 0 members.

    • Test case: team 1
      Expected: Contact list shows the members of the team. Team name correctly shown in status message.

    • Test case: team 0
      Expected: Contact list does not change. Error details shown in the status message.

    • Test case: team X (where X is greater than the last team's index)
      Expected: Similar to previous.

Removing members from a team

  1. Deleting a contact from a team

    • Prerequisites: Enter the command team INDEX to ensure that there are serveral contacts in a team. A contact that needs to be deleted should already be a member of that team.

    • Test Case: team 1 delete-contact 1
      Expected: The contact at index 1 of the team's member list should be deleted from the first team in the team list. After executing the command, enter team 1 to ensure that the contact has been removed from the team.

    • Test case: team 0 delete-contact 1
      Expected: This command will return an error message indicating that the index is not a non-zero unsigned integer. The contact will not be deleted from the team.

    • Other incorrect commands to try: team 1 delete-contact 0.

    • Test case: team X delete-contact 1 (where X is greater than the last team's index)
      Expected: This command will return an error message indicating that the team index provided is invalid as it does not exist.

    • Similar incorrect commands to try: team 1 delete-contact 0, team 1 delete-contact X, (where X is greater than the last team's index)
      Expected: Similar to previous.

Exporting team details

  1. Exporting team details

    • Prerequisites: Team list contains one or more teams. First team in list should have > 0 members.

    • Test Case: team 1 export
      Expected Outcome: All team details are exported successfully to clipboard

Deleting a team

  1. Deleting a team

    • Prerequisites: Team list contains one or more teams.

    • Test case: team 1 delete
      Expected: Team is deleted from the team list. Contact list does not change. Status message shows team name and its members.

    • Test case: team 0 delete
      Expected: Team list does not change. Contact list does not change. Error details shown in the status message.

    • Test case: team X delete (where X is greater than the last team's index)
      Expected: Similar to previous.

Corrupted or Missing Data files

  1. Dealing with missing/corrupted data files

    • Prerequisites: Add a contact. Access addressbook.json and remove the name field from a address book. This simulates corrupt data. Restart the program to run into error.

    • Test Case: Delete addressbook.json and restart the app. Expected Outcome: A new addressbook.json is created.


Appendix: Effort

Difficulty Level and Challenges Faced

Throughout the development of our project, we encountered several significant challenges that tested our problem-solving skills and collaboration abilities.

One of the foremost hurdles we faced was gaining a comprehensive understanding of the underlying implementation of AddressBook Level 3. As we inherited the codebase from a previous developer, we needed considerable time to unravel the complexities within AddressBook. We meticulously dissected each component, deciphering its role in the application, and strategised on how to extend, modify, or replace existing features to tailor it for our CodeConnect application.

Another major challenge arose during the refactoring process of the pre-existing codebase. The codebase exhibited multiple layers of nesting, making it extremely difficult to refactor classes and methods. This extended into the test cases as well - making changes to one class meant that many of the original tests would have to be refactored to accommodate to modifications. Despite leveraging IntelliJ IDE’s intelligent refactoring features, we encountered difficulties in properly detecting and renaming some classes and methods. This led to instances of broken code, necessitating extensive debugging and testing efforts to rectify.

Additionally, we encountered learning curves as we navigated working together as a cohesive team utilising a Version Control System (GitHub). Merge conflicts were a recurring obstacle, resulting in inadvertent overwrites of previously implemented code. The culmination of these challenges peaked during the integration phase for V1.3, where merging our individually assigned features into the team repository's master branch demanded meticulous coordination and communication.

Despite these formidable challenges, our team persevered with determination and resourcefulness. Each hurdle became an opportunity for growth, reinforcing our collaboration skills, technical acumen, and adaptability in the face of complexity. Through tenacity and a shared commitment to excellence, we successfully navigated these challenges, emerging stronger and more capable as a unified team.

Effort Required

Developing CodeConnect demanded a significant allocation of effort from each team member. In addition to our regular weekly meetings, every developer was tasked with traversing through the meticulous stages of analysis, design, development, testing, and documentation for every new feature integrated into the application.

Given that we inherited a brownfield project, a considerable amount of time and resources were dedicated to understanding the intricate architecture of AB3. Ensuring compatibility and stability remained at the forefront of our efforts, prompting numerous brainstorming sessions and thorough evaluations of how each new feature would seamlessly integrate.

Furthermore, as not all team members were well-versed in utilising a Version Control System (VCS) within a collaborative setting, considerable effort was expended. Guided by the more experienced members of our team, these individuals diligently worked towards acquiring the necessary proficiency with the VCS. This learning curve should be acknowledged, as mastering a VCS is a substantial step for future software professionals and bears significant importance.

Achievements of Project

  1. Redesigning existing commands for better intuitiveness and fit for our target audience - student developers.
  2. Expanded existing search functionalities, empowering users to more efficiently navigate through their contacts.
  3. Seamless integration of contacts and teams, enabling users to manage both contacts and hackathon teams.
  4. Improved GUI of existing application to accommodate the new teams feature, enabling users to flawlessly transition between team members and contacts in the address book.

Effort Saved Through Reuse

Approximately 10% of our project's effort was conserved through the judicious reuse of existing components and libraries, particularly in the realm of commands and parsers. Leveraging the established practices of previous developers when modifying the application provided us with a valuable foundation, expediting the implementation of new functionalities.