Given a computer object get the USB version of the computer's soundcard, and if it's null return UNKNOWN
class Computer {
private final Soundcard soundcard;
Computer(final Soundcard soundcard) {
this.soundcard = soundcard;
}
Soundcard getSoundcard() {
return this.soundcard;
}
}
class Soundcard {
private final USB usb;
Soundcard(final USB usb) {
this.usb = usb;
}
USB getUsb() {
return this.usb;
}
}
class USB {
private final String version;
USB(final String version) {
this.version = version;
}
public String getVersion() {
return this.version;
}
}
// Horrible idea => NPE
public String getVersionWithNullsUnsafe() {
return Computer
.buildSampleComputer()
.getSoundcard()
.getUsb()
.getVersion();
}
// Better huh? => not really
public String getVersionWithNulls() {
String version = "UNKNOWN";
final Computer computer = Computer.buildSampleComputer();
if (computer != null) {
final Soundcard soundcard = computer.getSoundcard();
if (soundcard != null) {
final USB usb = soundcard.getUsb();
if (usb != null) {
version = usb.getVersion();
}
}
}
return version;
}
class Computer {
private final Soundcard soundcard;
Computer(final Soundcard soundcard) {
this.soundcard = soundcard;
}
Optional<Soundcard> getSoundcard() { // returning opional instead
return Optional.ofNullable(this.soundcard);
}
static Optional<Computer> buildSampleComputer() { // returning opional instead
return Optional.of(new Computer(
new Soundcard(
new USB("1.2")
)
)
);
}
}
class Soundcard {
private final USB usb;
Soundcard(final USB usb) {
this.usb = usb;
}
Optional<USB> getUsb() { // returning opional instead
return Optional.ofNullable(this.usb);
}
}
class USB {
private final String version;
USB(final String version) {
this.version = version;
}
public String getVersion() {
return this.version;
}
}
// this is fluent
// more elegant
// no side effects
// no mutability
// easy to read
public String getVersion() {
return Computer.buildSampleComputer()
.flatMap(Computer::getSoundcard)
.flatMap(Soundcard::getUsb)
.map(USB::getVersion)
.orElse("UNKNOWN");
}