1. Introduction

This portfolio serves to showcase my roles and contributions to the team project THRIFT. This project was part of the requirements of a year two software engineering module, CS2103T, that I had taken as an undergraduate in NUS.

In this project, I was the team lead and was primarily in charge of leading the team towards our end-product. My team members were: Lee Bo Qiang (User Experience Developer), Melvin Ang (Software Architect), Lye Jian Wen (Quality Assurance Manager) and Kenson Oen (Process Analyst). We all had important and major roles to play in order to ensure that THRIFT is successful.

1.1 Project: THRIFT

THRIFT is a finance tracker desktop application targeting money-conscious NUS students who wish to keep their spending in check. It allows its users to set a budget for each month and track incoming and outgoing transactions. This would remind the user not to overspend as they will constantly see their remaining balance for that month. The following image is how THRIFT looks like:

UGUI
Figure 1. Main window of THRIFT which displays the user’s balance as well as their transactions

1.2 Background of THRIFT

THRIFT is morphed from the original AddressBook-Level3 application which allows users to add contacts to create a personalised list. My team and I have since transformed the application to better suit our purpose.

1.3 Understanding this document

There are various text styles used in this portfolio and its usages are explained below:

This symbol denotes information that you may want to take note of when using the application.

The following text styles are only applicable to the section on the Developer Guide:

currentMonth

Text with grey highlight (called a mark-up) indicates that it is a method/variable name.

Expense

Bold text with mark-up indicates a class/package name.

2. Summary of Contributions

This section provides a summary on the various contributions that I have made to THRIFT.

2.1 Enhancements made

Major enhancements:

  • Added the ability to add transactions into the transaction list.

    • What it does: The add_expense and add_income commands allow the user to track their incoming and outgoing transactions.

    • Justification: It is a core feature to be able to add transactions into THRIFT.

    • Highlights: I had to modify the original AddressBook-Level3 codebase to add a transaction instead of a person. Additionally, the user is able to optionally annotate each transaction with a Remark and Tag.

  • Added the ability to set the budget for a specified month.

    • What it does: The budget command allows the user to set their budget for a particular month.

    • Justification: With a budget set, the user can see if they are within their spending limit for the month.

    • Highlights: I had enhanced THRIFT to show the updated balance whenever the user changes their budget.

Minor enhancements:

  • Modified the THRIFT interface to display transactions instead of people.

    • Justification: THRIFT deals with transactions and not people objects, there is no longer the need to maintain people objects.

    • Highlights: I coloured incomes as green and expenses as red to improve the user experience by making the displayed information intuitive.

2.2 Code contributed

Please follow these links to see a sample of my code: [Commits] [Pull requests] [RepoSense Code Contribution Dashboard]

