Skip to content

Commit 15d2779

Browse files
committed
Improve design of SimpleMath
Introduce PositiveInteger
1 parent ab1e8e5 commit 15d2779

File tree

3 files changed

+135
-33
lines changed

3 files changed

+135
-33
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
package com.craftsmanshipinsoftware.math;
2+
3+
import java.io.Serial;
4+
5+
final class PositiveInteger extends Number {
6+
7+
@Serial
8+
private static final long serialVersionUID = -4429661748302289322L;
9+
10+
private final Integer value;
11+
12+
private PositiveInteger(Integer value) {
13+
this.value = value;
14+
}
15+
16+
static PositiveInteger of(String value) {
17+
try {
18+
int number = Integer.parseInt(value);
19+
if (number < 0) {
20+
throw new IllegalArgumentException("Please enter a positive number! Input: %d".formatted(number));
21+
}
22+
return new PositiveInteger(number);
23+
} catch (NumberFormatException e) {
24+
throw new IllegalArgumentException("Please enter a valid number! Input: %s".formatted(value), e);
25+
}
26+
}
27+
28+
@Override
29+
public int intValue() {
30+
return this.value;
31+
}
32+
33+
@Override
34+
public long longValue() {
35+
return this.value.longValue();
36+
}
37+
38+
@Override
39+
public float floatValue() {
40+
return this.value.floatValue();
41+
}
42+
43+
@Override
44+
public double doubleValue() {
45+
return this.value.doubleValue();
46+
}
47+
48+
@Override
49+
public int hashCode() {
50+
return this.value.hashCode();
51+
}
52+
53+
@Override
54+
public boolean equals(Object obj) {
55+
if (this == obj) {
56+
return true;
57+
}
58+
if (!(obj instanceof PositiveInteger that)) {
59+
return false;
60+
}
61+
return this.value.equals(that.value);
62+
}
63+
64+
@Override
65+
public String toString() {
66+
return this.value.toString();
67+
}
68+
}

simple-math/src/main/java/com/craftsmanshipinsoftware/math/SimpleMath.java

+18-33
Original file line numberDiff line numberDiff line change
@@ -20,52 +20,34 @@ class SimpleMath {
2020
void printOutput() {
2121
try (Scanner scanner = new Scanner(inputStream)) {
2222
String firstInput = promptForInput("What is the first number? ", scanner);
23-
int firstNumber = validatedInput(firstInput);
23+
PositiveInteger firstNumber = PositiveInteger.of(firstInput);
2424
String secondInput = promptForInput("What is the second number? ", scanner);
25-
int secondNumber = validatedInput(secondInput);
26-
if (secondNumber == 0) {
27-
throw new IllegalArgumentException("Cannot divide by zero!");
28-
}
29-
this.printStream.println(output(firstNumber, secondNumber));
25+
PositiveInteger secondNumber = PositiveInteger.of(secondInput);
26+
this.printStream.println(formattedOutput(firstNumber, secondNumber));
3027
}
3128
}
3229

3330
@SuppressWarnings("PMD.SystemPrintln")
3431
private String promptForInput(String prompt, Scanner scanner) {
3532
System.out.print(prompt);
36-
String input = readInput(scanner);
33+
String input = scanner.hasNext() ? scanner.nextLine() : null;
3734
if (input == null || input.isBlank()) {
3835
throw new IllegalArgumentException("Input must not be empty!");
3936
}
4037
return input;
4138
}
4239

43-
private String readInput(Scanner scanner) {
44-
return scanner.hasNext() ? scanner.nextLine() : null;
45-
}
46-
47-
private static int validatedInput(String input) {
48-
try {
49-
int number = Integer.parseInt(input);
50-
if (number < 0) {
51-
throw new IllegalArgumentException("Please enter a positive number! Input: " + number);
52-
}
53-
return number;
54-
} catch (NumberFormatException e) {
55-
throw new IllegalArgumentException("Please enter a valid number! Input: " + input, e);
56-
}
57-
}
58-
59-
private static String output(int firstNumber, int secondNumber) {
60-
return String.format("""
61-
%d + %d = %d
62-
%d - %d = %d
63-
%d * %d = %d
64-
%d / %d = %d""",
65-
firstNumber, secondNumber, add(firstNumber, secondNumber),
66-
firstNumber, secondNumber, subtract(firstNumber, secondNumber),
67-
firstNumber, secondNumber, multiply(firstNumber, secondNumber),
68-
firstNumber, secondNumber, divide(firstNumber, secondNumber));
40+
private static String formattedOutput(PositiveInteger firstNumber, PositiveInteger secondNumber) {
41+
return """
42+
%s + %s = %d
43+
%s - %s = %d
44+
%s * %s = %d
45+
%s / %s = %d""".formatted(
46+
firstNumber, secondNumber, add(firstNumber.intValue(), secondNumber.intValue()),
47+
firstNumber, secondNumber, subtract(firstNumber.intValue(), secondNumber.intValue()),
48+
firstNumber, secondNumber, multiply(firstNumber.intValue(), secondNumber.intValue()),
49+
firstNumber, secondNumber, divide(firstNumber.intValue(), secondNumber.intValue())
50+
);
6951
}
7052

7153
private static int add(int firstNumber, int secondNumber) {
@@ -81,6 +63,9 @@ private static int multiply(int firstNumber, int secondNumber) {
8163
}
8264

8365
private static int divide(int firstNumber, int secondNumber) {
66+
if (secondNumber == 0) {
67+
throw new IllegalArgumentException("Cannot divide by zero!");
68+
}
8469
return firstNumber / secondNumber;
8570
}
8671
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package com.craftsmanshipinsoftware.math;
2+
3+
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
4+
5+
import org.assertj.core.api.SoftAssertions;
6+
import org.junit.jupiter.api.Test;
7+
import org.junit.jupiter.params.ParameterizedTest;
8+
import org.junit.jupiter.params.provider.NullAndEmptySource;
9+
10+
class PositiveIntegerTest {
11+
12+
@Test
13+
void valueMustBeANumber() {
14+
assertThatIllegalArgumentException()
15+
.isThrownBy(() -> PositiveInteger.of("asdf"))
16+
.withMessage("Please enter a valid number! Input: asdf");
17+
}
18+
19+
@Test
20+
void valueMustBePositive() {
21+
assertThatIllegalArgumentException()
22+
.isThrownBy(() -> PositiveInteger.of("-1"))
23+
.withMessage("Please enter a positive number! Input: -1");
24+
}
25+
26+
@ParameterizedTest
27+
@NullAndEmptySource
28+
void valueMustNotNullOrEmpty(String value) {
29+
assertThatIllegalArgumentException()
30+
.isThrownBy(() -> PositiveInteger.of(value))
31+
.withMessage("Please enter a valid number! Input: " + value);
32+
}
33+
34+
@Test
35+
@SuppressWarnings("PMD.JUnitTestsShouldIncludeAssert")
36+
void encapsulatesAPositiveNumber() {
37+
PositiveInteger positiveInteger = PositiveInteger.of("42");
38+
39+
SoftAssertions.assertSoftly(softly -> {
40+
softly.assertThat(positiveInteger.intValue()).isEqualTo(42);
41+
softly.assertThat(positiveInteger.longValue()).isEqualTo(42L);
42+
softly.assertThat(positiveInteger.floatValue()).isEqualTo(42.0f);
43+
softly.assertThat(positiveInteger.doubleValue()).isEqualTo(42.0);
44+
softly.assertThat(positiveInteger.hashCode()).isEqualTo(Integer.hashCode(42));
45+
softly.assertThat(positiveInteger).isEqualTo(PositiveInteger.of("42"));
46+
softly.assertThat(positiveInteger).hasToString("42");
47+
});
48+
}
49+
}

0 commit comments

Comments
 (0)