• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Best practices
2
3
4
5## <a name="interchangeable"></a>"Equals means interchangeable"
6
7Don't use AutoValue to implement value semantics unless you really want value
8semantics. In particular, you should never care about the difference between two
9equal instances.
10
11## <a name="mutable_properties"></a>Avoid mutable property types
12
13Avoid mutable types, including arrays, for your properties, especially if you
14make your accessor methods `public`. The generated accessors don't copy the
15field value on its way out, so you'd be exposing your internal state.
16
17Note that this doesn't mean your factory method can't *accept* mutable types as
18input parameters. Example:
19
20```java
21@AutoValue
22public abstract class ListExample {
23  abstract ImmutableList<String> names();
24
25  public static ListExample create(List<String> mutableNames) {
26    return new AutoValue_ListExample(ImmutableList.copyOf(mutableNames));
27  }
28}
29```
30
31## <a name="simple"></a>Keep behavior simple and dependency-free
32
33Your class can (and should) contain *simple* intrinsic behavior. But it
34shouldn't require complex dependencies and shouldn't access static state.
35
36You should essentially *never* need an alternative implementation of your
37hand-written abstract class, whether hand-written or generated by a mocking
38framework. If your behavior has enough complexity (or dependencies) that it
39actually needs to be mocked or faked, split it into a separate type that is
40*not* a value type. Otherwise it permits an instance with "real" behavior and
41one with "mock/fake" behavior to be `equals`, which does not make sense.
42
43## <a name="one_reference"></a>One reference only
44
45Other code in the same package will be able to directly access the generated
46class, but *should not*. It's best if each generated class has one and only one
47reference from your source code: the call from your static factory method to the
48generated constructor. If you have multiple factory methods, have them all
49delegate to the same hand-written method, so there is still only one point of
50contact with the generated code. This way, you have only one place to insert
51precondition checks or other pre- or postprocessing.
52
53## <a name="final"></a>Mark all concrete methods `final`
54
55Consider that other developers will try to read and understand your value class
56while looking only at your hand-written class, not the actual (generated)
57implementation class. If you mark your concrete methods `final`, they won't have
58to wonder whether the generated subclass might be overriding them. This is
59especially helpful if you are *[underriding](howto.md#custom)* `equals`,
60`hashCode` or `toString`!
61
62## <a name="constructor"></a>Maybe add an explicit, inaccessible constructor
63
64There are a few small advantages to adding a package-private, parameterless constructor to your abstract class. It prevents unwanted subclasses, and prevents an undocumented public constructor showing up in your generated API documentation. Whether these benefits are worth the extra noise in the file is a matter of your judgment.
65