2.3 Other contributions

  • Project management:

    • There were a total of 5 releases, from version 1.0 to 1.4. I managed every release on GitHub.

  • Enhancement to existing features:

    • Refactored the original AddressBook-Level3 codebase to fit our requirements. (Pull request #62)

    • Updated the original delete command to require a prefix i/INDEX to specify which transaction the user wishes to delete. This makes the delete command syntax consistent with the update command. (Pull request #104)

    • Updated the original find command to search for the specified keyword(s) in a transaction’s Remark as well as Description. (Pull request #163)

  • Documentation:

    • Updated the architecture diagrams in the original developer guide to suit the context of THRIFT. (Pull request #169)

    • Updated the user guide to acknowledge the original codebase.

  • Community:

    • Reviewed pull requests of new features (with non-trivial comments): #69, #168, #174, #175

3. Contributions to the User Guide

The following section illustrates my ability in writing documentation to guide end-users on using the various features of THRIFT.

{Start of extract}

Setting monthly budget: budget

Ready to save? One of the key steps in saving money is to clearly define your monthly budget. With a budget set, you will always see your remaining balance! This will definitely encourage you to spend wisely and to keep your spending in check. Take the first step in saving by setting your budget for each month in THRIFT!

It is not compulsory to set a budget for each month and you can use THRIFT normally without setting budgets.

Command syntax:

budget v/VALUE d/MONTH/YEAR

  • Sets your budget for the month specified in MONTH/YEAR as VALUE.

  • VALUE is any positive integer below one billion.

  • MONTH is in MM where it is between 01-12 inclusive.

  • YEAR is in YYYY where it is between 0001-9999 inclusive.

Example usage:

You wish to set your budget for the month October 2019 as $2000:

  1. Your current budget for the month October 2019 is $0.

    Step1
  2. You type: budget v/2000 d/10/2019 in the Command Box and press Enter.

    Step2
  3. You should see in the Result Box that your budget for October 2019 has been set to $2000.

    If you are changing your budget for the current displayed month, you should see the changes on the GUI immediately.
    Step3

{End of extract}

4. Contributions to the Developer Guide

The following section illustrates my ability in writing documentation to provide developers insights on the design of the application. It also showcases the technical depth of my contributions to THRIFT.

{Start of extract}

Adding transactions

We allow users to add Expense/Income transactions into THRIFT which enables record-keeping. This section will show how we handle such requests from the user at the back-end.

Implementation

We store every single Transaction added by the user into an ObservableList<Transaction>, which is a list object in TransactionList. We used an ObservableList because whenever there are changes to the list, any other component of THRIFT using it will automatically reflect its changes.

We implemented adding a Transaction through the following commands: add_expense/add_income. This process leverages on polymorphism: Expense and Income are both subclasses of the abstract class Transaction. Each Transaction contains the following mandatory fields: Description, TransactionDate and Value; as well as optional fields: Remark, and Set<Tag>. The following class diagram depicts this relation:

Polymorphism

Because of this polymorphism relation, many of the driver functions in THRIFT simply references Transaction and it will work for both Expense and Income transaction objects. For example, when inserting a new Expense/Income, the AddTransactionCommandParser will determine which object to initialize. The sequence diagram below shows how adding a Transaction work in the back-end:

PolymorphismCalling
Figure 2. Sequence diagram of how adding a new Transaction is processed with polymorphism

Expense and Income are normally instantiated by either ExpenseCommandParser#parse(String args) or IncomeCommandParser#parse(String args), which attempts to parse the various parameters supplied in args and return either a Expense or Income object. The following conditions will cause a ParseException to be thrown by the parser:

  1. Missing parameters

  2. Incorrect syntax (i.e. missing prefix, if it is required)

  3. Illegal values in parameters (i.e. special characters and symbols entered for a integer-only field)

  4. Multiple occurrences of parameters which only expects a single entry

If the user input is incorrect due to any of the reasons above, the usage syntax will be shown.

We will demonstrate how a Transaction is added into THRIFT and how the back-end handles each step of the process:

Step 1. The user executes add_expense n/Laksa v/3.50 to insert an Expense with its Description set to "Laksa" and its Value set to "3.50". The TransactionDate is set to the user’s current system date in the form "dd/mm/yyyy". The input is now checked and an attempt to parse each parameter occurs:

  • Description is parsed by AddTransactionCommandParser#parseTransactionDescription(ArgumentMultimap)

  • Value is parsed by AddTransactionCommandParser#parseTransactionValue(ArgumentMultimap)

  • TransactionDate is instantiated by AddTransactionCommandParser#parseTransactionDate()

ArgumentMultimap is a class that stores all the parsed parameters taken from the user input.

Since the user input is valid, the Expense is successfully created and inserted into the transaction list. The transaction list now contains 1 Transaction object.

AddTransaction1

Step 2. The user executes add_income n/Bursary v/500 r/Awarded for doing well in school to insert an Income. The input is now checked in a similar fashion as in Step 2 except that:

  • Remark is parsed by AddTransactionCommandParser#parseTransactionRemark(ArgumentMultimap)

Again, since the input is valid, the Income is successfully added into the transaction list. The transaction list now contains 2 Transaction objects.

AddTransaction2

The following activity diagram summarizes what happens when the user executes a command to add a new Transaction:

AddTransactionActivity
Figure 3. Activity diagram of adding a Transaction into the transaction list

Design considerations

There are many different ways to implement how a transaction is added into THRIFT. In this section, we will be justifying why we chose to implement it the way we did.

Aspect: Differentiating between Expense and Income
  • Alternative 1: (current choice): Introduce a Transaction parent class which both Expense and Income extends from.

    • Pros: Introduces polymorphism, easing references to either classes by simply referencing the Transaction object. For example, using a single List<Transaction> instead of needing 2 separate lists List<Expense> and List<Income>.

    • Cons: Reduces the readability of the program as polymorphism can be confusing.

  • Alternative 2: Keep Expense and Income classes separate, with each having their own specialized methods.

    • Pros: Maintains an intuitive design: Expense deducts money and Income increases money.

    • Cons: Incurs significant overhead and duplicated codes since it is likely that both Expense and Income will have very similar methods.

Alternative 1 was chosen because we want to model it close to the real world: both Expense and Income are described as being a Transaction.

Aspect: Managing how Value is stored and handled in Expense and Income
  • Alternative 1: (current choice): Disallow negative Value in Expense object, only using positive amount for both Expense and Income

    • Pros: Removes the need to implement support for inserting negative Value. This is due to how Value constraints are applied when restoring THRIFT data from the data file.

    • Cons: Requires the developer to manually negate the Value whenever calculations are done with a Expense object.

  • Alternative 2: Allow only negative amount in Expense object and only positive amount in Income object

    • Pros: Calculating the balance becomes trivial - simply sum up the entire List<Transaction>.

    • Cons: Parsing the user input to allow only a single negative symbol and no other symbols causes an overhead.

Alternative 1 was chosen because we want to keep the transaction list clean - only positive integers are stored.

{End of extract}