|
1 | 1 | # Introduction |
2 | 2 |
|
3 | | -There are various idiomatic approaches to solve Bob. |
4 | | -A basic approach can use a series of `if` statements to test the conditions. |
5 | | -An array can contain answers from which the right response is selected by an index calculated from scores given to the conditions. |
| 3 | +In this exercise, we’re working on a program to determine Bob’s responses based on the tone and style of given messages. Bob responds differently depending on whether a message is a question, a shout, both, or silence. Various approaches can be used to implement this logic efficiently and cleanly, ensuring the code remains readable and easy to maintain. |
6 | 4 |
|
7 | | -## General guidance |
| 5 | +## General Guidance |
8 | 6 |
|
9 | | -Regardless of the approach used, some things you could look out for include |
| 7 | +When implementing your solution, consider the following tips to keep your code optimized and idiomatic: |
10 | 8 |
|
11 | | -- If the input is trimmed, [`trim()`][trim] only once. |
| 9 | +- **Trim the Input Once**: Use [`trim()`][trim] only once at the start to remove any unnecessary whitespace. |
| 10 | +- **Use Built-in Methods**: For checking if a message is a question, prefer [`endsWith("?")`][endswith] instead of manually checking the last character. |
| 11 | +- **DRY Code**: Avoid duplicating code by combining the logic for determining a shout and a question when handling shouted questions. Following the [DRY][dry] principle helps maintain clear and maintainable code. |
| 12 | +- **Single Determinations**: Use variables for `questioning` and `shouting` rather than calling these checks multiple times to improve efficiency. |
| 13 | +- **Return Statements**: An early return in an `if` statement eliminates the need for additional `else` blocks, making the code more readable. |
| 14 | +- **Curly Braces**: While optional for single-line statements, some teams may require them for readability and consistency. |
12 | 15 |
|
13 | | -- Use the [`endsWith()`][endswith] `String` method instead of checking the last character by index for `?`. |
| 16 | +## Approach: Method-Based |
14 | 17 |
|
15 | | -- Don't copy/paste the logic for determining a shout and for determining a question into determining a shouted question. |
16 | | - Combine the two determinations instead of copying them. |
17 | | - Not duplicating the code will keep the code [DRY][dry]. |
| 18 | +```java |
| 19 | +class Bob { |
| 20 | + String hey(String input) { |
| 21 | + var inputTrimmed = input.trim(); |
| 22 | + |
| 23 | + if (isSilent(inputTrimmed)) |
| 24 | + return "Fine. Be that way!"; |
| 25 | + if (isYelling(inputTrimmed) && isAsking(inputTrimmed)) |
| 26 | + return "Calm down, I know what I'm doing!"; |
| 27 | + if (isYelling(inputTrimmed)) |
| 28 | + return "Whoa, chill out!"; |
| 29 | + if (isAsking(inputTrimmed)) |
| 30 | + return "Sure."; |
| 31 | + |
| 32 | + return "Whatever."; |
| 33 | + } |
| 34 | + |
| 35 | + private boolean isYelling(String input) { |
| 36 | + return input.chars() |
| 37 | + .anyMatch(Character::isLetter) && |
| 38 | + input.chars() |
| 39 | + .filter(Character::isLetter) |
| 40 | + .allMatch(Character::isUpperCase); |
| 41 | + } |
18 | 42 |
|
19 | | -- Perhaps consider making `questioning` and `shouting` values set once instead of functions that are possibly called twice. |
| 43 | + private boolean isAsking(String input) { |
| 44 | + return input.endsWith("?"); |
| 45 | + } |
20 | 46 |
|
21 | | -- If an `if` statement can return, then an `else if` or `else` is not needed. |
22 | | - Execution will either return or will continue to the next statement anyway. |
| 47 | + private boolean isSilent(String input) { |
| 48 | + return input.length() == 0; |
| 49 | + } |
| 50 | +} |
| 51 | +``` |
23 | 52 |
|
24 | | -- If the body of an `if` statement is only one line, curly braces aren't needed. |
25 | | - Some teams may still require them in their style guidelines, though. |
| 53 | +This approach defines helper methods for each type of message—silent, yelling, and asking—to keep each condition clean and easily testable. For more details, refer to the [Method-Based Approach][approach-method-based]. |
26 | 54 |
|
27 | | -## Approach: `if` statements |
| 55 | +## Approach: `if` Statements |
28 | 56 |
|
29 | 57 | ```java |
30 | 58 | import java.util.function.Predicate; |
@@ -56,9 +84,9 @@ class Bob { |
56 | 84 | } |
57 | 85 | ``` |
58 | 86 |
|
59 | | -For more information, check the [`if` statements approach][approach-if]. |
| 87 | +This approach utilizes nested `if` statements and a predicate for determining if a message is a shout. For more details, refer to the [`if` Statements Approach][approach-if]. |
60 | 88 |
|
61 | | -## Approach: answer array |
| 89 | +## Approach: Answer Array |
62 | 90 |
|
63 | 91 | ```java |
64 | 92 | import java.util.function.Predicate; |
@@ -86,16 +114,22 @@ class Bob { |
86 | 114 | } |
87 | 115 | ``` |
88 | 116 |
|
89 | | -For more information, check the [Answer array approach][approach-answer-array]. |
| 117 | +This approach uses an array of answers and calculates the appropriate index based on flags for shouting and questioning. For more details, refer to the [Answer Array Approach][approach-answer-array]. |
| 118 | + |
| 119 | +## Which Approach to Use? |
| 120 | + |
| 121 | +Choosing between the method-based approach, `if` statements, and answer array approach can come down to readability and maintainability. Each has its advantages: |
90 | 122 |
|
91 | | -## Which approach to use? |
| 123 | +- **Method-Based**: Clear and modular, great for readability. |
| 124 | +- **`if` Statements**: Compact and straightforward, suited for smaller projects. |
| 125 | +- **Answer Array**: Minimizes condition checks by using indices, efficient for a variety of responses. |
92 | 126 |
|
93 | | -Since benchmarking with the [Java Microbenchmark Harness][jmh] is currently outside the scope of this document, |
94 | | -the choice between `if` statements and answers array can be made by perceived readability. |
| 127 | +Experiment with these approaches to find the balance between readability and performance that best suits your needs. |
95 | 128 |
|
96 | 129 | [trim]: https://docs.oracle.com/javase/7/docs/api/java/lang/String.html#trim() |
97 | 130 | [endswith]: https://docs.oracle.com/javase/7/docs/api/java/lang/String.html#endsWith(java.lang.String) |
98 | 131 | [dry]: https://en.wikipedia.org/wiki/Don%27t_repeat_yourself |
| 132 | +[approach-method-based]: https://exercism.org/tracks/java/exercises/bob/approaches/method-based |
99 | 133 | [approach-if]: https://exercism.org/tracks/java/exercises/bob/approaches/if-statements |
100 | 134 | [approach-answer-array]: https://exercism.org/tracks/java/exercises/bob/approaches/answer-array |
101 | 135 | [jmh]: https://github.com/openjdk/jmh |
0 commit comments