About the Project
MoneyGoWhere is a personal finance application targeted to students at the National University of Singapore (NUS), designed by my team and I for our Software Engineering project. It was morphed from a basic command line Address Book. Some notable features include setting budget goals, viewing statistics, customised searching and sorting, setting reminders for bills, viewing exchange rates, changing the application currency and importing and exporting data from and to a Csv file.
My Role
My role was to complete find and sort features, and minor features such as natural language date parsing, exchange rate and changing the application currency. The sections that follow in this document will elaborate these features in detail. I have also made notable contributions to the User Guide and Developer Guide.
Listed in the table below are some notations that are used throughout the document.
Icon | Description |
---|---|
|
Command that can be executed, or a component, class or object in the architecture of the application |
|
Tips that might be helpful in navigating the application |
|
Important information that should be noted |
Useful information for a deeper understanding of the command |
As shown in Table 1, “Legend table”, these icons associated to their following descriptions, such as commands, tips, important information and useful information, enable greater clarity in understanding the document. Note that useful information will have text enclosed in its box.
Summary of contributions
This section shows a summary of my contributions to the team project.
-
Major enhancement #1: Implemented customisable find feature
-
What it does: It allows users to type
find
to display a range of spending entries based on different attributes. -
Justification: It enables the users to specifically view what they need to know, rather than scrolling through a long general list of spending entries.
-
Highlights: This enhancement has good integration with existing commands. It also required in-depth understanding of the underlying codebase.
-
-
Major enhancement #2: Implemented user-defined sort feature
-
What it does: It allows users to type
sort
to re-order the displayed spending entries based on preferred fields. -
Justification: It enables users to customise the order of the information being presented of greater priority, for instance, showing their most expensive purchases first, followed by date of purchase, to allow them to be mindful of their spending.
-
Highlights: This enhancement had a challenging design approach. It also required some restructuring of the code base implementation and an in-depth analysis of design alternatives.
-
-
Other enhancements: Implemented exchange rate and currency features, and natural language date parsing (Natty).
-
Code contributed: [Collated code]
Other contributions
-
Project management
-
Enhancements to existing features:
-
Documentation:
-
Community:
-
Tools:
Contributions to the User Guide
Listed below are sections I contributed to the User Guide, which includes the find and sort features and the flexible date formats section. It showcases my ability to write documentation targeting end-users. For brevity, detailed information for flexible date formats can be found in the User Guide.
Finding a spending : find
Searches for spending based on given keywords, cost range, date range, remarks or tags. You may refine the search results by entering more keywords.
Format: find [n/NAME_KEYWORDS] [c/COST_MIN] [c/COST_MAX] [d/DATE_START] [d/DATE_END] [r/REMARK_KEYWORDS] [t/TAG]…
DATE_START must be earlier or the same as DATE_END, and COST_MIN must be smaller or the same as COST_MAX. |
Date range can be input in the following ways:d/DATE_START d/DATE_END d/DATE_START to DATE_END d/DATE_START - DATE_END
|
Cost range can be input in the following ways:c/COST_MIN c/COST_MAX c/COST_MIN-COST_MAX c/COST_MIN - COST_MAX
|
Examples:
-
find n/Java book c/100.20-150.00 d/01/09/2019 - 30/09/2019
Returns a list of spending with matching the keywordsJava
orbook
within the cost range100.20
to150.00
and date range within01/09/2019
to30/09/2019
. -
find d/yesterday d/today t/food t/leisure
Returns a list of spending withinyesterday
andtoday
that havefood
orleisure
tags.
Expected Output:
Spending entries which match the search criteria are listed.
Sorting spending entries : sort
Sorts all spending based on a given order to view information more clearly.
Format: sort [PREFIX/SORT_ORDER]…
Examples:
-
sort d/ASC c/DESC
Sorts current spending displayed by Date in ascending order. If they are the same, sort by Cost in descending order. -
sort n/DESC
Sorts current spending displayed by Name in descending order.
Expected Output:
An example is shown below.
sort n/ASC d/DESC
Spending entries are sorted in alphabetical order where uppercase letters appear first, and a message is displayed based on the example in Figure 1, “Output of sort n/ASC d/DESC
”.
Contributions to the Developer Guide
Listed below are sections I contributed to the Developer Guide, which includes the features section for Find and Sort, and the Product Scope section. It showcases my ability to write technical documentation and display the technical depth of my contributions to the project.
Find feature
The find feature allows the user to search for a spending based on specified fields. More fields may added to increase specificity. For example, find n/Apple c/2.50-3.00
will find an Apple
of cost range $2.50
to $3.00
.
Implementation
Find is supported by having a Predicate
implemented for every field in Spending. Predicates are added based on valid input entered by the user. The FindCommandParser
class stores these predicates, which are combined using Java 8
streams with an AND
operation to form a more specific search query.
The sequence diagram below demonstrates how the find
command is executed:
find
commandThe following steps explain Figure 2, “Sequence diagram for an example find
command”:
-
The user enters
find n/apple
. -
LogicManager
callsSpendingBookParser#parseCommand()
. -
FindCommandParser
is created and validates user input, creating a list ofpredicates
. -
FindCommand
receivespredicates
and stores it in a list. -
On
execute()
,predicates
are reduced andModel#updateFilteredSpendingList(predicate)
is called to refresh the displayed list.
The lifeline for FindCommandParser should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of diagram.
|
To summarise what happens when the user uses the find
command, the following activity diagram is shown below:
find
commandThe following steps explain Figure 3, “Activity diagram for an example find
command”:
-
The user executes the
find
command. -
If there are valid inputs, each field from the input is saved as predicates into a predicate list.
-
Else, there are two cases.
-
If there is an invalid field, display an error message for the invalid field.
-
If there is a missing field, display an error message for the missing field.
-
Design Considerations
Listed in the table below are the design considerations for the find
command.
Aspect | Alternative 1 (current choice) | Alternative 2 |
---|---|---|
How find is executed |
Save all predicates to a list Cons: |
Access the underlying list and check all related objects. |
Based on Table 2, “Design considerations for find
command”, Alternative 1 was chosen as it was the easiest to implement and obeys the Open-Closed Principle (OCP) of the SOLID principles. Although Alternative 2 enables checking of the related objects directly, it has poor abstraction and changes in the function require prior knowledge of the structure of the entire code, making it difficult to implement.
Sort feature
The sort feature allows users to sort all currently displayed Spending entries automatically using the sort
command. The default sorting sequence is by: Date (Descending), Cost (Descending), Name (Ascending) and Remark (Ascending).
For example, sort n/ASC d/DESC
applies sorting by name in ascending order, followed by Date in descending order. This applies to any future commands entered.
Implementation
The sorting feature is supported by SpendingComparator
, a custom comparator to facilitate different sort ordering, and implements the following operation:
-
updateSortedSpendingList(comparator)
— Updates the sorted spending list with a new comparator.
This operation is exposed in the Model
interface as Model#updateSortedSpendingList(comparator)
.
At a high level view, SpendingComparator
and SortField
interacts in the manner shown below.
As shown in Figure 4, “High-level view of package interaction”, SortCommand
has an association to SortField
and a dependency to SpendingComparator
.
The sequence diagram below demonstrates how the sort
command is executed:
sort
commandThe following steps explain Figure 5, “Sequence diagram for an example sort
command”:
-
The user enters
sort n/ASC
. -
LogicManager
callsSpendingBookParser#parseCommand()
. -
SortCommandParser
is created and validates user input, creating a set offields
. -
SortCommand
receivesfields
and stores it. -
On
execute()
,fields
are passed into aSpendingComparator
object andModel#updateSortedSpendingList(comparator)
is called to refresh the displayed list.
The lifeline for SortCommandParser should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of diagram.
|
The following activity diagram summarises what happens when the user uses the sort
command:
sort
commandThe following steps explain Figure 6, “Activity diagram for an example sort
command”:
-
The user executes the
sort
command. -
If there are valid fields from the input, each field is saved into a list and determines sort order for
Model
. -
Else, there are two cases.
-
If there is an invalid field, display an error message for the invalid field.
-
If there is a missing field, display an error message for the missing field.
-
Design Considerations
Aspect | Alternative 1 (current choice) | Alternative 2 |
---|---|---|
How sort is executed |
Set a new comparator |
Sort the underlying list without a comparator |
Method design for sort |
Create filtered list from sorted list |
Create sorted list from filtered list |
Based on Table 3, “Design considerations for sort
command”, Alternative 1 was chosen as it was the easiest to implement and it does not violate Single Responsibility Principle (SRP) of the SOLID framework. The only downside of this approach is that changing any field classes may require modifying SpendingComparator
.
In contrast, for Alternative 2, manipulating the internal elements of the list directly is dangerous and can cause unintended side effects. There was also a huge difference for the method design for sort, and Alternative 1 was the easier approach to avoid side effects in Alternative 2.