se-edu/addressbook-level1

Name: addressbook-level1

Owner: Software Engineering Education - FOSS Resources

Description: A Java sample application for students. An AddressBook application written in procedural fashion.

Created: 2016-07-22 07:20:33.0

Updated: 2017-08-28 07:20:03.0

Pushed: 2018-02-09 06:58:44.0

Homepage: null

Size: 2519

Language: Java

GitHub Committers

UserMost Recent Commit# Commits

Other Committers

UserEmailMost Recent Commit# Commits

README

AddressBook (Level 1)

Table of Contents


User Guide

This product is not meant for end-users and therefore there is no user-friendly installer. Please refer to the Setting up section to learn how to set up the project.

Starting the program

Using IntelliJ

  1. Find the project in the Project Explorer (usually located at the left side)
  2. If the Project Explorer is not visible, press ALT+1 for Windows/Linux, CMD+1 for macOS to open the Project Explorer tab
  3. Go to the src folder and locate the AddressBook file
  4. Right click the file and select Run AddressBook.main()
  5. The program now should run on the Console (usually located at the bottom side)
  6. Now you can interact with the program through the Console

Using Command Line

  1. 'Build' the project using IntelliJ (Build -> Build Project)
  2. Open the Terminal/Command Prompt. Note: You can open a terminal inside Intellij too (View -> Tool Windows -> Terminal)
  3. cd into the project's out\production\addressbook-level1 directory. Note: That is the where Intellij puts its compiled class files.
  4. Type java seedu.addressbook.AddressBook, then Enter to execute
  5. Now you can interact with the program through the CLI
List of commands
Viewing help: help

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

Format: add NAME p/PHONE_NUMBER e/EMAIL

Words in UPPER_CASE are the parameters
Phone number and email can be in any order but the name must come first.

Examples:

Listing all persons: list

Shows a list of persons, as an indexed list, in the order they were added to the address book, oldest first.

Format: list

Finding a person by keyword find

Finds persons that match given keywords

Format: find KEYWORD [MORE_KEYWORDS]

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:

Deleting a person: delete

Format: delete INDEX

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

Examples:

Clearing all entries: clear

Clears all entries from the address book.
Format: clear

Exiting the program: exit

Format: exit

Saving the data

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

Changing the save location

Address book data are saved in a file called addressbook.txt in the project root folder. You can change the location by specifying the file path as a program argument.

Example:

The file path must contain a valid file name and a valid parent directory.
File name is valid if it has an extension and no reserved characters (OS-dependent).
Parent directory is valid if it exists.
Note for non-Windows users: if the file already exists, it must be a 'regular' file.

When running the program inside IntelliJ, there is a way to set command line parameters before running the program.


Developer Guide

Setting up

Prerequisites

Importing the project into IntelliJ

  1. Open IntelliJ (if you are not in the welcome screen, click File > Close Project to close the existing project dialog first)
  2. Set up the correct JDK version
  3. Click Configure > Project Defaults > Project Structure
  4. If JDK 8 is listed in the drop down, select it. If it is not, click New... and select the directory where you installed JDK 8.
  5. Click OK.
  6. Click Import Project
  7. Locate the project directory and click OK
  8. Select Create project from existing sources and click Next
  9. Rename the project if you want. Click Next
  10. Ensure that your src folder is checked. Keep clicking Next
  11. Click Finish
Design

AddressBook saves data in a plain text file, one line for each person, in the format NAME p/PHONE e/EMAIL. Here is an example:

 Doe p/98765432 e/johnd@gmail.com
 Doe p/12346758 e/jane@gmail.com

All person data are loaded to memory at start up and written to the file after any command that mutates data. In-memory data are held in a ArrayList<String[]> where each String[] object represents a person.

Testing

Windows

  1. Open a DOS window in the test folder
  2. Run the runtests.bat script
  3. If the script reports that there is no difference between actual.txt and expected.txt, the test has passed.

Mac/Unix/Linux

  1. Open a terminal window in the test folder
  2. Run the runtests.sh script
  3. If the script reports that there is no difference between actual.txt and expected.txt, the test has passed.

Troubleshooting test failures


Learning Outcomes

Learning Outcomes are the things you should be able to do after studying this code and completing the corresponding exercises.

Set up a project in an IDE [LO-IdeSetup]
Exercise: Setup project in IntelliJ

Part A:

Part B:

Navigate code efficiently [LO-CodeNavigation]

The AddressBook.java code is rather long, which makes it cumbersome to navigate by scrolling alone. Navigating code using IDE shortcuts is a more efficient option. For example, CTRL+B will navigate to the definition of the method/field at the cursor.

Learn basic IntelliJ code navigation features.

Exercise: Learn to navigate code using shortcuts
Use a debugger [LO-Debugging]

Learn basic IntelliJ debugging features.

Exercise: Learn to step through code using the debugger

Prerequisite: [LO-IdeSetup]

Demonstrate your debugging skills using the AddressBook code.

Here are some things you can do in your demonstration:

  1. Set a 'break point'
  2. Run the program in debug mode
  3. 'Step through' a few lines of code while examining variable values
  4. 'Step into', and 'step out of', methods as you step through the code
