You are on page 1of 16

ISYS6633003 - Programming Mastery Prepared By:

Binus International University - Exercise Handout 2021 Even Andreas Kurniawan, D6034

Week: 04

Topics: Designing Classes

A. Discuss Week 03 Exercises

1) Days Alive

Problem Statement : Your task is to write a program that determines


how many days you have been alive.

You can construct and set a Calendar object from a given year, month,
and day, like this:

Calendar jamesGoslingsBirthday = Calendar.getInstance();


jamesGoslingsBirthday.set(1955, 5, 19);

There is a method for adding days to a given day, for example:

Calendar later = Calendar.getInstance();


later.set(1955, 5, 19);
later.add(Calendar.DATE, 100);

You can then find out what the result is, by applying the get method:

System.out.println(later.get(Calendar.YEAR));
System.out.println(later.get(Calendar.MONTH));
System.out.println(later.get(Calendar.DATE));

However, that approach does not solve our problem (unless you are willing to replace 100
with other values until, by trial and error, you obtain today’s date.) Instead, use the
getTimeInMillis method like this:

Page 1 of 16
ISYS6633003 - Programming Mastery Prepared By:
Binus International University - Exercise Handout 2021 Even Andreas Kurniawan, D6034
long timeDiff = (day2.getTimeInMillis() -
day1.getTimeInMillis());
int daysAlive = (int) (timeDiff / (1000*60*60*24));

In our situation, one of the Day objects is jamesGoslingsBirthday, and the other is today’s
date. This can be obtained with the constructor that has no arguments:

Calendar today = Calendar.getInstance();

Then we can invoke the following code to get the daysAlive =

long timeDiff = (today.getTimeInMillis() -


jamesGoslingsBirthday.getTimeInMillis());
int daysAlive = (int) (timeDiff / (1000*60*60*24));

After learning the days alive concept, please create a simple java program using Calendar
class to have the following example output :

Today: 2022-03-01
Days alive: 7301

It is allowed to use any birth date as the data.

2) Make a simple menu

Problem Statement : Your task is to


design a class Menu. An object of this
class can display a menu such as =

1) Open new account

2) Log into existing account

3) Help

4) Quit

Page 2 of 16
ISYS6633003 - Programming Mastery Prepared By:
Binus International University - Exercise Handout 2021 Even Andreas Kurniawan, D6034

The numbers should be supplied automatically when options are added to the menu.

Step 1 : Find out which methods you are asked to supply.

The problem description lists two tasks:

- Display the menu.

- Add an option to the menu.

Step 2 : Specify the public interface.

Here we turn the list in Step 1 into a set of methods, with specific types for the parameter
variables and the return values :

mainMenu.addOption("Open new account");


mainMenu.addOption("Log into existing account");
mainMenu.display();

Now we have a specific list of methods:

public void addOption(String option)


public void display()

To complete the public interface, we need to specify the constructors. We have two choices:

- Supply a constructor Menu(String firstOption) that makes a menu with one option.

- Supply a constructor Menu() that makes a menu with no options.

Either choice will work fine. If we decide in favor of the second choice, the user of the class
needs to call addOption to add the first option—after all, there is no sense in having a menu
with no options. At first glance, that seems like a burden for the programmer using the class.
But actually, it is usually conceptually simpler if an API has no special cases (such as having to

Page 3 of 16
ISYS6633003 - Programming Mastery Prepared By:
Binus International University - Exercise Handout 2021 Even Andreas Kurniawan, D6034

supply the first option in the constructor). Therefore, we decide that “simplest is best” and
specify the constructor

public Menu()

Step 3 : Document the public interface.

Here is the documentation, with comments, that describes the class and its
methods:

/**

A menu that is displayed on a console.

*/

public class Menu

/**

Constructs a menu with no options.

*/

public Menu()

/**

Adds an option to the end of this menu.

@param option the option to add

*/

public void addOption(String option)

/**

Displays the menu on the console.

*/

public void display()

Page 4 of 16
ISYS6633003 - Programming Mastery Prepared By:
Binus International University - Exercise Handout 2021 Even Andreas Kurniawan, D6034

Step 4 : Determine instance variables.

What data does a Menu option need to keep in order to fulfill its responsibilities? Of course,
in order to display the menu, it needs to store the menu text. Now consider the addOption
method. That method adds a number and the option to the menu text. Where does the
number come from? The menu object needs to store it too, so that it can increment
whenever addoption is called.

