Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Immutability with Immutables

Immutability with Immutables

Why Immutability? Why is it important and what do we get out of it? How do we do it in Android.

BrianPlummer

June 14, 2016
Tweet

More Decks by BrianPlummer

Other Decks in Technology

Transcript

  1. Data should be like hot dogs Don’t let people take

    bites out of your hot dog or data!
  2. By Hand • All private and all final fields •

    No mutator methods • Exclusive access to mutable components (ref guarding) • Final class
  3. By Hand • All private and all final fields •

    No mutator methods • Exclusive access to mutable components (ref guarding) • Final class • Object creation is hard! (constructors, toString, hashcode…)
  4. Introducing Immutables.org “The core of immutables is modelling. Good modelling

    is at the heart of creating good applications and services, and of good design in general” • Immutable objects - Constructed once, in a consistent state and can be shared • Mandatory attributes - Will fail if they are missing • No sneaky modifications - When passed to other code • Naturally thread safe • Object definitions are pleasant to write and read • No boilerplate setter and getters • Clean code - based off of tenets of Effective Java
  5. Immutables data types -> convenience • String • Primitives •

    List, Set, Map, MultiMap, MultiSet • addFoo(T), addFoo(T…..), addAllFoo(Iterable<? extends T> • putBar(K, V), putAllBar(Map<K, V>), putBar(Map.Entry<K, V>)
  6. Three options for handling non-required fields • Optional • Default

    Value • Nullable Annotation Collections just work!!
  7. Optional • Fully supported! • com.google.common.base.Optional<T> • java.util.Optional* from java

    8 • com/io.atlassian.fugue.Option • Optional values default to Optional.absent() when omitted
  8. Nullability @Value.Immutable interface NullAccepted { @Nullable Integer emptyFirst(); @Nullable Long

    emptySecond(); } NullAccepted obj = ImmutableNullAccepted.builder() .emptyFirst(null) .build();
  9. Serialization • Simple serialization - implement/extend Serializable • @Serial.Version -

    applies serial version to enclosing types • @Serial.Structural - enables structural serialization so you can evolve your data • Using above annotations will cause generated objects to impl java.lang.Serializable • Just include: org.immutables:serial:2.2.5
  10. Gson • Generation of TypeAdapterFactories which use NO reflection •

    Just include: org.immutables:gson:2.2.5 org.immutables:value:2.2.5
  11. Mutating the data • with* methods are generated • Modifies

    values of attributes by returning new immutable obj
  12. Mutating the data • with* methods are generated • Modifies

    values of attributes you want to change Value changedValue = ImmutableValue.copyOf(existingValue) .withName("Changed Name") .withValues(Arrays.asList("Only new value")) .build(); @Value.Immutable public interface Value { String name(); String address(); List<String> values(); }
  13. Mutating the data • with* methods are generated • Modifies

    values of attributes you want to change List<Classroom> classrooms = ImmutableList.<Classroom>builder() .addAll(school.classrooms()) .add(newClassroom) .build(); school = ImmutableSchool.copyOf(school).withClassrooms(classrooms);
  14. Style annotation • @Value.Style annotation allows for attribute customization of

    generated code @Value.Style( get = {"is*", "get*"}, // Detect 'get' and 'is' prefixes in accessor methods init = "set*", // Builder initialization methods will have 'set' prefix typeAbstract = {"Abstract*"}, // 'Abstract' prefix will be detected and trimmed typeImmutable = "*", // No prefix or suffix for generated immutable type builder = "new", // construct builder using 'new' instead of factory method build = "create", // rename 'build' method on builder to 'create' visibility = ImplementationVisibility.PUBLIC, // Generated class will be always public defaults = @Value.Immutable(copy = false)) // Disable copy methods by default