Introduction
This portfolio is meant to document my overall contributions to the CS2103T Software Engineering Project, Billboard.
Overview
In this project, we form a team of five to develop a cross platform financial tracking application Billboard. Billboard is for those who prefer to use desktop applications to manage and keep track of their expenses. Billboard is optimized for those who prefer to work with a Command Line Interface (CLI) while still enjoying all the benefits of having a fully fledged Graphical User Interface (GUI). It is written in Java, and has about 15 kLoC.
The following is the UI of Billboard:
Summary of contributions
-
Major enhancement: added the feature to undo/redo commands
-
What it does: allows you to undo all previous commands one at a time. The counter command redo can reverse the undone commands.
-
Justification: This feature improves the product significantly because it provides a convenient way for to user to rectify the mistakes made in previous commands.
-
Highlights: This enhancement affects existing and future commands. It required an in-depth analysis of design alternatives. The implementation too was challenging as it required deep copy of existing Billboard.
-
-
Minor enhancement:
-
added a history command that allows the user to view all the previous commands.
-
added a feature that allows the user to to navigate to previous commands using up/down keys.
-
-
Code contributed: [Functional code]
-
Other contributions:
-
Project setup:
-
Restructured the previous AddressBook Level-3 project to Billboard. Deleted the dead code and added attributes for Billboard. #1
-
-
Documentation:
-
Community:
-
Tools:
-
Applied Statistic Tool to get the statistics of the project.
-
-
Contributions to the User Guide
Given below are sections I contributed to the User Guide of Billboard, including the usage of features that I implemented such as undo/redo, history and up/down navigation, but due to the page limitation, I am only able to show the undo/redo user guide to you. It showcase my ability to write good documentation for target users.
Undo and Redo: undo/redo
-
Undo the previous action: undo
You can useundo
command restore the previous billboard state from state history.undo
will ignore the parameter you key in.
Usage:undo
-
Redo the previous undo action: redo
You can useredo
command to redo a previously undone command and restore undone billboard state from state history.redo
will ignore the parameter you key in.
Usage:redo
Contributions to the Developer Guide
Given below are sections I contributed to the Developer Guide of Billboard, including the technical information of features that I implemented such as undo/redo, history and up/down navigation, but due to the page limitation, I am only able to show the undo/redo developer guide to you. It showcase my ability to write good technical documentation for potential developers, and the technical depth of my contributions to the project.
Undo/Redo feature
Implementation
The undo/redo mechanism is facilitated by VersionedBillboard
.
If you successfully execute a command that will change the Billboard state,
the current Billboard state will automatically commit to the VersionedBillboard
.
The current state will be store into the stateList
,
and a state pointer currentStatePointer
will be maintained.
List of command that will commit to VersionedBillboard: - AddArchiveCommand - AddCommand - AddTagCommand - ClearCommand - DeleteArchiveCommand - DeleteCommand - RevertArchiveCommand - EditCommand - RemoveTagCommand
Additionally, it implements the following operations:
-
VersionedBillboard#commit()
— Saves the current billboard state in its history. -
VersionedBillboard#undo()
— Restores the previous billboard state from its history. -
VersionedBillboard#redo()
— Restores a previously undone billboard state from its history.
These operations is exposed in the VersionedBillboard
class as VersionedBillboard#commit()
., VersionedBillboard#undo()
and VersionedBillboard#redo()
respectively.
Given below is an example usage scenario and how the undo/redo mechanism behaves at each step.
Step 1. The user launches the application for the first time. The VersionedBillboard
will be initialized with the initial billboard state, and the currentStatePointer
pointing to that single billboard state.
Step 2. The user executes delete 5
command to delete the 5th expense in the billboard. The delete
command calls VersionedBillboard#commit()
, causing the modified state of the billboard after the delete 5
command executes to be saved in the stateList
, and the statePointer
is shifted to the newly inserted billboard state.
Step 3. The user executes add n/buy …
to add a new person. The add
command also calls Model#commit()
, causing another modified billboard state to be saved into the stateList
.
If a command fails its execution, it will not call VersionedBillboard#commit() , so the billboard state will not be saved into the stateList .
|
Step 4. The user now decides that adding the expense was a mistake, and decides to undo that action by executing the undo
command. The undo
command will call VersionedBillboard#undo()
, which will shift the currentStatePointer
once to the left, pointing it to the previous billboard state, and restores the billboard to that state.
If the currentStatePointer is pointing to the initial billboard state,
then there are no previous billboard states to restore.
The undo command uses VersionedBillboard#isRedoable() to check if this is the case.
If so, it will return an error to the user rather than attempting to perform the undo.
|
The following sequence diagram shows how the undo operation works:
undo
Command
The lifeline for UndoCommand should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of diagram.
|
The redo
command does the opposite — it calls VersionedBillboard#redo()
, which shifts the currentStatePointer
once to the right, pointing to the previously undone state, and restores the billboard to that state.
If the currentStatePointer is at index stateList.size() - 1 , pointing to the latest billboard state, then there are no undone billboard states to restore. The redo command uses VersionedBillboard#isRedoable() to check if this is the case. If so, it will return an error to the user rather than attempting to perform the redo.
|
Step 5. The user then decides to execute the command list
. Commands that do not modify the billboard, such as list
, will usually not call VersionedBillboard#commit()
, VersionedBillboard#undo()
or VersionedBillboard#redo()
. Thus, the stateList
remains unchanged.
Step 6. The user executes clear
, which calls VersionedBillboard#commit()
. Since the currentStatePointer
is not pointing at the end of the stateList
, all billboard states after the statePointer
will be purged. We designed it this way because it no longer makes sense to redo the add n/buy …
command. This is the behavior that most modern desktop applications follow.
The following activity diagram summarizes what happens when a user executes a new command:
Design Considerations
Aspect: How undo & redo executes
-
Alternative 1 (current choice): Saves the entire billboard.
-
Pros: Easy to implement.
-
Cons: May have performance issues in terms of memory usage.
-
-
Alternative 2: Individual command knows how to undo/redo by itself.
-
Pros: Will use less memory (e.g. for
delete
, just save the expense being deleted). -
Cons: We must ensure that the implementation of each individual command are correct.
-
Aspect: Data structure to support the undo/redo commands
-
Alternative 1 (current choice): Use a list to store the history of billboard states.
-
Pros: Easy for new Computer Science student undergraduates to understand, who are likely to be the new incoming developers of our project.
-
Cons: Logic is duplicated twice. For example, when a new command is executed, we must remember to update both
Model
andVersionedBillboard
.
-
-
Alternative 2: Use
HistoryManager
for undo/redo-
Pros: We do not need to maintain a separate list, and just reuse what is already in the codebase.
-
Cons: Requires dealing with commands that have already been undone: We must remember to skip these commands. Violates Single Responsibility Principle and Separation of Concerns as
HistoryManager
now needs to do two different things.
-