Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[T6A1][F09-C3] #854

Open
wants to merge 14 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file modified doc/Diagrams.pptx
Binary file not shown.
72 changes: 20 additions & 52 deletions doc/LearningOutcomes.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,9 @@ After studying this code and completing the corresponding exercises, you should
1. [Use abstract classes/methods `[LO-Abstract]`](#use-abstract-classesmethods-lo-abstract)
1. [Follow Liskov Substitution Principle `[LO-LSP]`](#follow-liskov-substitution-principle-lo-lsp)
1. [Use Java-FX for GUI programming `[LO-JavaFx]`](#use-java-fx-for-gui-programming-lo-javafx)
1. [Apply Dependency Inversion Principle `[LO-DIP]`](#apply-dependency-inversion-principle-lo-dip)
1. [Use Dependency Injection `[LO-DI]`](#use-dependency-injection-lo-di)
1. [Apply Open-Closed Principle `[LO-OCP]`](#apply-open-closed-principle-lo-ocp)
1. [Analyze Coupling and Cohesion of designs `[LO-CouplingCohesion]`](#analyze-coupling-and-cohesion-of-designs-lo-couplingcohesion)
1. [Work in a 2KLoC code base `[LO-2KLoC]`](#work-in-a-2kloc-code-base-lo-2kloc)
1. [Apply Dependency Inversion Principle `[LO-DIP]`](#apply-dependency-inversion-principle)
1. [Use Dependency Injection `[LO-DI]`](#use-dependency-injection)
1. [Apply Open-Closed Principle `[LO-OCP]`](#apply-open-closed-principle)

------------------------------------------------------------------------------------------------------

Expand Down Expand Up @@ -99,73 +97,43 @@ Covered by `[LO-Polymorphism]`

* Note how `Logic` class depends on the `StorageFile` class. This is a violation of DIP.
* Modify the implementation as follows so that both `Logic` and `StorageFile` now depend on the abstraction
`Storage`. (Note: The term *abstraction* here is referring to the conception of abstracting, not to the fact that `Storage` class is `abastract`)<br>
<img src="images/LogicStroageFileDIP.png" width="300">
* Where else in the code do you notice the application of DIP?
`Storage`.<br>
<img src="images/LogicStroageFileDIP.png">

------------------------------------------------------------------------------------------------------

## Use Dependency Injection `[LO-DI]`

Note how `Logic` class depends on the `StorageFile` class. This means when testing the `Logic` class,
our test cases execute the `StorageFile` class as well. What if we want to test the `Logic` class without
getting the `StorageFile` class involved? That is a situation where we can use *Dependency Injection*.

#### Exercise: Facilitate injecting a StorageStub

* Change the implementation as follows so that we can inject a `StorageStub` when testing the `Logic`
* Note how `Logic` class depends on the `StorageFile` class. This means when testing the `Logic` class,
our test cases executes the `StorageFile` class as well. What if we want to test the `Logic` class without
getting the `StorageFile` class involved?

* Now, change the implementation as follows so that we can inject a `StorageStub` when testing the `Logic`
class. <br>
<img src="images/DependencyInjection.png" width="600">
<img src="images/DependencyInjection.png">

> If you did the exercise in [`LO-DIP`](#apply-dependency-inversion-principle-lo-dip)
> If you did the exercise in [`LO-DIP`](#apply-dependency-inversion-principle)
already but those changes are in a different branch, you may be able to reuse some of those commits
by cherry picking them from that branch to the branch you created for this exercise. <br>
Note: *cherry picking* is simply copy-pasting a commit from one branch to another. In SourceTree, you can
right-click on the commit your want to copy to the current branch, and choose 'Cherry pick'
* Implement the `StorageStub` such that calls to the `save` method do nothing (i.e. empty method body).
* Update the `LogicTest` to work with the `StorageStub` instead of the actual `StorageFile` object. <br>
i.e. `Logic` injects a `StorageStub` object to replace the dependency of `Logic` on `Storage` before
testing `Logic`.
* Implement the `StorageStub` to ignore calls to the `save` method.
Update the `LogicTest` to work with the `StorageStub` instead of the actual `StorageFile` object.

------------------------------------------------------------------------------------------------------

## Apply Open-Closed Principle `[LO-OCP]`

#### Exercise: Analyze OCP-compliance of the `Logic` class
#### Exercise: Add a new command

* Consider adding a new command to the Address Book. e.g. an `edit` command.
* Notice how little you need to change in the `Logic` class to extend its behavior so that it can execute
the new command.
That is because `Logic` follows the OCP i.e. `Logic` is *open to be extended* with more
* Add a new command to the Address Book. e.g. an `edit` command
* Notice how little you need to change in the `Logic` class that is responsible for executing the commands.
That is because classes `Logic` and `*Command` follow the OCP i.e. `Logic` is *open to be extended* with more
commands but *closed for modifications*.
* Is it possible to make the `Parser` class more OCP-compliant in terms of extending it to handle more
command types?
* In terms of how it saves data, does `Logic` become more OCP-compliant
after applying DIP as given in [`LO-DIP`](#apply-dependency-inversion-principle-lo-dip)?
How can you improve `Logic`'s OCP-compliance further so that it can not only work with different types
of storages, but different number of storages (e.g. save to both a text file and a database).

* Think about how to make the `Person` class similarly open to be extended with more contact details
(e.g. `SkypeId`) without needing modifications to its code during those extensions.

------------------------------------------------------------------------------------------------------

## Analyze Coupling and Cohesion of designs `[LO-CouplingCohesion]`

* As you saw above, DIP helps us to avoid *coupling* from higher-level classes to lower-level classes.

* Notice how having a separate `Formattter` class (an application of SIP) improves the *cohesion* of
the `MainWindow` class as well as the `Formatter` class.

#### Exercise: Identify places to reduce coupling and increase cohesion

* Where else in the design coupling can be reduced further, or cohesion can be increased further?

------------------------------------------------------------------------------------------------------

## Work in a 2KLoC code base `[LO-2KLoC]`

#### Exercise: Enhance AddressBook

* Enhance AddressBook in some way. e.g. add a new command

------------------------------------------------------------------------------------------------------

71 changes: 47 additions & 24 deletions doc/UserGuide.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# User Guide

This product is not meant for end-users and therefore there is no user-friendly installer.
This product is not meant for end-users and therefore there is no user-friendly installer.
Please refer to the [Setting up](DeveloperGuide.md#setting-up) section to learn how to set up the project.

## Starting the program
Expand All @@ -16,23 +16,39 @@ Please refer to the [Setting up](DeveloperGuide.md#setting-up) section to learn
Format: `help`

> Help is also shown if you enter an incorrect command e.g. `abcd`

## Adding a person: `add`
Adds a person to the address book<br>
Format: `add NAME [p]p/PHONE_NUMBER [p]e/EMAIL [p]a/ADDRESS [t/TAG]...`
> Words in `UPPER_CASE` are the parameters, items in `SQUARE_BRACKETS` are optional,
> items with `...` after them can have multiple instances. Order of parameters are fixed.
>
Format: `add NAME [p]p/PHONE_NUMBER [p]e/EMAIL [p]a/ADDRESS [t/TAG]...`

> Words in `UPPER_CASE` are the parameters, items in `SQUARE_BRACKETS` are optional,
> items with `...` after them can have multiple instances. Order of parameters are fixed.
>
> Put a `p` before the phone / email / address prefixes to mark it as `private`. `private` details can only
> be seen using the `viewall` command.
>
>
> Persons can have any number of tags (including 0)

Examples:
Examples:
* `add John Doe p/98765432 e/johnd@gmail.com a/John street, block 123, #01-01`
* `add Betsy Crowe pp/1234567 e/betsycrowe@gmail.com pa/Newgate Prison t/criminal t/friend`

## Editting a person: `add`
Edit a existing person's detail in the address book<br>
Format: `edit INDEX n/NAME [p]p/PHONE_NUMBER [p]e/EMAIL [p]a/ADDRESS [t/TAG]...`

> Words in `UPPER_CASE` are the parameters, items in `SQUARE_BRACKETS` are optional,
> items with `...` after them can have multiple instances. Order of parameters are fixed.
>
> Put a `p` before the phone / email / address prefixes to mark it as `private`. `private` details can only
> be seen using the `viewall` command.
>
> Persons can have any number of tags (including 0)

Examples:
* `edit 1 n/John Doe p/98765432 e/johnd@gmail.com a/John street, block 123, #01-01`
* `edit 2 n/Betsy Crowe pp/1234567 e/betsycrowe@gmail.com pa/Newgate Prison t/criminal t/friend`

## Listing all persons : `list`
Shows a list of all persons in the address book.<br>
Format: `list`
Expand All @@ -41,10 +57,10 @@ Format: `list`
Finds persons whose names contain any of the given keywords.<br>
Format: `find KEYWORD [MORE_KEYWORDS]`

> The search is case sensitive, the order of the keywords does not matter, only the name is searched,
> The search is case sensitive, the order of the keywords does not matter, only the name is searched,
and persons matching at least one keyword will be returned (i.e. `OR` search).

Examples:
Examples:
* `find John`<br>
Returns `John Doe` but not `john`
* `find Betsy Tim John`<br>
Expand All @@ -54,56 +70,63 @@ Examples:
Deletes the specified person from the address book. Irreversible.<br>
Format: `delete INDEX`

> Deletes the person at the specified `INDEX`.
> Deletes the person at the specified `INDEX`.
The index refers to the index number shown in the most recent listing.

Examples:
Examples:
* `list`<br>
`delete 2`<br>
Deletes the 2nd person in the address book.
* `find Betsy`<br>
* `find Betsy`<br>
`delete 1`<br>
Deletes the 1st person in the results of the `find` command.

## View non-private details of a person : `view`
Displays the non-private details of the specified person.<br>
Format: `view INDEX`

> Views the person at the specified `INDEX`.
> Views the person at the specified `INDEX`.
The index refers to the index number shown in the most recent listing.

Examples:
Examples:
* `list`<br>
`view 2`<br>
Views the 2nd person in the address book.
* `find Betsy` <br>
* `find Betsy` <br>
`view 1`<br>
Views the 1st person in the results of the `find` command.

## View all details of a person : `viewall`
Displays all details (including private details) of the specified person.<br>
Format: `viewall INDEX`

> Views all details of the person at the specified `INDEX`.
> Views all details of the person at the specified `INDEX`.
The index refers to the index number shown in the most recent listing.

Examples:
Examples:
* `list`<br>
`viewall 2`<br>
Views all details of the 2nd person in the address book.
* `find Betsy`<br>
* `find Betsy`<br>
`viewall 1`<br>
Views all details of the 1st person in the results of the `find` command.

## View all the tags : `viewalltags`
Displays all tags in current storage file.<br>
Format: `viewalltags`

Examples:
* `viewalltags`<br>

## Clearing all entries : `clear`
Clears all entries from the address book.<br>
Format: `clear`
Format: `clear`

## Exiting the program : `exit`
Exits the program.<br>
Format: `exit`
Format: `exit`

## Saving the data
## Saving the data
Address book data are saved in the hard disk automatically after any command that changes the data.<br>
There is no need to save manually.

Expand All @@ -113,5 +136,5 @@ You can change the location by specifying the file path as a program argument.<b

> The file name must end in `.txt` for it to be acceptable to the program.
>
> When running the program inside Eclipse, you can
> When running the program inside Eclipse, you can
[set command line parameters before running the program](http://stackoverflow.com/questions/7574543/how-to-pass-console-arguments-to-application-in-eclipse).
Binary file modified doc/images/DependencyInjection.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified doc/images/LogicStroageFileDIP.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 8 additions & 2 deletions src/seedu/addressbook/commands/AddCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -58,13 +58,19 @@ public ReadOnlyPerson getPerson() {
}

@Override
public CommandResult execute() {
public CommandResult execute() throws Exception{
try {
addressBook.addPerson(toAdd);
return new CommandResult(String.format(MESSAGE_SUCCESS, toAdd));
} catch (UniquePersonList.DuplicatePersonException dpe) {
return new CommandResult(MESSAGE_DUPLICATE_PERSON);
} catch (Exception e) {
throw new Exception();
}
}


@Override
public boolean isMutating(){
return true;
}
}
5 changes: 5 additions & 0 deletions src/seedu/addressbook/commands/ClearCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,9 @@ public CommandResult execute() {
addressBook.clear();
return new CommandResult(MESSAGE_SUCCESS);
}

@Override
public boolean isMutating(){
return true;
}
}
9 changes: 8 additions & 1 deletion src/seedu/addressbook/commands/Command.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,9 @@ public static String getMessageForPersonListShownSummary(List<? extends ReadOnly

/**
* Executes the command and returns the result.
* @throws Exception
*/
public abstract CommandResult execute();
public abstract CommandResult execute() throws Exception;

/**
* Supplies the data the command will operate on.
Expand All @@ -65,4 +66,10 @@ public int getTargetIndex() {
public void setTargetIndex(int targetIndex) {
this.targetIndex = targetIndex;
}

/**
* @return true if the command mutate the data. Otherwise return false
*/
public abstract boolean isMutating();

}
6 changes: 5 additions & 1 deletion src/seedu/addressbook/commands/DeleteCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,5 +38,9 @@ public CommandResult execute() {
return new CommandResult(Messages.MESSAGE_PERSON_NOT_IN_ADDRESSBOOK);
}
}


@Override
public boolean isMutating(){
return true;
}
}
Loading