1. Overview
1.1 About the Project
ResuMe is a desktop resume management application developed by a team of students from National University of Singapore (NUS). The application is aimed at university students, who may want to manage different resumes due to internship and job applications.
The project builds upon the code from Address Book Level 3 (AB3), a desktop Address Book application. ResuMe retains the characteristics of AB3, and thus ResuMe has a Graphical User Interface (GUI) while most interactions happen through the Command Line Interface (CLI).
The application is developed using Java, and within a short span of 6 weeks we have contributed a total of more than 25,000 lines of code to the application.
1.2 About the Team
The team consists of 5 Year 2 Computer Science students from NUS, taking the Software Engineering module, CS2103T.
2. Summary of Contributions
2.1 Individual Contributions
My code contributions can be found here: Functional and Test code (via RepoSense)
2.1.1 Enhancements Implemented
-
Major enhancement: added the ability to modify items in the resume:
redit
-
What it does: allows the user to selectively modify the items in a specified resume.
-
Justification: This is a key feature in the application because a user would need to select existing items in the resume to be included before generating them.
-
Highlights: This enhancement is particularly tricky to implement due to the various possibilities of input that a user can give. For example, a combination of internship and project items. Careful parsing of the input is required before the command is processed.
-
-
Major enhancement: added the ability to add items in the resume based on tags:
tagpull
-
What it does: allows the user to add items that have been given a particular tag.
-
Justification: This increases the convenience of modifying a resume, since items that have the same tags are likely to be included togehter in the resume.
-
-
Minor enhancement: modified the
edit
command and its parser to suit the application-
Justification: ResuMe requires handling of various item types such as
Internship
,Project
andSkill
items. Therefore, it is necessary to morph the existingParser
from AB3 to suit our needs.
-
-
Minor enhancement: wrote the
view
command-
Justification: Items such as
Project
omit a lot of details in our list in the GUI. Theview
command helps include more details about theItem
.
-
2.2 Contributions to team-based tasks:
2.2.1 Morphed CommandResult in overall architecture
-
What it means:
CommandResult
has been separated to many different subclasses which correspond to the differentCommand
. -
Justification: Several
CommandResult
require a special boolean value to indicate that it is the result of a certainCommand
. With only one class, the constructor would have to take in many booleans in the constructor and this gets very messy.
2.2.2 Project management
-
Managed releases
v1.1
-v1.2
(2 releases) on GitHub -
Managed GitHub issue tracker
-
Set-up Travis and Coveralls
3. 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. |
Pulling tagged items into a resume: tagpull
Pulls all the internship
, project
and skill
items with the specified tag(s) into a resume
.
Format: tagpull RESUME_INDEX [#/ TAG]…
This command does not remove items from the resume and will add items on top of the existing items.
|
Example 1: Pulling items using one tag
Before you try this example, please ensure you have added some items with the tag "SE". You may verify for their presence by using the list
command.
Try typing in these commands:
-
list i/ res
-
tagpull 1 #/ SE
Outcome:
-
The first command lists out all
resumes
. Assuming you want to modify the contents of the firstresume
in the list box.Figure 1. List of all resume items -
The second command pulls all items which has "SE" as the tag into the
resume
at index 1, named "Winter 2019". The following screenshot illustrates the outcome of the command if we have 1internship
item and 2project
items tagged with "SE".Figure 2. Resume content aftertagpull
Example 2: Pulling items using multiple tags
Now, maybe you have categorised your items by using multiple tags. So, you think just pulling items using one tags is not sufficient. Our tagpull
supports that too!
Before you try this example, please ensure you have added some items with the tag "SE" and/or "github". You may verify for their presence by using the list
command.
Try typing in these commands:
-
list i/ res
-
tagpull 1 #/ SE #/ github
Outcome:
-
The first command lists out all
resumes
. Assuming you want to modify the contents of the firstresume
in the list box.Figure 3. List of all resume items -
The second command pulls all items which has "SE" or "github" as the tag into the
resume
at index 1, named "Winter 2019". The following screenshot illustrates the outcome of the command if we have 1internship
item and 2project
items tagged with "SE", and 1skill
item tagged with "github".Figure 4. Resume content after tagpull
4. 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. |
Resume Edit feature
The Resume Edit feature or redit
allows user to modify the content items of the Resume
(for example, adding a Skill
item or removing an Internship
item). It is not to be confused with the edit
command, which simply modifies the fields of an Item
(such as name).
Current Implementation
The redit
command is facilitated by ResumeEditCommand
, which extends Command
. Therefore, like any other Command
classes, it will have an execute
method.
Given below is an example usage scenario and how the redit
works at each step.
Step 1. The user launches the application, and uses the add
command to add several Resume
, Internship
, Project
, and Skill
items.
Step 2. The user executes redit 1 int/ 2
command to add the second Internship
in the list of Internship
items to the first Resume
in the list of Resume
items.
Step 3. This calls ResumeBookParser#parseCommand()
, which would create a new ResumeEditCommandParser
object and call the ResumeEditCommandParser#parse()
method.
Step 4. A new ResumeEditCommand
object is created. It contains the index of the Resume
that is to be modified, and three Optional<List<Integer>>
representing the indices of Internship
, Project
and Skill
to be modified into the Resume
. In this example, the Project
and Skill
indices are represented by empty Optional
because the user did not specify any project or skill indices. (This will be further elaborated in the next section)
Step 5. The ResumeEditCommand#execute()
method is called with the current model
. A copy of the Resume
is created and its content is set to refer to the Internship
, Project
and Skill
items specified by the user.
Step 6. A new ResumeEditCommandResult
object, which contains the edited copy of the Resume
, is created and returned.
The following sequence diagram shows the process of invokation for redit
:
Representation of indices after parsing
In Step 4. above, it is mentioned that Optional<List<Integer>>
is used to represent the indices of Internship
, Project
, and Skill
items. This section elaborates further on the representation.
To explain the various representations, we will use the example of executing redit 1 int/ 2 3 proj/
:
-
A non-empty
List<Integer>
wrapped withOptional
is used to represent the indices when the user specifies both the item prefix and the item indices. In the above example, indices ofInternship
items will be represented by aList<Integer>
of2
and3
, wrapped withOptional
. -
An empty
List<Integer>
wrapped withOptional
is used to represent the indices when the user specifies the item prefix, but no item indices are given. In the above example, indices ofProject
items will be represented by an emptyList<Integer>
wrapped withOptional
. -
An empty
Optional
is used to represent the indices when the user does not specify the item prefix. In the above example, indices ofSkill
items will be represented with an emptyOptional
.
The three representations are used because redit
facilitates the following:
-
If the prefix and indices are both present, the resume will be modified to contain the content items of that prefix at the specified indices. In the same example above,
Resume
at index 1 will be modified to containInternship
items at indices 2 and 3. -
If the prefix is specified but no indices are present, the resume will be modified to remove all the items of that prefix. In the example above,
Resume
at index 1 will be modified to have all itsProject
items removed. -
If the prefix is not specified, the resume will have the items of that prefix unmodified. In the example above,
Resume
at index 1 will not have itsSkill
items modified. If originally there were 4Skill
items, then after the command execution, it will still have 4Skill
items.
The following activity diagram summarises the execution of ResumeEditCommand
:
Design Considerations
Aspect: Whether ResumeEditCommand
should extend EditCommand
-
Alternative 1 (current choice):
ResumeEditCommand
does not extendEditCommand
, but extendsCommand
.-
Pros: Since
redit
modifies the content items of theResume
and not theResume
details, this reduces the size of responsibility forEditCommand
. Each command class now does one and only one thing so Single Responsibility Principle is observed. -
Cons: Unable to exploit polymorphism if there is similarity with the
EditCommand
. From user’s point-of-view, it may also be confusing to have bothredit
andedit
.
-
-
Alternative 2:
ResumeEditCommand
extendsEditCommand
-
Pros: Some methods in
EditCommand
may be able to be inherited byResumeEditCommand
, reducing code duplication. -
Cons: If the functionality of
ResumeEditCommand
is limited, it could have been combined withEditCommand
entirely. If the intention ofEditCommand
is to change theItem
details (such as name), andResumeEditCommand
only modifies the content items of theResume
(without changing any details), then this is also a violation of the Liskov Substitution Principle.
-
Aspect: Representation of indices after parsing
-
Alternative 1 (current choice): Usage of
Optional<List<Integer>>
-
Pros: The 3 different cases is naturally represented when
List<Integer>
is wrapped withOptional
. There is also an enhanced safety, reducing risk ofNullPointerException
. -
Cons: More checks are required to ensure that the
Optional
is not empty before getting its value.
-
-
Alternative 2: Usage of
null
andList<Integer>
-
Pros: Implementation is much simpler, and code becomes much more concise.
-
Cons: High risk of getting a
NullPointerException
ifnull
is not handled carefully.
-