DEV Community

Discussion on: Why you should NOT HATE Java!

 
siy profile image
Sergiy Yevtushenko • Edited

I'd rather say that all these are signs of poorly though out and inconsistent language. One laughable example is that code written with infix methods often can be made non-compilable by adding one more line feed.
Another (significant) disadvantage is that Kotlin encourages developer to write hacky, hard to read and understand code. Optional chaining and elvis operator are especially easy to abuse.

Thread Thread
 
devdufutur profile image
Rudy Nappée

I'm not sure

user?.address?.streetName ?: "No street"

is weirder than

Optional.ofNullable(user).map(User::getAddress).map(Address::getStreetName).orElse("No street")

But I'm sure it's shorter :)

About infix notation, I'm not a big fan in everyday code but it can be handy for DSL. Again, great powers...

Thread Thread
 
siy profile image
Sergiy Yevtushenko

Your code is shorted for two reasons:

  • It assumes that user has type String, although for fair comparison it should have type Optional<String>
  • You just stepping through object properties (BTW, your code might be a code smell, because it knows too much about User internals). If you try to actually compose operations, your code will not look so short.

You may try to rewrite code below with optional chaining:

public UserProfileResponse userProfileRequestHandler(User.Id userId) {
    User user = userService.findById(userId);
    if (user == null) {
        return UserProfileResponse.error(USER_NOT_FOUND);
    }

    UserProfileDetails details = userProfileService.findById(userId);

    if (details == null) {
        return UserProfileResponse.of(user, UserProfileDetails.defaultDetails());
    }

    return UserProfileResponse.of(user, details);
}
Enter fullscreen mode Exit fullscreen mode

For comparison, monadic version of this code looks so:

public UserProfileResponse userProfileRequestHandler(User.Id userId) {
        return userService.findById(userId)
            .map(user -> UserProfileResponse.of(user, userProfileService.findById(userId)
                .orElseGet(UserProfileDetails::defaultDetails)))
            .orElseGet(() -> UserProfileResponse.error(USER_NOT_FOUND));
    }
Enter fullscreen mode Exit fullscreen mode
Thread Thread
 
devdufutur profile image
Rudy Nappée

Just assumed User/Address were kt data classes / java POJO but Indeed callee could've been returned a Optional