Browse Source

Merge pull request #666 from exercism/hello-world

Updates now that two-fer is part of the track!
FridaTveit 9 years ago
parent
commit
83bf9111cf

exercises/clock/HINT.md → exercises/clock/HINTS.md View File


+ 0
- 49
exercises/hello-world/GETTING_STARTED.md View File

1
-----
2
-# Quick Start Guide
3
-
4
-This guide picks-up where [Running the Tests (in Java)](http://exercism.io/languages/java/tests)
5
-left off.  If you haven't reviewed those instructions, do so now.
6
-
7
-Need more information?  A **step-by-step tutorial** is available in this directory at TUTORIAL.md or you can read 
8
-the [HTML version](https://github.com/exercism/java/blob/master/exercises/hello-world/TUTORIAL.md).
9
-
10
-The following instructions work equally well on Windows, Mac OS X and Linux.
11
-
12
-## Solve "Hello World"
13
-
14
-Try writing a solution that passes one test at a time, running Gradle each time:
15
-
16
-
17
-```
18
-$ gradle test
19
-```
20
-
21
-## Iterate through the tests
22
-
23
-After your first test passes, iterate on your solution, testing after each change.
24
-
25
-## All the tests pass?  Submit your solution!
26
-
27
-With a working solution that we've reviewed, we're ready to submit it to
28
-exercism.io.
29
-
30
-```
31
-$ exercism submit src/main/java/HelloWorld.java
32
-```
33
-
34
-## Next Steps
35
-
36
-From here, there are a number of paths you can take.
37
-
38
-1. Move on to the next exercise
39
-2. Review (and comment on) others' submissions to this exercise
40
-3. Submit another iteration
41
-4. Contribute to Exercism
42
-
43
-
44
-We sincerely hope you learn and enjoy being part of this community.  If at any time you need assistance
45
-do not hesitate to ask for help:
46
-
47
-http://exercism.io/languages/java/help
48
-
49
-Cheers!

+ 0
- 7
exercises/hello-world/HINT.md View File

1
-The default implementation for this exercise uses an [exception](https://docs.oracle.com/javase/tutorial/essential/exceptions/) 
2
-which will cause the test to fail with the provided error message.
3
-This particular exception type, [UnsupportedOperationException](http://docs.oracle.com/javase/8/docs/api/?java/lang/UnsupportedOperationException.html), 
4
-is commonly thrown to alert developers that a method has not yet been implemented.
5
-Throwing exceptions in this manner means the tests will compile but not pass right away.
6
-
7
-To make the test pass you need to remove the line which throws the exception and replace it with your implementation of the method.

+ 4
- 0
exercises/hello-world/HINTS.md View File

1
+Since this is your first Java exercise, we've included a detailed TUTORIAL.md
2
+file that guides you through your solution. Check it out for tips and
3
+assistance!
4
+

+ 113
- 362
exercises/hello-world/TUTORIAL.md View File

1
-NOTE: You can also view the HTML version of this file here:
2
-https://github.com/exercism/java/blob/master/exercises/hello-world/TUTORIAL.md
1
+# Table of Contents
3
 
2
 
3
+* [Introduction](#introduction)
4
+* [Exercise Structure](#exercise-structure)
4
 * [Solving "Hello, World!"](#solving-hello-world)
5
 * [Solving "Hello, World!"](#solving-hello-world)
5
- * [Reading Gradle output](#reading-gradle-output)
6
- * [Fixing the first failing test](#fixing-the-first-failing-test)
7
- * [Enabling and fixing the second test](#enabling-and-fixing-the-second-test)
8
- * [Enabling the last test](#enabling-the-last-test)
9
- * [Refactoring](#refactoring)
10
 * [Submitting your first iteration](#submitting-your-first-iteration)
6
 * [Submitting your first iteration](#submitting-your-first-iteration)
11
 * [Next Steps](#next-steps)
7
 * [Next Steps](#next-steps)
12
- * [Review (and comment on) others' submissions to this exercise](#review-and-comment-on-others-submissions-to-this-exercise)
13
- * [Extend an exercise](#extend-an-exercise)
14
 
8
 
15
-----
16
-
17
-# Solving "Hello, World!"
9
+# Introduction
18
 
10
 
19
 Welcome to the first exercise on the Java track!
11
 Welcome to the first exercise on the Java track!
20
 
12
 
21
-This is a step-by-step guide to solving this exercise.
13
+This document is a step-by-step guide to solving this exercise. The
14
+instructions should work equally well on Windows, Mac OS X and Linux.
22
 
15
 
23
-Each exercise comes with a set of tests.  The first pass through the
24
-exercise is about getting all of the tests to pass, one at a time.
16
+Even if you are already familiar with Java basics, stepping through this guide
17
+may be helpful as it will help you understand the output from the tool, Gradle,
18
+that we use to compile and test our code, as well as introduce some of the
19
+patterns common to all exercises in this track.
25
 
20
 
26
-If you have not installed the Java Development Kit and Gradle, you must do
27
-so now.  For help with this, see: http://exercism.io/languages/java/installing
21
+# Exercise Structure
28
 
22
 
29
-----
23
+When you fetch a new Java exercise, you will receive:
30
 
24
 
31
-This guide picks-up where [Running the Tests (in Java)](http://exercism.io/languages/java/tests)
32
-left off.  If you haven't reviewed those instructions, do so now.
25
+* __one or more test files__ (always). These live in the `src/test/java`
26
+directory and define a set of tests that our solution must satisfy before we
27
+can safely declare that it is working.
28
+* __one or more starter files__ (initially). If provided, these live in the
29
+`src/main/java` directory and define shells of the classes you will need
30
+in order to solve the current problem.
33
 
31
 
34
-The following instructions work equally well on Windows, Mac OS X and Linux.
32
+# Solving "Hello, World!"
35
 
33
 
36
-## Reading Gradle output
34
+Before proceeding any further, make sure you have completed the required setup
35
+steps described by the links below:
36
+* [Installing Java](http://exercism.io/languages/java/installing);
37
+* [Running the Tests (in Java)](http://exercism.io/languages/java/tests).
38
+
39
+## Step 1: Run the tests against the starter solution
37
 
40
 
38
 Use Gradle to run the tests:
41
 Use Gradle to run the tests:
39
 
42
 
51
 
54
 
52
 Each line that begins with a colon (like `:compileJava`) is Gradle telling
55
 Each line that begins with a colon (like `:compileJava`) is Gradle telling
53
 us that it's starting that task.  The first three tasks are about compiling
56
 us that it's starting that task.  The first three tasks are about compiling
54
-the source code of our *solution*. We've done you a favor and included just
55
-enough code for the solution that it compiles.
57
+the source code of our _solution_. This exercise contains starter files with
58
+just enough code for the solution to compile without requiring modification.
56
 
59
 
57
 When a task is successful, it generally does not output anything.  This is
60
 When a task is successful, it generally does not output anything.  This is
58
 why `:compileJava` and `:classes` do not produce any additional output.
61
 why `:compileJava` and `:classes` do not produce any additional output.
60
 
63
 
61
 So far, so good...
64
 So far, so good...
62
 
65
 
63
-The next three tasks are about compiling source code of the *tests*.
66
+The next three tasks are about compiling source code of the _tests_.
64
 
67
 
65
 ```
68
 ```
66
 :compileTestJava
69
 :compileTestJava
74
 ```
77
 ```
75
 :test
78
 :test
76
 
79
 
77
-HelloWorldTest > helloSampleName FAILED
78
-    java.lang.UnsupportedOperationException: Delete this statement and write your own implementation.
79
-        at HelloWorld.hello(HelloWorld.java:3)
80
-        at HelloWorldTest.helloSampleName(HelloWorldTest.java:22)
81
-
82
-HelloWorldTest > helloNoName FAILED
83
-    java.lang.UnsupportedOperationException: Delete this statement and write your own implementation.
84
-        at HelloWorld.hello(HelloWorld.java:3)
85
-        at HelloWorldTest.helloNoName(HelloWorldTest.java:11)
86
-
87
-HelloWorldTest > emptyStringIsComparedByValue FAILED
88
-    java.lang.UnsupportedOperationException: Delete this statement and write your own implementation.
89
-        at HelloWorld.hello(HelloWorld.java:3)
90
-        at HelloWorldTest.emptyStringIsComparedByValue(HelloWorldTest.java:17)
91
-
92
-HelloWorldTest > helloAnotherSampleName FAILED
80
+GreeterTest > testThatGreeterReturnsTheCorrectGreeting FAILED
93
     java.lang.UnsupportedOperationException: Delete this statement and write your own implementation.
81
     java.lang.UnsupportedOperationException: Delete this statement and write your own implementation.
94
-        at HelloWorld.hello(HelloWorld.java:3)
95
-        at HelloWorldTest.helloAnotherSampleName(HelloWorldTest.java:27)
82
+        at getGreeting(Greeter.java:4)
83
+        at GreeterTest.testThatGreeterReturnsTheCorrectGreeting(GreeterTest.java:9)
96
 
84
 
97
-4 tests completed, 4 failed
85
+1 tests completed, 1 failed
98
 :test FAILED
86
 :test FAILED
99
 
87
 
100
 FAILURE: Build failed with an exception.
88
 FAILURE: Build failed with an exception.
101
 
89
 
102
 * What went wrong:
90
 * What went wrong:
103
 Execution failed for task ':test'.
91
 Execution failed for task ':test'.
104
-> There were failing tests. See the report at: file:///home/logan/hello-world/build/reports/tests/index.html
92
+> There were failing tests. See the report at: file:///home/<username>/hello-world/build/reports/tests/index.html
105
 
93
 
106
 * Try:
94
 * Try:
107
 Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.
95
 Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.
111
 Total time: 12.361 secs
99
 Total time: 12.361 secs
112
 ```
100
 ```
113
 
101
 
114
-Seeing the word "fail" TEN TIMES might give you the impression you've done
115
-something horribly wrong.  You haven't.  It's a whole lot of noise over
116
-a few tests not passing.
102
+Seeing the word "FAILED" might give you the impression you've done
103
+something wrong.  You haven't.  This output is just a very verbose way of
104
+telling us that the included test did not pass. This is expected - we haven't
105
+written any code to help it pass yet!
117
 
106
 
118
 Let's focus in on the important bits:
107
 Let's focus in on the important bits:
119
 
108
 
120
 ```
109
 ```
121
-HelloWorldTest > helloSampleName FAILED
110
+GreeterTest > testThatGreeterReturnsTheCorrectGreeting FAILED
122
     java.lang.UnsupportedOperationException: Delete this statement and write your own implementation.
111
     java.lang.UnsupportedOperationException: Delete this statement and write your own implementation.
123
 ```
112
 ```
124
 
113
 
125
-...is read: "Within the test class named `HelloWorldTest`, the test method
126
-`helloSampleName` did not pass because an `UnsupportedOperationException` was thrown with the message
127
-`Delete this statement and write your own implementation.`."
114
+...is read: "Within the test class named `GreeterTest`, the test method
115
+`testThatGreeterReturnsTheCorrectGreeting` did not pass because an
116
+`UnsupportedOperationException` was thrown with the message `Delete this
117
+statement and write your own implementation.`."
128
 
118
 
129
-The next line of the stack trace tells us where the exception was thrown:
119
+The next line of the [stack trace](https://stackoverflow.com/questions/3988788/what-is-a-stack-trace-and-how-can-i-use-it-to-debug-my-application-errors)
120
+tells us where this `UnsupportedOperationException` was thrown:
130
 
121
 
131
 ```
122
 ```
132
-        at HelloWorld.hello(HelloWorld.java:3)
123
+        at getGreeting(Greeter.java:4)
133
 ```
124
 ```
134
 
125
 
135
-Looks like it was on line 3 in the HelloWorld file.
126
+Looks like it was on line 4 in the `Greeter.java` file. Let's update that line
127
+as instructed, and try running the tests again.
136
 
128
 
137
-We should remove this line from our `HelloWorld.java` file.
129
+## Step 2: Replace the `UnsupportedOperationException` 
138
 
130
 
139
-In your favorite text editor, open `src/main/java/HelloWorld.java`.
131
+In your favorite text editor, open `src/main/java/Greeter.java`. You should
132
+find the source of the exception encountered above on line 4:
140
 
133
 
141
-Delete the contents of that line and replace it with the following:
142
 ```java
134
 ```java
143
-return null;
144
-```
145
-Now you can run `gradle test` again.
146
-
147
-You should see a new error this time, don't worry though, you're making progress.
148
-
149
-```
150
-HelloWorldTest > helloNoName FAILED
151
-    java.lang.AssertionError: expected:<Hello, World!> but was:<null>
152
-```
153
-...is read: "Within the test class named HelloWorldTest, 
154
-the test method helloNoName did not pass because the solution did not satisfy an assertion. 
155
-Apparently, we expected to see the string 'Hello, World!' but the value null was returned instead.
156
-
157
-The last line of the stack trace tells us exactly where this unsatisfied assertion lives:
158
-
159
-```
160
-        at HelloWorldTest.helloNoName(HelloWorldTest.java:10)
135
+throw new UnsupportedOperationException("Delete this statement and write your own implementation.");
161
 ```
136
 ```
162
-Looks like the crime was discovered on line 10 in the test file.
163
 
137
 
164
-Knowing these two facts,
138
+[`Exception`s](https://docs.oracle.com/javase/tutorial/essential/exceptions/)
139
+are often used in Java to draw the attention of a developer when something goes
140
+wrong. In our case, nothing is wrong per se; we just haven't written our
141
+solution yet! The use of an
142
+[`UnsupportedOperationException`](http://docs.oracle.com/javase/8/docs/api/?java/lang/UnsupportedOperationException.html)
143
+in this situation is designed to remind us of exactly this fact. It effectively
144
+says: "Your Code Goes Here!".
165
 
145
 
166
-1. The return value was not what was expected, and
167
-2. The failure was on line 10 of the test,
168
-
169
-We can turn this failure into success.
170
-
171
-
172
-## Fixing the first test
173
-
174
-Open `src/test/java/HelloWorldTest.java`
175
-and go to line 10.
146
+Delete the contents of line 4 and replace it with the following:
176
 
147
 
177
 ```java
148
 ```java
178
-assertEquals("Hello, World!", HelloWorld.hello(""));
149
+return null;
179
 ```
150
 ```
180
 
151
 
181
-The test is expecting that `hello()`, when given an empty string (`""`),
182
-returns "Hello, World!".  Instead, `hello()` is returning `null`.
183
-Let's fix that.
184
-
185
-Open `src/main/java/HelloWorld.java`.
186
-
187
-```java
188
-public class HelloWorld {
189
-  public static String hello(String name) {
190
-    return null;
191
-  }
192
-}
193
-```
152
+Now run `gradle test` again.
194
 
153
 
195
-Let's change that to return the expected string:
154
+You should see a new error this time. Don't worry though, that still
155
+represents forward progress!
196
 
156
 
197
-```java
198
-public class HelloWorld {
199
-  public static String hello(String name) {
200
-    return "Hello, World!";
201
-  }
202
-}
203
 ```
157
 ```
204
-
205
-Save the file and run the tests again:
206
-
158
+GreeterTest > testThatGreeterReturnsTheCorrectGreeting FAILED
159
+    java.lang.AssertionError: expected:<Hello, World!> but was:<null>
207
 ```
160
 ```
208
-$ gradle test
209
-:compileJava
210
-:processResources UP-TO-DATE
211
-:classes
212
-:compileTestJava
213
-:processTestResources UP-TO-DATE
214
-:testClasses
215
-:test
216
-
217
-HelloWorldTest > helloSampleName FAILED
218
-    org.junit.ComparisonFailure: expected:<Hello, [Alice]!> but was:<Hello, [World]!>
219
-        at org.junit.Assert.assertEquals(Assert.java:115)
220
-        at org.junit.Assert.assertEquals(Assert.java:144)
221
-        at HelloWorldTest.helloSampleName(HelloWorldTest.java:22)
222
-
223
-HelloWorldTest > helloNoName PASSED
224
-
225
-HelloWorldTest > emptyStringIsComparedByValue PASSED
226
-
227
-HelloWorldTest > helloAnotherSampleName FAILED
228
-    org.junit.ComparisonFailure: expected:<Hello, [Bob]!> but was:<Hello, [World]!>
229
-        at org.junit.Assert.assertEquals(Assert.java:115)
230
-        at org.junit.Assert.assertEquals(Assert.java:144)
231
-        at HelloWorldTest.helloAnotherSampleName(HelloWorldTest.java:27)
232
-
233
-4 tests completed, 2 failed
234
-:test FAILED
235
 
161
 
236
-FAILURE: Build failed with an exception.
162
+...is read: "Within the test class named `GreeterTest`, 
163
+the test method `testThatGreeterReturnsTheCorrectGreeting` did not pass because
164
+the solution did not satisfy an assertion." 
237
 
165
 
238
-* What went wrong:
239
-Execution failed for task ':test'.
240
-> There were failing tests. See the report at: file:///home/logan/hello-world/build/reports/tests/index.html
241
-
242
-* Try:
243
-Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.
166
+Apparently, our test was expecting to see the string "Hello, World!", but it
167
+received the value `null` instead.
244
 
168
 
245
-BUILD FAILED
169
+The last line of the stack trace tells us exactly where this "unsatisfied
170
+assertion" lives:
246
 
171
 
247
-Total time: 20.855 secs
248
 ```
172
 ```
173
+        at testThatGreeterReturnsTheCorrectGreeting(GreeterTest.java:9)
174
+```
175
+Looks like the mismatch was discovered on line 9 in the test file.
249
 
176
 
250
-Woohoo! :)  You can see that `helloNoName()` and `emptyStringIsComparedByValue()` are
251
-now passing.
252
-
253
-Let's tackle the next test...
254
-
177
+Knowing these two facts:
255
 
178
 
179
+1. that the return value was not what was expected, and
180
+2. that the failure was on line 9 of the test file,
256
 
181
 
257
-## Fixing the second test
182
+we can turn this failure into success.
258
 
183
 
259
-Right now, we've hardcoded the greeting.  This second test has
260
-unleashed a new expectation: that our program must incorporate a name given
261
-into that greeting.  When given the name "`Alice`", that's who should be
262
-greeted instead of "`World`".
184
+## Step 3: Fix the test!
263
 
185
 
264
-(Re)open `src/main/java/HelloWorld.java`.
186
+Open `src/test/java/GreeterTest.java` and go to line 9. It reads:
265
 
187
 
266
 ```java
188
 ```java
267
-public class HelloWorld {
268
-  public static String hello(String name) {
269
-    return "Hello, World!";
270
-  }
271
-}
189
+assertEquals("Hello, World!", new Greeter().getGreeting());
272
 ```
190
 ```
273
 
191
 
274
-While `hello()` does accept a reference to a string named `name`, it is not
275
-using it in the output.  Let's change that:
192
+The test is expecting that the method `getGreeting()` returns "Hello, World!".
193
+Instead, `getGreeting()` is returning `null`. Let's fix that.
276
 
194
 
195
+Open `src/main/java/Greeter.java`. It should look like this:
277
 
196
 
278
 ```java
197
 ```java
279
-public class HelloWorld {
280
-  public static String hello(String name) {
281
-    return "Hello, " + name + "!";
282
-  }
283
-}
284
-```
285
-
286
-... and rerun the tests ...
287
-
288
-```
289
-$ gradle test
290
-:test
291
-
292
-HelloWorldTest > helloSampleName PASSED
293
-
294
-HelloWorldTest > helloNoName FAILED
295
-    org.junit.ComparisonFailure: expected:<Hello, [World]!> but was:<Hello, []!>
296
-        at org.junit.Assert.assertEquals(Assert.java:115)
297
-        at org.junit.Assert.assertEquals(Assert.java:144)
298
-        at HelloWorldTest.helloNoName(HelloWorldTest.java:11)
198
+class Greeter {
299
 
199
 
300
-HelloWorldTest > emptyStringIsComparedByValue FAILED
301
-    org.junit.ComparisonFailure: expected:<Hello, [World]!> but was:<Hello, []!>
302
-        at org.junit.Assert.assertEquals(Assert.java:115)
303
-        at org.junit.Assert.assertEquals(Assert.java:144)
304
-        at HelloWorldTest.emptyStringIsComparedByValue(HelloWorldTest.java:17)
305
-
306
-HelloWorldTest > helloAnotherSampleName PASSED
307
-
308
-4 tests completed, 2 failed
309
-:test FAILED
310
-
311
-FAILURE: Build failed with an exception.
312
-
313
-* What went wrong:
314
-Execution failed for task ':test'.
315
-> There were failing tests. See the report at: file:///home/logan/hello-world/build/reports/tests/index.html
316
-
317
-* Try:
318
-Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.
319
-
320
-BUILD FAILED
200
+    String getGreeting() {
201
+        return null;
202
+    }
321
 
203
 
322
-Total time: 12.466 secs
204
+}
323
 ```
205
 ```
324
 
206
 
325
-Wait... didn't we just fix the test?  Why is it failing?  Take a closer look...
207
+Remove the `return null` that we previously added, and instead return the
208
+string our test was expecting:
326
 
209
 
327
-In fact, `helloSampleName()` *is* passing.  It's just that at the same time,
328
-we just inadvertently broke the first tests: `helloNoName()` and `emptyStringIsComparedByValue()`.
329
-
330
-This is one tiny example of the benefit of maintaining a test suite: if we
331
-use them to drive out our code, the second we break the program the tests
332
-say so.  Since we saw them passing just *before* our latest change,
333
-whatever we *just* did most likely cause that regression.
334
-
335
-Our latest change was making the greeting dependent on the name given. Our
336
-first two tests expects that if either a blank string or null are given as the
337
-name, then "`World`" should be substituted in.  Let's implement that.
338
-
339
-`src/main/java/HelloWorld.java`:
340
 ```java
210
 ```java
341
-public class HelloWorld {
342
-  public static String hello(String name) {
343
-    if(name == null || "".equals(name)) {
344
-      name = "World";
211
+    String getGreeting() {
212
+        return "Hello, World!";
345
     }
213
     }
346
-    return "Hello, " + name + "!";
347
-  }
348
-}
349
 ```
214
 ```
350
 
215
 
351
-... and re-run the tests ...
216
+Save the file and run the tests again:
352
 
217
 
353
 ```
218
 ```
354
 $ gradle test
219
 $ gradle test
355
-...
220
+:compileJava
221
+:processResources UP-TO-DATE
222
+:classes
223
+:compileTestJava
224
+:processTestResources UP-TO-DATE
225
+:testClasses
356
 :test
226
 :test
357
 
227
 
358
-HelloWorldTest > helloSampleName PASSED
359
-
360
-HelloWorldTest > helloNoName PASSED
361
-
362
-HelloWorldTest > emptyStringIsComparedByValue PASSED
363
-
364
-HelloWorldTest > helloAnotherSampleName PASSED
228
+GreeterTest > testThatGreeterReturnsTheCorrectGreeting PASSED
365
 
229
 
366
 BUILD SUCCESSFUL
230
 BUILD SUCCESSFUL
367
 
231
 
368
 Total time: 11.717 secs
232
 Total time: 11.717 secs
369
 ```
233
 ```
370
 
234
 
371
-Oh, hello!  Turns out, the solution we put into place didn't just apply for
372
-"`Alice`" but "`Bob`" equally well.  In this case, the test succeeded with
373
-no additional code on our part.
374
-
375
-
376
-
377
-## Refactoring
378
-
379
-Now that you've got all the tests passing, you might consider whether
380
-the code is in the most readable/maintainable/efficient shape.  What makes
381
-for "good" design of software is a big topic.  The pursuit of it underlies
382
-much of what makes up the more valuable conversations on Exercism.
383
-
384
-For now, let's just take a quick review of our solution and see if there's
385
-any part of it we'd like to refactor.  Refactoring is changing the way
386
-a bit of code reads without changing what it does.
387
-
388
-Right now, the details of detecting whether the caller of `hello()` has
389
-given a name or not (i.e. `name` is either `null` or an empty string) is
390
-sitting right next to the core responsibility of the method: to produce a
391
-personalized greeting.
392
-
393
-```java
394
-public class HelloWorld {
395
-  public static String hello(String name) {
396
-    if(name == null || "".equals(name)) {
397
-      name = "World";
398
-    }
399
-    return "Hello, " + name + "!";
400
-  }
401
-}
402
-```
403
-
404
-How would things read if we extracted those details into a separate method
405
-and at the same time, replaced the `if` with a ternary expression?
406
-
407
-```java
408
-public class HelloWorld {
409
-
410
-  public static String hello(String name) {
411
-    String whom = isBlank(name) ? "World" : name;
412
-    return "Hello, " + whom + "!";
413
-  }
414
-
415
-  private static boolean isBlank(String string) {
416
-    return string == null || "".equals(string);
417
-  }
418
-}
419
-```
420
-
421
-By extracting that logic into the `isBlank()` method, we've added a little
422
-abstraction to our program -- it's not as literal as it was before.  Yet,
423
-it allows us to defer *needing* to understand *how* "blankness" is
424
-detected.  If we can assume that `isBlank()` just works, we don't have to
425
-downshift in our head to those details.  Instead, we can remain at the same
426
-level of thinking: to whom are we greeting?
427
-
428
-The ternary operator allowed us to express that choice in a more compact
429
-form.  Less to read without losing the intent.
430
-
431
-Finally, we introduced another variable: `whom`.  Doing so gives a name to
432
-the output of the ternary expression.  We certainly could have continued
433
-to reuse `name`, but by introducing a second `String` to hold the
434
-calculated value this keeps crisp the two ideas: `name` is what's given
435
-and `whom` is what's been determined.
436
-
437
-We made a bunch of changes, let's make sure we didn't break the program!
438
-
439
-```
440
-$ gradle test
441
-...
442
-HelloWorldTest > helloSampleName PASSED
443
-
444
-HelloWorldTest > helloNoName PASSED
445
-
446
-HelloWorldTest > emptyStringIsComparedByValue PASSED
447
-
448
-HelloWorldTest > helloAnotherSampleName PASSED
449
-...
450
-```
451
-
452
-This illustrates another benefit of writing tests: you can make significant
453
-changes to the structure of the program and very quickly restore your
454
-confidence that the program still works.  These tests are a far cry from a
455
-"proof" of correctness, but well-written tests do a much better job of
456
-(very quickly) giving us evidence that it is.  Without them, we manually
457
-run the program with different inputs and/or inspecting the code
458
-line-by-line -- time-consuming and error prone.
459
-
460
-
235
+Success! Our solution passes the only test case supplied. We're good to go!
461
 
236
 
462
 # Submitting your first iteration
237
 # Submitting your first iteration
463
 
238
 
465
 exercism.io.
240
 exercism.io.
466
 
241
 
467
 ```
242
 ```
468
-$ exercism submit src/main/java/HelloWorld.java
243
+$ exercism submit src/main/java/Greeter.java
469
 ```
244
 ```
470
 
245
 
471
-
472
-
473
 # Next Steps
246
 # Next Steps
474
 
247
 
475
 From here, there are a number of paths you can take.
248
 From here, there are a number of paths you can take.
476
 
249
 
250
+Regardless of what you decide to do next, we sincerely hope you learn
251
+and enjoy being part of this community.  If at any time you need assistance
252
+do not hesitate to ask for help:
253
+
254
+http://exercism.io/languages/java/help
255
+
256
+Cheers!
477
 
257
 
478
 ## Move on to the next exercise
258
 ## Move on to the next exercise
479
 
259
 
483
 $ exercism fetch java
263
 $ exercism fetch java
484
 ```
264
 ```
485
 
265
 
486
-
487
 ## Review (and comment on) others' submissions to this exercise
266
 ## Review (and comment on) others' submissions to this exercise
488
 
267
 
489
 The heart of Exercism are the conversations about coding
268
 The heart of Exercism are the conversations about coding
503
 
282
 
504
 http://exercism.io/tracks/java/exercises
283
 http://exercism.io/tracks/java/exercises
505
 
284
 
506
-
507
-
508
-## Submit another iteration
509
-
510
-You are also encouraged to consider additional "requirements" on a given
511
-exercise.
512
-
513
-For example, you could add a test or two that requires that the greeting
514
-use the capitalized form on the person's name, regardless of the case they
515
-used.
516
-
517
-In that situation, you'd write a test to set-up that new expectation and
518
-then implement that in the code (the same process we just went through
519
-together, above).
520
-
521
-
522
-
523
 ## Contribute to Exercism
285
 ## Contribute to Exercism
524
 
286
 
525
-The entire of Exercism is Open Source and is the labor of love for over
287
+The entire of Exercism is Open Source and is a labor of love for over
526
 100 maintainers and many more contributors.
288
 100 maintainers and many more contributors.
527
 
289
 
528
 A starting point to jumping in can be found here:
290
 A starting point to jumping in can be found here:
529
 
291
 
530
-https://github.com/exercism/problem-specifications/blob/master/CONTRIBUTING.md
531
-
532
-
533
-----
534
-
535
-Regardless of what you decide to do next, we sincerely hope you learn
536
-and enjoy being part of this community.  If at any time you need assistance
537
-do not hesitate to ask for help:
538
-
539
-http://exercism.io/languages/java/help
540
-
541
-Cheers!
292
+https://github.com/exercism/docs/tree/master/contributing-to-language-tracks

+ 7
- 0
exercises/hello-world/src/example/java/Greeter.java View File

1
+class Greeter {
2
+
3
+    String getGreeting() {
4
+        return "Hello, World!";
5
+    }
6
+
7
+}

+ 0
- 9
exercises/hello-world/src/example/java/HelloWorld.java View File

1
-public class HelloWorld {
2
-    public static String hello(String name) {
3
-        if (name == null || name.isEmpty()) {
4
-            return "Hello, World!";
5
-        }
6
-
7
-        return String.format("Hello, %s!", name);
8
-    }
9
-}

exercises/hello-world/src/main/java/HelloWorld.java → exercises/hello-world/src/main/java/Greeter.java View File

1
-public class HelloWorld {
2
-    public static String hello(String name) {
1
+class Greeter {
2
+
3
+    String getGreeting() {
3
         throw new UnsupportedOperationException("Delete this statement and write your own implementation.");
4
         throw new UnsupportedOperationException("Delete this statement and write your own implementation.");
4
     }
5
     }
6
+
5
 }
7
 }

+ 12
- 0
exercises/hello-world/src/test/java/GreeterTest.java View File

1
+import org.junit.Test;
2
+
3
+import static org.junit.Assert.assertEquals;
4
+
5
+public class GreeterTest {
6
+
7
+    @Test
8
+    public void testThatGreeterReturnsTheCorrectGreeting() {
9
+        assertEquals("Hello, World!", new Greeter().getGreeting());
10
+    }
11
+
12
+}

+ 0
- 28
exercises/hello-world/src/test/java/HelloWorldTest.java View File

1
-import org.junit.Test;
2
-import org.junit.Ignore;
3
-
4
-import static org.junit.Assert.assertEquals;
5
-
6
-public class HelloWorldTest {
7
-
8
-    @Test
9
-    public void helloNoName() {
10
-        assertEquals("Hello, World!", HelloWorld.hello(""));
11
-        assertEquals("Hello, World!", HelloWorld.hello(null));
12
-    }
13
-
14
-    @Test
15
-    public void emptyStringIsComparedByValue() {
16
-        assertEquals("Hello, World!", HelloWorld.hello(new String("")));
17
-    }
18
-    
19
-    @Test
20
-    public void helloSampleName() {
21
-        assertEquals("Hello, Alice!", HelloWorld.hello("Alice"));
22
-    }
23
-
24
-    @Test
25
-    public void helloAnotherSampleName() {
26
-        assertEquals("Hello, Bob!", HelloWorld.hello("Bob"));
27
-    }
28
-}

exercises/isogram/HINT.md → exercises/isogram/HINTS.md View File


exercises/simple-cipher/HINT.md → exercises/simple-cipher/HINTS.md View File


+ 0
- 3
exercises/two-fer/HINT.md View File

1
-To help you focus on one test at a time, [@Ignore](http://junit.sourceforge.net/javadoc/org/junit/Ignore.html)
2
-annotations have been added to every test but the first one. Any test with an `@Ignore` annotation will be skipped
3
-when you run the tests.

+ 38
- 0
exercises/two-fer/HINTS.md View File

1
+Most Java exercises include multiple test cases. These cases are structured to
2
+support a useful process known as
3
+[test-driven development (TDD)](https://en.wikipedia.org/wiki/Test-driven_development).
4
+TDD involves repeating a structured cycle that helps programmers build complex
5
+functionality piece by piece rather than all at once. That cycle can be
6
+described as follows:
7
+
8
+1. Add a test that describes one piece of desired functionality your code is
9
+currently missing.
10
+2. Run the tests to verify that this newly-added test fails.
11
+3. Update your existing code until:
12
+    - All the old tests continue to pass;
13
+    - The new test also passes.
14
+4. [Clean up](https://en.wikipedia.org/wiki/Code_refactoring) your code, making
15
+sure that all tests continue to pass. This typically involves renaming
16
+variables, removing duplicated chunks of logic, removing leftover logging, etc.
17
+5. Return to step 1 until all desired functionality has been built!
18
+
19
+The test files in this track contain _all_ the tests your solution should pass
20
+to be considered valid. That doesn't immediately seem to be compatible with the
21
+cycle described above, in which tests are written one by one. However, the
22
+tool that we use to write our tests, [JUnit](http://junit.org), provides an
23
+[@Ignore](http://junit.sourceforge.net/javadoc/org/junit/Ignore.html)
24
+[annotation](https://docs.oracle.com/javase/tutorial/java/annotations/) that
25
+can be used to temporarily skip an already-written test. Using this annotation,
26
+we make sure that the test files we deliver to you satisfy the following rules:
27
+
28
+- The first test in any test file is _not_ skipped by default.
29
+- All but the first test in any test file _are_ skipped by default.
30
+
31
+This allows you to simulate the TDD cycle by following these slightly-modified
32
+steps:
33
+
34
+1. Run the tests to verify that _at most one_ test currently fails.
35
+2. Update your existing code until all the non-skipped tests pass.
36
+3. Clean up your code, making sure that all non-skipped tests continue to pass.
37
+4. Remove the topmost `@Ignore` annotation in the test file.
38
+5. Return to step 1 until no tests are skipped and all tests pass!