Skip to content

Instantly share code, notes, and snippets.

@FredrikWendt
Created October 30, 2012 12:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save FredrikWendt/3979886 to your computer and use it in GitHub Desktop.
Save FredrikWendt/3979886 to your computer and use it in GitHub Desktop.
Fluent APIs to prevent NullPointerException
public class Consumer implements UserAPIConsumer {
@Override
public void doit(UserAPI userAPI) {
userAPI.withCurrentOrNextPeriod(new BillingPeriodContext() {
@Override
public void executedIfPeriodExists(BillingPeriod period) {
System.out.println("yes: " + period);
}
@Override
public void executedOtherwise() {
System.out.println("no: no period available");
}
});
}
}
public interface UserAPI {
/**
* Invokes the corresponding method on the supplied context.
*/
void withCurrentOrNextPeriod(BillingPeriodContext context);
}
public interface BillingPeriodContext {
void executedIfPeriodExists(BillingPeriod period);
void executedOtherwise();
}
public class Consumer implements UserAPIConsumer {
@Override
public void doit(UserAPI userAPI) {
Nullable<BillingPeriod> periodRef = userAPI.getCurrentOrNextPeriod();
if (periodRef.hasValue()) {
System.out.println("Yay: " + periodRef.getValue());
}
}
}
public class BadConsumerStillPossible implements UserAPIConsumer {
@Override
public void doit(UserAPI userAPI) {
Nullable<BillingPeriod> periodRef = userAPI.getCurrentOrNextPeriod();
System.out.println("Hmm, still skipping null check: " + periodRef.getValue());
}
}
public interface Nullable<T> {
/**
* Returns true if it's safe to call {@link #getValue()}.
*/
boolean hasValue();
/**
* Throws a runtime exception if called when
* {@link #hasValue()} would return false.
*/
T getValue();
}
public interface UserAPI {
/**
* Returns the current or next billing period,
* if one's available.
*/
Nullable<BillingPeriod> getCurrentOrNextPeriod();
}
// same as original/first version
/**
* An API consumer may implement this to use the UserAPI.
*/
public interface UserAPIConsumer {
void doit(UserAPI userAPI);
}
public interface UserAPI {
/**
* Returns true if the user has a current or next
* billing period.
*/
boolean userHasCurrentOrNextBillingPeriod();
/**
* Returns the current or next billing period,
* if one's available.
*/
BillingPeriod getCurrentOrNextPeriod();
}
/**
* An API consumer may implement this to use the UserAPI.
*/
public interface UserAPIConsumer {
void doit(UserAPI userAPI);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment