CodeSOD: Functionally Null
Starting in Java 8, Java introduced support for lambdas. Under the hood, they're a soup of anonymous classes, generics (and the associated type erasure), but they at least look like (and mostly behave like) lambdas. Functional programming came to Java a decade ago.
Ich's predecessor saw this new tool and decided that they needed to use it everywhere.
public final class Account2BankConnection implements Function<Account, BankConnection> { @Override public BankConnection apply(final Account account) { final Iban iban = new Function<String, Iban>() { @Override public Iban apply(final String input) { return input != null ? new Iban(input) : null; } }.apply(account.getIban()); final Bic bic = new Function<String, Bic>() { @Override public Bic apply(final String input) { return input != null ? new Bic(input) : null; } }.apply(account.getBic()); return new BankConnection(iban, bic, account.getOwner()); }}
The goal of this code is to take a bank account and construct the correct bank connection object for it. It implements the Function<T, R> interface, part of Java's functional programming approach. The apply method of this interface will convert an Account into a BankConnection.
It's already questionable about whether or not that's the right approach, but it's probably fine. And then we look at the internals of the method. Which creates two other anonymous Function<T, R> types, with their own apply methods, all of which exist to do null checks.
The result is a big pile of boilerplate that doesn't need to be there, and completely disguises what the code is actually doing. The entire point of the functional types in Java is that you can pass functions around- these aren't getting passed anywhere, they're used in-line and disposed of right away.
I could see, perhaps, a generic null-validating Function type, something that'd let folks do final IBan iban = new NullCheck<String, IBan>().apply(account.getIban()). Then again, I'm not sure that is any clearer than the ternary, and while we're at it, I think the Iban and Bic types should probably handle construction with null strings in a smart way, making the null check completely pointless and avoiding scenarios where BankConnection's constructor is going to have to deal with nulls itself.
In the end, while this code is a mistake, it's not the billion dollar mistake that nulls are. Just a little interest on it.
[Advertisement] ProGet's got you covered with security and access controls on your NuGet feeds. Learn more.