while I was reviewing some code, I came across this snippet.
List<User> users = /* Some code that initializes the list */;
users.stream()
.filter(user -> user.getAddress().isPresent())
.map(/* Some code */)
// And so on...
The call of method user.getAddress() returns an Optional<Address>. Following the famous Law of Demeter (LoD), the above code is not clean. However, I cannot figure out how to refactor it to make it cleaner.
As a first attempt could be to add to the User class a method hasAddress(), but this method overcomes the need of having an Optional<Address>, IMO.
How should I refactor the above code? In this case, is it worth to satisfy the LoD?
EDIT: I missed specifying that in the map method I do not want to return the address.
Well, you summarized it yourself pretty well: If you wanted to couple more loosely by introducing
hasAddress(), why return anOptional.Reading into what the LoD says, it talks about having "limited" knowledge about "closely related" units. Sounds like a gray area to me, but going further it also mentions the "Only one dot" rule. Still, I would agree with the comments to your question that a null check (or
isPresent()) is entirely fine (heck, a real null check technically doesn't even need a dot ;P ).If you wanted to really encapsulate more, you could remove the
getAddress()completely and instead offer:But again, as the commenters pointed out: Is it worth it/necessary? All these laws/principles are rarely absolute and more guidelines than dogmas. In this case it might be about balancing LoD vs. KISS.
In the end, it is up to you to decide whether this specific example benefits from moving the functionality of your stream into the User class. Both are valid, and readability/maintainability/cleanliness depend on: