Role: Team Lead, Developer, Git Expert
Responsibilities: DevOps, Integration, Scheduling and tracking
Overview
Student Planner is a all-in-one desktop manager application that allows students to manage their contacts, tasks, events and expenses. The user interacts with it using a CLI, and it has a GUI created with JavaFX. It is written in Java, and has about 10 kLoC.
Summary of contributions
-
Major enhancement: added the ability to backup and restore user data
-
What it does: allows the user to backup current user data both online and locally. Backups can be restored by using the restore command.
-
Justification: This feature improves the product significantly because our target users have the app on many desktops and this provides a convenient way to synchronise them among many devices.
-
Highlights: This enhancement enables a generic class that can be easily extended by developers to support more types of online backup services in future. It requires an in-depth analysis of design alternatives. The implementation too was challenging as the backing up and restoring of online data may take a long time, existing implementation will cause the application to freeze until any backup is completed. The current implementation exhibits a working knowledge of multithreaded applications, concurrency, event driven programming as well as GUI application design.
-
Credits: GitHub Api by kohsuke.
-
-
Code contributed: [Overview]
-
Other contributions:
-
Project management:
-
Managed all releases on GitHub
-
Configure and added coveralls and related DevOps tools
-
-
Enhancements to existing features:
-
Modified/added additional tests for existing features
-
-
Documentation:
-
Setup, refactored and modified most of the initial documentation prior to v1.1
-
Did cosmetic tweaks to existing contents of the User Guide
-
-
Community:
-
Tools:
-
Integrated a third party library (Github Api by kohsuke) to the project (https://github.com/kohsuke/github-api)
-
Integrated a new Github App (Travis.com) to the team repo
-
This is different from other teams still using the old deprecated OAuth Flow used on the older Travis.org domain
-
-
-
Contributions to the User Guide
Given below are snippets of sections I contributed to the User Guide. They showcase my ability to write documentation targeting end-users. |
Backup data : backup
Allow user to backup data locally or to online services.
Format: backup | [GITHUB ACCESS_TOKEN]
Examples:
-
backup
Creates a local backup to the backup paths inpreferences.json
. -
backup github ACCESS_TOKEN_HERE
Creates an online backup to GitHub Gists using the provided personal access token.
Contributions to the Developer Guide
Given below are snippets of 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. |
Backup Feature
Backups Types
The application supports both local and online backups
Backup and Restore Storage Implementation
A OnlineStorage
interface must be implemented by all forms of Online backup and restore services. This allows developers to easily add and extend the list of supported backup services by implementing a common set of methods.
The current minimum set of methods that must be implemented are
-
OnlineStorage#saveContentToStorage
. -
OnlineStorage#readContentFromStorage
.
For local backups, the book specific {Book}Storage
interface adapted from AddressBookStorage
are implemented and used.
Design Considerations
Aspect: How is the backup command initiated
The backup mechanism is unique from the other command implementation as the execution of a BackupCommand
uses an event driven approach to activate a backup request instead of going through the model manager. Backup command is executed this way
because of the following reason.
Backup requires the current in memory book data inside the Model
, however the execute
function is actually passed our model
containing the required books data. We can raise a backup event directly with the books data provided in the model we have access too
The raised event is observed and handled by the storage manager which performs the backup (either local or through supported online services) using the books from the model
passed in through the OnlineBackupEvent
or LocalBackupEvent
The Sequence Diagram below shows how the components interact for the scenario where the user issues the local backup command backup
.
backup
command (local backup)
Note how Logic simply raises a LocalBackupEvent instead of posting the backup request from the Model . This is because logic has the model
and can simply pass the required data along in the event to storage directly.
The event is propagated through the EventsCenter to the Storage and UI bypassing the Model
|
The Sequence Diagram below shows how the components interact for the scenario where the user issues the online github backup command backup GITHUB AUTH_TOKEN
.
backup GITHUB AUTH_TOKEN
command (online github backup)Aspect: Implementation of performing backup
-
Alternative 1 (current choice): Performing backup of data files using worker threads.
-
Pros: Solves the age old problem of a graphical application appearing to freeze which can away end user experience as when the main JavaFX thread is blocked as is the case in the inherited default AB4 codebase
-
Cons: Difficult to ensure that threads have no unsafe threads operations especially since we are dealing with file storage. Cross thread exception is difficult to handle. Difficult to ensure that no two threads attempt to access the same resource. Inter-thread synchronisation and cross thread exception handling is difficult too. we have to implement a way to check when all threads are complete and signal the main ui thread to provide user with a proper success or failure notification
-
-
Alternative 2: Utilise the existing implementation of blocking the main GUI thread whenever a file storage operation is being performed
-
Pros: No work needed in implementation.
-
Cons: Notable freezes in Student Planner application even for small files. User cannot perform any other operation while backup is being performed
-
Further justification
Concurrency is not a topic commonly taught in beginning software engineering classes. The class that this application was created for is no exception. The common reason for this is that concurrency and multithreading are two slightly advanced topics that students will not usually touch in beginning modules. However, one can consider this to be a paradox as most beginner software engineering modules will involve the creation of an application with graphical output which usually consists of long running operations which should not be handled or performed on the main GUI thread. This is the best time to teach students about using worker or background threads to prevent main GUI thread from blocking operations such as file I/O, it is also the most succinct demonstration of the need for concurrency.
Command Flow
When a user enters a backup command to perform data backup. BackupCommand#execute
raises a LocalBackupEvent
or a OnlineBackupEvent
.
The StorageManager
subscribes to the events and will perform the backup of the various books such as ReadOnlyAddressBook
, ReadOnlyExpenseBook
etc provided in the event payload. This allows us to separate
backup concerns from the Model as explain above earlier, in a similar manner, the storage component is also decoupled from the model component with regards to backup operations.
For example in the case of saving backup data to GitHub. We have the flow of steps.
-
After a correct backup command is entered by the user,
BackupCommand#execute
raises aOnlineBackupEvent
with the payload consisting ofOnlineStorage.Type
, the various book models, and a authentication token. -
StorageManager#handleOnlineBackupEvent
callsbackupOnline
which starts anExecutorService
to perform data backup to Github storage with worker tasks fromgetOnlineBackupTask
To prevent the main JavaFX UI thread from freezing during the entire duration of the online backup, worker threads are used to performs the online backup without blocking the main thread.
Tasks created using
javafx.concurrent.tasks
allows us to use task handlers which run in the context of the main JavaFX application thread.This allows us to capture any thrown exceptions in the worker thread and show to the user in the form of a error popup.
backupTask.setOnFailed(event -> { raise(new DataSavingExceptionEvent((Exception) backupTask.getException())); });
This multi-threaded approach allows us to perform long running tasks on worker threads while still waiting for all backup threads to complete before showing success notification for the user.
backupTask.setOnSucceeded(event -> { raise(new NewResultAvailableEvent(backupTask.getMessage())); raise((OnlineBackupSuccessResultEvent) backupTask.getValue()); });
-
The specific online service that implements the
OnlineStorage
interface will be called. In this example,GithubStorage#saveContentToStorage
is called for the respective data books which utilises a third party Github API Library to create and save gists to GitHub. -
When each backup task for each book data is completed, a
OnlineBackupSuccessResultEvent
is raised by thesetOnSucceeded
task handler. -
Model#handleOnlineBackupSuccessResultEvent
receives the event and updates theUserPrefs
model based on the gist id returned from the successful backup -
A
UserPrefsChangedEvent
is fired which is handled byStorage
which saves the updatedUserPrefs
to storage. -
A
NewNotificationAvailableEvent
is also fired. This event is handled by theUiManager
which callsshowNotification
that creates a new notification and shows it to the user.
Restore Feature
Restore Types
The application supports both local and online restore of backup made using the backup
feature
-
For local restore, the backup book files specified in
preferences.json
will be used. -
For online restore, for example Github restore, the gist ids in
preferences.json
which represent the reference url to the backup data files will be used.
Design Considerations
Aspect: How is the restore command initiated
The restore feature is similar to backup feature in terms of both features using an event driven approach to reduce coupling and increase cohesion of the different components, specifically
the model
and storage
components.
Restore commands sends either a LocalRestoreEvent
or a OnlineRestoreEvent
event
The raised event is observed and handled by the storage manager which performs the reading of the local or online files into the appropriate data book objects such as ReadOnlyAddressBook
An event is then triggered by storage
on successful restore which informs model
that an update to the in memory state is required.
Backup of data
-
Backup of data to local storage
-
Prerequisites: Backup file paths in
preferences.json
has default file path values before application is started
Test case:backup
Expected: All books data is backup to file paths located frompreferences.json
. Notification is shown to user that local backup is successful. -
Prerequisites: Backup file paths in
preferences.json
isnull
before application is started
Test case:backup
Expected: All books data is backup to default file paths located underdata
directory.preferences.json
will also be updated with default backup file paths. Notification is shown to user that local backup is successful. -
Prerequisites: Backup file paths in
preferences.json
are directories before application is started
Test case:backup
Expected: All books data is backup to default file paths located underdata
directory.preferences.json
will also be updated with default backup file paths. Notification is shown to user that local backup is successful.
-
-
Backup of data to online storage service
-
Test case:
backup GITHUB VALID_AUTH_TOKEN
Expected: Book data is saved to Github gists. Status message updates to show successful backup. Success notifications with the corresponding data backup urls will be created and shown to user. -
Test case:
backup INVALID
Expected: No backup is performed. Invalid online service or command details shown in status message with command usage. -
Test case:
backup GITHUB
Expected: No backup is performed. Invalid github backup command details shown in status message as no authentication token is provided. -
Test case:
backup GITHUB invalidToken
Expected: Command is executed but error popup with "Could not save data to file" appears due to invalid auth token provided. Status bar updates to show backup failed. -
Test case:
backup service invalid invalid
Expected: No backup is performed. Invalid command details shown in status message with command usage.
-