Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 53cbbda

Browse files
committedMar 14, 2025
Make some improvements, although it's not complete yet.
1 parent 6db542e commit 53cbbda

File tree

13 files changed

+92
-54
lines changed

13 files changed

+92
-54
lines changed
 

‎exercises/concept/tim-from-marketing-2/.classpath

+10-10
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
<?xml version="1.0" encoding="UTF-8"?>
22
<classpath>
3-
<classpathentry kind="src" output="bin/main" path=".meta/src/reference/java">
3+
<classpathentry kind="src" output="bin/starterTest" path="src/test/java">
44
<attributes>
5-
<attribute name="gradle_scope" value="main"/>
6-
<attribute name="gradle_used_by_scope" value="main,test"/>
5+
<attribute name="gradle_scope" value="starterTest"/>
6+
<attribute name="gradle_used_by_scope" value="starterTest"/>
7+
<attribute name="test" value="true"/>
78
</attributes>
89
</classpathentry>
910
<classpathentry kind="src" output="bin/starterSource" path="src/main/java">
@@ -12,20 +13,19 @@
1213
<attribute name="gradle_used_by_scope" value="starterSource"/>
1314
</attributes>
1415
</classpathentry>
15-
<classpathentry kind="src" output="bin/starterTest" path="src/test/java">
16-
<attributes>
17-
<attribute name="gradle_scope" value="starterTest"/>
18-
<attribute name="gradle_used_by_scope" value="starterTest"/>
19-
<attribute name="test" value="true"/>
20-
</attributes>
21-
</classpathentry>
2216
<classpathentry kind="src" output="bin/test" path="build/gen/test/java">
2317
<attributes>
2418
<attribute name="gradle_scope" value="test"/>
2519
<attribute name="gradle_used_by_scope" value="test"/>
2620
<attribute name="test" value="true"/>
2721
</attributes>
2822
</classpathentry>
23+
<classpathentry kind="src" output="bin/main" path=".meta/src/reference/java">
24+
<attributes>
25+
<attribute name="gradle_scope" value="main"/>
26+
<attribute name="gradle_used_by_scope" value="main,test"/>
27+
</attributes>
28+
</classpathentry>
2929
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-17/"/>
3030
<classpathentry kind="con" path="org.eclipse.buildship.core.gradleclasspathcontainer"/>
3131
<classpathentry kind="output" path="bin/default"/>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# ???
2+
3+
The **Optional<T>** type was introduced in Java 8 as a way to indicate that a method _may_ return a value.
4+
5+
Before Java 8, developers had to implement null checks:
6+
7+
```java
8+
public Employee getEmployee(String name) {
9+
// Assume that getEmployeeByName retrieves an Employee from a database
10+
Employee employee = getEmployeeByName(name);
11+
if (employee != null) {
12+
return employee;
13+
} else {
14+
throw new IllegalArgumentException("Employee not found");
15+
}
16+
}
17+
```
18+
19+
It is important to understand that the Optional API does not eliminate the null checking,
20+
but it defers it until the end of a series of methods, as long as all those methods return an optional object.
21+
22+
TBD: Rephrase this last paragraph.
23+
24+
The Optional type is mainly used as returned type. Using it as a parameter type or field type is less common and
25+
not recommended, as explained by one well-known Java language architect in [this SO answer](https://stackoverflow.com/questions/26327957/should-java-8-getters-return-optional-type).

‎exercises/concept/tim-from-marketing-2/.docs/hints.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
- This method returns an `Optional<Employee>` object, not an `Employee` one.
66

7-
## 2. Return the name and department of a given employee in a certain format
7+
## 2. Return the name and department of a given employee in a certain format
88

99
- You can call the method `getEmployeeById(int)` to get the employee.
10-
- Remember the syntax of the `ifPresentOrElse()` method.
10+
- Remember the syntax of the `ifPresentOrElse()` method.

‎exercises/concept/tim-from-marketing-2/.docs/instructions.md

+3-2
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ You will be writing two methods: `getEmployeeById(int)` and `getEmployeeDetailsB
88

99
## 1. Get an employee by ID
1010

11-
Implement the `getEmployeeById(int)` method so that it returns an Optional<Employee> object.
11+
Implement the `getEmployeeById(int)` method so that it returns an Optional<Employee> object.
12+
1213
If the employee does not exist, returns an empty Optional instance.
1314

1415
## 2. Return the name and department of a given employee in a certain format
@@ -21,4 +22,4 @@ getEmployeeDetailsById(1) => "1 - Tim - Marketing"
2122
getEmployeeDetailsById(3) => "3 - Steve - Engineering"
2223
```
2324

24-
If the employee does not exist or is null, it returns `No employee found for id: [id]`.
25+
If the employee does not exist or is null, it returns `No employee found for id: [id]`.

‎exercises/concept/tim-from-marketing-2/.docs/introduction.md

+13-18
Original file line numberDiff line numberDiff line change
@@ -2,24 +2,24 @@
22

33
## Optional
44

5-
## Introduction
5+
The **Optional<T>** type was introduced in Java 8 as a way to indicate that a method _may_ return a value.
66

7-
The **Optional<T>** type was introduced in Java 8 as a way to indicate that a method will return an object of type T or an empty value. It is present in type signatures of many core Java methods.
8-
Before Java 8, developers had to implement null checks:
7+
In other words, there is a chance the method returns "no value" at all.
8+
9+
## Creating an Optional<T> object
10+
11+
Given an object of type Employee, an Optional<Employee> object is created as follows:
912

1013
```java
11-
public Employee getEmployee(String name) {
12-
// Assume that getEmployeeByName retrieves an Employee from a database
13-
Employee employee = getEmployeeByName(name);
14-
if (employee != null) {
15-
return employee;
16-
} else {
17-
throw new IllegalArgumentException("Employee not found");
18-
}
19-
}
14+
Employee employee = new Employee();
15+
Optional<Employee> optionalEmployee = Optional.of(employee);
2016
```
2117

22-
With the Optional API, the code above can be simplified to:
18+
`optionalEmployee` is a wrapper of `employee`.
19+
20+
TBD: explain empty, present and get.
21+
22+
## Usage
2323

2424
```java
2525
public Optional<Employee> getEmployee(String name) {
@@ -62,8 +62,3 @@ public Optional<Integer> getEmployeeAge(String name) {
6262
.orElse("No employee found");
6363
}
6464
```
65-
66-
It is important to understand that the Optional API does not eliminate the null checking,
67-
but it defers it until the end of a series of methods, as long as all those methods return an optional object.
68-
The Optional type is mainly used as returned type. Using it as a parameter type or field type is less common and
69-
not recommended, as explained by one well-known Java language architect in [this SO answer](https://stackoverflow.com/questions/26327957/should-java-8-getters-return-optional-type)

‎exercises/concept/tim-from-marketing-2/.meta/config.json

+11-3
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,25 @@
11
{
2+
"name": "tim-from-marketing-2",
3+
"uuid": "a6cfc286-8c62-4f5b-8e59-f6bfc4374092",
4+
"concepts": [
5+
"optional-type"
6+
],
27
"authors": [
38
"josealonso"
49
],
10+
"contributors": [
11+
"kahgoh"
12+
],
513
"files": {
614
"solution": [
7-
"src/main/java/EmployeeService.java"
15+
"src/main/java/EmployeeDatabase.java"
816
],
917
"test": [
10-
"src/test/java/EmployeeServiceTest.java"
18+
"src/test/java/EmployeeDatabaseTest.java"
1119
],
1220
"exemplar": [
1321
".meta/src/reference/java/EmployeeService.java"
14-
],
22+
]
1523
},
1624
"icon": "nullability",
1725
"blurb": "Learn to use the Optional class by helping Tim print details of his company employees."

‎exercises/concept/tim-from-marketing-2/.meta/design.md

+3-3
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,8 @@
33
## Goal
44

55
The goal of this exercise is to teach the student how to use the Optional API.
6-
We will use the most common methods: `ifPresent`, `orElse`, `ifPresentOrElse`, `orElseThrow`.
6+
We will use the most common methods: `ifPresent`, `orElse`, `ifPresentOrElse`, `orElseThrow`.
77
The `isPresent` and `get` methods are not presented, since they do not provide any value over an ordinary null check.
8-
Some methods of the Stream API are needed. This is a bit problematic, since they have not been explained in the current Java track.
98

109
## Learning objectives
1110

@@ -35,8 +34,9 @@ This Concept Exercise's prerequisites Concepts are:
3534
## Analyzer
3635

3736
This exercise could benefit from the following rules in the [analyzer]:
37+
3838
- `essential`: If the solution uses `null` in any method, encourage the student to use `Optional<T>` instead.
39-
- `actionable`: If the solution uses the `get` or `isPresent` methods of the Optional<T> API, encourage the student to use `orElse`, `orElseThrow` or `ifPresentOrElse` instead.
39+
- `actionable`: If the solution uses the `get` or `isPresent` methods of the Optional<T> API, encourage the student to use `orElse`, `orElseThrow` or `ifPresentOrElse` instead.
4040
- `informative`: TODO.
4141

4242
If the solution does not receive any of the above feedback, it must be exemplar.

‎exercises/concept/tim-from-marketing-2/.meta/src/reference/java/Employee.java

+4-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
import java.util.Objects;
2-
import java.util.Optional;
2+
3+
/**
4+
* Holds information about an employee. There is no need to change this file.
5+
*/
36

47
class Employee {
58
private final int id;

‎exercises/concept/tim-from-marketing-2/.meta/src/reference/java/EmployeeService.java ‎exercises/concept/tim-from-marketing-2/.meta/src/reference/java/EmployeeDatabase.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,12 @@
22
import java.util.Optional;
33
import java.util.Objects;
44

5-
class EmployeeService {
5+
class EmployeeDatabase {
66

77
// This list is populated in the tests
88
private List<Employee> employeesList;
99

10-
public EmployeeService(List<Employee> listOfEmployees) {
10+
public EmployeeDatabase(List<Employee> listOfEmployees) {
1111
employeesList = listOfEmployees;
1212
}
1313

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
eclipse.preferences.version=1
2+
org.eclipse.jdt.core.classpath.outputOverlappingAnotherSource=ignore
3+
org.eclipse.jdt.core.compiler.codegen.targetPlatform=17
4+
org.eclipse.jdt.core.compiler.compliance=17
5+
org.eclipse.jdt.core.compiler.source=17

‎exercises/concept/tim-from-marketing-2/build.gradle

+2
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ dependencies {
1010
testImplementation platform("org.junit:junit-bom:5.10.0")
1111
testImplementation "org.junit.jupiter:junit-jupiter"
1212
testImplementation "org.assertj:assertj-core:3.25.1"
13+
14+
testRuntimeOnly "org.junit.platform:junit-platform-launcher"
1315
}
1416

1517
test {

‎exercises/concept/tim-from-marketing-2/src/main/java/EmployeeService.java ‎exercises/concept/tim-from-marketing-2/src/main/java/EmployeeDatabase.java

+2-3
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
1-
import java.util.ArrayList;
21
import java.util.List;
32
import java.util.Objects;
43
import java.util.Optional;
54

6-
class EmployeeService {
5+
class EmployeeDatabase {
76

87
private List<Employee> employeesList;
98

10-
public EmployeeService(List<Employee> listOfEmployees) {
9+
public EmployeeDatabase(List<Employee> listOfEmployees) {
1110
// This list is populated in the tests
1211
employeesList = listOfEmployees;
1312
}

‎exercises/concept/tim-from-marketing-2/src/test/java/EmployeeServiceTest.java ‎exercises/concept/tim-from-marketing-2/src/test/java/EmployeeDatabaseTest.java

+10-10
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@
88
import java.util.ArrayList;
99
import java.util.Optional;
1010

11-
public class EmployeeServiceTest {
11+
public class EmployeeDatabaseTest {
1212

13-
private EmployeeService employeeService;
13+
private EmployeeDatabase employeeDatabase;
1414
private List<Employee> listOfEmployees = new ArrayList<>();
1515

1616
void initList() {
@@ -23,62 +23,62 @@ void initList() {
2323
@BeforeEach
2424
void setup() {
2525
initList();
26-
employeeService = new EmployeeService(listOfEmployees);
26+
employeeDatabase = new EmployeeDatabase(listOfEmployees);
2727
}
2828

2929
@Test
3030
@Tag("task:1")
3131
@DisplayName("Retrieve one employee by id")
3232
void retrieveOneEmployeeById() {
33-
assertThat(employeeService.getEmployeeById(2))
33+
assertThat(employeeDatabase.getEmployeeById(2))
3434
.isEqualTo(Optional.of(listOfEmployees.get(1)));
3535
}
3636

3737
@Test
3838
@Tag("task:2")
3939
@DisplayName("Retrieve other employee by id")
4040
void retrieveOtherEmployeeById() {
41-
assertThat(employeeService.getEmployeeById(3))
41+
assertThat(employeeDatabase.getEmployeeById(3))
4242
.isEqualTo(Optional.of(listOfEmployees.get(2)));
4343
}
4444

4545
@Test
4646
@Tag("task:3")
4747
@DisplayName("Retrieve employee by id when some fields are null")
4848
void retrieveEmployeeById_withNullFields() {
49-
assertThat(employeeService.getEmployeeById(4))
49+
assertThat(employeeDatabase.getEmployeeById(4))
5050
.isEqualTo(Optional.of(listOfEmployees.get(3)));
5151
}
5252

5353
@Test
5454
@Tag("task:4")
5555
@DisplayName("Retrieve employee by id when the id does not exist")
5656
void retrieveEmployeeById_forANonExistingId() {
57-
assertThat(employeeService.getEmployeeById(7))
57+
assertThat(employeeDatabase.getEmployeeById(7))
5858
.isEqualTo(Optional.empty());
5959
}
6060

6161
@Test
6262
@Tag("task:5")
6363
@DisplayName("Retrieve employee details by id")
6464
void retrieveEmployeeDetailsById() {
65-
assertThat(employeeService.getEmployeeDetailsById(2))
65+
assertThat(employeeDatabase.getEmployeeDetailsById(2))
6666
.isEqualTo("2 - Joe - Sales");
6767
}
6868

6969
@Test
7070
@Tag("task:6")
7171
@DisplayName("Retrieve employee details by id when some fields are null")
7272
void retrieveEmployeeDetailsById_withNullFields() {
73-
assertThat(employeeService.getEmployeeDetailsById(4))
73+
assertThat(employeeDatabase.getEmployeeDetailsById(4))
7474
.isEqualTo("No employee found for id: 4");
7575
}
7676

7777
@Test
7878
@Tag("task:7")
7979
@DisplayName("Retrieve employee details by id when the id does not exist")
8080
void retrieveEmployeeDetailsById_forANonExistingId() {
81-
assertThat(employeeService.getEmployeeDetailsById(7))
81+
assertThat(employeeDatabase.getEmployeeDetailsById(7))
8282
.isEqualTo("No employee found for id: 7");
8383
}
8484
}

0 commit comments

Comments
 (0)
Please sign in to comment.