xref: /aosp_15_r20/external/auto/value/userguide/practices.md (revision 1c2bbba85eccddce6de79cbbf1645fda32e723f0)
1*1c2bbba8SAndroid Build Coastguard Worker# Best practices
2*1c2bbba8SAndroid Build Coastguard Worker
3*1c2bbba8SAndroid Build Coastguard Worker
4*1c2bbba8SAndroid Build Coastguard Worker## <a name="interchangeable"></a>"Equals means interchangeable"
5*1c2bbba8SAndroid Build Coastguard Worker
6*1c2bbba8SAndroid Build Coastguard WorkerUse AutoValue when you want value semantics. Under value semantics, if `a` and
7*1c2bbba8SAndroid Build Coastguard Worker`b` are instances of the same AutoValue class, and `a.equals(b)`, then `a` and
8*1c2bbba8SAndroid Build Coastguard Worker`b` are considered interchangeable, and `a` can be used in place of `b`
9*1c2bbba8SAndroid Build Coastguard Workereverywhere and vice versa. If your AutoValue use case does not satisfy these
10*1c2bbba8SAndroid Build Coastguard Workercontracts, then AutoValue may not be a good fit.
11*1c2bbba8SAndroid Build Coastguard Worker
12*1c2bbba8SAndroid Build Coastguard Worker## <a name="mutable_properties"></a>Avoid mutable property types
13*1c2bbba8SAndroid Build Coastguard Worker
14*1c2bbba8SAndroid Build Coastguard WorkerAvoid mutable types, including arrays, for your properties, especially if you
15*1c2bbba8SAndroid Build Coastguard Workermake your accessor methods `public`. The generated accessors don't copy the
16*1c2bbba8SAndroid Build Coastguard Workerfield value on its way out, so you'd be exposing your internal state.
17*1c2bbba8SAndroid Build Coastguard Worker
18*1c2bbba8SAndroid Build Coastguard WorkerNote that this doesn't mean your factory method can't *accept* mutable types as
19*1c2bbba8SAndroid Build Coastguard Workerinput parameters. Example:
20*1c2bbba8SAndroid Build Coastguard Worker
21*1c2bbba8SAndroid Build Coastguard Worker```java
22*1c2bbba8SAndroid Build Coastguard Worker@AutoValue
23*1c2bbba8SAndroid Build Coastguard Workerpublic abstract class ListExample {
24*1c2bbba8SAndroid Build Coastguard Worker  abstract ImmutableList<String> names();
25*1c2bbba8SAndroid Build Coastguard Worker
26*1c2bbba8SAndroid Build Coastguard Worker  public static ListExample create(List<String> mutableNames) {
27*1c2bbba8SAndroid Build Coastguard Worker    return new AutoValue_ListExample(ImmutableList.copyOf(mutableNames));
28*1c2bbba8SAndroid Build Coastguard Worker  }
29*1c2bbba8SAndroid Build Coastguard Worker}
30*1c2bbba8SAndroid Build Coastguard Worker```
31*1c2bbba8SAndroid Build Coastguard Worker
32*1c2bbba8SAndroid Build Coastguard Worker## <a name="simple"></a>Keep behavior simple and dependency-free
33*1c2bbba8SAndroid Build Coastguard Worker
34*1c2bbba8SAndroid Build Coastguard WorkerYour class can (and should) contain *simple* intrinsic behavior. But it
35*1c2bbba8SAndroid Build Coastguard Workershouldn't require complex dependencies and shouldn't access static state.
36*1c2bbba8SAndroid Build Coastguard Worker
37*1c2bbba8SAndroid Build Coastguard WorkerYou should essentially *never* need an alternative implementation of your
38*1c2bbba8SAndroid Build Coastguard Workerhand-written abstract class, whether hand-written or generated by a mocking
39*1c2bbba8SAndroid Build Coastguard Workerframework. If your behavior has enough complexity (or dependencies) that it
40*1c2bbba8SAndroid Build Coastguard Workeractually needs to be mocked or faked, split it into a separate type that is
41*1c2bbba8SAndroid Build Coastguard Worker*not* a value type. Otherwise it permits an instance with "real" behavior and
42*1c2bbba8SAndroid Build Coastguard Workerone with "mock/fake" behavior to be `equals`, which does not make sense.
43*1c2bbba8SAndroid Build Coastguard Worker
44*1c2bbba8SAndroid Build Coastguard Worker## <a name="one_reference"></a>One reference only
45*1c2bbba8SAndroid Build Coastguard Worker
46*1c2bbba8SAndroid Build Coastguard WorkerOther code in the same package will be able to directly access the generated
47*1c2bbba8SAndroid Build Coastguard Workerclass, but *should not*. It's best if each generated class has one and only one
48*1c2bbba8SAndroid Build Coastguard Workerreference from your source code: the call from your static factory method to the
49*1c2bbba8SAndroid Build Coastguard Workergenerated constructor. If you have multiple factory methods, have them all
50*1c2bbba8SAndroid Build Coastguard Workerdelegate to the same hand-written method, so there is still only one point of
51*1c2bbba8SAndroid Build Coastguard Workercontact with the generated code. This way, you have only one place to insert
52*1c2bbba8SAndroid Build Coastguard Workerprecondition checks or other pre- or postprocessing.
53*1c2bbba8SAndroid Build Coastguard Worker
54*1c2bbba8SAndroid Build Coastguard Worker## <a name="final"></a>Mark all concrete methods `final`
55*1c2bbba8SAndroid Build Coastguard Worker
56*1c2bbba8SAndroid Build Coastguard WorkerConsider that other developers will try to read and understand your value class
57*1c2bbba8SAndroid Build Coastguard Workerwhile looking only at your hand-written class, not the actual (generated)
58*1c2bbba8SAndroid Build Coastguard Workerimplementation class. If you mark your concrete methods `final`, they won't have
59*1c2bbba8SAndroid Build Coastguard Workerto wonder whether the generated subclass might be overriding them. This is
60*1c2bbba8SAndroid Build Coastguard Workerespecially helpful if you are *[underriding](howto.md#custom)* `equals`,
61*1c2bbba8SAndroid Build Coastguard Worker`hashCode` or `toString`!
62*1c2bbba8SAndroid Build Coastguard Worker
63*1c2bbba8SAndroid Build Coastguard Worker## <a name="constructor"></a>Maybe add an explicit, inaccessible constructor
64*1c2bbba8SAndroid Build Coastguard Worker
65*1c2bbba8SAndroid Build Coastguard WorkerThere 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.
66