Skip to content

Conversation

@swegner
Copy link
Contributor

@swegner swegner commented Mar 31, 2016

This is a sample for [BEAM-134] Investigate use of AutoValue

In the case of IsmFormat, there are four inner-classes used as immutable value types which can be simplified with AutoValue. Each of them demonstrate some interesting functionality:

  • KeyPrefix is the simplest of the bunch, and it's implementation basically disappears after conversion.
  • IsmRecord can act as two different types (value or metadata), and has validation logic in its getters they verify correct usage. In this case, we can keep the existing getter functionality and let AutoValue hook into separate package-private abstract properties. IsmShard is similar in this respect.
  • Footer provides has custom logic in its .toString() to include a version string. For other value classes, AutoValue will generate a toString() implementation compatible with the equivalent Objects.toStringHelper version. In this case, we can keep the existing implementation and AutoValue won't override it.

As noted in the JIRA issue, I've identified 39 distinct classes which could be similarly converted. The benefits to converting are:

  • Less boilerplate code to maintain.
  • Eliminate a common source of bugs.
  • Lower the barrier to writing immutable value types, which carry their own benefits.

I recommend we take this work.

@davorbonaci
Copy link
Member

This looks nice to me. Some magic, but reduces the amount of code.

Let's leave this pull request open for a week or so. This will give more people a chance to comment on this code pattern.

this.sharedKeySize = sharedBytes;
this.unsharedKeySize = unsharedBytes;
}
@AutoValue
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like that this is not retained at compile time. (No action needed)

@swegner
Copy link
Contributor Author

swegner commented Mar 31, 2016

Also note: AutoValue is a build-time dependency only. The @AutoValue annotation is marked with @RetentionPolicy.SOURCE, meaning the annotations discarded after compilation. The annotation processor generates package-private classes that should only be used within the implementation of the abstract class. In the pom.xml, the dependency is marked <scope>provided</scope>, meaning the dependency isn't transitive and won't be present at runtime.

@kennknowles
Copy link
Member

Love it. I did some brief checking into comparable libraries.

  • lombok: mutates the current class to add getters and setters. This is actually forbidden for annotation processors as I understand them, so I guess Lombok uses more fragile hooks to accomplish it. I agree with criticism that this is slightly more "magical", in a bad way.
  • immutables: very similar. They emphasize builders, which autovalue can also provide. Immutables works with interfaces, which seems nice.
  • FreeBuilder (also originating from Google) is a subset of AutoValue and seems a lower vitality project.

I am torn between my bias towards Google technology and the (admittedly modest) bonus of interface support in Immutables. Immutables also has some built-in support for Java standard lib classes - can you dig into the differences there?

@swegner
Copy link
Contributor Author

swegner commented Apr 12, 2016

Thanks for surfacing a few more options, @kennknowles. After looking at a few, my preference is for AutoValue. Some notes on each:

AutoValue:

  • Most popular (based on GitHub stars; I couldn't find a source of Maven stats)
  • Standard annotation processor; fully-supported in Maven, IntelliJ & Eclipse
  • Generated code is hidden; no user-visible API
  • Very flexible usage patterns

lombok

  • Also very popular
  • Supports many use-cases other than immutable type-generation. Feels more like adding language features on top of Java, similar to Typescript does for Javascript
  • Mutates source classes; as you note, this contradicts the annotation processor spec and may not play nicely with IDEs.
  • Generates visible APIs; harder to follow code without access to generated code or knowledge of lombok.

immutables

  • Much less popular than AutoValue and lombok
  • Most similar to AutoValue, but supports generating interface implementations.
  • Much more configuration-driven; lots of knobs to customize generated implementations since they are typically API-visible. As a result, there seems to be much more library-specific code.

FreeBuilder

  • Much less popular than AutoValue and lombok
  • Strives only to support builder pattern; factory methods not supported.

@kennknowles
Copy link
Member

Awesome. Thanks for the details. I'm sold on it. Since @lukecwik is the expert on this code, he should be the one to LGTM this particular use. There are some other places that we may immediately use it, such as a follow-up to #120.

static final int FIXED_LENGTH = 3 * LONG_BYTES + 1;
static final byte VERSION = 2;

private final long indexPosition;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could make version an actual field, its not a big deal to store the extra byte for each footer.

Then this would remove even more code from here.

@swegner swegner force-pushed the autovalue-example branch 3 times, most recently from 0168f14 to 293fdcf Compare April 15, 2016 17:42
@swegner
Copy link
Contributor Author

swegner commented Apr 15, 2016

I've addressed all feedback so far. Please take another look. @lukecwik

@lukecwik
Copy link
Member

Based upon http://mvnrepository.com/, this is the popularity of those projects as dependencies of other projects:
autovalue: 107 usages
lombok: 924 usages
immutables: 29 usages
FreeBuilder: 4 usages

@lukecwik
Copy link
Member

LGTM

Please fix conflict and then I can merge.

@swegner swegner force-pushed the autovalue-example branch from 293fdcf to 649b006 Compare April 20, 2016 17:46
@swegner
Copy link
Contributor Author

swegner commented Apr 20, 2016

Rebased. Should be good-to-go. @lukecwik

@swegner
Copy link
Contributor Author

swegner commented Apr 22, 2016

@davorbonaci Should AutoValue get backported to Dataflow SDK?

Reasons NOT TO backport: It's not new functionality.
Reasons TO backport: Other functionality we backport may depend on it. This is already the case with DisplayData.

I'm leaning towards not backporting. It should be easy to re-implement the parts of DisplayData which depend on it. /cc @bjchambers

@davorbonaci
Copy link
Member

I think the best choice is to back-port on a need basis, i.e., if and when another PR needs it.

mareksimunek pushed a commit to mareksimunek/beam that referenced this pull request May 9, 2018
pl04351820 pushed a commit to pl04351820/beam that referenced this pull request Dec 20, 2023
becketqin pushed a commit to becketqin/beam that referenced this pull request Jan 18, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants