Autovalue or simple POJO
Intention:
Try com.google.auto.value, is it really useful?
Description:
I had a discussion about boilerplate code and its impact on the readability/component weight/unit test coverage.
Is it really useful?
Below is listed a simple example of a bean annotated with AutoValue, which during build phase automatically entire bean + it's builder is generated with equals/hashcode/toString.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package eca.test.wrappers; | |
import com.google.auto.value.AutoValue; | |
import com.google.common.base.Optional; | |
@AutoValue | |
public abstract class RequestWrapper { | |
public abstract String getName(); | |
public abstract String getSurname(); | |
abstract public Optional<String> getPhone(); | |
abstract public Optional<String> getGroup(); | |
public static Builder builder() { | |
return new AutoValue_RequestWrapper.Builder() | |
.setPhone(Optional.<String>absent()) | |
.setGroup(Optional.<String>absent()); | |
} | |
@AutoValue.Builder | |
public abstract static class Builder { | |
public abstract Builder setName(String value); | |
public abstract Builder setSurname(String value); | |
abstract Builder setPhone(Optional<String> value); | |
public Builder setPhone(String value) { | |
return setPhone(Optional.fromNullable(value)); | |
} | |
abstract Builder setGroup(Optional<String> value); | |
public Builder setGroup(String value) { | |
return setGroup(Optional.fromNullable(value)); | |
} | |
public abstract RequestWrapper build(); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package eca.test.wrappers; | |
import com.google.common.base.Optional; | |
import javax.annotation.Generated; | |
@Generated("com.google.auto.value.processor.AutoValueProcessor") | |
final class AutoValue_RequestWrapper extends RequestWrapper { | |
private final String name; | |
private final String surname; | |
private final Optional<String> phone; | |
private final Optional<String> group; | |
private AutoValue_RequestWrapper( | |
String name, | |
String surname, | |
Optional<String> phone, | |
Optional<String> group) { | |
if (name == null) { | |
throw new NullPointerException("Null name"); | |
} | |
this.name = name; | |
if (surname == null) { | |
throw new NullPointerException("Null surname"); | |
} | |
this.surname = surname; | |
this.phone = phone; | |
this.group = group; | |
} | |
@Override | |
public String getName() { | |
return name; | |
} | |
@Override | |
public String getSurname() { | |
return surname; | |
} | |
@Override | |
public Optional<String> getPhone() { | |
return phone; | |
} | |
@Override | |
public Optional<String> getGroup() { | |
return group; | |
} | |
@Override | |
public String toString() { | |
return "RequestWrapper{" | |
+ "name=" + name + ", " | |
+ "surname=" + surname + ", " | |
+ "phone=" + phone + ", " | |
+ "group=" + group | |
+ "}"; | |
} | |
@Override | |
public boolean equals(Object o) { | |
if (o == this) { | |
return true; | |
} | |
if (o instanceof RequestWrapper) { | |
RequestWrapper that = (RequestWrapper) o; | |
return (this.name.equals(that.getName())) | |
&& (this.surname.equals(that.getSurname())) | |
&& ((this.phone == null) ? (that.getPhone() == null) : this.phone.equals(that.getPhone())) | |
&& ((this.group == null) ? (that.getGroup() == null) : this.group.equals(that.getGroup())); | |
} | |
return false; | |
} | |
@Override | |
public int hashCode() { | |
int h = 1; | |
h *= 1000003; | |
h ^= name.hashCode(); | |
h *= 1000003; | |
h ^= surname.hashCode(); | |
h *= 1000003; | |
h ^= (phone == null) ? 0 : phone.hashCode(); | |
h *= 1000003; | |
h ^= (group == null) ? 0 : group.hashCode(); | |
return h; | |
} | |
static final class Builder extends RequestWrapper.Builder { | |
private String name; | |
private String surname; | |
private Optional<String> phone; | |
private Optional<String> group; | |
Builder() { | |
} | |
Builder(RequestWrapper source) { | |
this.name = source.getName(); | |
this.surname = source.getSurname(); | |
this.phone = source.getPhone(); | |
this.group = source.getGroup(); | |
} | |
@Override | |
public RequestWrapper.Builder setName(String name) { | |
this.name = name; | |
return this; | |
} | |
@Override | |
public RequestWrapper.Builder setSurname(String surname) { | |
this.surname = surname; | |
return this; | |
} | |
@Override | |
public RequestWrapper.Builder setPhone(Optional<String> phone) { | |
this.phone = phone; | |
return this; | |
} | |
@Override | |
public RequestWrapper.Builder setGroup(Optional<String> group) { | |
this.group = group; | |
return this; | |
} | |
@Override | |
public RequestWrapper build() { | |
String missing = ""; | |
if (name == null) { | |
missing += " name"; | |
} | |
if (surname == null) { | |
missing += " surname"; | |
} | |
if (!missing.isEmpty()) { | |
throw new IllegalStateException("Missing required properties:" + missing); | |
} | |
return new AutoValue_RequestWrapper( | |
this.name, | |
this.surname, | |
this.phone, | |
this.group); | |
} | |
} | |
} |
Conclusion:
In case the model is really simple it might be useful, but when it has variation of references/nulable/ or custom validation than I would say it does not bring a lot of value.
References:
Documentation: https://github.com/google/auto/tree/master/value