- Create a PR to the upstream repo
- Do as parallel branches:
Level-7
andLevel-8
- Do increments
A-MoreOOP
,A-Packages
,A-JUnit
,A-Jar
- Do as parallel branches:
A-JavaDoc
,A-CodingStandard
,Level-9
In this week, we try to practice git branching as we do the iP.
0 Do any leftover iP increments from the previous week
- Remember to do any leftover increments from the past weeks before starting on the current week's increments. This guideline applies to future weeks too.
1 Create a PR to the upstream repo
Create a pull request (PR) from the master
branch of your fork to the upstream repo.
- PR name:
[{Your name}] Duke Increments
e.g.,[John Doe] Duke Increments
If you are reluctant to give full name, you may give the first half of your name only
2 Do as parallel branches: Level-7
and Level-8
Do Level 7 in a branch named branch-Level-7
. Without merging that branch, go back to the master
branch and implement Level 8 in a separate branch named branch-Level-8
. Now, go back to the master
branch and merge the two branches one after the other. As before, tag the commit (in the master
branch, after merging) that achieves the respective deliverable, and push to your fork.
Remember to push the branches to your fork so that the bot can detect them.
Advanced git users: do not delete the branch after merging.
Merge without a fast-forward so that git creates a separate commit for the merge.
Level-7
: Save
Level 7. Save
Save the tasks in the hard disk automatically whenever the task list changes. Load the data from the hard disk whe Duke starts up. You may hard-code the file name and location e.g., [project_root]/data/duke.txt
The format of the file is up to you. Example:
T | 1 | read book
D | 0 | return book | June 6th
E | 0 | project meeting | Aug 6th 2-4pm
T | 1 | join sports club
Level-8
: Dates and Times
Level 8. Dates and Times
Teach Duke to understand dates and times. For example, if the command is deadline return book /by 2/12/2019 1800
, Duke understands 2/12/2019 1800
as 2nd of December 2019, 6pm, instead of storing
it simply as a String.
- Minimal: Store deadline dates as a
java.time.LocalDate
in your task objects. Accept dates in a format such asyyyy-mm-dd
format (e.g.,2019-10-15
) and print in a different format such asMMM d yyyy
e.g., (Oct 15 2019
). - Stretch goal: Use dates and times in more meaningful ways. e.g., add a command to print deadlines/events occurring on a specific date.
A code snippet using the LocalDate
class:
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
public class Main {
public static void main(String[] args) {
//create dates from strings
LocalDate d1 = LocalDate.parse("2019-12-01");
LocalDate d2 = LocalDate.parse("2019-12-02");
LocalDate d3 = LocalDate.parse("2019-12-02");
//compare dates
System.out.println(d1.isBefore(d2)); // -> true
System.out.println(d1.isAfter(d2)); // -> false
System.out.println(d2.equals(d3)); // -> true
//work with dates
System.out.println(d1.getDayOfWeek()); // -> SUNDAY
System.out.println(d1.getMonth()); // -> DECEMBER
System.out.println(d1.plus(1, ChronoUnit.YEARS)); // -> 2020-12-01
// get today's date and print it in a specific format
LocalDate d4 = LocalDate.now();
System.out.println(d4); // -> 2019-10-15
System.out.println(d4.format(DateTimeFormatter.ofPattern("MMM d yyyy"))); // -> Oct 15 2019
}
}
3 Do increments A-MoreOOP
, A-Packages
, A-JUnit
, A-Jar
As in the previous week, commit, tag, and push, as you do the following increments in the master
branch (no need to use separate branches).
A-MoreOOP
: More OOP
Refactor the code to extract out closely related code as classes.
- Minimal: Extract the following classes:
Ui
: deals with interactions with the userStorage
: deals with loading tasks from the file and saving tasks in the fileParser
: deals with making sense of the user commandTaskList
: contains the task list e.g., it has operations to add/delete tasks in the list
For example, the code of the main class could look like this:
public class Duke {
private Storage storage;
private TaskList tasks;
private Ui ui;
public Duke(String filePath) {
ui = new Ui();
storage = new Storage(filePath);
try {
tasks = new TaskList(storage.load());
} catch (DukeException e) {
ui.showLoadingError();
tasks = new TaskList();
}
}
public void run() {
//...
}
public static void main(String[] args) {
new Duke("data/tasks.txt").run();
}
}
- Stretch Goal: Consider extracting more classes. e.g.,
*Command
classes (i.e.,AddCommand
,DeleteCommand
,ExitCommand
etc.) that inherits from an abstractCommand
class, so that you can write the main logic of the App as follows:
You can get some inspiration from how the code of the addressbook-level2 is organized.public void run() { ui.showWelcome(); boolean isExit = false; while (!isExit) { try { String fullCommand = ui.readCommand(); ui.showLine(); // show the divider line ("_______") Command c = Parser.parse(fullCommand); c.execute(tasks, ui, storage); isExit = c.isExit(); } catch (DukeException e) { ui.showError(e.getMessage()); } finally { ui.showLine(); } } }
A-JUnit
: JUnit Testing
Add JUnit tests to test the behavior of the code.
Conventions to follow:
- Add test code in a folder named
[project root]\src\test\java\
folder (reason: to follow the convention followed by the project structure so far). - Name the test class to match the class being tested (
Todo.java
can be tested byTodoTest.java
), and put it in a package to match. For example,- Class being tested
seedu.duke.Todo
:src\main\java\seedu\duke\Todo.java
- Test class
seedu.duke.TodoTest
:src\test\java\seedu\duke\TodoTest.java
- Class being tested
Requirements:
- Minimum: More than two test methods, preferably targeting more than one class (if you have multiple classes)
- Stretch goal: test methods to target all public methods of all classes
Adding JUnit support to your project: As JUnit is a third-party library, you need to add support to it specifically in your project.
- Add a folder named
[project root]\src\test\java\
(you may have to do this outside of Intellij) - Go to Intellij and add a new module to the project as follows.
File
→New
→Module From Existing Sources ...
- Choose the
[project root]\src\test\
(not thejava
) folder. - In the next screen, select
Create module from existing sources
- Keep clicking
Next
until the process is complete
- In the
Project
panel of Intellij, expand the newly-createdtest
module, right-click on thejava
folder inside it, and chooseMark Directory as
→Test Source Root
(that will make the folder turn to green color). - Now, create a class inside the
java
folder and type@Test
inside it. A code example given below.
Note: If you are using packages, create this class in a matching package (to testduke.Duke
class, create aduke.DukeTest
i.e., insrc\test\java\duke\DukeTest.java
).public class DukeTest { @Test }
- Note how the
@Test
turn to red because Intellij (not having JUnit support yet) does not understand it. But it will pop up a hint, asking if you want to add support for JUnit. SelectAdd JUnit 5.* to classpath
. - In the dialog that pops up, you can optionally tick the
Sources
,JavaDocs
andAnnotations
boxes. After that, clickOK
to add the JUnit 5 to the project dependencies. - To check if JUnit integration is working as expected,
- Add a dummy test method to the class e.g.,
import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertEquals; public class DukeTest { @Test public void dummyTest(){ assertEquals(2, 2); } }
- Run the test (right-click on the class and choose
Run DukeTest
.
- Add a dummy test method to the class e.g.,
- To be able to refer to
Duke
fromDukeTest
class, you need to addmain
module as a dependency of thetest
module you just created.- Option 1: When you add a reference to the
Duke
inside theDukeTest
, Intellij will flag it as an error and will give you an option (i.e., in the bulb icon that pops up) to add themain
module as a dependency. - Option 2: Follow the info here to add the dependency yourself.
- Option 1: When you add a reference to the
Refer to the Gradle tutorial at the Duke repo (i.e., the repo you forked from) to find how to use JUnit via Gradle.
Use Gradle to automate some of the build tasks of the project. Refer to the Gradle tutorial at the Duke repo (i.e., the repo you forked from) to find how to set up Gradle for your project.
- Minimal: Set up gradle so that you can build and run Duke using gradle.
- Recommended: Set up gradle to run unit tests.
- Stretch Goal: Use gradle to automate more things in your project.
A-Jar
: JAR file
Package the app as an executable JAR file so that it can be distributed easily.
Do not commit the JAR file created. Instead, you can make the JAR file available in the following manner.
- Go to your fork on GitHub and create a new release.
- In the page where you fill the details of th release,
- give an appropriate version number e.g.,
v0.1
- attach the JAR file where it says
Attach binaries by dropping them ...
.
- give an appropriate version number e.g.,
If you are using Gradle for your project, refer to the Gradle tutorial at the Duke repo (i.e., the repo you forked from) to find how to create a jar file using Gradle.
Use Gradle to automate some of the build tasks of the project. Refer to the Gradle tutorial at the Duke repo (i.e., the repo you forked from) to find how to set up Gradle for your project.
- Minimal: Set up gradle so that you can build and run Duke using gradle.
- Recommended: Set up gradle to run unit tests.
- Stretch Goal: Use gradle to automate more things in your project.
4 Do as parallel branches: A-JavaDoc
, A-CodingStandard
, Level-9
As in the step 1 above, implement these three increments as three parallel branches first (branch names: branch-A-JavaDoc
, branch-A-CodingStandard
, branch-Level-9
), and then merge them one-by-one. Hopefully,
you will encounter some merge conflicts so that you get to practice de-conflicting branches.
Level-9
: Find
Level 9. Find
Give users a way to find a task by searching for a keyword.
Example:
find book
____________________________________________________________
Here are the matching tasks in your list:
1.[T][✓] read book
2.[D][✓] return book (by: June 6th)
____________________________________________________________