Java

Lesson 01

Null handling and Optional boundaries

Make absence explicit at method boundaries with Optional or exceptions, instead of returning null from finder code.

Good Code

src/main/java/dev/review/user/UserService.java
public final class UserService {
    private final UserRepository users;

    public UserService(UserRepository users) {
        this.users = Objects.requireNonNull(users);
    }

    public UserProfile profileFor(UserId id) {
        Objects.requireNonNull(id, "id");

        User user = users.findById(id)
            .orElseThrow(() -> new UserNotFoundException(id));

        return UserProfile.from(user);
    }
}

Bad Code

src/main/java/UserService.java
public class UserService {
    private UserRepository users;

    public UserProfile profileFor(String id) {
        User user = users.findById(id);

        return new UserProfile(user.name(), user.email());
    }
}

Review Notes

What to review

Good Code

The good version treats missing users as part of the contract. The repository returns an Optional, the service checks its input, and the failure path is named.

Bad Code

The bad version lets null travel through the application. Reviewers have to infer whether findById can miss, and the actual error appears later as a less helpful NullPointerException.

Takeaways

  • A Java method should make missing data visible in its return type or exception path, not hide it behind a nullable value.