Developer Guide
- Setting up, getting started
- Design
- Implementation
- Documentation, logging, testing, configuration, dev-ops
- Appendix
Setting up, getting started
Refer to the guide Setting up and getting started.
Design
Architecture
The Architecture Diagram given above explains the high-level design of InternHunter. Given below is a quick
overview of each component. As seen in the diagram, InternHunter follows a multi-layered architecture whereby
components of lower layers are independent of higher layers. e.g. the Logic
component can make use of methods in
the Model
but not vice versa.
.puml
files used to create diagrams in this document can be found in the diagrams folder. Refer to the PlantUML Tutorial at se-edu/guides to learn how to create and edit diagrams.
Main
has two classes called Main
and MainApp
. It is responsible for,
- At app launch: Initializes the components in the correct sequence, and connects them up with each other.
- At shut down: Shuts down the components and invokes cleanup methods where necessary.
Commons
represents a collection of classes used by multiple other components.
The rest of the App consists of four components.
-
UI
: The UI of the App. -
Logic
: The command executor. -
Model
: Holds the data of the App in memory. -
Storage
: Reads data from, and writes data to, the hard disk.
Each of the four components,
- defines its API in an
interface
with the same name as the Component. - exposes its functionality using a concrete
{Component Name}Manager
class (which implements the corresponding APIinterface
mentioned in the previous point.
For example, the Logic
component (see the class diagram given below) defines its API in the Logic.java
interface and exposes its functionality using the LogicManager.java
class which implements the Logic
interface.
How the architecture components interact with each other
The Sequence Diagram below shows how the components interact with each other for the scenario where the user issues
the command delete me 1
to delete a profile item.
The sections below give more details of each component.
Ui component
Note: The class diagram for the Ui is a simplified version of the implementation. Generics are used in the implementation but is omitted in the class diagram.
API :
Ui.java
The Ui consists of a MainWindow
that is made up of parts e.g. CommandBox
, ResultDisplay
, ListPanel
, InformationDisplay
, Tabs
etc.
All these, including the MainWindow
, inherit from the abstract UiPart
class.
The Tabs
is located at the most left of the application and it consists of three tabs which defines the main three data item CompanyItem
, ApplicationItem
, ProfileItem
.
The ListPanel
is located at the center of the application and it consists of Ui CompanyCard
, ApplicationCard
, ProfileCard
to display key information of each data idea.
The InformationDisplay
appears at the right of the application and it consists of Ui CompanyDisplay
, ApplicationDisplay
, ProfileDisplay
. The InformationDisplay
displays the full information regarding the data item.
The ResultDisplay
and CommandBox
appears at the bottom of the application and the ResultDisplay
is above the
CommandBox
even though the Ui does not show it explicitly.
The Ui
components uses the JavaFX UI framework. The layout of these UI parts are defined in matching .fxml
files that are in the src/main/resources/view
folder. For example, the layout of the MainWindow
is specified in MainWindow.fxml
. The styling of the application is mainly at MainWindow.css
.
The Ui
component,
- Executes user commands using the
Logic
component. - Listens for changes to
Model
data so that the UI can be updated with the modified data.
Logic component
API :
Logic.java
-
Logic
uses theMainParser
class to parse the user command. - This results in a
Command
object which is executed by theLogicManager
. - The command execution can affect the
Model
(e.g. deleting an application). - The result of the command execution is encapsulated as a
CommandResult
object which is passed back to theUi
. - In addition, the
CommandResult
object can also instruct theUi
to perform certain actions, such as switching tabs or displaying the matching internships window to the user.
Given below is the Sequence Diagram for interactions within the Logic
component for the execute("delete app 1")
API call.
Model component
Breakdown of the Company, Internship and Application packages:
Breakdown of the Profile package:
API :
Model.java
The Model
,
- stores a
UserPrefs
object that represents the user’s preferences i.e. GUI settings and file paths of saved data. - stores the application data.
- exposes an unmodifiable
ObservableList
forCompanyItem
,ApplicationItem
andProfileItem
respectively, that can be ‘observed’ i.e. the UI can be bound to this list so that the UI automatically updates when the data in the list changes. - does not depend on any of the other three components.
Storage component
API :
Storage.java
The Storage component,
- can save UserPref objects in json format and read it back.
- can save the InternHunter data in json format and read it back.
Common classes
Classes used by multiple components are in the seedu.internhunter.commons
package.
Implementation
This section describes some noteworthy details on how certain features are implemented.
Command
classes
Implementation
There are 4 different subclasses of Item
in InternHunter, namely CompanyItem
, InternshipItem
, ApplicationItem
, and
ProfileItem
.
There are 2 types of commands:
- Commands that are dependent on the type of
Item
- e.g.
AddCommand
,DeleteCommand
,EditCommand
- These commands are implemented as abstract classes that inherit from the
Command
class. Type specific commands likeAddCompanyCommand
andAddApplicationCommand
inherit from the abstractAddCommand
class.
- e.g.
- Commands that are not dependent on the type of
Item
- e.g.
HelpCommand
,ExitCommand
- These commands are implemented as concrete classes and inherit directly from the
Command
class.
- e.g.
From this point on, we will be using ABCCommand
to represent commands that are dependent on type and
XYZCommand
to represent commands that are independent of type.
The following shows the class diagram for Command
and its subclasses:
Design considerations
Aspect: Whether ABCCommand
should be abstract and split into 4 other ABCItemCommand
or handle the 4 Item
types on its own
Alternatives considered
Alternative 1 (current choice): ABCCommand
is split into 4 other ABCItemCommand
. InternHunter parses the
user input and creates the specific ABCItemCommand
for execution. The following activity diagram shows how the
execution of the AddApplicationCommand
will work.
- Pros:
- Each command has its own specific task to execute. This means that classes are more flexible and can be changed very easily.
- Higher cohesion as the class is only dependent on the one
Item
type - Short and concise
execute
method, providing better readability and maintainability
- Cons:
- More classes have to be created
Alternative 2: ABCCommand
is a concrete class and handles the execution of all 4 Item
types.
InternHunter parses the user input and creates the general ABCCommand
for execution. The following
activity diagram shows how the AddCommand
will work.
- Pros:
- Only one command is needed, reducing the number of classes created
- Cons:
-
execute
method becomes extremely long as it needs to contain switch statements to handle the execution ofABCCommand
for the 4 different types ofItem
-
ABCCommand
class is vulnerable to drastic changes when the parsing method of any oneItem
class changes -
ABCCommand
class holds more dependencies as it is now dependent on the 4Item
classes - Poor readability and maintainability
- A slight overhead increase as
Item
type needs to be passed in as a parameter to theABCCommand
, additional check for nullity in the parameter passed in is required
-
Conclusion: Our group settled on the first design, since it better adheres to OOP principles such as
Single Responsibility Principle. Our design meant that each specific ABCItemCommand
is only dependent on the Item
itself and not subjected to the changes in implementation of the other Item
classes. This means that it will only
have one reason to change. Moreover, this leads to lower coupling, which makes maintenance, integration and
testing easier. This ended up being a good choice as we had some changes in the parsing requirements of one
of the Item
classes, InternshipItem
. If we had gone with the second design, the concrete ABCCommand
might
have broken down as it might not be suited to the different parsing requirements in the InternshipItem
.
Delete company feature
What it is
Users are able to execute a command to delete a company from their list of companies in InternHunter. Upon the successful deletion of a company, all internships within that company, if any, will also be deleted (as they are a part of the company, i.e. companies and the internships that they offer have a whole-part / composition relationship). As a result, all applications made to internships from the company to be deleted, if any, will also be deleted as per the delete internship feature. This feature is intended to be used when the user is viewing the Company tab. However, the user is free to execute the delete company command while they are on another tab, and InternHunter will simply switch over to the Company tab if and when the command has finished executing successfully.
Command format: delete com INDEX
- Where
INDEX
is the index of the company to be deleted in the list of companies
Implementation
Upon a user’s entry of a valid delete company command, a DeleteCompanyCommand
object is created.
DeleteCompanyCommand
is a class that extends the DeleteCommand
abstract class that in turn extends the
Command
abstract class.
DeleteCompanyCommand
implements the execute()
method from the Command
abstract class whereby upon execution, the
method will delete the respective company in the model’s list of companies if a valid index is given.
This is how the DeleteCompanyCommand#execute()
method works upon execution:
- The tab that the user is currently viewing is obtained via the
Model#getTabName()
method. - The company to be deleted is retrieved from the model’s
companyList
via theCommandUtil#getCompany()
method. - All the internships within the company, if any, are deleted via a self-invocation to
DeleteCompanyCommand
’s owndeleteAllInternshipsInCompany()
method. - The company is then deleted from the model via the
model#deleteCompany()
method. - The deletion is successful and a
CommandResult
is returned with an appropriate success message to indicate operation success via theCommandUtil#getCommandResult()
method. TheCommandResult
also indicates whether the tab needs to be switched to the Company tab or not, based on if the user was already viewing the Company tab or not as retrieved in Step 1.
The following sequence diagrams show how the delete company feature works successfully, using the example command
delete com 3
:
Sequence diagram for handle delete display switch index can be found here
Design considerations
Aspect: How applications made to internships from the company to be deleted are deleted
Alternatives considered
-
Alternative 1 (current choice): Delete all applications made to internships from the company to be deleted by
executing delete internship commands.
- Pros:
- Avoids rewriting code / code duplication by calling methods that have already been implemented to achieve the desired functionality.
- Ensures consistent behaviour - when an internship is deleted because a company is deleted, what happens to any application for that internship will be the same as what would happen to it if a delete internship command was executed directly by the user for the same internship.
- Cons:
- Introduces a dependency on
DeleteInternshipCommand
.
- Introduces a dependency on
- Pros:
-
Alternative 2: Delete all applications made to internships from the company to be deleted without executing
delete internship commands, i.e. by implementing delete internship command’s internal workings.
- Pros:
- Not dependent on
DeleteInternshipCommand
.
- Not dependent on
- Cons:
- Introduces dependencies on
InternshipItem
andApplicationItem
. - Violates the DRY principle:
- Introduces code duplication.
- Decentralizes the behaviour of what happens to an application made for an internship that is being deleted,
since there are now 2 separate implementations for this (one in
DeleteCompanyCommand
and the other inDeleteInternshipCommand
). The implications of this are:- Cannot guarantee consistent behaviour - when an internship is deleted because a company is deleted, what happens to any application for that internship may not be the same as what would happen to it if a delete internship command was executed directly by the user for the same internship.
- Updating this behaviour will require updating code in both places rather than one centralised place.
- Introduces dependencies on
- Pros:
User profile feature
What it is
The user profile feature behaves like a resume for the user to keep track of noteworthy events and milestones in one’s professional life.
There are three categories of profile items namely: achievement
, skill
and experience
. One of the operations
that can be applied on profile items is editing.
Editing user profile item
The edit me
command for the user profile allows the user to update the fields of the each profile item by
specifying the targeted index and at least one field.
Implementation
- The
edit me
command is implemented by theEditProfileCommandParser
andEditProfileCommand
. -
EditProfileCommandParser#parse(...)
method creates aEditProfileItemDescriptor
based on the fields of the input provided by the user. TheEditProfileItemDescriptor
is then used in instantiating theEditProfileCommand
by theEditProfileCommandParser
. -
EditProfileCommand
implements theexecute(...)
method from theCommand
abstract class whereby upon execution, the method will edit the specified profile item in the model’s profile list.
The following sequence diagrams show how the editing profile Item feature works successfully, using the example command
edit me 1 t/Learn HTML
:
- After the user enters an input to edit the user profile, the input is first parsed by the
MainParser
looks out for the command word, recognizes theedit
command and funnels the input toEditCommandParser
. - The
EditCommandParser
then identifies the item type, which is profile item and returns theEditProfileCommandParser
. - The
EditProfileCommandParser
then parses for the index and fields to be edited and returns aEditProfileCommand
containing a editProfileItemDescriptor. The following sequence diagram depicts how theEditProfileCommand
works:
- When
EditProfileCommand
is executed it which retrieves the targetedprofileItemToEdit
from thelastShownList
(which contains the profile items the user is able to see) and updates the model with theeditedProfileItem
created from theeditProfileItemDescriptor
using thecreateEditedProfileItem(...)
of theEditProfileCommand
. - CommandResult is return to indicate a successful operation.
Design considerations
Aspect: How Logic components interact with Model
Alternatives considered
-
Alternative 1 (current choice): Logic components interact with the model interface solely and not directly
with model’s internal components:
profileList
andFilteredList
in theprofileList
.- Pros:
- This obeys the Law of Demeter which stresses for components to avoid interacting directly with internal
components of other objects. This reduces coupling which increases testability as
EditProfileCommand
only requires one model stub as opposed to more objects stubs of the model for testing. - This also increases maintainability as
EditProfileCommand
only has to be concerned with the methods that Model interface provides and not the other implementation details should they be subjected to change.
- This obeys the Law of Demeter which stresses for components to avoid interacting directly with internal
components of other objects. This reduces coupling which increases testability as
- Cons:
- This increases code volume within
Model
as the model interface needs to provide every method to interact with all the collections it contains.
- This increases code volume within
- Pros:
-
Alternative 2 (used in v1.2): The model acts as a container for its collections, allowing clients to retrieve these collections and directly operate on it. For example,
FilteredList
andprofileList
are both retrieved from the model from within theEditProfileCommand
and then thesetItemList()
operation is called directly on theprofileList
to update its value.model.getProfileList().setItem(profileItemToEdit, EditedProfileItem)
The following sequence diagram shows how the logic components bypass with model interface to interact directly with the
FilteredList
and the profileList
:
- Pros:
- This reduces code volume by keeping the model interface lean as it no longer has to provide methods for all operations of its internal components.
- This may marginally improve performance as it bypasses the model interface to interact with the
profileList
andFilteredList
directly.
- Cons:
- This exposes the internal components of the
Model
which increases coupling asEditProfileCommand
is now dependent onFilteredList
and theItemListManager
which reduces testability and maintainability.
- This exposes the internal components of the
Switch screen feature
What it is
Users are able to execute a command to switch their tabs in InternHunter. There are 3 tabs: Company, Application, and Profile. Take for example, switching to the company tab. Upon the successful switching of tabs, the screen will display a list of companies and also display the information of the last known index of that tab, i.e if the index that was previously saved in that tab was the 3rd index, when switching back to this tab, it will show the information of the 3rd index.
Command format: switch TYPE
TYPE
is the type of tab.
There are three TYPE
s:
com
app
me
Implementation
Upon a user’s entry of a valid switch command, a SwitchCommand
object is created. SwitchCommand
is a class that extends the Command
abstract class as well as having direct association with TabName
, an enumeration, as well as having a dependency to the Model
interface as it relies on some of its method.
SwitchCommand
implements the execute(...)
method from the Command
abstract class whereby upon execution, the
method will switch the tab and the screen if a valid command is provided.
This is how the SwitchCommand#execute(...)
method works upon execution:
- The current tab that the user is viewing is obtained via the
Model#getTabName()
method. - The input tab will be check against the current tab.
2a. If both the tabs are the same, a same tab message will be passed toCommandUtil#getCommandResult(...)
method.
2b. If both the tabs are different, a success message will be passed toCommandUtil#getCommandResult(...)
method.
The overall process of how SwitchCommand
was generated:
The process of how SwitchCommand
interacts with the model:
This is how the CommandUtil#getCommandResult(...)
method works upon execution:
- The current tab that the user is viewing is obtained via the
Model#getTabName()
method. - The input tab will be check against the current tab.
2a. If both the tabs are the same, aCommandResult
with a same tab message is return.
2b. If both the tabs are different, we will change the tab to the input’s tab name viaModel#setTabName(...)
. ACommandResult
with a success message is return.
The process of how getCommandResult
is being generated:
The following activity diagram summarizes what happens when a user executes a switch command:
The above activity diagram shows the logic and the path execution when the switch command is executed. The code will check if there is any missing input or if the input is not one of the three mentioned in the Command format
above. If the aforementioned 2 conditions are not met, an error message is displayed. If the input is one of the three mentioned above in the Command format
, there will be further checks if the user are already in the same tab.
Design considerations
Aspect: Should the tabs be allowed to change only by the SwitchCommand
.
Alternatives Considered
-
Alternative 1 (current choice): Allow the switch of tabs to not only be accessible via the switch command, but rather extract it out for all commands excluding
exit
,help
andclear
.- Pros:
- Allows user to type once instead of twice when executing a single command and wanting to view it. (This optimization is to allow for a faster way to type and view the changes).
- By abstract the method out from switch command, it obeys the DRY principle as all the commands will be calling a single method.
- This allows and obeys the Open-Close principle as new implementation of commands can just be calling this single method at the end.
- Allows user to have a second alternative to switch tabs just for viewing purpose.
- Reduces some dependency between each commands as they would not need to call the switch command to switch tabs.
- Allows user to type once instead of twice when executing a single command and wanting to view it. (This optimization is to allow for a faster way to type and view the changes).
- Cons:
- User might switch tab accidentally because of inputting the wrong
TYPE
. - Increases some form of coupling between all commands as they are now linked to this single method.
- User might switch tab accidentally because of inputting the wrong
- Pros:
-
Alternative 2: Only allow switch command to be the only way to switch tabs.
- Pros:
- This introduces a “type-safe” checks like in Java where only if the user is in the correct tab, then he or she will be able to add items to that item type.
- Easier to implement.
- Cons:
- This introduces the need to type twice in order to view the execution of the command.
- Pros:
Storage feature
What it is
After a command is successfully executed, InternHunter automatically saves users’ data to JSON files. Moreover,
every time the GuiSettings
is modified, InternHunter updates the user preferences JSON file. Users can transfer or
backup the JSON files manually. The storage component is responsible for both reading and saving the data.
Implementation
InternHunter uses Jackson, a high-performance JSON processor for Java. It can serialize Java objects into JSON and
deserialize JSON into Java objects. InternHunter’s model has 4 different types of data: ApplicationItem
,
CompanyItem
, InternshipItem
, and ProfileItem
. They first need to be converted to Jackson-friendly versions of
themselves, where each field is a string or another Jackson-friendly object. User preference is saved as a UserPrefs
object.
-
Storage
handles the storage for allItem
lists and user preferences. -
UserPrefsStorage
handles the storage for user preferences. -
ItemListStorage
handles the storage forItem
lists. -
JsonSerializableItemList
represents a Jackson-friendly version of anItem
list. -
JsonAdaptedItem
represents a Jackson-friendly version of anItem
.
JsonAdaptedItem
is an abstract class representing a Jackson-friendly version of the Item
class in the model component.
It has one method toModelType()
which convert itself to an Item
object. There are 4 classes extending
JsonAdaptedItem
:
-
JsonAdaptedApplicationItem
the Jackson-friendly version ofApplicationItem
. -
JsonAdaptedCompanyItem
the Jackson-friendly version ofCompanyItem
. -
JsonAdaptedInternshipItem
the Jackson-friendly version ofInternshipItem
. -
JsonAdaptedProfileItem
the Jackson-friendly version ofProfileItem
.
InternHunter automatically saves user data after every command. The following sequence diagram demonstrates how
InternHunter does it. Let commandString
be any valid command string.
This is how the LogicManager#execute()
method works upon execution:
-
LogicManager
will execute the givencommandString
. -
LogicManager
calls theModelManager#getUnfilteredApplicationList()
to get the current application item list. -
LogicManager
calls theStorageManager#saveApplicationItemList(...)
to save the current application item list. -
LogicManager
calls theModelManager#getUnfilteredCompanyList()
to get the current company item list. -
LogicManager
calls theStorageManager#saveCompanyItemList(...)
to save the current company item list. -
LogicManager
calls theModelManager#getUnfilteredProfileList()
to get the current profile item list. -
LogicManager
calls theStorageManager#saveProfileItemList(...)
to save the current profile item list.
Design considerations
Aspect: How to handle 3 types of Item
list
InternHunter maintains 3 types of Item
lists: ApplicationItem
, CompanyItem
, and ProfileItem
lists.
Both ItemListStorage
and JsonSerializableItemList
use the same logic regardless of the Item
type.
Alternatives Considered
-
Alternative 1: current choice: Creates a base abstract class
JsonAdaptedItem
and makesItemListStorage
andJsonSerializableItemList
use generics.- Pros:
- Adheres to OOP principle, specifically polymorphism.
- Less code duplication.
- Makes adding a new
Item
type easy. To be able to save and read a newItem
type, only a new class representing its Jackson-friendly version needs to be created. - Makes further extension to the
ItemListStorage
andJsonSerializableItemList
faster.
- Cons:
- More complicated as Jackson does not provide a direct way to convert a generic object to its JSON format.
- Pros:
-
Alternative 2: Each
Item
type has their ownItemListStorage
andJsonSerializableItemList
.- Pros:
- Easier to implement.
- Cons:
- Much longer code with much duplication.
- Adding a new
Item
type requires at least 3 new classes to be made. - Extending the
ItemListStorage
andJsonSerializableItemList
class would require changes to all the different versions corresponding to the differentItem
types.
- Pros:
Clear feature
What it is
In the beginning, users can see how the app works with sample data. After that, users can decide to
clear all the entries in InternHunter with just a clear
command.
Implementation
The following diagram illustrates whether InternHunter uses sample data.
When users enters the clear
command, InternHunter will reset all three lists. Here is a sequence diagram showcasing how
InternHunter does it.
This is how the ClearCommand#execute()
method works upon execution:
- A new empty
ItemList
for the application item list is created. -
ModelManager#setApplicationList(...)
is called with the recently created empty list as the argument. - A new empty
ItemList
for the company item list is created. -
ModelManager#setCompanyList(...)
is called with the recently created empty list as the argument. - A new empty
ItemList
for the profile item list is created. -
ModelManager#setProfileList(...)
is called with the recently created empty list as the argument.
Design considerations
Aspect: How to clear the lists
InternHunter only lets users create applications for internships already added to companies. When users apply for an internship,
InternHunter will create an ApplicationItem
with the given InternsipItem
. Hence, InternHunter needs to
check whether the internships in both lists are consistent.
Alternatives Considered
-
Alternative 1: current choice: Clear all three lists at once.
- Pros:
- Guarantees data consistency.
- Cons:
- Less freedom for users.
- Pros:
-
Alternative 2: Clear each list individually.
- Pros:
- Users can choose which list to be cleared.
- Cons:
- High risk of data inconsistency due to the linkage between company and application lists.
- Pros:
Match command feature
What it is
Users are able to execute a command to generate a list of matching internships that matches their current profile
skills. This matching is done by filtering the list of profile items that has the category skill
and
using it to filter the list of internships. Remaining internships are those that consist of at least one
Requirement
that matches the user’s list of skills.
Command format: match
Implementation
MatchCommand
is a class that extends the Command
abstract class. It has a dependency to the Model
interface as it relies on getting the profile list and company list from the model.
Here is a class diagram to show how the MatchCommand
is implemented:
This is how the MatchCommand#execute(...)
method works upon execution:
- The list of profile items and company items are first obtained via the
Model#getProfileItemList()
method andModel#getCompanyItemList()
respectively. - Then, the list of profile skills that the user has is obtained via a self-invocation to
MatchCommand#getSkillList(...)
method. - Next, the list of all internships from the list of companies is obtained via its own
MatchCommand#getInternshipList(...)
method. - Then,
MatchCommand#getMatchingInternships(...)
is invoked to obtain the list of matching internships. - Finally,
MatchCommand#getMatchingInternshipsCommandResult(...)
method is used to generate theCommandResult
. This method returns a differentCommandResult
depending if the matchingInternships is empty or not.
5a. If the matchingInternships list is empty, then the no matching internships message will be passed to theCommandResult
.
5b. Otherwise, the showing matching internships message will be passed to theCommandResult
. This internship list will be passed intoCommandResult#setMatchingInternships(...)
method for display in the Ui.
The following sequence diagrams show how the match command works:
Design considerations
Aspect: How to generate the matching internships
Alternatives Considered
Alternative 1 (current choice): Methods to generate the matching internships, namely getSkillList
,
getInternshipList
, and getMatchingInternships
are implemented within MatchCommand
.
- Pros:
- Still adheres to the Single Responsibility Principle as the
MatchCommand
is meant to generate the list of matching internships. Having additional methods to match internships to profile skills are still within the responsibility of this class. - Higher cohesion as
Model
does not need to have additional responsibilities like executing algorithms. - Increased flexibility as the matching algorithm can be easily changed within this
MatchCommand
.
- Still adheres to the Single Responsibility Principle as the
- Cons:
-
MatchCommand
becomes longer as it needs additional methods to generate the list of matching internships.
-
Alternative 2: Methods to generate the matching internships, namely getSkillList
,
getInternshipList
, and getMatchingInternships
are implemented within Model
.
- Pros:
-
MatchCommand
will be very short as it just needs to call thegetMatchingInternships
method from theModel
interface and generate the correctCommandResult
from there.
-
- Cons:
-
Model
becomes more complicated as it needs to support more methods. This in turns causes theModelManager
class, which implements theModel
interface to be overly complex as it needs to provide the algorithms to filter and generate the matching internship list. - Lower cohesion as the
Model
interface has additional responsibilities and functionalities.Model
now has to deal with algorithms, instead of keeping to what aModel
does which is to manage the app data of the user.
-
Documentation, logging, testing, configuration, dev-ops
Appendix
Appendix A: Product Scope
Target user profile:
- university students applying for tech internships
- prefer desktop apps over other types
- can type fast
- prefers typing to mouse interactions
- is reasonably comfortable using CLI apps
Value proposition: Improves your planning, confidence and readiness for tech-related internship applications by improving your interview skills and search strategy.
Appendix B: User Stories
Priorities: High (must have) - * * *
, Medium (nice to have) - * *
, Low (unlikely to have) - *
Priority | As a … | I want to … | So that I can… |
---|---|---|---|
* * * |
user | maintain a list of company profiles | keep track of companies that I’m interested in |
* * * |
user | add a company profile | keep track of companies that I’m interested in |
* * * |
user | delete a company profile | remove company profiles that I no longer need / am no longer interested in |
* * * |
user | edit a company profile | keep my company profiles updated and accurate |
* * * |
user | view a company profile | see its details |
* * |
user | find company profiles by name | quickly look up company profiles without having to search manually |
* * |
user | list all company profiles in my list | see my full list of companies |
* * * |
user | add an internship to a company profile | keep track of the internships that that company is offering |
* * * |
user | delete an internship from a company profile | remove erroneous / outdated entries |
* * * |
user | edit an internship from a company profile | keep the list of internships that a company offers updated and accurate |
* * * |
user | view a company’s internships when I view their profile | see what internships they are offering |
Priority | As a … | I want to … | So that I can… |
---|---|---|---|
* * * |
user | maintain a list of my internship applications | keep track of them |
* * * |
user | add an internship application | keep track of the internships that I have applied for |
* * * |
user | delete an internship application | remove internship applications that I no longer need / am no longer interested in |
* * * |
user | edit an internship application | keep my internship applications updated and accurate |
* * * |
user | view an internship application | see its details |
* * |
user | find internship applications by job title | quickly look up my internship applications without having to search manually |
* * |
user | list all internship applications in my list | see my full list of internship applications |
* * * |
user | record and see an internship application’s status | keep track of them |
* * * |
user | save the dates of my upcoming interviews | keep track of them |
* * * |
user | maintain a user profile | have an overview of my experience, skills and achievements |
* * * |
user | add information to my user profile | keep my user profile updated and accurate |
* * * |
user | delete information from my user profile | keep my user profile updated and accurate |
* * * |
user | edit information in my user profile | keep my user profile updated and accurate |
Priority | As a … | I want to … | So that I can… |
---|---|---|---|
* * * |
user | view information in my user profile | see its details |
* * |
user | find information in my user profile by title | quickly look up specific information in my user profile without having to search manually |
* * |
user | list all the information in my user profile | see the full list of information in my user profile |
* * * |
user | switch between the multiple pages of the app | |
* * |
user | automatically find internships based on my skill set | find internships that may be more suitable for me |
* * * |
new user | see usage instructions | refer to instructions when I forget how to use the app |
* * * |
user | get error feedback when a command fails | know what went wrong |
* * |
user | navigate the application easily through a clear user interface | |
* * |
user | get fast feedback from the app | |
* * |
user | easily clear all data from the app | start from a clean slate |
Appendix C: Use Cases
(For all use cases below, the System is InternHunter
and the Actor is the user
)
Use case: UC01 - Add a company
Guarantees: Addition of company is successful.
MSS
- User requests to add a company and provides details.
- InternHunter adds the company to the list of companies.
Use case ends.
Extensions
1a. InternHunter detects an error in the input format.
1a1. InternHunter displays an error message and informs the user of the valid input format.
Use case resumes from step 1.
Use case: UC02 - Delete a company
Precondition: User already has an existing list of companies.
Guarantees: Deletion of company is successful.
MSS
- User requests to delete a company.
- InternHunter removes the company from the list of companies.
Use case ends.
Extensions
1a. InternHunter detects an error in the input format.
1a1. InternHunter displays an error message and informs the user of the valid input format.
Use case resumes from step 1.
1b. InternHunter detects an invalid index.
1b1. InternHunter displays an error message and informs the user that the index is out of bounds.
Use case resumes from step 1.
Use case: UC03 - Edit a company
Precondition: User already has an existing list of companies.
Guarantees: Editing of company is successful.
MSS
- User requests to edit the details of a company and provides details.
- InternHunter updates the details of the company.
Use case ends.
Extensions
1a. InternHunter detects an error in the input format.
1a1. InternHunter displays an error message and informs the user of the valid input format.
Use case resumes from step 1.
1b. InternHunter detects an invalid index.
1b1. InternHunter displays an error message and informs the user that the index is out of bounds.
Use case resumes from step 1.
Use case: UC04 - View a company
Precondition: User already has an existing list of companies.
Guarantees: Viewing of company is successful.
MSS
- User requests to view a company.
- InternHunter displays the company.
Use case ends.
Extensions
1a. InternHunter detects an error in the input format.
1a1. InternHunter displays an error message and informs the user of the valid input format.
Use case resumes from step 1.
1b. InternHunter detects an invalid index.
1b1. InternHunter displays an error message and informs the user that the index is out of bounds.
Use case resumes from step 1.
Use case: UC05 - Find companies
Precondition: User already has an existing list of companies.
Guarantees: Companies whose names matches the keywords specified are listed.
MSS
- User searches for a company by name.
- InternHunter displays the companies sought.
Use case ends.
Extensions
1a. InternHunter detects an error in the input format.
1a1. InternHunter displays an error message and informs the user of the valid input format.
Use case resumes from step 1.
2a. InternHunter does not find any companies that matches query.
2a1. InternHunter informs user that no companies are found.
Use case ends.
Use case: UC06 - List all companies
Precondition: User already has an existing list of companies.
Guarantees: All companies stored in InternHunter are shown.
MSS
- User queries for all companies.
- InternHunter displays all company it stores.
Use case ends.
Extensions
1a. InternHunter detects an error in the input format.
1a1. InternHunter displays an error message and informs the user of the valid input format.
Use case resumes from step 1.
Use case: UC07 - Add an internship
Precondition: User already has an existing list of companies.
Guarantees: Addition of internship to company is successful.
MSS
- Similar MSS to UC01 - adding a company except user is now adding an internship.
Extensions
1a. Similar to extension 1a of UC01 - adding a company except user is adding an internship.
1b. InternHunter detects an invalid index.
1b1. InternHunter displays an error message and informs the user that the index is out of bounds.
Use case resumes from step 1.
Use case: UC08 - Delete an internship
- Similar to UC02 - delete a company except user is deleting an internship.
Use case: UC09 - Edit an internship
- Similar to UC03 - editing a company except user is editing an internship.
Use case: UC10 - Add an application
Precondition: User already has an existing list of internships in a company.
Guarantees: Addition of application is successful.
MSS
- Similar MSS to UC01 - adding a company except user is adding an application.
Extensions
- Similar to extension of UC07 - adding an internship except user is adding an application.
Use case: UC11 - Delete an application
- Similar to UC02 - deleting a company except user is deleting an application.
Use case: UC12 - Edit an application
- Similar to UC03 - editing a company except user is editing an application.
Use case: UC13 - View an application
- Similar to UC04 - viewing a company except user is viewing an application.
Use case: UC14 - Find applications
- Similar to UC05 - finding companies except user is finding applications.
Use case: UC15 - List all applications
- Similar to UC06 - listing all companies except user is listing all applications.
Use case: UC16 - Add user profile item
- Similar to UC01 - adding a company except user is adding a user profile item.
Use case: UC17 - Delete a user profile item
- Similar to UC02 - deleting a company except user is deleting a user profile item.
Use case: UC18 - Edit a user profile item
- Similar to UC03 - editing a company except user is editing a user profile item.
Use case: UC19 - View a user profile item
- Similar to UC04 - viewing a company except user is viewing a user profile item.
Use case: UC20 - Find user profile items
- Similar to UC05 - finding companies except user is finding user profile items.
Use case: UC21 - List all user profile items
- Similar to UC06 - listing all companies except user is listing all user profiles items.
Use case: UC22 - Match skills in user profile to internship requirements
MSS
- User requests to see the list of internships that matches her profile skills.
- InternHunter generates and displays the list of internships.
Extensions
2a. User have no internships that matches her profile skills.
2a1. InternHunter displays an error message and informs the user that she has no matching internships.
2a2. Use case ends.
Use case: UC23 - Switch tabs
Guarantees: InternHunter switches to the queried tab.
MSS
- User requests to switch the tab of the screen.
- InternHunter switches to the requested tab.
Use case ends.
Extensions
1a. InternHunter detects an error in the input format.
1a1. InternHunter displays an error message and informs the user of the valid input format.
Use case resumes from step 1.
1b. InternHunter detects that the user is already in that tab.
1b1. InternHunter displays a message and informs the user that he is already in that tab.
Use case ends.
Use case: UC24 - Clear all entries
Guarantees: All entries in InternHunter will be cleared.
MSS
- User requests to clear all entries.
- InternHunter deletes all of its entries.
Use case ends.
Use case: UC25 - Get help
Guarantees: User will get directions to the user guide.
MSS
- User requests to see the help window.
- InternHunter displays help message directing user to user guide.
Use case ends.
Use case: UC26 - Exit
MSS
- User requests to exit InternHunter.
- InternHunter prompts for confirmation.
- User confirms intention to exit.
- InternHunter exits.
Use case ends.
Extensions
2a. User chooses to cancel the confirmation.
Use case ends.
Appendix D: Non-Functional Requirements
- Should work on any mainstream OS as long as it has Java 11 or above installed.
- Should work on both 32-bit and 64-bit environment.
- Should be for a single user i.e. (not a multi-user product).
- Should respond to commands within 2 seconds.
- The data should be stored locally and should be in a human editable text file.
- Should work without requiring an installer.
- Should only use third-party frameworks or libraries which are free, open-source and have permissive license term and do not require installation by user of the software.
Appendix E: Glossary
- CLI: Command-Line Interface
- OS: Operating System
- Mainstream OS: Windows, Linux, Unix, OS-X
- JSON: JavaScript Object Notation
- DRY: Don’t Repeat Yourself
- OOP: Object-oriented programming
Appendix F: Instructions for Manual Testing
Given below are instructions to test the app manually.
Launch and shutdown
-
Initial launch.
-
Download the jar file and copy into an empty folder.
-
Double-click the jar file.
Expected: Shows the GUI with a set of sample data. The window size may not be optimum.
-
-
Saving window preferences.
-
Resize the window to an optimum size. Move the window to a different location. Close the window.
-
Re-launch the app by double-clicking the jar file.
Expected: The most recent window size and location is retained.
-
-
Shutting down.
- Quit the app by typing
exit
.
Expected: An Exit pop-out dialog will confirm the intention to exit InternHunter. For all users, you can use tab on keyboard to navigate. For MacOS users, use spacebar to confirm the exit, while the rest can use Enter to confirm the exit.
- Quit the app by typing
Note
- If an item exist before in InternHunter, a duplicate error message will be shown.
- If the command relating to a certain item type is executed on other tab, InternHunter will automatically switch the tab to correct tab. i.e executing
add com
commands on application tab will bring the tab state of InternHunter from application tab to company tab. - When doing
add
,edit
, the right display will automatically adjust and reflect the recently executed command.
Adding a company
-
Adding a company called Amazon with its non-optional relevant fields such as address being
201 Victoria St
, email beingAmazonHires@amazon.com
and phone number being65000545
.-
Prerequisites: Amazon not already added in InternHunter.
-
Test case:
add com n/Amazon a/201 Victoria St e/AmazonHires@amazon.com p/65000545
Expected: A card displaying information of the company is added. The right display will show full information of the company added. -
Test case:
add com n/Google Florida a/101 Tampines St e/GoogleHires@google.com p/62343434 t/Cloud Computing t/Artificial Intelligence
Expected: The difference compared to the above test case is, this adds some tags to the card which will show bothCloud Computing
andArtificial Intelligence
. It is reflected inside a blue box inside the card. -
Test case:
add com n/Facebook a/301 Raffles St e/FacebookHires@fb.com
Expected: An error message will be shown, showing information of how this command should be entered. The command box text will turn red to inform you of the invalid command.
-
Adding an internship
-
Adding an internship with Job title
Machine Learning Engineer
.-
Prerequisites: A company have to exist first, and add it to the company via a valid index.
-
Test case:
add int 1 j/Machine Learning Engineer
Expected: In the right display, the information of the internship will be shown. -
Test case:
add int 1 j/Frontend developer r/React
Expected: In the right display, the information of the internship will be shown with requirements. -
Test case:
add int 1
Expected: An error message will be shown, showing information of how this command should be entered. The command box text will turn red to inform you of the invalid command.
-
Adding an application
-
Adding an application is simulating applying for an application.
-
Prerequisites: An internship must exist first before you can apply for it.
-
Test case:
add app 5 i/1 d/24-12-20 s/interview
Expected: A card displaying information of this application is added. There will be a status showing as interview. The date will be shown as 24 dec and the year is taken to be from year 2000-2099(Note that the date have to be in the future). -
Test case:
add app 5 i/3
(ensure that you have a third internship first)
Expected: Similar to the above test case, however the status will be shown as the default status applied. The date will be today’s date and the time will be taken to be 2359. -
Test case:
add app 1
Expected: An error message will be shown, showing information of how this command should be entered. The command box text will turn red to inform you of the invalid command.
-
Adding a profile item
-
Adding a skill/experience/achievement set into our profile list.
-
Prerequisites: This particular profile item’s title should not be already added in InternHunter.
-
Test case:
add me c/skill t/React d/Created a mini MOBA game
Expected: A card displaying information of this profile item is added. There will be a circular colorful icon on the right of the card that will represent skills. -
Test case:
add me c/achievement t/Hackathon d/1st place
Expected: Similar to the above test case, instead of a circular colorful icon, there will be a trophy representing achievement. -
Test case:
add me c/experience t/Interned at google d/Worked as a frontend developer
Expected: Similar to both the above test case, instead, there will be a clipboard icon to represent experience. -
Test case:
add me
Expected: An error message will be shown, showing information of how this command should be entered. The command box text will turn red to inform you of the invalid command.
-
Editing a company
-
Editing some fields in company.
-
Prerequisites: The company must exist and be accessed via a valid index.
-
Test case:
edit com 1 t/Frontend developer t/Backend developer t/Fullstack developer
Expected: The tags that are in the blue box will be changed to Frontend developer, Backend developer, Fullstack developer. It is visible on both the card and the right display. -
Test case:
edit com 1 p/91910808
Expected: The phone number of the company will be changed. It is visible on both the card and the right display. -
Test case:
edit com 1 t/
Expected: Removes all the tags for this card. -
Test case:
edit com 1
Expected: An error message will be shown, showing information of how this command should be entered. The command box text will turn red to inform you of the invalid command.
-
Editing an internship
-
Editing some fields in internship.
-
Prerequisites: The internship must exist and be accessed via a valid index.
-
Test case:
edit int 1 i/1 r/Java r/Python
Expected: The 1st internship at the first company will have the requirement java and python. Note that it overrides any existing requirements in that internship. (Note that if an application for this internship exist, these changes will be reflected as tags in blue boxes on the card in the application tab). Executeswitch app
to confirm it. -
Test case:
edit int 1 i/2 r/React r/CSS r/HTML
Expected: The 2nd internship at the first company will have the requirement React native. Similarly to the above test case, any existing requirements in that internship will be overidden. -
Test case:
edit int 1
Expected: An error message will be shown, showing information of how this command should be entered. The command box text will turn red to inform you of the invalid command.
-
Editing an application
-
Editing some fields in application.
-
Prerequisites: The application must exist and be accessed via a valid index.
-
Test case:
edit app 1 s/accepted
Expected: The status that was on the card will be changed into a green status with the word accepted. -
Test case:
edit app
Expected: An error message will be shown, showing information of how this command should be entered. The command box text will turn red to inform you of the invalid command.
-
Editing a profile item
-
Editing some fields in the profile item.
-
Prerequisites: The profile item must exist and be accessed via a valid index.
-
Test case:
edit me 2 c/achievement t/Hackathon at Shoppee d/2nd place
Expected: Its description on the right display will be 2nd place instead. -
Test case:
edit me
Expected: An error message will be shown, showing information of how this command should be entered. The command box text will turn red to inform you of the invalid command.
-
Viewing a company
-
Viewing full information of a company.
-
Prerequisites: The company item must exist and the card be access via a valid index. Also, having more than 2 cards and current right display is showing information of the first card. You can execute
view com 1
first. -
Test case:
view com 2
Expected: The right display will change and show the full information of the 2nd company in the list. -
Test case:
view com 0
Expected: An error message informing you that index is not a non-zero unsigned integer. The command box text will turn red to inform you of the invalid command. -
Test case:
view com
Expected: An error message will be shown, showing information of how this command should be entered. The command box text will turn red to inform you of the invalid command.
-
Viewing an application
-
Viewing full information of an application.
-
Prerequisites: The application item must exist and the card be access via a valid index. Also, having more than 2 cards and current right display is showing information of the first card. You can execute
view app 1
first. -
Test case:
view app 2
Expected: The right display will change and show the full information of the 2nd application in the list. -
Test case:
view app 0
Expected: An error message informing you that index is not a non-zero unsigned integer. The command box text will turn red to inform you of the invalid command. -
Test case:
view app
Expected: An error message will be shown, showing information of how this command should be entered. The command box text will turn red to inform you of the invalid command.
-
View a profile Item
-
Viewing full information of a profile item.
-
Prerequisites: The profile item must exist and the card be access via a valid index. Also, having more than 2 cards and current right display is showing information of the first card. You can execute
view me 1
first. -
Test case:
view me 2
Expected: The right display will change and show the full information of the 2nd profile item in the list. -
Test case:
view me 0
Expected: An error message informing you that index is not a non-zero unsigned integer. The command box text will turn red to inform you of the invalid command. -
Test case:
view me
Expected: An error message will be shown, showing information of how this command should be entered. The command box text will turn red to inform you of the invalid command.
-
Finding company/companies
-
Finding specific keyword(s) in the list of company/companies.
-
Prerequisites: List all companies using the
list com
command. At least one company.find
method andlist
method works hand in hand. -
Test case:
find com google
Expected: Any titles in the card that containsgoogle
will be matched. i.eGoogle
,Google Florida
. HoweverGoogleMalaysia
will not be matched. -
Test case:
find com
Expected: An error message will be shown, showing information of how this command should be entered. The command box text will turn red to inform you of the invalid command.
-
Listing out all company/companies
-
Listing out all company/companies.
-
Prerequisites: Assuming that you have used
find
for company in the earlier manual testing. -
Test case:
list com
Expected: All the companies that the user have will be displayed. -
Test case:
list com 2
Expected: An error message will be shown, stating that there should not be any inputs after theITEM_TYPE
.
-
Finding application(s)
-
Finding specific keyword(s) in the list of application(s).
-
Prerequisites: List all applications using the
list app
command. At least one application.find
method andlist
method works hand in hand. -
Test case:
find app engineer
Expected: Any titles in the card that containssoftware
will be matched. i.eEngineer
,Front End Engineer
. HoweverFrontEndEngineer
will not be matched. -
Test case:
find app
Expected: An error message will be shown, showing information of how this command should be entered. The command box text will turn red to inform you of the invalid command.
-
Listing out all application(s)
-
Listing out all application(s).
-
Prerequisites: Assuming that you have used
find
for application in the earlier manual testing. -
Test case:
list app
Expected: All the application that the user have will be displayed. -
Test case:
list app 2
Expected: An error message will be shown, stating that there should not be any inputs after theITEM_TYPE
.
-
Finding profile item(s)
-
Finding specific keyword(s) in the list of profile item(s).
-
Prerequisites: List all profile items using the
list me
command. At least one profile item.find
method andlist
method works hand in hand. -
Test case:
find me hackathon
Expected: Any titles in the card that containshackathon
will be matched. i.eHackathon
,2020 Hackathon
. HoweverShoppeeHackathon
will not be matched. -
Test case:
find me
Expected: An error message will be shown, showing information of how this command should be entered. The command box text will turn red to inform you of the invalid command.
-
Listing out all profile item(s)
-
Listing out all profile item(s).
-
Prerequisites: Assuming that you have used
find
for profile items in the earlier manual testing. -
Test case:
list me
Expected: All the profile items that the user have will be displayed. -
Test case:
list me 2
Expected: An error message will be shown, stating that there should not be any inputs after theITEM_TYPE
.
-
Deleting a company
-
Deleting a module according to the index shown on the card.
-
Prerequisites: The company item must exist and access via a valid index as indicated on a card.
-
Test case:
delete com 2
Expected: The second card will be deleted. Details of the deleted company can be seen in the result display. All the internships in this company will be deleted as well. Note that if there is an application that is linked to any internships that this company had, it will be deleted as well. -
Test case:
delete com 0
Expected: An error message informing you that index is not a non-zero unsigned integer. The command box text will turn red to inform you of the invalid command. -
Test case:
delete com
Expected: An error message will be shown, showing information of how this command should be entered. The command box text will turn red to inform you of the invalid command.
-
Deleting an internship
-
Deleting an internship from a certain company.
-
Prerequisites: The company item and internship item must exist and both to be access via a valid index.
-
Test case:
delete int 1 i/1
Expected: On the right display, it will remove the internship item from the company. -
Test case:
delete int 1 i/0
Expected: An error message informing you that index is not a non-zero unsigned integer. The command box text will turn red to inform you of the invalid command. -
Test case:
delete int 1
Expected: An error message will be shown, showing information of how this command should be entered. The command box text will turn red to inform you of the invalid command.
-
Deleting an application
-
Deleting an application.
-
Prerequisites: The application item must exist and be access via a valid index.
-
Test case:
delete app 1
Expected: The first card will be deleted. Details of the deleted application can be seen in the result display. -
Test case:
delete app 0
Expected: An error message informing you that index is not a non-zero unsigned integer. The command box text will turn red to inform you of the invalid command. -
Test case:
delete app
Expected: An error message will be shown, showing information of how this command should be entered. The command box text will turn red to inform you of the invalid command.
-
Deleting a profile item
-
Deleting a profile item.
-
Prerequisites: The profile item must exist and be access via a valid index. At least 2 profile items for this manual testing.
-
Test case:
delete me 2
Expected: The second card will be deleted. The rest of the cards will shift upwards with index being updated. Details of the deleted profile can be seen in the result display. -
Test case:
delete me 0
Expected: An error message informing you that index is not a non-zero unsigned integer. The command box text will turn red to inform you of the invalid command. -
Test case:
delete me
Expected: An error message will be shown, showing information of how this command should be entered. The command box text will turn red to inform you of the invalid command.
-
Switching of tabs
-
Switching tabs.
-
Prerequisites: Assuming you are on the company tab. If not execute
switch com
. -
Test case:
switch com
Expected: A message will be displayed in the result display to inform you that you are already on the company tab. -
Test case:
switch app
Expected: The top left will show the tab will be at application. A message will be displayed in the result display to inform you that you have switched to application tab. The screen should now display cards that holds application information and the right display will show information of the last know index of the application tab. -
Test case:
switch int
Expected: An error message wil be shown, stating that int is a invalid item type for this case. The command box text will turn red to inform you of the invalid command. -
Test case:
switch
Expected: An error message will be shown, showing information of how this command should be entered. The command box text will turn red to inform you of the invalid command.
-
Matching skills to internship requirements
-
Finding if any internships requirements matches the skills that you have.
-
Prerequisites: There is some internships added and the skills that you have put into the profile matches the requirements in internship. Now that now you have learnt how to use
switch
andview
, useswitch com
andswitch me
and the relevantview
commands to check the skills as well as some internships requirements. -
Test case:
match
Expected: A new window will pop-up and show you all the matched internships. Note that you can use esc on your keyboard to close the window.
-
Viewing help
-
Viewing help.
- Test case:
help
Expected: Help window appears with InternHunter’s user guide url. Note that you can use esc on your keyboard to close the window.
- Test case:
Clearing all the data in the app
-
Clearing all existing data in InternHunter.
-
Prerequisites: Some data has been added to InternHunter.
-
Test case:
clear
Expected: All data cleared from all tabs.
-
Saving the data
-
Dealing with corrupted data files.
-
Corrupt the current save file under ./data/. Edit the json with some random characters that make the JSON format unreadable. Alternatively, you could go to
profileitemlist.json
and add-
to descriptors. -
Double-click the jar file
Expected: Shows the GUI with no data. -
Delete the current save file under ./data/.
-
Double-click the jar file
Expected: Shows the GUI with no data.
-
Appendix G: Effort
InternHunter is a challenging endeavour as it deals with 4 different entities (company, internship, application and profile items) and much consideration has to be put into the interaction, management and storage of these entities that seeks to reduce code duplication as much as possible by using Object Oriented Principles and other design patterns.
To approach the management of different entities in the model. The abstract Item
class is used a blueprint for
the other entities to extend. After which, Itemlist
can be used as a collection type offering common methods to
manipulate the collection of different entities by leveraging on the polymorphism and dynamic binding. This negates
the need for the creation of different individual collections types for each entity, thereby abiding to
the DRY principle.
Another challenge faced was dealing the the close coupling of the company, internship and application objects whereby company shares a composition relationship with its internships and an internship share a composition relationship with the application. This means that an internship cannot exists without the company it belongs to and the application cannot exist without the internship that it is applied to. This creates a need for interesting commands such as the delete company command which has a cascading effect, where a deletion of a company will require its internships and the internship’s applications to be deleted as well. This preserves data integrity of InternHunter by ensuring that data is consistent.
The UI has also been completely revamped to have a different look and feel from Address Book 3. It uses a tab interface for switching between and displaying the different entities of InternHunter and a right display panel to show the details of each entity item which the cards in the list cannot show.
Appendix H: Sequence Diagrams
Sequence diagram for handle delete display switch index