Hello there! I am Computer Science undergraduate student studying at National University of Singapore (NUS). This document highlights all the projects I have contributed to over the course of the studies, and I hope it gives you a better idea of what I can do!
Overview
README is a desktop bookmark manager/RSS feed reader application. README lets users store webpages for offline reading, in addition to subscribig to feeds so that their favourite content is automatically downloaded and delivered to them.
The application is the product of a brownfield project for the NUS module CS2103T. We built our application from an existing addressbook application.
We envision users to use our application to store a large number of entries (which refers to links in the application), so it is vital that they have a way to navigate these many entries. As such, my responsibility in this project is to develop a powerful system to organise and manage entries in README.
Summary of contributions
Given below are contributions that I made to this application. |
Major enhancement: Entry management system
I implemented a collection of several commands that allow users to navigate their large number of entries in the application.
-
Justification: Essential for heavy users so that they can search for and navigate their large numbers of entries efficiently, and allows them to partition their entries into groups using tags and the archive.
-
Highlights:
-
Archives command: Users can archive (instead of delete) entries they have read for future reference.
-
Find command: Enhanced so users can search for entries in the list of currently displayed entries using any of the fields and/or tags.
-
Context switching: Users can make the application display different entries (saved entries, archived entries etc.) via context-switching commands.
-
Minor enhancement: Morphing addressbook to entrybook
I contributed significantly to refactors and renames of codebase to fit the context of our application.
Code contributed:
For an overview of all of code contributed by me, refer to the CS2103T module dashboard!
Otherwise, refer to the links below to relevant pull requests for each enhancement.
Other contributions:
-
Project management:
-
I managed the release of version 1.3.1 of our application.
-
-
Community:
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. |
Finding entries (by title, description, etc.): find
Finds entries whose fields contain any of the given keyphrases.
Format: find [a/SEARCH_PHRASE] [ti/TITLE_SEARCH_PHRASE] [d/DESCRIPTION_SEARCH_PHRASE] [l/LINK_SEARCH_PHRASE] [t/TAG_TO_SEARCH]…
Examples:
-
Find entries with title containing the phrase
lambda
, or link containing the phrasegithub
.-
find ti/lambda l/github
-
lambda
(red) or link containing github
(orange) shown after find command-
Find entries with the tag
infoTheory
.-
find t/infoTheory
-
infoTheory
shown after find command
Archiving an entry: archive
Moves the specified entry to the archive and removes its downloaded content.
Format: archive INDEX
Examples:
-
Move the 2nd entry in the reading list to the archives and remove its downloaded content.
-
list
-
archive 2
-
archives
-
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. |
Context-specific commands
Current implementation
In order to implement the multiple commands for the application, we require a way to disallow certain commands in certain contexts.
For example, when the user is viewing the archives, commands he enter are parsed in the "Archive context" as shown above.
If he enters the archive
command, it will not be recognised as a valid command since every entry shown is already archived.
When a user is uses the list
command, he switches to the "List context".
Now, when he enters the archive
command with valid arguments, it is successfully executed.
However, the unarchive
command will now not be recognised.
This presents two main problems; the need for separate command parsers for each context, and a way for the application to keep track of its context.
Current Implementation
Modular Parser classes
We require individual Parser classes for each context. Each Parser class should only parse commands allowed for the context it represents.
The following classes were created to support this feature (refer to the class diagram given below).
-
EntryBookParser
— the base abstract class all Parsers extend from. -
EntryBookListParser
— Parser for the list context. -
EntryBookArchivesParser
— Parser for the archives context. -
EntryBookFeedsParser
— Parser for the feeds context. -
EntryBookSearchParser
— Parser for the search context.
Each Parser class has a parseCommand(String)
operation that parses the string command.
EntryBookParser#parseCommand(String)
is the fallback operation used when any of its children
fail to parse the command. It successfully parses commands that is common in any context (e.g. exit
, help
).
Context state for Model
Context is represented by the enum class ModelContext
.
Model
to holds this information of the context the application is in, which decides
Parser class Logic
should use when a command is executed.
Each ModelContext
holds a static Parser class that parses commands for the context it represents.
The following operations are implemented.
-
Model#getContext()
— gets the context the application is in. -
Model#setContext(ModelContext)
— sets the context the application is in.
Model#setContext(ModelContext)
is called when a context-switching command is executed
(refer to the User Guide for the list of these commands).
Given below is the sequence diagram for the context-switching command, archives
.
archives
command.-
The user launches the application.
-
The
ModelManager
will default toModelContext.CONTEXT_LIST
context. -
The user enters the
archives
command. -
The current context,
ModelContext.CONTEXT_LIST
, is retrieved from theModelManager
. -
Static parser class
EntryBookListParser
in theModelContext.CONTEXT_LIST
is used to parse the command. -
Command is parsed successfully, and
ArchivesCommand
created. -
When the command is executed, context in
ModelManager
is set toModelContext.CONTEXT_ARCHIVES
. -
This triggers the
ModelManager
to display theEntryBook
for the archives, via listeners.
Design Considerations
-
Alternative 1 (current choice): Context information is held by
Model
-
Pros: makes the most sense for the context to change only if a context-switching command is successfully executed, and
Command
only has a reference toModel
, notLogic
. -
Cons:
Model
is slightly more dependent onLogic
since it has an indirect reference to Parser classes. This causes more coupling.
-
-
Alternative 2: Context information is held by
Logic
-
Pros: weakens the dependency of
Model
onLogic
. Context can then be thought of as a state for theLogic
module, which is also responsible for parsing commands. -
Cons: making this work will involve architectural changes since only the
UI
module has a reference toLogic
module class (Parser).
-
Ultimately, Alternative 1 was chosen because we later decided that context should have a one-to-one correspondence to which entrybook to display to the user (refer to [Multiple-EntryBooks]), in addition to being the option which required the least modification to the rest of the code base to implement.