Automate CLI testing [LO-AutomatedCliTesting]

Learn how to automate testing of CLIs.

Exercise: Practice automated CLI testing
Use Collections [LO-Collections]

Note how the AddressBook class uses ArrayList<> class (from the Java Collections library) to store a list of String or String[] objects.

Learn how to use some Java Collections classes, such as ArrayList and HashMap

Exercise: Use HashMap

Currently, a person's details are stored as a String[]. Modify the code to use a HashMap<String, String> instead. A sample code snippet is given below.

ate static final String PERSON_PROPERTY_NAME = "name";
ate static final String PERSON_PROPERTY_EMAIL = "email";

Map<String,String> john = new HashMap<>();
.put(PERSON_PROPERTY_NAME, "John Doe");
.put(PERSON_PROPERTY_EMAIL, "john.doe@email.com");
c.
Use Enums [LO-Enums]
Exercise: Use HashMap + Enum

Similar to the exercise in the LO-Collections section, but also bring in Java enum feature.

ate enum PersonProperty  {NAME, EMAIL, PHONE};

Map<PersonProperty,String> john = new HashMap<>();
.put(PersonProperty.NAME, "John Doe");
.put(PersonProperty.EMAIL, "john.doe@email.com");
c.
Use Varargs [LO-Varargs]

Note how the showToUser method uses Java Varargs feature.

Exercise: Use Varargs

Modify the code to remove the use of the Varargs feature. Compare the code with and without the varargs feature.

Follow a coding standard [LO-CodingStandard]

The given code follows the coding standard for the most part.

This learning outcome is covered by the exercise in [LO-Refactor].

Apply coding best practices [LO-CodingBestPractices]

Most of the given code follows the best practices mentioned here.

This learning outcome is covered by the exercise in [LO-Refactor]

Refactor code [LO-Refactor]

Resources:

Exercise: Refactor the code to make it better

Note: this exercise covers two other Learning Outcomes: [LO-CodingStandard], [LO-CodingBestPractices]

Abstract methods well [LO-MethodAbstraction]

Notice how most of the methods in AddressBook are short and focused (does only one thing and does it well).

Case 1. Consider the following three lines in the main method.

String userCommand = getUserInput();
echoUserCommand(userCommand);
String feedback = executeCommand(userCommand);

If we include the code of echoUserCommand(String) method inside the getUserInput() (resulting in the code given below), the behavior of AddressBook remains as before. However, that is a not a good approach because now the getUserInput() is doing two distinct things. A well-abstracted method should do only one thing.

String userCommand = getUserInput(); //also echos the command back to the user
String feedback = executeCommand(userCommand);

Case 2. Consider the method removePrefixSign(String s, String sign). While it is short, there are some problems with how it has been abstracted.

  1. It contains the term sign which is not a term used by the AddressBook vocabulary.

    A method adds a new term to the vocabulary used to express the solution. Therefore, it is not good when a method name contains terms that are not strictly necessary to express the solution (e.g. there is another term already used to express the same thing) or not in tune with the solution (e.g. it does not go well with the other terms already used).

  2. Its implementation is not doing exactly what is advertised by the method name and the header comment. For example, the code does not remove only prefixes; it removes sign from anywhere in the s.

  3. The method can be more general and more independent from the rest of the code. For example, the method below can do the same job, but is more general (works for any string, not just parameters) and is more independent from the rest of the code (not specific to AddressBook)

    
    moves prefix from the given fullString if prefix occurs at the start of the string.
    
    ate static String removePrefix(String fullString, String prefix) { ... }
    

    If needed, a more AddressBook-specific method that works on parameter strings only can be defined. In that case, that method can make use of the more general method suggested above.

Exercise: Improve abstraction of method

Refactor the method removePrefixSign as suggested above.

Follow SLAP [LO-SLAP]

Notice how most of the methods in AddressBook are written at a single level of abstraction (cf se-edu/se-book:SLAP)

Here is an example:

public static void main(String[] args) {
    showWelcomeMessage();
    processProgramArgs(args);
    loadDataFromStorage();
    while (true) {
        userCommand = getUserInput();
        echoUserCommand(userCommand);
        String feedback = executeCommand(userCommand);
        showResultToUser(feedback);
    }
}
Exercise 1: Reduce SLAP of method

In the main method, replace the processProgramArgs(args) call with the actual code of that method. The main method no longer has SLAP. Notice how mixing low level code with high level code reduces readability.

Exercise 2: Refactor the code to make it worse!

Sometimes, going in the wrong direction can be a good learning experience too. In this exercise, we explore how low code qualities can go.

Work in a 1kLoC code base[LO-1KLoC]
Exercise: Enhance the code

Enhance the AddressBook to prove that you can work in a codebase of 1KLoC.
Remember to change code in small steps, update/run tests after each change, and commit after each significant change.

Some suggested enhancements:


Contributors

The full list of contributors for se-edu can be found here.


Contact Us


This work is supported by the National Institutes of Health's National Center for Advancing Translational Sciences, Grant Number U24TR002306. This work is solely the responsibility of the creators and does not necessarily represent the official views of the National Institutes of Health.