Therefore, our instance variables are :

public class Menu


{
private String menuText;
private int optionCount;
. . .
}

Step 5 : Implement constructors and methods.

We now implement the constructors and methods in the class, one at a time, in the order
that is most convenient. The constructor seems pretty easy:

public Menu()

menuText = "";

optionCount = 0;

The display method is easy as well:

public void display()

{
System.out.println(menuText);
}

Page 5 of 16
ISYS6633003 - Programming Mastery Prepared By:
Binus International University - Exercise Handout 2021 Even Andreas Kurniawan, D6034

The addOption method requires a bit more thought. Here is the pseudocode:

- Increment the option count

- Add the following to the menu text:

The option count

A ) symbol

The option to be added

A "newline" character that causes the next option to appear on a new line

How do you add something to a string? If you look at the API of the String class, you will find
a method concat. For example, the call

menuText.concat(option)

creates a string consisting of the strings menuText and option. You can then store that string
back into the menuText variable:

menuText = menuText.concat(option);

You can achieve the same effect with the + operator:

menuText = menuText + option;

We use the + operator in our solution because it is so convenient. Our method then
becomes

public void addOption(String option)


{

optionCount = optionCount + 1;

menuText = menuText + optionCount + ") " + option + "\n";

Page 6 of 16
ISYS6633003 - Programming Mastery Prepared By:
Binus International University - Exercise Handout 2021 Even Andreas Kurniawan, D6034

Step 6 : Wrap it up

Please compile the previous steps into a working simple java program by implementing
classes to have the following output :

1) Open new account

2) Log into existing account

3) Help

4) Quit

Page 7 of 16
ISYS6633003 - Programming Mastery Prepared By:
Binus International University - Exercise Handout 2021 Even Andreas Kurniawan, D6034

B. Recall Week 04 Material

1) Providing a Cohesive Public Interface

If you find that the public interface of a class refers to multiple


concepts, then that is a good sign that it may be time to use
separate classes instead. Consider, for example, the public
interface of the CashRegister class below :

public class CashRegister


{
public static final double QUARTER_VALUE = 0.25;
public static final double DIME_VALUE = 0.1;
public static final double NICKEL_VALUE = 0.05;
. . .
public void receivePayment(int dollars, int quarters,
int dimes, int nickels, int pennies)
. . .
}

There are really two concepts here: a cash register that holds coins and computes their total,
and the values of individual coins. It makes sense to have a separate Coin class and have
coins responsible for knowing their values.

public class Coin


{
. . .
public Coin(double aValue, String aName) { . . . }
public double getValue() { . . . }
. . .
}

Then the CashRegister class can be simplified:

Page 8 of 16
ISYS6633003 - Programming Mastery Prepared By:
Binus International University - Exercise Handout 2021 Even Andreas Kurniawan, D6034
public class CashRegister
{
. . .
public void receivePayment(int coinCount, Coin coinType)
{ . . . }
{
payment = payment + coinCount * coinType.getValue();
}
. . .
}

2) Minimizing Dependencies

Many methods need other classes in order to do their jobs. For example,
the receivePayment method of the restructured CashRegister class now
uses the Coin class. We say that the CashRegister class depends on the
Coin class.

Here is an example of minimizing dependencies. Consider how we have


always printed a bank balance:

System.out.println("The balance is now $" + momsSavings.getBalance());

Why don’t we simply have a printBalance method?

public void printBalance() // Not recommended


{
System.out.println("The balance is now $" + balance);
}

The method depends on System.out. Not every computing environment has System.out. For
example, an automatic teller machine doesn’t display console messages. In other words, this
design violates the rule of minimizing dependencies. The printBalance method couples the
BankAccount class with the System and PrintStream classes.It is best to place the code for
producing output or consuming input in a separate class. That way, you decouple
input/output from the actual work of your classes.

Page 9 of 16
ISYS6633003 - Programming Mastery Prepared By:
Binus International University - Exercise Handout 2021 Even Andreas Kurniawan, D6034

3) Separating Accessors and Mutators

A mutator method changes the state of an object. Conversely, an


accessor method asks an object to compute a result, without
changing the state. Some classes have been designed to have only
accessor methods and no mutator methods at all. Such classes are
called immutable.

For example, the toUpperCase method does not change characters


from the original string. Instead, it constructs a new string that
contains the uppercase characters:

String name = "John Q. Public";


String uppercased = name.toUpperCase(); // name is not changed

