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!

PROJECT: README

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:

  • Community:

    • Regularly review pull requests (PR). See here for the complete list!

    • Otherwise, look below for PRs with non-trivial comments:

    • Reported bugs and gave suggestions for another group’s project, TravelBuddy:

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]…​

  • At least one of the optional fields must be provided.

  • The search is case insensitive. e.g hans will match Hans

  • The search matches anywhere for title, description and link. e.g. ans B will match Hans Bo

  • The search matches exactly for tags. e.g. 'science' will match 'science', but not 'scienceandtech'

  • The search phrase with prefix a/ will try to match with every field in the entry according to the above rules.

    • i.e. find a/keyphrase is equivalent to find ti/keyphrase d/keyphrase l/keyphrase t/keyphrase

  • Entries matching at least one field will be returned (i.e. OR search).

    • e.g. find ti/aaa d/bbb l/ccc t/ddd will match an entry with title Aaawesome and an entry with description abbbA

Examples:

  • Find entries with title containing the phrase lambda, or link containing the phrase github.

    1. find ti/lambda l/github

ug findfieldx
Figure 1. Only entries with title containing lambda (red) or link containing github (orange) shown after find command
  • Find entries with the tag infoTheory.

    1. find t/infoTheory

ug findtagx
Figure 2. Only entries with tag infoTheory shown after find command

 


Archiving an entry: archive

Moves the specified entry to the archive and removes its downloaded content.

Format: archive INDEX

  • Archives the entry at the specified INDEX.

  • The index refers to the index number shown in the displayed entry list.

  • The index must be a positive integer 1, 2, 3, …​

Examples:

  • Move the 2nd entry in the reading list to the archives and remove its downloaded content.

    1. list

    2. archive 2

    3. archives

ug archivex 1
Figure 3. Archiving the second entry
ug archivex 2
Figure 4. Entry is saved in the 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.

ContextSpecificCommandActivityDiagram
Figure 5. Activity diagram for command execution

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.

LogicClassDiagram
Figure 6. Class Diagram of the Logic Component with parser classes.

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.

ChangeContextSdForModel
Figure 7. Sequence diagram for the archives command.
  1. The user launches the application.

  2. The ModelManager will default to ModelContext.CONTEXT_LIST context.

  3. The user enters the archives command.

  4. The current context, ModelContext.CONTEXT_LIST, is retrieved from the ModelManager.

  5. Static parser class EntryBookListParser in the ModelContext.CONTEXT_LIST is used to parse the command.

  6. Command is parsed successfully, and ArchivesCommand created.

  7. When the command is executed, context in ModelManager is set to ModelContext.CONTEXT_ARCHIVES.

  8. This triggers the ModelManager to display the EntryBook 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 to Model, not Logic.

    • Cons: Model is slightly more dependent on Logic 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 on Logic. Context can then be thought of as a state for the Logic module, which is also responsible for parsing commands.

    • Cons: making this work will involve architectural changes since only the UI module has a reference to Logic 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.