Introduction and Overview
This Portfolio is a documentation of the contributions that I have made during the development of the application, titled NUSSU Connect.
NUSSU Connect is a CLI application developed by team F09-1 and it aims to cater to the needs of executive committee members of the NUS Student Union (NUSSU).
It comes with multiple features that NUSSU executive committee members will find useful. This includes budgets and expenses management, human resource allocation, easy management of contacts lists, and all the information stored within this application will have an additional security guarantee by the multi-user access level feature.
Summary of contributions
In this project, my main contribution is in the Search Pruning feature and the main purpose of this feature is to ease the process of managing a large list of contacts. Further details about my contributions will be explained in this section.
-
Major enhancement: Search Pruning feature with
find
andundofind
commands.-
What it does: Each subsequent execution of
find
commands allows users to search according to the current displayed list of contacts.undofind
command does the opposite and reverts the lastfind
command executed. -
Why we need this feature: NUSSU exco is an organization that will most likely be required to keep track of a large database of important contacts. Therefore it will be time-consuming and tedious to locate specific contact information from the database. A search pruning feature will resolve this problem as users will be able to narrow down the search space in discrete steps so that they could retrieve the information they want in smaller and readable chunks.
-
Highlights: This enhancement is mainly created from scratch with some help from documentations on how the
Predicate
class works. This enhancement was also created with re-usability in mind and any form of filtering done withPredicate
will be able to utilize this feature.
-
-
Minor enhancement: Added an enhancement to Search Pruning Feature that allows users to see a history of keywords that they have executed previously.
-
What it does: Every time a user performs a search, the command result box will display the list of keywords previously executed by the user and it describes how the current displayed list is being filtered.
-
-
Minor enhancement: Improved find command by introducing searching by tags and exclude functionality.
-
What it does: Searching by tags allows users to filter the contacts according to the tagged description of each contact. Exclude functionality allows users to remove unwanted results from their search.
-
-
Code contributed: [Overview]
-
Other contributions:
-
Project management:
-
Managed releases
v1.1
,v1.2
,v1.2.1
andv1.3
(4 releases) on GitHub. -
Managed milestones and deadlines of the project.
-
-
Documentatations:
-
Updating Class Diagrams of Model in developer guide to reflect the changes in implementation. (Pull Requests #144).
-
Minor Tweaks to ReadMe, User Guide and Developer Guide to meet module requirements.
-
-
Tools:
-
Setting up of Coveralls in team repository
-
-
Community:
-
Contributions to the User Guide
This section shows part of my contributions in the User Guide that explains to end-users about how they can utilize the Search Pruning Feature. |
Search Pruning Feature with list, find and undofind commands
The Search Pruning feature was introduced to NUSSU Connect in v1.1 and it lets you trim the list of contacts with every successive find command. This feature will you to search through a large list of contacts in a much more intuitive manner without the hassle of typing a long single line command that is usually error-prone.
To provide you with an idea on how you can utilize the Search Pruning feature, the concept of the Search Pruning
feature will be further illustrated with the example below
1. Search Pruning with Find Commands
2 . Making a mistake and undoing it with undofind command
Contributions to the Developer Guide
This section shows part of my contributions in the Developer Guide that explains the underlying implementation behind the Search Pruning feature. |
Search Pruning Feature
The Search Pruning mechanism is facilitated by the SearchHistoryManager
class, and within it is a searchHistoryStack
that stores Predicate
objects.
Predicate
objects are used to filter FilteredList
objects by calling the setPredicate()
method of FilteredList
. By storing Predicate
objects
in SearchHistoryManager, it stores the search logic that was previously used by the FilteredList
object, and hence, simulates the storing Search History
without storing the actual data.
In NUSSU Connect, the main SearchHistoryManger
object is in ModelManager
and it stores Predicate<Person>
objects used for the filtering of filteredPersons
list.
If you want to utilize SearchHistoryManager for your own use case, you can initialize a new SearchHistoryManager object with its' generic constructor.
|
Current Implementation
The main implementation behind SearchHistoryManager
is a Stack Data Structure and the following 4 methods of SearchHistoryManager
are exposed for your usage
-
executeNewSearch(Predicate<T> predicate)
updates system search logic to the next state and returns aPredicate
object storing the system search logic after the update. -
revertLastSearch()
reverts system search logic to the previous state and returns aPredicate
object storing the system search logic after revert. -
clearSearchHistory()
clears all system search logic from in-app memory. -
isEmpty()
returns true ifsearchHistoryStack
is empty.
Given below are illustrations to help you understand how the first three method works internally. But before carrying on, you need to take note of the following.
In the diagrams, 'UP' is the short-form for User Predicate and 'SP' is the short-form for System Predicate. User Predicate stores the logic specified by the user and it is not the actual search logic used for filtering of FilteredList objects. On the other hand, System Predicate stores the search logic for the system and it will be used to filter FilteredList objects. |
User Predicate and System Predicate are not actual Classes and they are simply there to help simplify the explanation. In the actual implementation, there is no way to differentiate one from the other. |
executeNewSearch(Predicate<T> predicate)
Upon calling this method, there will be two different situations
-
Situation 1:
searchHistoryStack
is empty
Upon receiving a new User Predicate, SearchHistoryManager will simply push the new User Predicate intosearchHistoryStack
as a System Predicate.
-
Situation 2:
searchHistoryStack
is not empty
Before pushing the newPredicate
into the stack,SearchHistoryManager
will first retrieve the System Predicate object at the top of the stack. After retrieving it, it will call theand()
method with the User Predicate, creating a new System Predicate which will then be pushed into the top of the stack.
This method will return the new System Predicate at the top of the stack.
revertLastSearch()
This method will pop the System Predicate at the top of the stack.
In the event that the stack is already empty, this method will throw EmptyHistoryException
.
If the stack is not empty after the pop, this method will return the System Predicate at the top of the stack. Else,
it will return a Predicate
object with a search logic that always defaults to true.
clearSearchHistory()
This method will simply empty the stack.
How SearchHistory
The following sequence diagrams shows you how the IncludeNameFindCommand
and UndoFind
commands
utilize SearchHistoryManager
to perform Search Pruning. Other variations of FindCommand
works similarly to
IncludeNameFindCommand
and the sequence diagram for IncludeNameFindCommand
is also relevant to them.
-
IncludeNameFind
command
-
UndoFind
command
Design Considerations
Aspect: What data is stored in search history stack
-
Alternative 1(current choice): Save a Stack of
Predicate
objects-
Pros:
-
Does not need to store the data in search history explicitly which saves memory
-
SearchHistoryManager
class is reusable for any Search Pruning done withPredicate
-
-
Cons:
-
Developers need to understand how
Predicate
works before utilizingSearchHistoryManager
to perform Search Pruning. -
Predicate
objects by itself does not perform the Search Pruning. We have to make an additional call to thesetPredicate()
method of theFilteredList
class with thePredicate
object.
-
-
-
Alternative 2: Save a Stack of Lists containing
Person
objects in search history-
Pros:
-
It is easy to understand from the code that we are filtering according to
Person
objects.
-
-
Cons:
-
More memory is required as
Person
objects has to be duplicated multiple times into a new Lists. -
SearchHistoryManager
can only be used for Search Pruning on objects that is aPerson
.
-
-
Aspect: How the Predicate at the top of the Stack is retrieved from SearchHistoryManager
-
Alternative 1(current choice):
Predicate
is returned from the methodsexecuteSearch()
andrevertLastSearch()
-
Pros:
-
No need for an extra method call to retrieve system search logic in the form of
Predicate
fromSearchHistoryManager
.
-
-
Cons:
-
No clear distinction between Update and Retrieval of system search logic.
-
-
-
Alternative 2:
Predicate
is not returned from the methodsexecuteSearch()
andrevertLastSearch()
, but is instead retrieved with another method.-
Pros:
-
Clearer distinction between Update and Retrieval of system search logic.
-
-
Cons:
-
Need to perform 2 method calls separately to retrieve
Predicate
object fromSearchHistoryManager
after an update to search logic. -
Need to implement another method specifically for retrieval of
Predicate
object. -
Other developers utilizing
SearchHistoryManger
need to remember that they need to retrievePredicate
object fromSearchHistoryManager
separately after an update to search logic.
-
-