Overview
Cow is a group project task manager aimed at students. Its main features include individual task management, and project groupmate management and task assignment. It is a desktop application with a command line interface, which is also further enhanced by a graphical user interface created with JavaFX.
Cow was developed in 2018 by a team of 5 undergraduate students as part of a software engineering module. This personal project portfolio documents my contributions to Cow. Cow is written in Java, and has about 15 kLoC.
Summary of contributions
-
Major enhancement: added the ability to assign and unassign tasks to groupmates.
-
What it does: allows the user to assign a task to a contact and vice versa, and unassign them from each other.
-
Justification: This is a key feature for students who manage group projects, as they need to keep track of everyone’s tasks and ensure that their projects will be completed on time.
-
Highlights: This enhancement required the implementation of a many-to-many relationship without a relational database. This was challenging as it required changes to some core components of the app, and thus resulted in many code changes throughout the codebase.
-
-
Minor enhancement: added unique identifiers to contacts and tasks so that Cow is able to identify tasks and contacts between edits, and also to differentiate between nearly-identical tasks and people.
-
Code contributed: [Collated code at RepoSense]
-
Other contributions:
-
Project management:
-
Managed releases
v1.1
andv1.2
(2 releases) on GitHub -
Created milestones on GitHub
-
Created PR review duty roster
-
-
Documentation:
-
Participated in the renaming effort of the app: #8
-
-
Community:
-
Tools:
-
Set up the team repository.
-
Set up Travis CI integration.
-
-
Contributions to the User Guide
Given below are sections I contributed to the User Guide. They showcase my ability to write documentation targeting end-users. |
Assign tasks to contact: contacts assign
Assigns a task to a specified person in Cow.
Format: contacts assign c/CONTACT_INDEX k/TASK_INDEX
Examples:
-
contacts list
tasks list
contacts assign c/2 k/1
Assigns the 2nd person in Cow to the 1st task in Cow -
contacts find Alex
tasks list
contacts assign c/1 k/3
Assigns the 1st person in the list of people resulting from thecontacts find
command to the 3rd task in Cow
Unassign tasks from contact: contacts unassign
Unassigns a task from a specified person in Cow.
Format: contacts unassign c/CONTACT_INDEX k/TASK_INDEX
Assign person to task: tasks assign
Assigns a person to a specified task in Cow.
Format: tasks assign k/TASK_INDEX c/CONTACT_INDEX
Examples:
-
contacts list
tasks list
tasks assign k/1 c/2
Assigns the 1st task in Cow to the 2nd person in Cow -
contacts list
tasks find n/Cows
contacts assign k/3 c/1
Assigns the 3rd task in the list of tasks resulting from thetasks find
command to the first person in Cow
Unassign person from tasks: tasks unassign
Unassigns a person from a specified task in Cow.
Format: tasks unassign k/TASK_INDEX c/CONTACT_INDEX
Contributions to the Developer Guide
Given below are sections I contributed to the Developer Guide. They showcase my ability to write technical documentation and the technical depth of my contributions to the project. |
Assigning and unassigning tasks and contacts
Current implementation
Tasks and contacts can be assigned to each other using the commands tasks assign
and contacts assign
, and unassigned by the tasks unassign
and contacts unassign
commands.
This many-to-many relationship is stored as a list of task IDs and person IDs in the Person and Task classes respectively. The IDs are UUIDs, chosen because they are guaranteed to be globally unique and are not dependent on the IDs of other tasks and persons. The IDs are generated randomly by the Person and Task classes if they are not provided to their respective constructors.
The commands are parsed by AssignCommandParser
and UnassignCommandParser
, which are used by both TasksParser
and ContactsParser
. Both parsers will execute their respective AssignCommand
and UnassignCommand
. If both the specified task and contact are found, the task and person IDs will be added to Person.taskIds
and Task.personIds
respectively, and the edited objects will be saved to disk. As happens when the edit commands are run, indicateAddressBookChanged()
is called to update the UI. The data flow is similar to the one for EditCommand
in the previous section.
The figure below is a sequence diagram that illustrates what happens when the user assigns a contact to a task. The process for assigning tasks to contacts and the unassign process are both very similar to this.
These diagrams are generated using PlantUML. The files used to generate the image files can be found in docs/diagrams/plantuml .
|
Error handling
AssignCommand
will also throw errors if a user tries to assign a task to a contact when the contact has already been assigned. Although this is not strictly necessary as the IDs are stored in sets and it would have been impossible to assign someone twice, the error message assures the user that no double assignments will be made, and thus improves the user experience. Similarly, UnassignCommand
throws errors if the user attempts to unassign a contact from a task when the contact is not assigned to it.
Alternative implementations considered
An alternative implementation that was considered was to model the many-to-many relationship using an Assignment
class, which will act like a join table in relational databases. This would have slightly decoupled the Person
and Task
classes. However, we chose not to implement it this way as a Person
will always be assigned to a Task
, and also because implementing such a relationship with manually managed IDs is extremely complex without a relational database to abstract away the complexity.
Future Enhancements
Both AssignCommand
and UnassignCommand
have nearly identical implementations for both tasks and contacts. This is intentional, as this leaves room for the implementation of task or contact specific features. An example of such a possibility is an unassign all feature, e.g. contacts unassign c/3
, which will be able to unassign contact 3 from all his tasks.
Assign people to a task
MSS
-
User requests to list people.
-
Cow shows a list of people.
-
User requests to list tasks.
-
Cow shows a list of tasks.
-
User requests to assign a person to a task.
-
Cow assigns the person to the task.
Use case ends
Extensions
-
2a. The list is empty.
Use case ends.
-
4a. The list is empty.
Use case ends.
-
5a. User provides an invalid person or task index.
-
5a1. Cow shows an error message.
Use case ends.
-
-
5b. User requests to assign a person already assigned to the task.
-
5b1. Cow shows a message telling the user the person is already assigned.
Use case ends.
-
Unassign person from a task
MSS
-
User searches for a contact.
-
Cow displays the contact.
-
User requests to view tasks assigned to the contact.
-
Cow displays a list of tasks assigned to the contact.
-
User requests to unassign a contact from a task.
-
Cow unassigns the contact from the task.
Use case ends
Extensions
-
2a. The list is empty.
Use case ends.
-
4a. The list is empty.
Use case ends.
-
5a. User provides an invalid person or task index.
-
5a1. Cow shows an error message.
Use case ends.
-
-
5b. User requests to unassign a person that is not assigned to the task.
-
5b1. Cow shows a message telling the user the person is not assigned.
Use case ends.
-
Assigning a Task to a Contact
-
Assigning a task to a contact and vice versa while some or all tasks and contacts are listed.
-
Prerequisites: List tasks using the
tasks list
ortasks find
commands, and list contacts using thecontacts list
orcontacts find
commands. There must be at least 1 task and 2 contacts on screen. -
Test case:
tasks assign c/1 k/1
Expected: First task is assigned to the first contact. Details of the assignment are shown in the status message. Timestamp in the status bar is updated. -
Test case:
tasks assign c/1 k/1
Expected: No assignment is made. Error detail is shown in the status message. Status bar remains the same. -
Test case:
contacts assign c/1 k/1
Expected: No assignment is made. Error detail is shown in the status message. Status bar remains the same. -
Test case:
contacts assign c/2 k/1
Expected: Second contact is assigned to the first task. Details of the assignment are shown in the status message. Timestamp in the status bar is updated. -
Test case:
contacts assign c/2 k/1
Expected: No assignment is made. Error detail is shown in the status message. Status bar remains the same. -
Test case:
tasks assign c/2 k/1
Expected: No assignment is made. Error detail is shown in the status message. Status bar remains the same. -
Other incorrect assign commands to try:
tasks assign
orcontacts assign
,tasks assign c/x
orcontacts assign c/x
(where x is any integer),tasks assign k/x
orcontacts assign k/x
(where x in any integer),tasks assign c/x k/y
orcontacts assign c/x k/y
(where x is negative or larger than the contacts list size and/or y is negative or larger than the task list size).
-
Unassigning a Task from a Contact
-
Unassigning a task from a contact and vice versa while some or all tasks and contacts are listed.
-
Prerequisites: List tasks using the
tasks list
ortasks find
commands, and list contacts using thecontacts list
orcontacts find
commands. There must be at least 1 task and 2 contacts on screen. Task 1 must be assigned to contacts 1 and 2, as detailed in the previous test case. -
Test case:
tasks unassign c/1 k/1
Expected: First task is unassigned from the first contact. Details of the unassignment are shown in the status message. Timestamp in the status bar is updated. -
Test case:
tasks unassign c/1 k/1
Expected: No unassignment is made. Error detail is shown in the status message. Status bar remains the same. -
Test case:
contacts unassign c/1 k/1
Expected: No unassignment is made. Error detail is shown in the status message. Status bar remains the same. -
Test case:
contacts unassign c/2 k/1
Expected: Second contact is unassigned from the first task. Details of the unassignment are shown in the status message. Timestamp in the status bar is updated. -
Test case:
contacts unassign c/2 k/1
Expected: No unassignment is made. Error detail is shown in the status message. Status bar remains the same. -
Test case:
tasks unassign c/2 k/1
Expected: No unassignment is made. Error detail is shown in the status message. Status bar remains the same. -
Other incorrect unassign commands to try:
tasks unassign
orcontacts unassign
,tasks unassign c/x
orcontacts unassign c/x
(where x is any integer),tasks unassign k/x
orcontacts unassign k/x
(where x in any integer),tasks unassign c/x k/y
orcontacts unassign c/x k/y
(where x is negative or larger than the contacts list size and/or y is negative or larger than the task list size).
-
PROJECT: ShowFace
During the same semester that I worked on Cow, I was also developing ShowFace.io, a React web app that allows groups to find the best time to meet. In this project, I was the lead developer, delivering features nearly every day.