Overview
This portfolio aims to document my contributions to MooLah
MooLah is a desktop expense tracking application, which was morphed from the code of Software Engineering Education’s AddressBook - Level 3 used for teaching Software Engineering principles.
MooLah is written in Java and has around 23 kLoC. It aims to provide a streamlined expense tracking solution to NUS students who are more comfortable with Command-Line Interfaces (CLI). With features such as auto-completion, and syntax highlighting, and expense analysis features like budgeting, and statistics. MooLah provides users an expense tracking solution which is both useful and easy to use.
Summary of contributions
-
Major enhancement: added Easier Command-Line feature.
As this project required the use of a Command-Line interface for user interaction, user input can sometimes require a lot of typing and users may find it difficult to remember all the different commands available and the syntax required to use these commands.
This feature consists of several features which make Command-Line easier to use, and to reduce the need for users to refer to the user guide.
Component 1: Aliases
-
What it does:
This feature allows the user to save input to an alias, allowing them to create shortcuts for command which they frequently require. This saves them time by reducing the keystrokes required to enter a command, as well as reduces the need to remember what exactly needs to be entered.
Component 2: Syntax highlighting
-
What it does:
This feature provides some validation of user input. It highlights valid command words used for commands as well as the prefixes delimiting arguments within the command. It also makes the user’s input more readable, as commands may require many arguments and prefixes, it may be difficult for users to read their input before entering the command. -
Justification: This feature improves the product significantly because a user does not need to remember confusing commands and syntax. Especially due to the fact that our application supports a large number of commands. This allows users to see what valid commands there are as well as what arguments are required without having to press enter the command and see an error message.
-
Highlights: This feature required in-depth analysis of the command syntax of the original code base. The implementation was challenging as it required the use of regular expressions to analyse user input so that the right sections of text were properly highlighted. This feature also required integration of RichTextFx JavaFx extensions. As RichTextFx only provided a text styling for multi-line text areas, this feature required significant usage of JavaFx’s event dispatch and in order to ensure that the text area can properly simulate a single-line textfield.
-
Credits: The RichTextFx demo’s included some existing logic for syntax highlighting which was modified for use in MooLash as the behaviour of syntax highlighting in the demo’s code did not require different highlighting behaviour in different context.
Component 3: Input suggestions
-
What it does:
As with the previous components, the main reason this feature was implemented was to reduce the need for users to have to refer to user guides or remember a lot of commands and their syntax. This feature suggests completions to the user’s current input to provide them with possible commands they may enter, as well as provide them information of what arguments are required by the command and what the prefixes for the argument stand for. -
Highlights: This feature required in-depth analysis of the command syntax of the original code base. It required modification to the existing Prefix class for it to provide more information to the user. The implementation was challenging as MooLah supports almost 30 commands, all of which have different arguments. As such the feature needed to be designed such that it was scalable to support new commands as well as modification to existing commands. Similar to the syntax highlighting feature, this feature uses a significant use of JavaFx as well.
Component 4: Generic commands.
-
As mentioned previously, MooLah supports around 30 commands, several of which do similar thing (e.g. There are several commands which add information to MooLah use the word 'add'. In order to differentiate these commands, they require a much longer name to be clear as to what the command does. This feature allows multiple commands to use the same word and be parsed differently based on the context they are used.
Major enhancement:
Minor enhancement:
-
initial refactoring of AddressBook into MooLah to allow tracking of expenses*
While expenses trackers are similar to an address book such they keep a record of items, the requirements to store expenses are much different. The person class needed to be refactored quite heavily. Additionally, as Expense should be able to share a name unlike the behaviour of the existing Person class, a new way to differentiate Expenses needed to be implemented. #40 #42
Code contributed: RepoSense link
Other contributions:
-
Project management:
-
Wrote tests to significantly increase coverage:
-
Documentation:
-
Made changes to UG diagrams to match changes to the code #285
-
-
Tools:
-
Integrated a third party library (RichTextFX) to the project #93
-
Integrated TestFx into the project for Testing GUI components. #271
(* much of the code was sourced from AddressBook4 GUI-Tests)
-
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. |
Making inputs quick and easy.
Do you have trouble remembering commands and what arguments they require? MooLah provides several features which will help you remember them and make your life much easier!
Creating a shortcut: alias
If you find yourself entering the same thing over and over, MooLah allows you to type less by
assigning this command to an alias
. This will allow you to type this alias
in place of the original long
command.
To assign an alias
, use the the addalias
command with the following format:
addalias a/<ALIAS_NAME> i/<INPUT>
There are two kinds of alias you can make, aliases which act as a standalone command, or an alias which accepts arguments.
Variation 1: Standalone
You can store an entire command using an alias
, and then use this alias
in place of that command. For example:
addalias a/chicken i/ addexpense d/ chicken rice p/2.30 c/food
This saves the command addexpense d/ chicken Rice p/2.30 c/food
to chicken
. Subsequently, you may use
this alias in place of using the full command.
Variation 2: with arguments
You may also save an incomplete input to an alias
. For example:
addalias a/ addfood i/ addexpense c/Food
Subsequently, entering the following:
addfood d/chickenrice p/2.30
is equivalent to entering:
addexpense c/Food d/chickenrice p/2.30
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. |
Alias feature
The Alias feature allows users to assign inputs they may use very often to a shortcut, and execute the input by entering
the shortcut, (a.k.a Alias
), in place of the full or partial command.
Implementation
These user defined Alias
es are saved in an AliasMappings
object within UserPref
as seen in the above diagram.
Internally, the AliasMappings
object stores an Alias
in a Map<Strings, Alias> object. With the addition of AliasMappings
object to UserPref
,
UserPref
supports these additional operations:
-
UserPref#addUserAlias(Alias)
— Saves a specifiedAlias
to the user preferences for future use. -
UserPref#hasAlias(String)
— Query if the there is anAlias
with this name already defined. -
UserPref#getAlias(String)
— To get anAlias
with this name if it exists. -
UserPref#aliasNameIsReservedCommandWord(Alias)
— To query if thisAlias
is uses a name which clashes with existing built-in commands. -
UserPref#aliasCommandWordIsAlias(Alias)
— To query if thisAlias
input
begins with anotherAlias
, this is used to validate that anAlias
will not cause an infinite loop by chaining multiple aliases in a loop. -
UserPref#getAliasMappings()
— To access theAlias
saved by the user. -
UserPref#setAliasMappings(AliasMappings mappings)
— To overwrite all theAlias
saved by the user.
Alias creation
In order for the user to save an Alias
, they first define it using the AddAliasCommand
. The AddAliasCommand
command extends
UndoableCommand
to allow users to undo defining an Alias
. The following sequence diagram describe in more detail how an Alias
is added.
-
The user enters a command with the following syntax
addalias a/ <name> i/ <input>
. -
The
UI
passes this command string to theLogicManager
which passes it onto theMooLahParser
. -
The parser extracts the argument string and passes it to an
AliasCommandParser
.
-
The
AliasCommandParser
uses theArgumentTokenizer
to tokenize the argument string and extract thealias name
andinput
fields into anArgumentMultimap
. -
The arguments are obtained and to create a new
Alias
using the theAlias
parser inParserUtil
. -
An
AddAliasCommand
is created containing this newAlias
to add to theUserPref
. -
This is passed back to the
LogicManager
to callAddAliasCommand#run()
.
-
The
AddAliasCommand
is validated usingAddAliasCommand#validate()
. TheAlias
is checked to ensure it does not-
a. Have a clashing name used by an existing
Command
as a CommandWord. -
b. Have an input beginning with a supported
Alias
.
-
-
If it is not valid, an exception is thrown.
-
If it was validated that the
Alias
can be added. -
The
Alias
is then added to theAliasMappings
object withinUserPref
. -
The
Alias
is now usable by the user.
Usage of aliases in input
When a user enters an input
to be executed, the MooLahParser
will do the following:
-
Attemps to parse the
input
as an input which begins with a validCommandWord
-
If that fails, it will try to parse it as an input which begins with an
Alias
.-
If it successfully does so, it replaces the alias in the original
input
with theinput
stored in theAlias
. -
Finally, the
MooLahParser
re-parses the modifiedinput
.
-
-
If this too fails, an exception is thrown indicating that the command was invalid