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 Aliases 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 specifiedAliasto the user preferences for future use. -
UserPref#hasAlias(String)— Query if the there is anAliaswith this name already defined. -
UserPref#getAlias(String)— To get anAliaswith this name if it exists. -
UserPref#aliasNameIsReservedCommandWord(Alias)— To query if thisAliasis uses a name which clashes with existing built-in commands. -
UserPref#aliasCommandWordIsAlias(Alias)— To query if thisAliasinputbegins with anotherAlias, this is used to validate that anAliaswill not cause an infinite loop by chaining multiple aliases in a loop. -
UserPref#getAliasMappings()— To access theAliassaved by the user. -
UserPref#setAliasMappings(AliasMappings mappings)— To overwrite all theAliassaved 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
UIpasses this command string to theLogicManagerwhich passes it onto theMooLahParser. -
The parser extracts the argument string and passes it to an
AliasCommandParser.
-
The
AliasCommandParseruses theArgumentTokenizerto tokenize the argument string and extract thealias nameandinputfields into anArgumentMultimap. -
The arguments are obtained and to create a new
Aliasusing the theAliasparser inParserUtil. -
An
AddAliasCommandis created containing this newAliasto add to theUserPref. -
This is passed back to the
LogicManagerto callAddAliasCommand#run().
-
The
AddAliasCommandis validated usingAddAliasCommand#validate(). TheAliasis checked to ensure it does not-
a. Have a clashing name used by an existing
Commandas 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
Aliascan be added. -
The
Aliasis then added to theAliasMappingsobject withinUserPref. -
The
Aliasis 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
inputas 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
inputwith theinputstored in theAlias. -
Finally, the
MooLahParserre-parses the modifiedinput.
-
-
If this too fails, an exception is thrown indicating that the command was invalid