PROJECT: Deadline Manager
This portfolio serves to document my contributions in a team-based project for CS2103T Software Engineering. The module spans 6 weeks, culminating in a final product: Deadline Manager that is designed with features catering to students from NUS School of Computing. The project is completed with a team of 5 members, and our portfolios are located at team page.
1. Overview
Deadline Manager is an easy-to-use application to assist students in managing deadlines. Interacting through a Command Line Interface (CLI), users can easily manage their schedules and focus on what is most important. Deadline Manager is written in Java and builds upon AddressBook Level 4, a code base originally designed to teach Software Engineering principles. For more information and to take our project for a test run, please visit our home page [on GitHub].
2. Summary of Contributions
-
Major enhancement: added the ability to import to and export from Deadline Manager
-
What it does: This feature allows users to export a selection of tasks to a file. This file can be shared with friends, who can then import it to their own Deadline Manager. Furthermore, users can export their tasks as Comma Separated Values (CSV) format, which is compatible with other major Calendar applications.
-
Justification: Our Deadline Manager is targeted at users within NUS School of Computing. As most assignments/deadlines are common to the entire module, the ability to import/export tasks is essential as it allows students to share and remind each other of their schedules. Furthermore, even professors can make use of the import/export feature to update and remind students of upcoming assessments. The ability to export as CSV format further improves the user experience, as users can switch seamlessly to other major Calendar services such as Google Calendar.
-
Highlights: It is necessary to account for the various file I/O operations behaviour on different Operating Systems, and extensive testing is required. Furthermore, significant design consideration is required to ensure optimal user experiences are there are many potential usage scenarios. For example, it is likely that users may import duplicate tasks. To cater to the different scenarios, an entire ImportConflictResolver class is implemented to provide flexibility and simplicity for the user when importing.
-
Credits: The resource at CSV format compatible with Google Calendar provides specifications for exporting in CSV format.
-
-
Minor enhancement: changed how parameters are parsed by the app.
-
What it does: This enhancement makes changes to the parser so that an appropriate error will be thrown when the user provides duplicate parameters. This is in contrast to AddressBook - Level 4, where the app ignores repeated parameters (e.g. specify
name
more than once). -
Justification: The previous implementation can be confusing for the user as Deadline Manager silently ignores repeated parameters. The enhancement instead provides visual alert to the user so that erroneous commands can be rectified.
-
-
Other contributions:
-
Project management:
-
Enhancements to existing features:
-
Added additional checks to detect potential errors in file I/O operations (e.g. saving).
-
Refactored unit test for
AddCommandTest
by creatingModelStub
, a class containing scaffolding code common to other types ofCommandTest
. -
Fixed indentation to align coding style with OSS Style Guide: #315
-
-
Documentation:
-
Rewrote introduction chapters and add more signposting for Developer Guide, so that Developer Guide is more structured and easier to understand: #129
-
-
Community:
-
Tools:
-
Integrated TravisCI to the project to the team repo.
-
-
3. Contributions to the User Guide
Given below is an excerpt of sections I contributed to the User Guide. They showcase my ability to write documentation targeting end-users. |
3.1. Exporting a set of tasks: export
Exports the tasks that is currently displayed by the Deadline Manager. The tasks will be saved as a file at the provided FILEPATH
location.
Deadline Manager provides two different formats to export in.
-
eXtensible Markup Language (XML) format: XML is a format that Deadline Manager is fully compatible with. If exported as XML format, tasks can be imported back into another copy of Deadline Manager.
-
Comma Separated Values (CSV) format: CSV is a format that is supported by most calendar applications. If exported as CSV format, tasks can be imported into other applications like Google Calendar. Currently, Deadline Manager can only export names and deadlines of tasks.
Format: export [csv] p/FILEPATH [r/overwrite]
Examples:
-
export p/cs2101.xml
Creates and exports tasks tocs2101.xml
in the same folder as Deadline Manager. This file can be used in import later.
The following is a step-by-step guide on how the export command behaves.
Figure 3.9.1 (left) shows the sequence of events, starting from when the user enters the export p/cs2101.xml
command into the command box.
Figure 3.9.1 (right) shows Deadline Manager exporting the file and displaying a success message. The exported file is located at cs2101.xml in the same folder, and contains the tasks displayed in the deadline manager, namely "CS2101 Oral Presentation" in the screenshot above.
-
export p/cs2101.txt
(Exports a file successfully)
export p/cs2101.txt
Fails and returns an error ascs2101.txt
already exists when the second command is run. In order to protect your data, the second export command fails. -
export csv p/cs2103.csv
Creates and exports tasks tocs2103.csv
as CSV format. This file is compatible with most calendar applications and can be imported into Google Calendar. -
export p/"C:\Documents\cs2103.txt"
Creates and exports tasks tocs2103.txt
in theC:\Documents
folder.
3.2. Importing a set of tasks: import
Imports tasks that were previously generated by an export command. Deadline Manager will attempt to retrieve tasks from the provided FILEPATH
location.
Format: import p/FILEPATH [r/all | r/overwrite | r/skip]
Optional commands can provided to specify what Deadline Manager should do when there is an import conflict.
An import conflict occurs when you try to import a task, but the task (having the same name, deadline and other attributes) already exists in your Deadline Manager. When this happens, Deadline Manager needs to know what you want to do with these tasks. |
You can input either one of three commands to specify how to resolve an import conflict:
-
r/all
: Imports the new task, keeping both the existing and incoming tasks. -
r/overwrite
: Imports the new task, replacing the existing task. -
r/skip
: Does not import the conflicting task, keeping the existing task instead.
If you do not specify any command, Deadline Manager uses r/skip by default, i.e. it will ignore new tasks that cause import conflicts.
|
Examples:
-
(Assuming that we have previously exported to
cs2101.xml
)
import p/cs2101.xml r/all
Imports all tasks fromcs2101.xml
. Deadline Manager will save all tasks, even if duplicates already exist.
In Figure 3.10.1 (left), we assume that the user has previously exported to cs2101.xml
, which contains another copy of "CS2101 Oral Presentation". The user now attempts to import from cs2101.xml
.
The result of the import is shown in Figure 3.10.1 (right). Since the r/all
command is used, both copies of "CS2101 Oral Presentation" are saved.
-
import p/cs2101.xml
Imports all tasks fromcs2101.xml
. Since the r/all parameter is not specified, if an incoming task already exists in Deadline Manager, it is skipped.
4. Contributions to the Developer Guide
Given below is an excerpt of the Import/Export section that I contributed to the Developer Guide. They showcase my ability to write technical documentation and the technical depth of my contributions to the project. |
4.1. Import and export feature
The deadline manager supports import and export features. This feature uses 2 components: Storage
and Model
.
This section will first provide an overview into the components and API involved, before focusing on interactions between the components.
4.1.1. Current implementation
This section will give an overview of how the import and export features work with Model
and Storage
.
Overview of components
Internally, StorageManager
implements the following APIs from ImportExportStorage
interface:
-
importTaskCollection
: Given a filename, imports and returns aTaskCollection
. -
exportTaskCollection
: Given aTaskCollection
, exports and writes to a specified file.
An ImportExportExceptionEvent is raised if Deadline Manager fails to read or write files for any reason. |
The complementary ModelManager
implements the following APIs necessary for Import and Export:
-
importTaskCollection
: Creates and posts a new import request event -
exportTaskCollection
: Creates and posts a new export request event.
The request events are posted to the EventCenter
, which will dispatch to all subscribed components, such as Storage
.
Inter-component communication
To facilitate communication between the two components, the deadline manager uses the event-driven model.
An import or export request event is created by ModelManager
, and a handler in StorageManager
is invoked to handle the event.
After data has been successfully read or written, the response is placed in a DataAvailableEvent
for ModelManager
to process. Similarly, errors also are passed between the two components using events (such as ImportExportExceptionEvent
).
Due to space constraints, detailed technical implementation of inter-component communication is omitted, and an overview is presented below in Sequence Flow instead. You may wish to refer to the Developer Guide for details. |
4.1.2. Sequence flow
The above interactions between Model
and Storage
can be illustrated with the following sequence diagrams.
The figure above shows the sequence diagram for the interaction that happens when the user requests to export tasks.
Step 1. The user types in an export command. The Logic component parses the user’s command, and calls ModelManager’s exportTaskCollection
.
Step 2. The ModelManager
posts an ExportRequestEvent
to the EventsCenter
.
Step 3. The EventsCenter
dispatches the ExportRequestEvent
to Storage
.
Step 4. Storage
handles the ExportRequestEvent
and writes to file. At this stage, the export is complete.
A similar interaction is seen when importing from a file.
The sequence diagram above shows the interactions that happen when a user attempts to import data from a file. The interactions are similar to export, with an additional step to resolve import conflict.
Due to space constraints, the step-by-step description for the import sequence diagram is omitted as the process is similar to export. Please refer to the Developer Guide for details. |
4.1.3. Import conflict resolver
An imported task is deemed conflicting with an existing task if the two tasks compare equal
with the internal implementation of Task’s equal
method.
If the user attempts to import a new conflicting task, Deadline Manager de-conflicts the task with one of the following resolvers:
-
IgnoreImportConflictResolver
: Discards the incoming task in favour of the existing task. -
OverwriteImportConflictResolver
: Updates the existing task to reflect the values of the incoming task. -
DuplicateImportConflictResolver
: Keep both copies.
The user can specify the de-conflict algorithm with flags. By default, the IgnoreResolver
is used.
Given below is a sequence diagram to illustrate the interactions between ModelManager
and OverwriteImportConflictResolver
. While OverwriteImportConflictResolver
is used as an example, the interactions with IgnoreImportConflictResolver
and DuplicateImportConflictResolver
are similar.
Step 1. After requesting for import, Storage returns the Tasks
that are serialised from file through an ImportDataAvailableEvent
. This event is dispatched to ModelManager
via EventsCenter
.
Step 2. ModelManager
retrieves the TaskCollection data, and for each task, ModelManager
checks whether the task already exists in the Model.
Step 3a. If the task already exists, the functional method resolve(() → add(), () → delete(), task)
is invoked. The Functional Programming style is used here, and ModelManager passes a reference to its add
and delete
methods.
Step 3b. OverwriteImportConflictResolver
will first delete()
the existing task, before it calls add()
on the new one. This behaviour is specific to OverwriteImportConflictResolver
. A DuplicateImportConflictResolver
will simply add the new entry, while a IgnoreImportConflictResolver
will do nothing.
Step 4. Otherwise, if the task doesn’t exist, ModelManager
simply adds the task to the model.
4.1.4. CSV format support
The discussion above has been format-agnostic, abstracting away details about the file formats. Deadline Manager supports both eXtensible Markup Language (XML) and Comma Separated Values (CSV) format.
Due to space constraints, detailed technical discussion of the CSV implementation is omitted, and is summarised with the following Sequence Diagram instead. This diagram is also replicated in Storage .
|
Notably, TaskCollectionReadStorage
and TaskCollectionWriteStorage
represents the disk reading and writing capabilities respectively; file format implementations can choose to support reading only, writing only, or both.
4.1.5. Design considerations
Aspect: Communication between Model
and Storage
Both the Model
and the Storage
components are required for import/export. However, they are separate components, and we need to establish a method of communication between the two components.
-
Alternative 1 (current choice):
Model
is maintained as being separate fromStorage
. The event-based style is used: an Import/Export event is created to signal a request, and another Import/Export event is created to signal that the data is ready.-
Pros:
Storage
is decoupled fromModel
, i.e. changes toModel
will not affect changes toStorage
, and vice versa. This is a good OOP practice. -
Cons: It is more difficult to implement and more overhead is incurred in passing data around. Calls are not immediate, and there is no way to immediately tell whether an execution succeeded or failed.
-
-
Alternative 2: Model executes an import/export method in Storage directly.
-
Pros: The data from the import/export request can be retrieved immediately and easily.
-
Cons:
Model
is more tightly coupled withStorage
, i.e.Model
andStorage
will no longer be separate components, but will instead know the inner workings of each other.
-
Aspect: How to resolve import conflicts
As described in Import conflict resolver, an import conflict arises when the user attempts to import tasks that already exist in Deadline Manager. We need an import conflict resolver to determine how to deal with these tasks.
-
Alternative 1 (current choice): An
ImportConflictResolver
class is implemented to resolve import conflicts. The user specifies which resolver algorithm to use, and the corresponding{Method}ImportConflictResolver
object is created to resolve import conflicts.-
Pros: This provides more flexibility for user to define how to resolve imports. Additionally, this is better Software Engineering practice as it follows the Single Responsibility Principle: the
ImportConflictResolver
object is responsible only for its own algorithm. -
Cons: It is more difficult to implement an entirely separate
ImportConflictResolver
class, complete with separate sub-classes for different algorithms.
-
-
Alternative 2: Use an
enum
to implement ImportConflictResolver. TheImportConflictResolver
enum provides a pre-defined selection of algorithms that the user can specify.-
Pros: There is no need to implement separate classes. Since the
ImportConflictResolver
enum is only useful within Model, it reside within Model as a private variable. -
Cons: If/else statements are required to determine which algorithm should be used. Additionally, an
ImportConflictResolver
implemented this way cannot be easily reused or extended.
-
Due to limited space in the PPP, an aspect on supporting different file formats is omitted. Please refer to the Developer Guide for more details. |