As a rule of thumb, a method that returns a value should not be a mutator. For example, one
would not expect that calling getBalance on a BankAccount object would change the
balance. (You would be pretty upset if your bank charged you a “balance inquiry fee”.) If you
follow this rule, then all mutators of your class have return type void.

Sometimes, this rule is bent a bit, and mutator methods return an informational value. For
example, the ArrayList class has a remove method to remove an object.

ArrayList<String> names = ...;


boolean success = names.remove("Romeo");

4) Minimizing Side Effects

A side effect of a method is any kind of modification of


data that is observable outside the method. Mutator
methods have a side effect, namely the modification of
the implicit parameter.

There is another kind of side effect that you should


avoid. A method should generally not modify its
parameter variables. Consider this example:

Page 10 of 16
ISYS6633003 - Programming Mastery Prepared By:
Binus International University - Exercise Handout 2021 Even Andreas Kurniawan, D6034
/**
Computes the total balance of the given accounts.
@param accounts a list of bank accounts
*/
public double getTotalBalance(ArrayList<String> accounts)
{
double sum = 0;
while (studentNames.size() > 0)
{
BankAccount account = accounts.remove(0); // Not
recommended
sum = sum + account.getBalance();
}
return sum;
}
}

This method removes all names from the accounts parameter variable. After a call

double total = getTotalBalance(allAccounts);

allAccounts is empty!

Page 11 of 16
ISYS6633003 - Programming Mastery Prepared By:
Binus International University - Exercise Handout 2021 Even Andreas Kurniawan, D6034

C. Exercise 1 : Design Cash Register Class

Problem Statement : Suppose you are asked to write a program that


simulates a cash register. A cashier record purchases and receive payment
from the customer. The cash register will show the change and then reset
the cash register for the next customer. We will assume that the cash
register accepts payment in dollars, quarters, dimes, nickels, and pennies.
Your task is to compute the change due to the customer.

For your information :

Quarter = 25 cents

Dime = 10 cents

Nickel = 5 cents

Penny = 1 cent

Already finish? Raise hand or type in the chat box to notify the lecturer that you have finished
this exercise.

Page 12 of 16
ISYS6633003 - Programming Mastery Prepared By:
Binus International University - Exercise Handout 2021 Even Andreas Kurniawan, D6034

D. Exercise 2 : Cash Register Unit Testing

Up to now, we have used a very simple approach to testing. We provided tester classes whose
main method computes values and prints actual and expected values. However, that approach
has limitations. The main method gets messy if it contains many tests. And if an exception occurs
during one of the tests, the remaining tests are not executed.

Unit testing frameworks were designed to quickly execute and evaluate test suites and to make
it easy to incrementally add test cases. One of the most popular testing frameworks is JUnit.

1) Create Test

Page 13 of 16
ISYS6633003 - Programming Mastery Prepared By:
Binus International University - Exercise Handout 2021 Even Andreas Kurniawan, D6034

2) Create Junit Class Test

Adjust Code Generation options as needed and click Ok.

3) Create Test Method

By default, netbeans will create testSomeMethod() for the test method as below =

Page 14 of 16
ISYS6633003 - Programming Mastery Prepared By:
Binus International University - Exercise Handout 2021 Even Andreas Kurniawan, D6034
public class CashRegisterTest {

public CashRegisterTest() {
}

@Test
public void testSomeMethod() {
}

You may adjust and create the test methods. Make sure that each test method contains Test
annotator and the method’s name starts with test. For example we can create two test
methods =

private static final double EPSILON = 1E-12;

@Test public void testTwoPurchases()

CashRegister register = new CashRegister();

register.recordPurchase(0.75);

register.recordPurchase(1.50);

register.receivePayment(2, 0, 5, 0, 0);

double expected = 0.25;

assertEquals(expected, register.giveChange(), EPSILON);

@Test public void testZeroBalance()

CashRegister register = new CashRegister();

register.recordPurchase(2.25);

register.recordPurchase(19.25);

register.receivePayment(21, 2, 0, 0, 0);

assertEquals(0, register.giveChange(), EPSILON);

Page 15 of 16
ISYS6633003 - Programming Mastery Prepared By:
Binus International University - Exercise Handout 2021 Even Andreas Kurniawan, D6034

4) Run Test

To run the test, we can click the class name and select Test File.

5) Observe the result

After running the test, we can immediately get the result of the test.

Page 16 of 16

You might also like